sea_query/query/
with.rs

1use crate::{
2    ColumnRef, DynIden, IntoIden, QueryStatementBuilder, QueryStatementWriter, SelectExpr,
3    SelectStatement, SimpleExpr, SqlWriter, SubQueryStatement, TableRef, Values,
4    {Alias, QueryBuilder},
5};
6use inherent::inherent;
7
8/// A table definition inside a WITH clause ([WithClause]).
9///
10/// A WITH clause can contain one or multiple common table expressions ([CommonTableExpression]).
11///
12/// These named queries can act as a "query local table" that are materialized during execution and
13/// then can be used by the query prefixed with the WITH clause.
14///
15/// A WITH clause can contain multiple of these [CommonTableExpression]. (Except in the case of
16/// recursive WITH query which can only contain one [CommonTableExpression]).
17///
18/// A [CommonTableExpression] is a name, column names and a query returning data for those columns.
19///
20/// Some databases (like sqlite) restrict the acceptable kinds of queries inside of the WITH clause
21/// common table expressions. These databases only allow [SelectStatement]s to form a common table
22/// expression.
23///
24/// Other databases like postgres allow modification queries (UPDATE, DELETE) inside of the WITH
25/// clause but they have to return a table. (They must have a RETURNING clause).
26///
27/// sea-query doesn't check this or restrict the kind of [CommonTableExpression] that you can create
28/// in rust. This means that you can put an UPDATE or DELETE queries into WITH clause and sea-query
29/// will succeed in generating that kind of sql query but the execution inside the database will
30/// fail because they are invalid.
31///
32/// It is your responsibility to ensure that the kind of WITH clause that you put together makes
33/// sense and valid for that database that you are using.
34///
35/// NOTE that for recursive WITH queries (in sql: "WITH RECURSIVE") you can only have a
36/// single [CommonTableExpression] inside of the WITH clause. That query must match certain
37/// requirements:
38///   * It is a query of UNION or UNION ALL of two queries.
39///   * The first part of the query (the left side of the UNION) must be executable first in itself.
40///     It must be non-recursive. (Cannot contain self reference)
41///   * The self reference must appear in the right hand side of the UNION.
42///   * The query can only have a single self-reference.
43///   * Recursive data-modifying statements are not supported, but you can use the results of a
44///     recursive SELECT query in a data-modifying statement. (like so: WITH RECURSIVE
45///     cte_name(a,b,c,d) AS (SELECT ... UNION SELECT ... FROM ... JOIN cte_name ON ... WHERE ...)
46///     DELETE FROM table WHERE table.a = cte_name.a)
47///
48/// It is mandatory to set the [Self::table_name] and the [Self::query].
49#[derive(Debug, Clone, Default, PartialEq)]
50pub struct CommonTableExpression {
51    pub(crate) table_name: Option<DynIden>,
52    pub(crate) cols: Vec<DynIden>,
53    pub(crate) query: Option<Box<SubQueryStatement>>,
54    pub(crate) materialized: Option<bool>,
55}
56
57impl CommonTableExpression {
58    /// Construct a new [`CommonTableExpression`]
59    pub fn new() -> CommonTableExpression {
60        Self::default()
61    }
62
63    /// Sets the CTE table name of the query.
64    pub fn table_name<T>(&mut self, table_name: T) -> &mut Self
65    where
66        T: IntoIden,
67    {
68        self.table_name = Some(table_name.into_iden());
69        self
70    }
71
72    /// Adds a named column to the CTE table definition.
73    pub fn column<C>(&mut self, col: C) -> &mut Self
74    where
75        C: IntoIden,
76    {
77        self.cols.push(col.into_iden());
78        self
79    }
80
81    /// Adds a named columns to the CTE table definition.
82    pub fn columns<T, I>(&mut self, cols: I) -> &mut Self
83    where
84        T: IntoIden,
85        I: IntoIterator<Item = T>,
86    {
87        self.cols
88            .extend(cols.into_iter().map(|col| col.into_iden()));
89        self
90    }
91
92    /// Some databases allow you to put "MATERIALIZED" or "NOT MATERIALIZED" in the CTE definition.
93    /// This will affect how during the execution of [WithQuery] the CTE in the [WithClause] will be
94    /// executed. If the database doesn't support this syntax this option specified here will be
95    /// ignored and not appear in the generated sql.
96    pub fn materialized(&mut self, materialized: bool) -> &mut Self {
97        self.materialized = Some(materialized);
98        self
99    }
100
101    /// Set the query generating the CTE content. The query's result must match the defined
102    /// columns.
103    pub fn query<Q>(&mut self, query: Q) -> &mut Self
104    where
105        Q: QueryStatementBuilder,
106    {
107        self.query = Some(Box::new(query.into_sub_query_statement()));
108        self
109    }
110
111    /// Create a CTE from a [SelectStatement] if the selections are named columns then this will
112    /// return a [CommonTableExpression] that has the column names set. The [Self::table_name] is
113    /// set if the [SelectStatement] from clause contains at least one table.
114    pub fn from_select(select: SelectStatement) -> Self {
115        let mut cte = Self::default();
116        cte.try_set_cols_from_selects(&select.selects);
117        if let Some(from) = select.from.first() {
118            match from {
119                TableRef::Table(iden) => cte.set_table_name_from_select(iden),
120                TableRef::SchemaTable(_, iden) => cte.set_table_name_from_select(iden),
121                TableRef::DatabaseSchemaTable(_, _, iden) => cte.set_table_name_from_select(iden),
122                TableRef::TableAlias(_, iden) => cte.set_table_name_from_select(iden),
123                TableRef::SchemaTableAlias(_, _, iden) => cte.set_table_name_from_select(iden),
124                TableRef::DatabaseSchemaTableAlias(_, _, _, iden) => {
125                    cte.set_table_name_from_select(iden)
126                }
127                _ => {}
128            }
129        }
130        cte.query = Some(Box::new(select.into_sub_query_statement()));
131        cte
132    }
133
134    fn set_table_name_from_select(&mut self, iden: &DynIden) {
135        self.table_name = Some(Alias::new(format!("cte_{}", iden.to_string())).into_iden())
136    }
137
138    /// Set up the columns of the CTE to match the given [SelectStatement] selected columns.
139    /// This will fail if the select contains non named columns like expressions of wildcards.
140    ///
141    /// Returns true if the column setup from the select query was successful. If the returned
142    /// value is false the columns are untouched.
143    pub fn try_set_cols_from_select(&mut self, select: &SelectStatement) -> bool {
144        self.try_set_cols_from_selects(&select.selects)
145    }
146
147    fn try_set_cols_from_selects(&mut self, selects: &[SelectExpr]) -> bool {
148        let vec: Option<Vec<DynIden>> = selects
149            .iter()
150            .map(|select| {
151                if let Some(ident) = &select.alias {
152                    Some(ident.clone())
153                } else {
154                    match &select.expr {
155                        SimpleExpr::Column(column) => match column {
156                            ColumnRef::Column(iden) => Some(iden.clone()),
157                            ColumnRef::TableColumn(table, column) => Some(
158                                Alias::new(format!("{}_{}", table.to_string(), column.to_string()))
159                                    .into_iden(),
160                            ),
161                            ColumnRef::SchemaTableColumn(schema, table, column) => Some(
162                                Alias::new(format!(
163                                    "{}_{}_{}",
164                                    schema.to_string(),
165                                    table.to_string(),
166                                    column.to_string()
167                                ))
168                                .into_iden(),
169                            ),
170                            _ => None,
171                        },
172                        _ => None,
173                    }
174                }
175            })
176            .collect();
177
178        if let Some(c) = vec {
179            self.cols = c;
180            return true;
181        }
182
183        false
184    }
185}
186
187/// For recursive [WithQuery] [WithClause]s the traversing order can be specified in some databases
188/// that support this functionality.
189#[derive(Debug, Clone, PartialEq)]
190pub enum SearchOrder {
191    /// Breadth first traversal during the execution of the recursive query.
192    BREADTH,
193    /// Depth first traversal during the execution of the recursive query.
194    DEPTH,
195}
196
197/// For recursive [WithQuery] [WithClause]s the traversing order can be specified in some databases
198/// that support this functionality.
199///
200/// The clause contains the type of traversal: [SearchOrder] and the expression that is used to
201/// construct the current path.
202///
203/// A query can have both SEARCH and CYCLE clauses.
204///
205/// Setting [Self::order] and [Self::expr] is mandatory. The [SelectExpr] used must specify an alias
206/// which will be the name that you can use to order the result of the [CommonTableExpression].
207#[derive(Debug, Clone, Default, PartialEq)]
208pub struct Search {
209    pub(crate) order: Option<SearchOrder>,
210    pub(crate) expr: Option<SelectExpr>,
211}
212
213impl Search {
214    /// Create a complete [Search] specification from the [SearchOrder] and a [SelectExpr]. The
215    /// given [SelectExpr] must have an alias specified.
216    pub fn new_from_order_and_expr<EXPR>(order: SearchOrder, expr: EXPR) -> Self
217    where
218        EXPR: Into<SelectExpr>,
219    {
220        let expr = expr.into();
221        expr.alias.as_ref().unwrap();
222        Self {
223            order: Some(order),
224            expr: Some(expr),
225        }
226    }
227
228    /// Constructs a new empty [Search].
229    pub fn new() -> Self {
230        Self::default()
231    }
232
233    /// The traversal order to be used.
234    pub fn order(&mut self, order: SearchOrder) -> &mut Self {
235        self.order = Some(order);
236        self
237    }
238
239    /// The given [SelectExpr] must have an alias specified.
240    ///
241    /// The actual expression will be the one used to track the path in the graph.
242    ///
243    /// The alias of the given [SelectExpr] will be the name of the order column generated by this
244    /// clause.
245    pub fn expr<EXPR>(&mut self, expr: EXPR) -> &mut Self
246    where
247        EXPR: Into<SelectExpr>,
248    {
249        let expr = expr.into();
250        expr.alias.as_ref().unwrap();
251        self.expr = Some(expr);
252        self
253    }
254}
255
256/// For recursive [WithQuery] [WithClause]s the CYCLE sql clause can be specified to avoid creating
257/// an infinite traversals that loops on graph cycles indefinitely. You specify an expression that
258/// identifies a node in the graph and that will be used to determine during the iteration of
259/// the execution of the query when appending of new values whether the new values are distinct new
260/// nodes or are already visited and therefore they should be added again into the result.
261///
262/// A query can have both SEARCH and CYCLE clauses.
263///
264/// Setting [Self::set], [Self::expr] and [Self::using] is mandatory.
265#[derive(Debug, Clone, Default, PartialEq)]
266pub struct Cycle {
267    pub(crate) expr: Option<SimpleExpr>,
268    pub(crate) set_as: Option<DynIden>,
269    pub(crate) using: Option<DynIden>,
270}
271
272impl Cycle {
273    /// Create a complete [Search] specification from the [SearchOrder] and a [SelectExpr]. The
274    /// given [SelectExpr] must have an alias specified.
275    pub fn new_from_expr_set_using<EXPR, ID1, ID2>(expr: EXPR, set: ID1, using: ID2) -> Self
276    where
277        EXPR: Into<SimpleExpr>,
278        ID1: IntoIden,
279        ID2: IntoIden,
280    {
281        Self {
282            expr: Some(expr.into()),
283            set_as: Some(set.into_iden()),
284            using: Some(using.into_iden()),
285        }
286    }
287
288    /// Constructs a new empty [Cycle].
289    pub fn new() -> Self {
290        Self::default()
291    }
292
293    /// The expression identifying nodes.
294    pub fn expr<EXPR>(&mut self, expr: EXPR) -> &mut Self
295    where
296        EXPR: Into<SimpleExpr>,
297    {
298        self.expr = Some(expr.into());
299        self
300    }
301
302    /// The name of the boolean column containing whether we have completed a cycle or not yet
303    /// generated by this clause.
304    pub fn set<ID>(&mut self, set: ID) -> &mut Self
305    where
306        ID: IntoIden,
307    {
308        self.set_as = Some(set.into_iden());
309        self
310    }
311
312    /// The name of the array typed column that contains the node ids (generated using the
313    /// [Self::expr]) that specify the current nodes path that will be generated by this clause.
314    pub fn using<ID>(&mut self, using: ID) -> &mut Self
315    where
316        ID: IntoIden,
317    {
318        self.using = Some(using.into_iden());
319        self
320    }
321}
322
323/// A WITH clause can contain one or multiple common table expressions ([CommonTableExpression]).
324///
325/// You can use this to generate [WithQuery] by calling [WithClause::query].
326///
327/// These named queries can act as a "query local table" that are materialized during execution and
328/// then can be used by the query prefixed with the WITH clause.
329///
330/// A WITH clause can contain multiple of these [CommonTableExpression]. (Except in the case of
331/// recursive WITH query which can only contain one [CommonTableExpression]).
332///
333/// A [CommonTableExpression] is a name, column names and a query returning data for those columns.
334///
335/// Some databases (like sqlite) restrict the acceptable kinds of queries inside of the WITH clause
336/// common table expressions. These databases only allow [SelectStatement]s to form a common table
337/// expression.
338///
339/// Other databases like postgres allow modification queries (UPDATE, DELETE) inside of the WITH
340/// clause but they have to return a table. (They must have a RETURNING clause).
341///
342/// sea-query doesn't check this or restrict the kind of [CommonTableExpression] that you can create
343/// in rust. This means that you can put an UPDATE or DELETE queries into WITH clause and sea-query
344/// will succeed in generating that kind of sql query but the execution inside the database will
345/// fail because they are invalid.
346///
347/// It is your responsibility to ensure that the kind of WITH clause that you put together makes
348/// sense and valid for that database that you are using.
349///
350/// NOTE that for recursive WITH queries (in sql: "WITH RECURSIVE") you can only have a
351/// single [CommonTableExpression] inside of the WITH clause. That query must match certain
352/// requirements:
353///   * It is a query of UNION or UNION ALL of two queries.
354///   * The first part of the query (the left side of the UNION) must be executable first in itself.
355///     It must be non-recursive. (Cannot contain self reference)
356///   * The self reference must appear in the right hand side of the UNION.
357///   * The query can only have a single self-reference.
358///   * Recursive data-modifying statements are not supported, but you can use the results of a
359///     recursive SELECT query in a data-modifying statement. (like so: WITH RECURSIVE
360///     cte_name(a,b,c,d) AS (SELECT ... UNION SELECT ... FROM ... JOIN cte_name ON ... WHERE ...)
361///     DELETE FROM table WHERE table.a = cte_name.a)
362///
363/// It is mandatory to set the [Self::cte]. With queries must have at least one CTE.
364/// Recursive with query generation will panic if you specify more than one CTE.
365///
366/// # Examples
367///
368/// ```
369/// use sea_query::{*, IntoCondition, IntoIden, tests_cfg::*};
370///
371/// let base_query = SelectStatement::new()
372///                     .column(Alias::new("id"))
373///                     .expr(1i32)
374///                     .column(Alias::new("next"))
375///                     .column(Alias::new("value"))
376///                     .from(Alias::new("table"))
377///                     .to_owned();
378///
379/// let cte_referencing = SelectStatement::new()
380///                             .column(Alias::new("id"))
381///                             .expr(Expr::col(Alias::new("depth")).add(1i32))
382///                             .column(Alias::new("next"))
383///                             .column(Alias::new("value"))
384///                             .from(Alias::new("table"))
385///                             .join(
386///                                 JoinType::InnerJoin,
387///                                 Alias::new("cte_traversal"),
388///                                 Expr::col((Alias::new("cte_traversal"), Alias::new("next"))).equals((Alias::new("table"), Alias::new("id")))
389///                             )
390///                             .to_owned();
391///
392/// let common_table_expression = CommonTableExpression::new()
393///             .query(
394///                 base_query.clone().union(UnionType::All, cte_referencing).to_owned()
395///             )
396///             .column(Alias::new("id"))
397///             .column(Alias::new("depth"))
398///             .column(Alias::new("next"))
399///             .column(Alias::new("value"))
400///             .table_name(Alias::new("cte_traversal"))
401///             .to_owned();
402///
403/// let select = SelectStatement::new()
404///         .column(ColumnRef::Asterisk)
405///         .from(Alias::new("cte_traversal"))
406///         .to_owned();
407///
408/// let with_clause = WithClause::new()
409///         .recursive(true)
410///         .cte(common_table_expression)
411///         .cycle(Cycle::new_from_expr_set_using(SimpleExpr::Column(ColumnRef::Column(Alias::new("id").into_iden())), Alias::new("looped"), Alias::new("traversal_path")))
412///         .to_owned();
413///
414/// let query = select.with(with_clause).to_owned();
415///
416/// assert_eq!(
417///     query.to_string(MysqlQueryBuilder),
418///     r#"WITH RECURSIVE `cte_traversal` (`id`, `depth`, `next`, `value`) AS (SELECT `id`, 1, `next`, `value` FROM `table` UNION ALL (SELECT `id`, `depth` + 1, `next`, `value` FROM `table` INNER JOIN `cte_traversal` ON `cte_traversal`.`next` = `table`.`id`)) SELECT * FROM `cte_traversal`"#
419/// );
420/// assert_eq!(
421///     query.to_string(PostgresQueryBuilder),
422///     r#"WITH RECURSIVE "cte_traversal" ("id", "depth", "next", "value") AS (SELECT "id", 1, "next", "value" FROM "table" UNION ALL (SELECT "id", "depth" + 1, "next", "value" FROM "table" INNER JOIN "cte_traversal" ON "cte_traversal"."next" = "table"."id")) CYCLE "id" SET "looped" USING "traversal_path" SELECT * FROM "cte_traversal""#
423/// );
424/// assert_eq!(
425///     query.to_string(SqliteQueryBuilder),
426///     r#"WITH RECURSIVE "cte_traversal" ("id", "depth", "next", "value") AS (SELECT "id", 1, "next", "value" FROM "table" UNION ALL SELECT "id", "depth" + 1, "next", "value" FROM "table" INNER JOIN "cte_traversal" ON "cte_traversal"."next" = "table"."id") SELECT * FROM "cte_traversal""#
427/// );
428/// ```
429#[derive(Debug, Clone, Default, PartialEq)]
430pub struct WithClause {
431    pub(crate) recursive: bool,
432    pub(crate) search: Option<Search>,
433    pub(crate) cycle: Option<Cycle>,
434    pub(crate) cte_expressions: Vec<CommonTableExpression>,
435}
436
437impl WithClause {
438    /// Constructs a new [WithClause].
439    pub fn new() -> Self {
440        Self::default()
441    }
442
443    /// Sets whether this clause is a recursive with clause of not.
444    /// If set to true it will generate a 'WITH RECURSIVE' query.
445    ///
446    /// You can only specify a single [CommonTableExpression] containing a union query
447    /// if this is set to true.
448    pub fn recursive(&mut self, recursive: bool) -> &mut Self {
449        self.recursive = recursive;
450        self
451    }
452
453    /// For recursive WITH queries you can specify the [Search] clause.
454    ///
455    /// This setting is not meaningful if the query is not recursive.
456    ///
457    /// Some databases don't support this clause. In that case this option will be silently ignored.
458    pub fn search(&mut self, search: Search) -> &mut Self {
459        self.search = Some(search);
460        self
461    }
462
463    /// For recursive WITH queries you can specify the [Cycle] clause.
464    ///
465    /// This setting is not meaningful if the query is not recursive.
466    ///
467    /// Some databases don't support this clause. In that case this option will be silently ignored.
468    pub fn cycle(&mut self, cycle: Cycle) -> &mut Self {
469        self.cycle = Some(cycle);
470        self
471    }
472
473    /// Add a [CommonTableExpression] to this with clause.
474    pub fn cte(&mut self, cte: CommonTableExpression) -> &mut Self {
475        self.cte_expressions.push(cte);
476        self
477    }
478
479    /// You can turn this into a [WithQuery] using this function. The resulting WITH query will
480    /// execute the argument query with this WITH clause.
481    pub fn query<T>(self, query: T) -> WithQuery
482    where
483        T: QueryStatementBuilder + 'static,
484    {
485        WithQuery::new().with_clause(self).query(query).to_owned()
486    }
487}
488
489impl From<CommonTableExpression> for WithClause {
490    fn from(cte: CommonTableExpression) -> WithClause {
491        WithClause::new().cte(cte).to_owned()
492    }
493}
494
495/// A WITH query. A simple SQL query that has a WITH clause ([WithClause]).
496///
497/// The [WithClause] can contain one or multiple common table expressions ([CommonTableExpression]).
498///
499/// These named queries can act as a "query local table" that are materialized during execution and
500/// then can be used by the query prefixed with the WITH clause.
501///
502/// A WITH clause can contain multiple of these [CommonTableExpression]. (Except in the case of
503/// recursive WITH query which can only contain one [CommonTableExpression]).
504///
505/// A [CommonTableExpression] is a name, column names and a query returning data for those columns.
506///
507/// Some databases (like sqlite) restrict the acceptable kinds of queries inside of the WITH clause
508/// common table expressions. These databases only allow [SelectStatement]s to form a common table
509/// expression.
510///
511/// Other databases like postgres allow modification queries (UPDATE, DELETE) inside of the WITH
512/// clause but they have to return a table. (They must have a RETURNING clause).
513///
514/// sea-query doesn't check this or restrict the kind of [CommonTableExpression] that you can create
515/// in rust. This means that you can put an UPDATE or DELETE queries into WITH clause and sea-query
516/// will succeed in generating that kind of sql query but the execution inside the database will
517/// fail because they are invalid.
518///
519/// It is your responsibility to ensure that the kind of WITH clause that you put together makes
520/// sense and valid for that database that you are using.
521///
522/// NOTE that for recursive WITH queries (in sql: "WITH RECURSIVE") you can only have a
523/// single [CommonTableExpression] inside of the WITH clause. That query must match certain
524/// requirements:
525///   * It is a query of UNION or UNION ALL of two queries.
526///   * The first part of the query (the left side of the UNION) must be executable first in itself.
527///     It must be non-recursive. (Cannot contain self reference)
528///   * The self reference must appear in the right hand side of the UNION.
529///   * The query can only have a single self-reference.
530///   * Recursive data-modifying statements are not supported, but you can use the results of a
531///     recursive SELECT query in a data-modifying statement. (like so: WITH RECURSIVE
532///     cte_name(a,b,c,d) AS (SELECT ... UNION SELECT ... FROM ... JOIN cte_name ON ... WHERE ...)
533///     DELETE FROM table WHERE table.a = cte_name.a)
534///
535/// It is mandatory to set the [Self::cte] and the [Self::query].
536#[derive(Debug, Clone, Default, PartialEq)]
537pub struct WithQuery {
538    pub(crate) with_clause: WithClause,
539    pub(crate) query: Option<Box<SubQueryStatement>>,
540}
541
542impl WithQuery {
543    /// Constructs a new empty [WithQuery].
544    pub fn new() -> Self {
545        Self::default()
546    }
547
548    /// Set the whole [WithClause].
549    pub fn with_clause(&mut self, with_clause: WithClause) -> &mut Self {
550        self.with_clause = with_clause;
551        self
552    }
553
554    /// Set the [WithClause::recursive]. See that method for more information.
555    pub fn recursive(&mut self, recursive: bool) -> &mut Self {
556        self.with_clause.recursive = recursive;
557        self
558    }
559
560    /// Add the [WithClause::search]. See that method for more information.
561    pub fn search(&mut self, search: Search) -> &mut Self {
562        self.with_clause.search = Some(search);
563        self
564    }
565
566    /// Set the [WithClause::cycle]. See that method for more information.
567    pub fn cycle(&mut self, cycle: Cycle) -> &mut Self {
568        self.with_clause.cycle = Some(cycle);
569        self
570    }
571
572    /// Add a [CommonTableExpression] to the with clause. See [WithClause::cte].
573    pub fn cte(&mut self, cte: CommonTableExpression) -> &mut Self {
574        self.with_clause.cte_expressions.push(cte);
575        self
576    }
577
578    /// Set the query that you execute with the [WithClause].
579    pub fn query<T>(&mut self, query: T) -> &mut Self
580    where
581        T: QueryStatementBuilder,
582    {
583        self.query = Some(Box::new(query.into_sub_query_statement()));
584        self
585    }
586}
587
588impl QueryStatementBuilder for WithQuery {
589    fn build_collect_any_into(&self, query_builder: &dyn QueryBuilder, sql: &mut dyn SqlWriter) {
590        query_builder.prepare_with_query(self, sql);
591    }
592
593    fn into_sub_query_statement(self) -> SubQueryStatement {
594        SubQueryStatement::WithStatement(self)
595    }
596}
597
598#[inherent]
599impl QueryStatementWriter for WithQuery {
600    pub fn build_collect_into<T: QueryBuilder>(&self, query_builder: T, sql: &mut dyn SqlWriter) {
601        query_builder.prepare_with_query(self, sql);
602    }
603
604    pub fn build_collect<T: QueryBuilder>(
605        &self,
606        query_builder: T,
607        sql: &mut dyn SqlWriter,
608    ) -> String;
609    pub fn build<T: QueryBuilder>(&self, query_builder: T) -> (String, Values);
610    pub fn to_string<T: QueryBuilder>(&self, query_builder: T) -> String;
611}