prisma / quaint

SQL Query AST and Visitor for Rust
Apache License 2.0
583 stars 61 forks source link

Reuse arguments on building #262

Open GrandChaman opened 3 years ago

GrandChaman commented 3 years ago

Hi !

Some database specific features are missing from this library. Rather than implementing everyone of them. It would be nice to be able to reuse an argument vectors, so that when concatenating queries, the arguments will be correctly numbered.

Something like (pseudo-code) :

let main_insert = Insert::single_into("my_table")
    .value("foo", 10)
    .build()
    .returning("id");
let following_insert = Insert::single_into("my_dep_table")
    .value("foo", 10)
    .value("main_id", Select::from_table("main_insert").column("id"))
    .build()
    .returning("id");
let final_select = Select::from_table("main_insert")
    .and_from("following_insert")
    .column(Column::from(("main_insert", "id")).alias("main_insert_id"))
    .column(Column::from(("following_insert", "id")).alias("following_insert_id"));
let params: Vec<Value<'_>> = Vec::with_capacity(128);
let (main_insert_query, params) = Postgres::build_with_params(main_insert, params);
let (following_insert_query, params) = Postgres::build_with_params(following_insert, params);
let (final_select_query, params) = Postgres::build_with_params(final_select, params);
let query = format!("WITH 'main_insert' AS ({}), 'following_insert' AS ({}) {};",
    main_insert_query, following_insert_query, final_select_query);
pimeys commented 3 years ago

Before reviewing the PR, have you tried extending the CTE interface for your needs?

https://prisma.github.io/quaint/quaint/ast/trait.IntoCommonTableExpression.html#method.into_cte

I'm just seeing this would fit for your needs, but it for now supports only SELECT queries. Should not be that bad to extend though?

GrandChaman commented 3 years ago

Yes, but sometimes one wants to use database specific function (that are not yet part of this library). Doing so with string concatenation makes it easier for onboarding rather than having to wait for every database specific feature to be available.

But you're right that in the attached example, the use case could be covered using the into_cte.

pimeys commented 3 years ago

I'd like to see a PR first implementing the CTE fixes, I need to think a bit more on the other PR before accepting the solution. And I'm pretty fried after a long day already :)