sea_query/backend/
query_builder.rs

1use std::{borrow::Cow, fmt, ops::Deref};
2
3use crate::*;
4
5const QUOTE: Quote = Quote(b'"', b'"');
6
7pub trait QueryBuilder:
8    QuotedBuilder + EscapeBuilder + TableRefBuilder + OperLeftAssocDecider + PrecedenceDecider + Sized
9{
10    /// The type of placeholder the builder uses for values, and whether it is numbered.
11    fn placeholder(&self) -> (&'static str, bool) {
12        ("?", false)
13    }
14
15    /// Prefix for tuples in VALUES list (e.g. ROW for MySQL)
16    fn values_list_tuple_prefix(&self) -> &str {
17        ""
18    }
19
20    /// Translate [`InsertStatement`] into SQL statement.
21    fn prepare_insert_statement(&self, insert: &InsertStatement, sql: &mut impl SqlWriter) {
22        if let Some(with) = &insert.with {
23            self.prepare_with_clause(with, sql);
24        }
25
26        self.prepare_insert(insert.replace, sql);
27
28        if let Some(table) = &insert.table {
29            sql.write_str(" INTO ").unwrap();
30
31            self.prepare_table_ref(table, sql);
32        }
33
34        if insert.default_values.unwrap_or_default() != 0
35            && insert.columns.is_empty()
36            && insert.source.is_none()
37        {
38            self.prepare_output(&insert.returning, sql);
39            sql.write_str(" ").unwrap();
40            let num_rows = insert.default_values.unwrap();
41            self.insert_default_values(num_rows, sql);
42        } else {
43            sql.write_str(" (").unwrap();
44            let mut cols = insert.columns.iter();
45            join_io!(
46                cols,
47                col,
48                join {
49                    sql.write_str(", ").unwrap();
50                },
51                do {
52                    self.prepare_iden(col, sql);
53                }
54            );
55
56            sql.write_str(")").unwrap();
57
58            self.prepare_output(&insert.returning, sql);
59
60            if let Some(source) = &insert.source {
61                sql.write_str(" ").unwrap();
62                match source {
63                    InsertValueSource::Values(values) => {
64                        sql.write_str("VALUES ").unwrap();
65                        let mut vals = values.iter();
66                        join_io!(
67                            vals,
68                            row,
69                            join {
70                                sql.write_str(", ").unwrap();
71                            },
72                            do {
73                                sql.write_str("(").unwrap();
74                                let mut cols = row.iter();
75                                join_io!(
76                                    cols,
77                                    col,
78                                    join {
79                                        sql.write_str(", ").unwrap();
80                                    },
81                                    do {
82                                        self.prepare_expr(col, sql);
83                                    }
84                                );
85
86                                sql.write_str(")").unwrap();
87                            }
88                        );
89                    }
90                    InsertValueSource::Select(select_query) => {
91                        self.prepare_select_statement(select_query.deref(), sql);
92                    }
93                }
94            }
95        }
96
97        self.prepare_on_conflict(&insert.on_conflict, sql);
98
99        self.prepare_returning(&insert.returning, sql);
100    }
101
102    fn prepare_union_statement(
103        &self,
104        union_type: UnionType,
105        select_statement: &SelectStatement,
106        sql: &mut impl SqlWriter,
107    ) {
108        match union_type {
109            UnionType::Intersect => sql.write_str(" INTERSECT (").unwrap(),
110            UnionType::Distinct => sql.write_str(" UNION (").unwrap(),
111            UnionType::Except => sql.write_str(" EXCEPT (").unwrap(),
112            UnionType::All => sql.write_str(" UNION ALL (").unwrap(),
113        }
114        self.prepare_select_statement(select_statement, sql);
115        sql.write_str(")").unwrap();
116    }
117
118    /// Translate [`SelectStatement`] into SQL statement.
119    fn prepare_select_statement(&self, select: &SelectStatement, sql: &mut impl SqlWriter) {
120        if let Some(with) = &select.with {
121            self.prepare_with_clause(with, sql);
122        }
123
124        sql.write_str("SELECT ").unwrap();
125
126        if let Some(distinct) = &select.distinct {
127            self.prepare_select_distinct(distinct, sql);
128            sql.write_str(" ").unwrap();
129        }
130
131        let mut selects = select.selects.iter();
132        join_io!(
133            selects,
134            expr,
135            join {
136                sql.write_str(", ").unwrap();
137            },
138            do {
139                self.prepare_select_expr(expr, sql);
140            }
141        );
142
143        if let Some(into_table) = &select.into {
144            self.prepare_select_into(into_table, sql);
145        }
146
147        let mut from_tables = select.from.iter();
148        join_io!(
149            from_tables,
150            table_ref,
151            first {
152                sql.write_str(" FROM ").unwrap();
153            },
154            join {
155                sql.write_str(", ").unwrap();
156            },
157            do {
158                self.prepare_table_ref(table_ref, sql);
159                self.prepare_index_hints(table_ref,select, sql);
160            },
161            last {
162                self.prepare_table_sample(select, sql);
163            }
164        );
165
166        for expr in &select.join {
167            sql.write_str(" ").unwrap();
168            self.prepare_join_expr(expr, sql);
169        }
170
171        self.prepare_condition(&select.r#where, "WHERE", sql);
172
173        let mut groups = select.groups.iter();
174        join_io!(
175            groups,
176            expr,
177            first {
178                sql.write_str(" GROUP BY ").unwrap();
179            },
180            join {
181                sql.write_str(", ").unwrap();
182            },
183            do {
184                self.prepare_expr(expr, sql);
185            }
186        );
187
188        self.prepare_condition(&select.having, "HAVING", sql);
189
190        if !select.unions.is_empty() {
191            select.unions.iter().for_each(|(union_type, query)| {
192                self.prepare_union_statement(*union_type, query, sql);
193            });
194        }
195
196        let mut orders = select.orders.iter();
197        join_io!(
198            orders,
199            expr,
200            first {
201                sql.write_str(" ORDER BY ").unwrap();
202            },
203            join {
204                sql.write_str(", ").unwrap();
205            },
206            do {
207                self.prepare_order_expr(expr, sql);
208            }
209        );
210
211        self.prepare_select_limit_offset(select, sql);
212
213        if let Some(lock) = &select.lock {
214            sql.write_str(" ").unwrap();
215            self.prepare_select_lock(lock, sql);
216        }
217
218        if let Some((name, query)) = &select.window {
219            sql.write_str(" WINDOW ").unwrap();
220            self.prepare_iden(name, sql);
221            sql.write_str(" AS (").unwrap();
222            self.prepare_window_statement(query, sql);
223            sql.write_str(")").unwrap();
224        }
225    }
226
227    // Translate the LIMIT and OFFSET expression in [`SelectStatement`]
228    fn prepare_select_limit_offset(&self, select: &SelectStatement, sql: &mut impl SqlWriter) {
229        if let Some(limit) = &select.limit {
230            sql.write_str(" LIMIT ").unwrap();
231            self.prepare_value(limit.clone(), sql);
232        }
233
234        if let Some(offset) = &select.offset {
235            sql.write_str(" OFFSET ").unwrap();
236            self.prepare_value(offset.clone(), sql);
237        }
238    }
239
240    /// Translate [`UpdateStatement`] into SQL statement.
241    fn prepare_update_statement(&self, update: &UpdateStatement, sql: &mut impl SqlWriter) {
242        if let Some(with) = &update.with {
243            self.prepare_with_clause(with, sql);
244        }
245
246        sql.write_str("UPDATE ").unwrap();
247
248        if let Some(table) = &update.table {
249            self.prepare_table_ref(table, sql);
250        }
251
252        self.prepare_update_join(&update.from, &update.r#where, sql);
253
254        sql.write_str(" SET ").unwrap();
255
256        let mut values = update.values.iter();
257        join_io!(
258            values,
259            row,
260            join {
261                sql.write_str(", ").unwrap();
262            },
263            do {
264                let (col, v) = row;
265                self.prepare_update_column(&update.table, &update.from, col, sql);
266                sql.write_str(" = ").unwrap();
267                self.prepare_expr(v, sql);
268            }
269        );
270
271        self.prepare_update_from(&update.from, sql);
272
273        self.prepare_output(&update.returning, sql);
274
275        self.prepare_update_condition(&update.from, &update.r#where, sql);
276
277        self.prepare_update_order_by(update, sql);
278
279        self.prepare_update_limit(update, sql);
280
281        self.prepare_returning(&update.returning, sql);
282    }
283
284    fn prepare_update_join(&self, _: &[TableRef], _: &ConditionHolder, _: &mut impl SqlWriter) {
285        // MySQL specific
286    }
287
288    fn prepare_update_from(&self, from: &[TableRef], sql: &mut impl SqlWriter) {
289        let mut from_iter = from.iter();
290        join_io!(
291            from_iter,
292            table_ref,
293            first {
294                sql.write_str(" FROM ").unwrap();
295            },
296            join {
297                sql.write_str(", ").unwrap();
298            },
299            do {
300                self.prepare_table_ref(table_ref, sql);
301            }
302        );
303    }
304
305    fn prepare_update_column(
306        &self,
307        _: &Option<Box<TableRef>>,
308        _: &[TableRef],
309        column: &DynIden,
310        sql: &mut impl SqlWriter,
311    ) {
312        self.prepare_iden(column, sql);
313    }
314
315    fn prepare_update_condition(
316        &self,
317        _: &[TableRef],
318        condition: &ConditionHolder,
319        sql: &mut impl SqlWriter,
320    ) {
321        self.prepare_condition(condition, "WHERE", sql);
322    }
323
324    /// Translate ORDER BY expression in [`UpdateStatement`].
325    fn prepare_update_order_by(&self, update: &UpdateStatement, sql: &mut impl SqlWriter) {
326        let mut orders = update.orders.iter();
327        join_io!(
328            orders,
329            expr,
330            first {
331                sql.write_str(" ORDER BY ").unwrap();
332            },
333            join {
334                sql.write_str(", ").unwrap();
335            },
336            do {
337                self.prepare_order_expr(expr, sql);
338            }
339        );
340    }
341
342    /// Translate LIMIT expression in [`UpdateStatement`].
343    fn prepare_update_limit(&self, update: &UpdateStatement, sql: &mut impl SqlWriter) {
344        if let Some(limit) = &update.limit {
345            sql.write_str(" LIMIT ").unwrap();
346            self.prepare_value(limit.clone(), sql);
347        }
348    }
349
350    /// Translate [`DeleteStatement`] into SQL statement.
351    fn prepare_delete_statement(&self, delete: &DeleteStatement, sql: &mut impl SqlWriter) {
352        if let Some(with) = &delete.with {
353            self.prepare_with_clause(with, sql);
354        }
355
356        sql.write_str("DELETE ").unwrap();
357
358        if let Some(table) = &delete.table {
359            sql.write_str("FROM ").unwrap();
360            self.prepare_table_ref(table, sql);
361        }
362
363        self.prepare_output(&delete.returning, sql);
364
365        self.prepare_condition(&delete.r#where, "WHERE", sql);
366
367        self.prepare_delete_order_by(delete, sql);
368
369        self.prepare_delete_limit(delete, sql);
370
371        self.prepare_returning(&delete.returning, sql);
372    }
373
374    /// Translate ORDER BY expression in [`DeleteStatement`].
375    fn prepare_delete_order_by(&self, delete: &DeleteStatement, sql: &mut impl SqlWriter) {
376        let mut orders = delete.orders.iter();
377        join_io!(
378            orders,
379            expr,
380            first {
381                sql.write_str(" ORDER BY ").unwrap();
382            },
383            join {
384                sql.write_str(", ").unwrap();
385            },
386            do {
387                self.prepare_order_expr(expr, sql);
388            }
389        );
390    }
391
392    /// Translate LIMIT expression in [`DeleteStatement`].
393    fn prepare_delete_limit(&self, delete: &DeleteStatement, sql: &mut impl SqlWriter) {
394        if let Some(limit) = &delete.limit {
395            sql.write_str(" LIMIT ").unwrap();
396            self.prepare_value(limit.clone(), sql);
397        }
398    }
399
400    /// Translate [`Expr`] into SQL statement.
401    fn prepare_expr(&self, simple_expr: &Expr, sql: &mut impl SqlWriter) {
402        self.prepare_expr_common(simple_expr, sql);
403    }
404
405    fn prepare_expr_common(&self, simple_expr: &Expr, sql: &mut impl SqlWriter) {
406        match simple_expr {
407            Expr::Column(column_ref) => {
408                self.prepare_column_ref(column_ref, sql);
409            }
410            Expr::Tuple(exprs) => {
411                self.prepare_tuple(exprs, sql);
412            }
413            Expr::Unary(op, expr) => {
414                self.prepare_un_oper(op, sql);
415                sql.write_str(" ").unwrap();
416                let drop_expr_paren =
417                    self.inner_expr_well_known_greater_precedence(expr, &(*op).into());
418                if !drop_expr_paren {
419                    sql.write_str("(").unwrap();
420                }
421                self.prepare_expr(expr, sql);
422                if !drop_expr_paren {
423                    sql.write_str(")").unwrap();
424                }
425            }
426            Expr::FunctionCall(func) => {
427                self.prepare_function_name(&func.func, sql);
428                self.prepare_function_arguments(func, sql);
429            }
430            Expr::Binary(left, op, right) => match (op, right.as_ref()) {
431                (BinOper::In, Expr::Tuple(t)) if t.is_empty() => {
432                    self.binary_expr(&1i32.into(), &BinOper::Equal, &2i32.into(), sql)
433                }
434                (BinOper::NotIn, Expr::Tuple(t)) if t.is_empty() => {
435                    self.binary_expr(&1i32.into(), &BinOper::Equal, &1i32.into(), sql)
436                }
437                _ => self.binary_expr(left, op, right, sql),
438            },
439            Expr::SubQuery(oper, sel) => {
440                if let Some(oper) = oper {
441                    self.prepare_sub_query_oper(oper, sql);
442                }
443                sql.write_str("(").unwrap();
444                self.prepare_query_statement(sel.deref(), sql);
445                sql.write_str(")").unwrap();
446            }
447            Expr::Value(val) => {
448                self.prepare_value(val.clone(), sql);
449            }
450            Expr::Values(list) => {
451                sql.write_str("(").unwrap();
452                let mut iter = list.iter();
453                join_io!(
454                    iter,
455                    val,
456                    join {
457                        sql.write_str(", ").unwrap();
458                    },
459                    do {
460                        self.prepare_value(val.clone(), sql);
461                    }
462                );
463                sql.write_str(")").unwrap();
464            }
465            Expr::Custom(s) => {
466                sql.write_str(s).unwrap();
467            }
468            Expr::CustomWithExpr(expr, values) => {
469                let (placeholder, numbered) = self.placeholder();
470                let mut tokenizer = Tokenizer::new(expr).iter().peekable();
471                let mut count = 0;
472                while let Some(token) = tokenizer.next() {
473                    match token {
474                        Token::Punctuation(mark) if mark == placeholder => match tokenizer.peek() {
475                            Some(Token::Punctuation(next_mark)) if next_mark == &placeholder => {
476                                sql.write_str(next_mark).unwrap();
477                                tokenizer.next();
478                            }
479                            Some(Token::Unquoted(tok)) if numbered => {
480                                if let Ok(num) = tok.parse::<usize>() {
481                                    self.prepare_expr(&values[num - 1], sql);
482                                }
483                                tokenizer.next();
484                            }
485                            _ => {
486                                self.prepare_expr(&values[count], sql);
487                                count += 1;
488                            }
489                        },
490                        _ => sql.write_str(token.as_str()).unwrap(),
491                    };
492                }
493            }
494            Expr::Keyword(keyword) => {
495                self.prepare_keyword(keyword, sql);
496            }
497            Expr::AsEnum(_, expr) => {
498                self.prepare_expr(expr, sql);
499            }
500            Expr::Case(case_stmt) => {
501                self.prepare_case_statement(case_stmt, sql);
502            }
503            Expr::Constant(val) => {
504                self.prepare_constant(val, sql);
505            }
506            Expr::TypeName(type_name) => {
507                self.prepare_type_ref(type_name, sql);
508            }
509        }
510    }
511
512    /// Translate [`CaseStatement`] into SQL statement.
513    fn prepare_case_statement(&self, stmts: &CaseStatement, sql: &mut impl SqlWriter) {
514        sql.write_str("(CASE").unwrap();
515
516        let CaseStatement { when, r#else } = stmts;
517
518        for case in when.iter() {
519            sql.write_str(" WHEN (").unwrap();
520            self.prepare_condition_where(&case.condition, sql);
521            sql.write_str(") THEN ").unwrap();
522
523            self.prepare_expr(&case.result, sql);
524        }
525        if let Some(r#else) = r#else {
526            sql.write_str(" ELSE ").unwrap();
527            self.prepare_expr(r#else, sql);
528        }
529
530        sql.write_str(" END)").unwrap();
531    }
532
533    /// Translate [`SelectDistinct`] into SQL statement.
534    fn prepare_select_distinct(&self, select_distinct: &SelectDistinct, sql: &mut impl SqlWriter) {
535        match select_distinct {
536            SelectDistinct::All => sql.write_str("ALL").unwrap(),
537            SelectDistinct::Distinct => sql.write_str("DISTINCT").unwrap(),
538            _ => {}
539        }
540    }
541
542    /// Translate [`IndexHint`][crate::extension::mysql::IndexHint] into SQL statement.
543    fn prepare_index_hints(
544        &self,
545        _table_ref: &TableRef,
546        _select: &SelectStatement,
547        _sql: &mut impl SqlWriter,
548    ) {
549    }
550
551    /// Translate [`TableSample`][crate::extension::postgres::TableSample] into SQL statement.
552    fn prepare_table_sample(&self, _select: &SelectStatement, _sql: &mut impl SqlWriter) {}
553
554    /// Translate [`LockType`] into SQL statement.
555    fn prepare_select_lock(&self, lock: &LockClause, sql: &mut impl SqlWriter) {
556        sql.write_str(self.lock_phrase(lock.r#type)).unwrap();
557        let mut tables = lock.tables.iter();
558        join_io!(
559            tables,
560            table_ref,
561            first {
562                sql.write_str(" OF ").unwrap();
563            },
564            join {
565                sql.write_str(", ").unwrap();
566            },
567            do {
568                self.prepare_table_ref(table_ref, sql);
569            }
570        );
571
572        if let Some(behavior) = lock.behavior {
573            match behavior {
574                LockBehavior::Nowait => sql.write_str(" NOWAIT").unwrap(),
575                LockBehavior::SkipLocked => sql.write_str(" SKIP LOCKED").unwrap(),
576            }
577        }
578    }
579
580    /// Translate [`SelectExpr`] into SQL statement.
581    fn prepare_select_expr(&self, select_expr: &SelectExpr, sql: &mut impl SqlWriter) {
582        self.prepare_expr(&select_expr.expr, sql);
583        match &select_expr.window {
584            Some(WindowSelectType::Name(name)) => {
585                sql.write_str(" OVER ").unwrap();
586                self.prepare_iden(name, sql);
587            }
588            Some(WindowSelectType::Query(window)) => {
589                sql.write_str(" OVER ").unwrap();
590                sql.write_str("( ").unwrap();
591                self.prepare_window_statement(window, sql);
592                sql.write_str(" )").unwrap();
593            }
594            None => {}
595        };
596
597        if let Some(alias) = &select_expr.alias {
598            sql.write_str(" AS ").unwrap();
599            self.prepare_iden(alias, sql);
600        };
601    }
602
603    /// Translate [`JoinExpr`] into SQL statement.
604    fn prepare_join_expr(&self, join_expr: &JoinExpr, sql: &mut impl SqlWriter) {
605        self.prepare_join_type(&join_expr.join, sql);
606        sql.write_str(" ").unwrap();
607        self.prepare_join_table_ref(join_expr, sql);
608        if let Some(on) = &join_expr.on {
609            self.prepare_join_on(on, sql);
610        }
611    }
612
613    fn prepare_join_table_ref(&self, join_expr: &JoinExpr, sql: &mut impl SqlWriter) {
614        if join_expr.lateral {
615            sql.write_str("LATERAL ").unwrap();
616        }
617        self.prepare_table_ref(&join_expr.table, sql);
618    }
619
620    /// Translate [`TableRef`] into SQL statement.
621    fn prepare_table_ref(&self, table_ref: &TableRef, sql: &mut impl SqlWriter) {
622        match table_ref {
623            TableRef::SubQuery(query, alias) => {
624                sql.write_str("(").unwrap();
625                self.prepare_select_statement(query, sql);
626                sql.write_str(")").unwrap();
627                sql.write_str(" AS ").unwrap();
628                self.prepare_iden(alias, sql);
629            }
630            TableRef::ValuesList(values, alias) => {
631                sql.write_str("(").unwrap();
632                self.prepare_values_list(values, sql);
633                sql.write_str(")").unwrap();
634                sql.write_str(" AS ").unwrap();
635                self.prepare_iden(alias, sql);
636            }
637            TableRef::FunctionCall(func, alias) => {
638                self.prepare_function_name(&func.func, sql);
639                self.prepare_function_arguments(func, sql);
640                sql.write_str(" AS ").unwrap();
641                self.prepare_iden(alias, sql);
642            }
643            _ => self.prepare_table_ref_iden(table_ref, sql),
644        }
645    }
646
647    fn prepare_column_ref(&self, column_ref: &ColumnRef, sql: &mut impl SqlWriter) {
648        match column_ref {
649            ColumnRef::Column(ColumnName(table_name, column)) => {
650                if let Some(table_name) = table_name {
651                    self.prepare_table_name(table_name, sql);
652                    sql.write_str(".").unwrap();
653                }
654                self.prepare_iden(column, sql);
655            }
656            ColumnRef::Asterisk(table_name) => {
657                if let Some(table_name) = table_name {
658                    self.prepare_table_name(table_name, sql);
659                    sql.write_str(".").unwrap();
660                }
661                sql.write_str("*").unwrap();
662            }
663        }
664    }
665
666    /// Translate [`UnOper`] into SQL statement.
667    fn prepare_un_oper(&self, un_oper: &UnOper, sql: &mut impl SqlWriter) {
668        sql.write_str(match un_oper {
669            UnOper::Not => "NOT",
670        })
671        .unwrap();
672    }
673
674    fn prepare_bin_oper_common(&self, bin_oper: &BinOper, sql: &mut impl SqlWriter) {
675        sql.write_str(match bin_oper {
676            BinOper::And => "AND",
677            BinOper::Or => "OR",
678            BinOper::Like => "LIKE",
679            BinOper::NotLike => "NOT LIKE",
680            BinOper::Is => "IS",
681            BinOper::IsNot => "IS NOT",
682            BinOper::In => "IN",
683            BinOper::NotIn => "NOT IN",
684            BinOper::Between => "BETWEEN",
685            BinOper::NotBetween => "NOT BETWEEN",
686            BinOper::Equal => "=",
687            BinOper::NotEqual => "<>",
688            BinOper::SmallerThan => "<",
689            BinOper::GreaterThan => ">",
690            BinOper::SmallerThanOrEqual => "<=",
691            BinOper::GreaterThanOrEqual => ">=",
692            BinOper::Add => "+",
693            BinOper::Sub => "-",
694            BinOper::Mul => "*",
695            BinOper::Div => "/",
696            BinOper::Mod => "%",
697            BinOper::LShift => "<<",
698            BinOper::RShift => ">>",
699            BinOper::As => "AS",
700            BinOper::Escape => "ESCAPE",
701            BinOper::Custom(raw) => raw,
702            BinOper::BitAnd => "&",
703            BinOper::BitOr => "|",
704            #[allow(unreachable_patterns)]
705            _ => unimplemented!(),
706        })
707        .unwrap();
708    }
709
710    /// Translate [`BinOper`] into SQL statement.
711    fn prepare_bin_oper(&self, bin_oper: &BinOper, sql: &mut impl SqlWriter) {
712        self.prepare_bin_oper_common(bin_oper, sql);
713    }
714
715    /// Translate [`SubQueryOper`] into SQL statement.
716    fn prepare_sub_query_oper(&self, oper: &SubQueryOper, sql: &mut impl SqlWriter) {
717        sql.write_str(match oper {
718            SubQueryOper::Exists => "EXISTS",
719            SubQueryOper::Any => "ANY",
720            SubQueryOper::Some => "SOME",
721            SubQueryOper::All => "ALL",
722        })
723        .unwrap();
724    }
725
726    /// Translate [`LogicalChainOper`] into SQL statement.
727    fn prepare_logical_chain_oper(
728        &self,
729        log_chain_oper: &LogicalChainOper,
730        i: usize,
731        length: usize,
732        sql: &mut impl SqlWriter,
733    ) {
734        let (simple_expr, oper) = match log_chain_oper {
735            LogicalChainOper::And(simple_expr) => (simple_expr, "AND"),
736            LogicalChainOper::Or(simple_expr) => (simple_expr, "OR"),
737        };
738        if i > 0 {
739            sql.write_str(" ").unwrap();
740            sql.write_str(oper).unwrap();
741            sql.write_str(" ").unwrap();
742        }
743        let both_binary = match simple_expr {
744            Expr::Binary(_, _, right) => {
745                matches!(right.as_ref(), Expr::Binary(_, _, _))
746            }
747            _ => false,
748        };
749        let need_parentheses = length > 1 && both_binary;
750        if need_parentheses {
751            sql.write_str("(").unwrap();
752        }
753        self.prepare_expr(simple_expr, sql);
754        if need_parentheses {
755            sql.write_str(")").unwrap();
756        }
757    }
758
759    /// Translate [`Function`] into SQL statement.
760    fn prepare_function_name_common(&self, function: &Func, sql: &mut impl SqlWriter) {
761        if let Func::Custom(iden) = function {
762            sql.write_str(&iden.0)
763        } else {
764            sql.write_str(match function {
765                Func::Max => "MAX",
766                Func::Min => "MIN",
767                Func::Sum => "SUM",
768                Func::Avg => "AVG",
769                Func::Abs => "ABS",
770                Func::Coalesce => "COALESCE",
771                Func::Count => "COUNT",
772                Func::IfNull => self.if_null_function(),
773                Func::Greatest => self.greatest_function(),
774                Func::Least => self.least_function(),
775                Func::CharLength => self.char_length_function(),
776                Func::Cast => "CAST",
777                Func::Lower => "LOWER",
778                Func::Upper => "UPPER",
779                Func::BitAnd => "BIT_AND",
780                Func::BitOr => "BIT_OR",
781                Func::Custom(_) => "",
782                Func::Random => self.random_function(),
783                Func::Round => "ROUND",
784                Func::Md5 => "MD5",
785                #[cfg(feature = "backend-postgres")]
786                Func::PgFunction(_) => unimplemented!(),
787            })
788        }
789        .unwrap();
790    }
791
792    fn prepare_function_arguments(&self, func: &FunctionCall, sql: &mut impl SqlWriter) {
793        sql.write_str("(").unwrap();
794        let mut args = func.args.iter().zip(func.mods.iter());
795
796        if let Some((arg, modifier)) = args.next() {
797            if modifier.distinct {
798                sql.write_str("DISTINCT ").unwrap();
799            }
800            self.prepare_expr(arg, sql);
801        }
802
803        for (arg, modifier) in args {
804            sql.write_str(", ").unwrap();
805            if modifier.distinct {
806                sql.write_str("DISTINCT ").unwrap();
807            }
808            self.prepare_expr(arg, sql);
809        }
810
811        sql.write_str(")").unwrap();
812    }
813
814    /// Translate [`QueryStatement`] into SQL statement.
815    fn prepare_query_statement(&self, query: &SubQueryStatement, sql: &mut impl SqlWriter);
816
817    fn prepare_select_into(&self, into_table: &SelectInto, sql: &mut impl SqlWriter);
818
819    fn prepare_with_query(&self, query: &WithQuery, sql: &mut impl SqlWriter) {
820        self.prepare_with_clause(&query.with_clause, sql);
821        self.prepare_query_statement(query.query.as_ref().unwrap().deref(), sql);
822    }
823
824    fn prepare_with_clause(&self, with_clause: &WithClause, sql: &mut impl SqlWriter) {
825        self.prepare_with_clause_start(with_clause, sql);
826        self.prepare_with_clause_common_tables(with_clause, sql);
827        if with_clause.recursive {
828            self.prepare_with_clause_recursive_options(with_clause, sql);
829        }
830    }
831
832    fn prepare_with_clause_recursive_options(
833        &self,
834        with_clause: &WithClause,
835        sql: &mut impl SqlWriter,
836    ) {
837        if with_clause.recursive {
838            if let Some(search) = &with_clause.search {
839                sql.write_str("SEARCH ").unwrap();
840                sql.write_str(match &search.order.as_ref().unwrap() {
841                    SearchOrder::BREADTH => "BREADTH",
842                    SearchOrder::DEPTH => "DEPTH",
843                })
844                .unwrap();
845                sql.write_str(" FIRST BY ").unwrap();
846
847                self.prepare_expr(&search.expr.as_ref().unwrap().expr, sql);
848
849                sql.write_str(" SET ").unwrap();
850
851                self.prepare_iden(search.expr.as_ref().unwrap().alias.as_ref().unwrap(), sql);
852                sql.write_str(" ").unwrap();
853            }
854            if let Some(cycle) = &with_clause.cycle {
855                sql.write_str("CYCLE ").unwrap();
856
857                self.prepare_expr(cycle.expr.as_ref().unwrap(), sql);
858
859                sql.write_str(" SET ").unwrap();
860
861                self.prepare_iden(cycle.set_as.as_ref().unwrap(), sql);
862                sql.write_str(" USING ").unwrap();
863                self.prepare_iden(cycle.using.as_ref().unwrap(), sql);
864                sql.write_str(" ").unwrap();
865            }
866        }
867    }
868
869    fn prepare_with_clause_common_tables(
870        &self,
871        with_clause: &WithClause,
872        sql: &mut impl SqlWriter,
873    ) {
874        let mut cte_first = true;
875        assert_ne!(
876            with_clause.cte_expressions.len(),
877            0,
878            "Cannot build a with query that has no common table expression!"
879        );
880
881        for cte in &with_clause.cte_expressions {
882            if !cte_first {
883                sql.write_str(", ").unwrap();
884            }
885            cte_first = false;
886
887            self.prepare_with_query_clause_common_table(cte, sql);
888        }
889    }
890
891    fn prepare_with_query_clause_common_table(
892        &self,
893        cte: &CommonTableExpression,
894        sql: &mut impl SqlWriter,
895    ) {
896        self.prepare_iden(cte.table_name.as_ref().unwrap(), sql);
897
898        if cte.cols.is_empty() {
899            sql.write_str(" ").unwrap();
900        } else {
901            sql.write_str(" (").unwrap();
902
903            let mut col_first = true;
904            for col in &cte.cols {
905                if !col_first {
906                    sql.write_str(", ").unwrap();
907                }
908                col_first = false;
909                self.prepare_iden(col, sql);
910            }
911
912            sql.write_str(") ").unwrap();
913        }
914
915        sql.write_str("AS ").unwrap();
916
917        self.prepare_with_query_clause_materialization(cte, sql);
918
919        sql.write_str("(").unwrap();
920
921        match &cte.query {
922            CteQuery::SubQuery(sub_query) => self.prepare_query_statement(sub_query, sql),
923            CteQuery::Values(items) => self.prepare_values_rows(items, sql),
924        }
925
926        sql.write_str(") ").unwrap();
927    }
928
929    fn prepare_with_query_clause_materialization(
930        &self,
931        cte: &CommonTableExpression,
932        sql: &mut impl SqlWriter,
933    ) {
934        if let Some(materialized) = cte.materialized {
935            if !materialized {
936                sql.write_str("NOT MATERIALIZED ")
937            } else {
938                sql.write_str(" MATERIALIZED ")
939            }
940            .unwrap()
941        }
942    }
943
944    fn prepare_with_clause_start(&self, with_clause: &WithClause, sql: &mut impl SqlWriter) {
945        sql.write_str("WITH ").unwrap();
946
947        if with_clause.recursive {
948            sql.write_str("RECURSIVE ").unwrap();
949        }
950    }
951
952    fn prepare_insert(&self, replace: bool, sql: &mut impl SqlWriter) {
953        if replace {
954            sql.write_str("REPLACE").unwrap();
955        } else {
956            sql.write_str("INSERT").unwrap();
957        }
958    }
959
960    fn prepare_function_name(&self, function: &Func, sql: &mut impl SqlWriter) {
961        self.prepare_function_name_common(function, sql)
962    }
963
964    /// Translate [`TypeRef`] into an SQL statement.
965    fn prepare_type_ref(&self, type_name: &TypeRef, sql: &mut impl SqlWriter) {
966        let TypeRef(schema_name, r#type) = type_name;
967        if let Some(schema_name) = schema_name {
968            self.prepare_schema_name(schema_name, sql);
969            write!(sql, ".").unwrap();
970        }
971        let mut base = r#type.0.as_ref();
972        let mut array_dims = 0;
973        while let Some(stripped) = base.strip_suffix("[]") {
974            base = stripped;
975            array_dims += 1;
976        }
977        if array_dims == 0 {
978            self.prepare_iden(r#type, sql);
979        } else {
980            let base_iden = DynIden(Cow::Owned(base.to_string()));
981            self.prepare_iden(&base_iden, sql);
982            for _ in 0..array_dims {
983                sql.write_str("[]").unwrap();
984            }
985        }
986    }
987
988    /// Translate [`JoinType`] into SQL statement.
989    fn prepare_join_type(&self, join_type: &JoinType, sql: &mut impl SqlWriter) {
990        self.prepare_join_type_common(join_type, sql)
991    }
992
993    fn prepare_join_type_common(&self, join_type: &JoinType, sql: &mut impl SqlWriter) {
994        sql.write_str(match join_type {
995            JoinType::Join => "JOIN",
996            JoinType::CrossJoin => "CROSS JOIN",
997            JoinType::InnerJoin => "INNER JOIN",
998            JoinType::LeftJoin => "LEFT JOIN",
999            JoinType::RightJoin => "RIGHT JOIN",
1000            JoinType::FullOuterJoin => "FULL OUTER JOIN",
1001            JoinType::StraightJoin => "STRAIGHT_JOIN",
1002        })
1003        .unwrap()
1004    }
1005
1006    /// Translate [`OrderExpr`] into SQL statement.
1007    fn prepare_order_expr(&self, order_expr: &OrderExpr, sql: &mut impl SqlWriter) {
1008        if !matches!(order_expr.order, Order::Field(_)) {
1009            self.prepare_expr(&order_expr.expr, sql);
1010        }
1011        self.prepare_order(order_expr, sql);
1012    }
1013
1014    /// Translate [`JoinOn`] into SQL statement.
1015    fn prepare_join_on(&self, join_on: &JoinOn, sql: &mut impl SqlWriter) {
1016        match join_on {
1017            JoinOn::Condition(c) => self.prepare_condition(c, "ON", sql),
1018            JoinOn::Columns(_c) => unimplemented!(),
1019        }
1020    }
1021
1022    /// Translate [`Order`] into SQL statement.
1023    fn prepare_order(&self, order_expr: &OrderExpr, sql: &mut impl SqlWriter) {
1024        match &order_expr.order {
1025            Order::Asc => sql.write_str(" ASC").unwrap(),
1026            Order::Desc => sql.write_str(" DESC").unwrap(),
1027            Order::Field(values) => self.prepare_field_order(order_expr, values, sql),
1028        }
1029    }
1030
1031    /// Translate [`Order::Field`] into SQL statement
1032    fn prepare_field_order(
1033        &self,
1034        order_expr: &OrderExpr,
1035        values: &Values,
1036        sql: &mut impl SqlWriter,
1037    ) {
1038        sql.write_str("CASE ").unwrap();
1039        let mut i = 0;
1040        for value in &values.0 {
1041            sql.write_str("WHEN ").unwrap();
1042            self.prepare_expr(&order_expr.expr, sql);
1043            sql.write_str("=").unwrap();
1044            self.write_value(sql, value).unwrap();
1045            sql.write_str(" THEN ").unwrap();
1046            write_int(sql, i);
1047            sql.write_str(" ").unwrap();
1048            i += 1;
1049        }
1050
1051        sql.write_str("ELSE ").unwrap();
1052        write_int(sql, i);
1053        sql.write_str(" END").unwrap();
1054    }
1055
1056    /// Write [`Value`] into SQL statement as parameter.
1057    fn prepare_value(&self, value: Value, sql: &mut impl SqlWriter);
1058
1059    /// Write [`Value`] inline.
1060    fn prepare_constant(&self, value: &Value, sql: &mut impl SqlWriter) {
1061        self.write_value(sql, value).unwrap();
1062    }
1063
1064    /// Translate a `&[ValueTuple]` into a VALUES list.
1065    fn prepare_values_list(&self, value_tuples: &[ValueTuple], sql: &mut impl SqlWriter) {
1066        sql.write_str("VALUES ").unwrap();
1067        let mut tuples = value_tuples.iter();
1068        join_io!(
1069            tuples,
1070            value_tuple,
1071            join {
1072                sql.write_str(", ").unwrap();
1073            },
1074            do {
1075                sql.write_str(self.values_list_tuple_prefix()).unwrap();
1076                sql.write_str("(").unwrap();
1077
1078                let mut values = value_tuple.clone().into_iter();
1079                join_io!(
1080                    values,
1081                    value,
1082                    join {
1083                        sql.write_str(", ").unwrap();
1084                    },
1085                    do {
1086                        self.prepare_value(value, sql);
1087                    }
1088                );
1089
1090                sql.write_str(")").unwrap();
1091            }
1092        );
1093    }
1094
1095    fn prepare_values_rows(&self, values: &[Values], sql: &mut impl SqlWriter) {
1096        sql.write_str("VALUES ").unwrap();
1097        let mut rows = values.iter();
1098        join_io!(
1099            rows,
1100            row,
1101            join {
1102                sql.write_str(", ").unwrap();
1103            },
1104            do {
1105                sql.write_str("(").unwrap();
1106
1107                let mut vals = row.clone().into_iter();
1108                join_io!(
1109                    vals,
1110                    val,
1111                    join {
1112                        sql.write_str(", ").unwrap();
1113                    },
1114                    do {
1115                        self.prepare_value(val, sql);
1116                    }
1117                );
1118
1119                sql.write_str(")").unwrap();
1120            }
1121        );
1122    }
1123
1124    /// Translate [`Expr::Tuple`] into SQL statement.
1125    fn prepare_tuple(&self, exprs: &[Expr], sql: &mut impl SqlWriter) {
1126        sql.write_str("(").unwrap();
1127        for (i, expr) in exprs.iter().enumerate() {
1128            if i != 0 {
1129                sql.write_str(", ").unwrap();
1130            }
1131            self.prepare_expr(expr, sql);
1132        }
1133        sql.write_str(")").unwrap();
1134    }
1135
1136    /// Translate [`Keyword`] into SQL statement.
1137    fn prepare_keyword(&self, keyword: &Keyword, sql: &mut impl SqlWriter) {
1138        match keyword {
1139            Keyword::Null => sql.write_str("NULL").unwrap(),
1140            Keyword::CurrentDate => sql.write_str("CURRENT_DATE").unwrap(),
1141            Keyword::CurrentTime => sql.write_str("CURRENT_TIME").unwrap(),
1142            Keyword::CurrentTimestamp => sql.write_str("CURRENT_TIMESTAMP").unwrap(),
1143            Keyword::Default => sql.write_str("DEFAULT").unwrap(),
1144            Keyword::Custom(iden) => sql.write_str(&iden.0).unwrap(),
1145        }
1146    }
1147
1148    /// Convert a SQL value into syntax-specific string
1149    fn value_to_string(&self, v: &Value) -> String {
1150        self.value_to_string_common(v)
1151    }
1152
1153    fn value_to_string_common(&self, v: &Value) -> String {
1154        let mut s = String::new();
1155        self.write_value(&mut s, v).unwrap();
1156        s
1157    }
1158
1159    #[doc(hidden)]
1160    fn write_value(&self, buf: &mut impl Write, value: &Value) -> fmt::Result {
1161        self.write_value_common(buf, value)
1162    }
1163
1164    #[doc(hidden)]
1165    fn write_value_common(&self, buf: &mut impl Write, value: &Value) -> fmt::Result {
1166        match value {
1167            Value::Bool(None)
1168            | Value::TinyInt(None)
1169            | Value::SmallInt(None)
1170            | Value::Int(None)
1171            | Value::BigInt(None)
1172            | Value::TinyUnsigned(None)
1173            | Value::SmallUnsigned(None)
1174            | Value::Unsigned(None)
1175            | Value::BigUnsigned(None)
1176            | Value::Float(None)
1177            | Value::Double(None)
1178            | Value::String(None)
1179            | Value::Char(None)
1180            | Value::Bytes(None) => buf.write_str("NULL")?,
1181            #[cfg(feature = "with-json")]
1182            Value::Json(None) => buf.write_str("NULL")?,
1183            #[cfg(feature = "with-chrono")]
1184            Value::ChronoDate(None) => buf.write_str("NULL")?,
1185            #[cfg(feature = "with-chrono")]
1186            Value::ChronoTime(None) => buf.write_str("NULL")?,
1187            #[cfg(feature = "with-chrono")]
1188            Value::ChronoDateTime(None) => buf.write_str("NULL")?,
1189            #[cfg(feature = "with-chrono")]
1190            Value::ChronoDateTimeUtc(None) => buf.write_str("NULL")?,
1191            #[cfg(feature = "with-chrono")]
1192            Value::ChronoDateTimeLocal(None) => buf.write_str("NULL")?,
1193            #[cfg(feature = "with-chrono")]
1194            Value::ChronoDateTimeWithTimeZone(None) => buf.write_str("NULL")?,
1195            #[cfg(feature = "with-time")]
1196            Value::TimeDate(None) => buf.write_str("NULL")?,
1197            #[cfg(feature = "with-time")]
1198            Value::TimeTime(None) => buf.write_str("NULL")?,
1199            #[cfg(feature = "with-time")]
1200            Value::TimeDateTime(None) => buf.write_str("NULL")?,
1201            #[cfg(feature = "with-time")]
1202            Value::TimeDateTimeWithTimeZone(None) => buf.write_str("NULL")?,
1203            #[cfg(feature = "with-jiff")]
1204            Value::JiffDate(None) => buf.write_str("NULL")?,
1205            #[cfg(feature = "with-jiff")]
1206            Value::JiffTime(None) => buf.write_str("NULL")?,
1207            #[cfg(feature = "with-jiff")]
1208            Value::JiffDateTime(None) => buf.write_str("NULL")?,
1209            #[cfg(feature = "with-jiff")]
1210            Value::JiffTimestamp(None) => buf.write_str("NULL")?,
1211            #[cfg(feature = "with-jiff")]
1212            Value::JiffZoned(None) => buf.write_str("NULL")?,
1213            #[cfg(feature = "with-rust_decimal")]
1214            Value::Decimal(None) => buf.write_str("NULL")?,
1215            #[cfg(feature = "with-bigdecimal")]
1216            Value::BigDecimal(None) => buf.write_str("NULL")?,
1217            #[cfg(feature = "with-uuid")]
1218            Value::Uuid(None) => buf.write_str("NULL")?,
1219            #[cfg(feature = "with-ipnetwork")]
1220            Value::IpNetwork(None) => buf.write_str("NULL")?,
1221            #[cfg(feature = "with-mac_address")]
1222            Value::MacAddress(None) => buf.write_str("NULL")?,
1223            #[cfg(feature = "postgres-array")]
1224            Value::Array(_, None) => buf.write_str("NULL")?,
1225            #[cfg(feature = "postgres-vector")]
1226            Value::Vector(None) => buf.write_str("NULL")?,
1227            #[cfg(feature = "postgres-range")]
1228            Value::Range(None) => buf.write_str("NULL")?,
1229            Value::Bool(Some(b)) => buf.write_str(if *b { "TRUE" } else { "FALSE" })?,
1230            Value::TinyInt(Some(v)) => {
1231                write_int(buf, *v);
1232            }
1233            Value::SmallInt(Some(v)) => {
1234                write_int(buf, *v);
1235            }
1236            Value::Int(Some(v)) => {
1237                write_int(buf, *v);
1238            }
1239            Value::BigInt(Some(v)) => {
1240                write_int(buf, *v);
1241            }
1242            Value::TinyUnsigned(Some(v)) => {
1243                write_int(buf, *v);
1244            }
1245            Value::SmallUnsigned(Some(v)) => {
1246                write_int(buf, *v);
1247            }
1248            Value::Unsigned(Some(v)) => {
1249                write_int(buf, *v);
1250            }
1251            Value::BigUnsigned(Some(v)) => {
1252                write_int(buf, *v);
1253            }
1254            Value::Float(Some(v)) => write!(buf, "{v}")?,
1255            Value::Double(Some(v)) => write!(buf, "{v}")?,
1256            Value::String(Some(v)) => self.write_string_quoted(v, buf),
1257            Value::Char(Some(v)) => {
1258                self.write_string_quoted(std::str::from_utf8(&[*v as u8]).unwrap(), buf)
1259            }
1260            Value::Bytes(Some(v)) => self.write_bytes(v, buf),
1261            #[cfg(feature = "with-json")]
1262            Value::Json(Some(v)) => self.write_string_quoted(&v.to_string(), buf),
1263            #[cfg(feature = "with-chrono")]
1264            Value::ChronoDate(Some(v)) => {
1265                buf.write_str("'")?;
1266                write!(buf, "{}", v.format("%Y-%m-%d"))?;
1267                buf.write_str("'")?;
1268            }
1269            #[cfg(feature = "with-chrono")]
1270            Value::ChronoTime(Some(v)) => {
1271                buf.write_str("'")?;
1272                write!(buf, "{}", v.format("%H:%M:%S%.6f"))?;
1273                buf.write_str("'")?;
1274            }
1275            #[cfg(feature = "with-chrono")]
1276            Value::ChronoDateTime(Some(v)) => {
1277                buf.write_str("'")?;
1278                write!(buf, "{}", v.format("%Y-%m-%d %H:%M:%S%.6f"))?;
1279                buf.write_str("'")?;
1280            }
1281            #[cfg(feature = "with-chrono")]
1282            Value::ChronoDateTimeUtc(Some(v)) => {
1283                buf.write_str("'")?;
1284                write!(buf, "{}", v.format("%Y-%m-%d %H:%M:%S%.6f %:z"))?;
1285                buf.write_str("'")?;
1286            }
1287            #[cfg(feature = "with-chrono")]
1288            Value::ChronoDateTimeLocal(Some(v)) => {
1289                buf.write_str("'")?;
1290                write!(buf, "{}", v.format("%Y-%m-%d %H:%M:%S%.6f %:z"))?;
1291                buf.write_str("'")?;
1292            }
1293            #[cfg(feature = "with-chrono")]
1294            Value::ChronoDateTimeWithTimeZone(Some(v)) => {
1295                buf.write_str("'")?;
1296                write!(buf, "{}", v.format("%Y-%m-%d %H:%M:%S%.6f %:z"))?;
1297                buf.write_str("'")?;
1298            }
1299            #[cfg(feature = "with-time")]
1300            Value::TimeDate(Some(v)) => {
1301                buf.write_str("'")?;
1302                buf.write_str(&v.format(time_format::FORMAT_DATE).unwrap())?;
1303                buf.write_str("'")?;
1304            }
1305            #[cfg(feature = "with-time")]
1306            Value::TimeTime(Some(v)) => {
1307                buf.write_str("'")?;
1308                buf.write_str(&v.format(time_format::FORMAT_TIME).unwrap())?;
1309                buf.write_str("'")?;
1310            }
1311            #[cfg(feature = "with-time")]
1312            Value::TimeDateTime(Some(v)) => {
1313                buf.write_str("'")?;
1314                buf.write_str(&v.format(time_format::FORMAT_DATETIME).unwrap())?;
1315                buf.write_str("'")?;
1316            }
1317            #[cfg(feature = "with-time")]
1318            Value::TimeDateTimeWithTimeZone(Some(v)) => {
1319                buf.write_str("'")?;
1320                buf.write_str(&v.format(time_format::FORMAT_DATETIME_TZ).unwrap())?;
1321                buf.write_str("'")?;
1322            }
1323            // Jiff date and time dosen't need format string
1324            // The default behavior is what we want
1325            #[cfg(feature = "with-jiff")]
1326            Value::JiffDate(Some(v)) => {
1327                buf.write_str("'")?;
1328                write!(buf, "{v}")?;
1329                buf.write_str("'")?;
1330            }
1331            #[cfg(feature = "with-jiff")]
1332            Value::JiffTime(Some(v)) => {
1333                buf.write_str("'")?;
1334                write!(buf, "{v}")?;
1335                buf.write_str("'")?;
1336            }
1337            // Both JiffDateTime and JiffTimestamp map to timestamp
1338            #[cfg(feature = "with-jiff")]
1339            Value::JiffDateTime(Some(v)) => {
1340                use crate::with_jiff::JIFF_DATE_TIME_FMT_STR;
1341                buf.write_str("'")?;
1342                write!(buf, "{}", v.strftime(JIFF_DATE_TIME_FMT_STR))?;
1343                buf.write_str("'")?;
1344            }
1345            #[cfg(feature = "with-jiff")]
1346            Value::JiffTimestamp(Some(v)) => {
1347                use crate::with_jiff::JIFF_TIMESTAMP_FMT_STR;
1348                buf.write_str("'")?;
1349                write!(buf, "{}", v.strftime(JIFF_TIMESTAMP_FMT_STR))?;
1350                buf.write_str("'")?;
1351            }
1352            #[cfg(feature = "with-jiff")]
1353            // Zoned map to timestamp with timezone
1354            Value::JiffZoned(Some(v)) => {
1355                use crate::with_jiff::JIFF_ZONE_FMT_STR;
1356                buf.write_str("'")?;
1357                write!(buf, "{}", v.strftime(JIFF_ZONE_FMT_STR))?;
1358                buf.write_str("'")?;
1359            }
1360            #[cfg(feature = "with-rust_decimal")]
1361            Value::Decimal(Some(v)) => write!(buf, "{v}")?,
1362            #[cfg(feature = "with-bigdecimal")]
1363            Value::BigDecimal(Some(v)) => write!(buf, "{v}")?,
1364            #[cfg(feature = "with-uuid")]
1365            Value::Uuid(Some(v)) => {
1366                buf.write_str("'")?;
1367                write!(buf, "{v}")?;
1368                buf.write_str("'")?;
1369            }
1370            #[cfg(feature = "postgres-array")]
1371            Value::Array(_, Some(v)) => {
1372                if v.is_empty() {
1373                    buf.write_str("'{}'")?;
1374                } else {
1375                    buf.write_str("ARRAY [")?;
1376
1377                    let mut viter = v.iter();
1378
1379                    if let Some(element) = viter.next() {
1380                        self.write_value(buf, element)?;
1381                    }
1382
1383                    for element in viter {
1384                        buf.write_str(",")?;
1385                        self.write_value(buf, element)?;
1386                    }
1387                    buf.write_str("]")?;
1388                }
1389            }
1390            #[cfg(feature = "postgres-vector")]
1391            Value::Vector(Some(v)) => {
1392                buf.write_str("'[")?;
1393                let mut viter = v.as_slice().iter();
1394
1395                if let Some(element) = viter.next() {
1396                    write!(buf, "{element}")?;
1397                }
1398
1399                for element in viter {
1400                    buf.write_str(",")?;
1401                    write!(buf, "{element}")?;
1402                }
1403                buf.write_str("]'")?;
1404            }
1405            #[cfg(feature = "with-ipnetwork")]
1406            Value::IpNetwork(Some(v)) => {
1407                buf.write_str("'")?;
1408                write!(buf, "{v}")?;
1409                buf.write_str("'")?;
1410            }
1411            #[cfg(feature = "with-mac_address")]
1412            Value::MacAddress(Some(v)) => {
1413                buf.write_str("'")?;
1414                write!(buf, "{v}")?;
1415                buf.write_str("'")?;
1416            }
1417            #[cfg(feature = "postgres-range")]
1418            Value::Range(Some(v)) => {
1419                buf.write_str("'")?;
1420                write!(buf, "{v}")?;
1421                buf.write_str("'")?;
1422            }
1423        };
1424
1425        Ok(())
1426    }
1427
1428    #[doc(hidden)]
1429    /// Write ON CONFLICT expression
1430    fn prepare_on_conflict(&self, on_conflict: &Option<OnConflict>, sql: &mut impl SqlWriter) {
1431        if let Some(on_conflict) = on_conflict {
1432            self.prepare_on_conflict_keywords(sql);
1433            self.prepare_on_conflict_target(&on_conflict.targets, sql);
1434            self.prepare_on_conflict_condition(&on_conflict.target_where, sql);
1435            self.prepare_on_conflict_action(&on_conflict.action, sql);
1436            self.prepare_on_conflict_condition(&on_conflict.action_where, sql);
1437        }
1438    }
1439
1440    #[doc(hidden)]
1441    /// Write ON CONFLICT target
1442    fn prepare_on_conflict_target(
1443        &self,
1444        on_conflict_targets: &OnConflictTarget,
1445        sql: &mut impl SqlWriter,
1446    ) {
1447        match on_conflict_targets {
1448            OnConflictTarget::Identifiers(identifiers) => {
1449                self.prepare_on_conflict_target_identifiers(identifiers, sql)
1450            }
1451            OnConflictTarget::Constraint(constraint) => {
1452                self.prepare_on_conflict_target_constraint(constraint, sql)
1453            }
1454        }
1455    }
1456
1457    #[doc(hidden)]
1458    /// Write ON CONFLICT target
1459    fn prepare_on_conflict_target_identifiers(
1460        &self,
1461        identifiers: &[OnConflictIdentifier],
1462        sql: &mut impl SqlWriter,
1463    ) {
1464        let mut targets = identifiers.iter();
1465        join_io!(
1466            targets,
1467            target,
1468            first {
1469                sql.write_str("(").unwrap();
1470            },
1471            join {
1472                sql.write_str(", ").unwrap();
1473            },
1474            do {
1475                match target {
1476                    OnConflictIdentifier::Column(col) => {
1477                        self.prepare_iden(col, sql);
1478                    }
1479                    OnConflictIdentifier::Expr(expr) => {
1480                        self.prepare_expr(expr, sql);
1481                    }
1482                }
1483            },
1484            last {
1485                sql.write_str(")").unwrap();
1486            }
1487        );
1488    }
1489
1490    #[doc(hidden)]
1491    fn prepare_on_conflict_target_constraint(&self, constraint: &str, sql: &mut impl SqlWriter) {
1492        sql.write_fmt(format_args!("ON CONSTRAINT \"{}\"", constraint))
1493            .unwrap();
1494    }
1495
1496    #[doc(hidden)]
1497    /// Write ON CONFLICT action
1498    fn prepare_on_conflict_action(
1499        &self,
1500        on_conflict_action: &Option<OnConflictAction>,
1501        sql: &mut impl SqlWriter,
1502    ) {
1503        self.prepare_on_conflict_action_common(on_conflict_action, sql);
1504    }
1505
1506    fn prepare_on_conflict_action_common(
1507        &self,
1508        on_conflict_action: &Option<OnConflictAction>,
1509        sql: &mut impl SqlWriter,
1510    ) {
1511        if let Some(action) = on_conflict_action {
1512            match action {
1513                OnConflictAction::DoNothing(_) => {
1514                    sql.write_str(" DO NOTHING").unwrap();
1515                }
1516                OnConflictAction::Update(update_strats) => {
1517                    self.prepare_on_conflict_do_update_keywords(sql);
1518                    let mut update_strats_iter = update_strats.iter();
1519                    join_io!(
1520                        update_strats_iter,
1521                        update_strat,
1522                        join {
1523                            sql.write_str(", ").unwrap();
1524                        },
1525                        do {
1526                            match update_strat {
1527                                OnConflictUpdate::Column(col) => {
1528                                    self.prepare_iden(col, sql);
1529                                    sql.write_str(" = ").unwrap();
1530                                    self.prepare_on_conflict_excluded_table(col, sql);
1531                                }
1532                                OnConflictUpdate::Expr(col, expr) => {
1533                                    self.prepare_iden(col, sql);
1534                                    sql.write_str(" = ").unwrap();
1535                                    self.prepare_expr(expr, sql);
1536                                }
1537                            }
1538                        }
1539                    );
1540                }
1541            }
1542        }
1543    }
1544
1545    #[doc(hidden)]
1546    /// Write ON CONFLICT keywords
1547    fn prepare_on_conflict_keywords(&self, sql: &mut impl SqlWriter) {
1548        sql.write_str(" ON CONFLICT ").unwrap();
1549    }
1550
1551    #[doc(hidden)]
1552    /// Write ON CONFLICT keywords
1553    fn prepare_on_conflict_do_update_keywords(&self, sql: &mut impl SqlWriter) {
1554        sql.write_str(" DO UPDATE SET ").unwrap();
1555    }
1556
1557    #[doc(hidden)]
1558    /// Write ON CONFLICT update action by retrieving value from the excluded table
1559    fn prepare_on_conflict_excluded_table(&self, col: &DynIden, sql: &mut impl SqlWriter) {
1560        sql.write_char(self.quote().left()).unwrap();
1561        sql.write_str("excluded").unwrap();
1562        sql.write_char(self.quote().right()).unwrap();
1563        sql.write_str(".").unwrap();
1564        self.prepare_iden(col, sql);
1565    }
1566
1567    #[doc(hidden)]
1568    /// Write ON CONFLICT conditions
1569    fn prepare_on_conflict_condition(
1570        &self,
1571        on_conflict_condition: &ConditionHolder,
1572        sql: &mut impl SqlWriter,
1573    ) {
1574        self.prepare_condition(on_conflict_condition, "WHERE", sql)
1575    }
1576
1577    #[doc(hidden)]
1578    /// Hook to insert "OUTPUT" expressions.
1579    fn prepare_output(&self, _returning: &Option<ReturningClause>, _sql: &mut impl SqlWriter) {}
1580
1581    #[doc(hidden)]
1582    /// Hook to insert "RETURNING" statements.
1583    fn prepare_returning(&self, returning: &Option<ReturningClause>, sql: &mut impl SqlWriter) {
1584        if let Some(returning) = returning {
1585            sql.write_str(" RETURNING ").unwrap();
1586            match &returning {
1587                ReturningClause::All => sql.write_str("*").unwrap(),
1588                ReturningClause::Columns(cols) => {
1589                    let mut cols_iter = cols.iter();
1590                    join_io!(
1591                        cols_iter,
1592                        column_ref,
1593                        join {
1594                            sql.write_str(", ").unwrap();
1595                        },
1596                        do {
1597                            self.prepare_column_ref(column_ref, sql);
1598                        }
1599                    );
1600                }
1601                ReturningClause::Exprs(exprs) => {
1602                    let mut exprs_iter = exprs.iter();
1603                    join_io!(
1604                        exprs_iter,
1605                        expr,
1606                        join {
1607                            sql.write_str(", ").unwrap();
1608                        },
1609                        do {
1610                            self.prepare_expr(expr, sql);
1611                        }
1612                    );
1613                }
1614            }
1615        }
1616    }
1617
1618    #[doc(hidden)]
1619    /// Translate a condition to a "WHERE" clause.
1620    fn prepare_condition(
1621        &self,
1622        condition: &ConditionHolder,
1623        keyword: &str,
1624        sql: &mut impl SqlWriter,
1625    ) {
1626        match &condition.contents {
1627            ConditionHolderContents::Empty => (),
1628            ConditionHolderContents::Chain(conditions) => {
1629                sql.write_str(" ").unwrap();
1630                sql.write_str(keyword).unwrap();
1631                sql.write_str(" ").unwrap();
1632                for (i, log_chain_oper) in conditions.iter().enumerate() {
1633                    self.prepare_logical_chain_oper(log_chain_oper, i, conditions.len(), sql);
1634                }
1635            }
1636            ConditionHolderContents::Condition(c) => {
1637                sql.write_str(" ").unwrap();
1638                sql.write_str(keyword).unwrap();
1639                sql.write_str(" ").unwrap();
1640                self.prepare_condition_where(c, sql);
1641            }
1642        }
1643    }
1644
1645    #[doc(hidden)]
1646    /// Translate part of a condition to part of a "WHERE" clause.
1647    fn prepare_condition_where(&self, condition: &Condition, sql: &mut impl SqlWriter) {
1648        let simple_expr = condition.clone().into();
1649        self.prepare_expr(&simple_expr, sql);
1650    }
1651
1652    #[doc(hidden)]
1653    /// Translate [`Frame`] into SQL statement.
1654    fn prepare_frame(&self, frame: &Frame, sql: &mut impl SqlWriter) {
1655        match *frame {
1656            Frame::UnboundedPreceding => sql.write_str("UNBOUNDED PRECEDING").unwrap(),
1657            Frame::Preceding(v) => {
1658                self.prepare_value(v.into(), sql);
1659                sql.write_str("PRECEDING").unwrap();
1660            }
1661            Frame::CurrentRow => sql.write_str("CURRENT ROW").unwrap(),
1662            Frame::Following(v) => {
1663                self.prepare_value(v.into(), sql);
1664                sql.write_str("FOLLOWING").unwrap();
1665            }
1666            Frame::UnboundedFollowing => sql.write_str("UNBOUNDED FOLLOWING").unwrap(),
1667        }
1668    }
1669
1670    #[doc(hidden)]
1671    /// Translate [`WindowStatement`] into SQL statement.
1672    fn prepare_window_statement(&self, window: &WindowStatement, sql: &mut impl SqlWriter) {
1673        let mut partition_iter = window.partition_by.iter();
1674        join_io!(
1675            partition_iter,
1676            expr,
1677            first {
1678                sql.write_str("PARTITION BY ").unwrap();
1679            },
1680            join {
1681                sql.write_str(", ").unwrap();
1682            },
1683            do {
1684                self.prepare_expr(expr, sql);
1685            }
1686        );
1687
1688        let mut order_iter = window.order_by.iter();
1689        join_io!(
1690            order_iter,
1691            expr,
1692            first {
1693                sql.write_str(" ORDER BY ").unwrap();
1694            },
1695            join {
1696                sql.write_str(", ").unwrap();
1697            },
1698            do {
1699                self.prepare_order_expr(expr, sql);
1700            }
1701        );
1702
1703        if let Some(frame) = &window.frame {
1704            match frame.r#type {
1705                FrameType::Range => sql.write_str(" RANGE ").unwrap(),
1706                FrameType::Rows => sql.write_str(" ROWS ").unwrap(),
1707            };
1708            if let Some(end) = &frame.end {
1709                sql.write_str("BETWEEN ").unwrap();
1710                self.prepare_frame(&frame.start, sql);
1711                sql.write_str(" AND ").unwrap();
1712                self.prepare_frame(end, sql);
1713            } else {
1714                self.prepare_frame(&frame.start, sql);
1715            }
1716        }
1717    }
1718
1719    #[doc(hidden)]
1720    /// Translate a binary expr to SQL.
1721    fn binary_expr(&self, left: &Expr, op: &BinOper, right: &Expr, sql: &mut impl SqlWriter) {
1722        // If left has higher precedence than op, we can drop parentheses around left
1723        let drop_left_higher_precedence =
1724            self.inner_expr_well_known_greater_precedence(left, &(*op).into());
1725
1726        // Figure out if left associativity rules allow us to drop the left parenthesis
1727        let drop_left_assoc = left.is_binary()
1728            && op == left.get_bin_oper().unwrap()
1729            && self.well_known_left_associative(op);
1730
1731        let left_paren = !drop_left_higher_precedence && !drop_left_assoc;
1732        if left_paren {
1733            sql.write_str("(").unwrap();
1734        }
1735        self.prepare_expr(left, sql);
1736        if left_paren {
1737            sql.write_str(")").unwrap();
1738        }
1739
1740        sql.write_str(" ").unwrap();
1741        self.prepare_bin_oper(op, sql);
1742        sql.write_str(" ").unwrap();
1743
1744        // If right has higher precedence than op, we can drop parentheses around right
1745        let drop_right_higher_precedence =
1746            self.inner_expr_well_known_greater_precedence(right, &(*op).into());
1747
1748        let op_as_oper = Oper::BinOper(*op);
1749        // Due to representation of trinary op between as nested binary ops.
1750        let drop_right_between_hack = op_as_oper.is_between()
1751            && right.is_binary()
1752            && matches!(right.get_bin_oper(), Some(&BinOper::And));
1753
1754        // Due to representation of trinary op like/not like with optional arg escape as nested binary ops.
1755        let drop_right_escape_hack = op_as_oper.is_like()
1756            && right.is_binary()
1757            && matches!(right.get_bin_oper(), Some(&BinOper::Escape));
1758
1759        // Due to custom representation of casting AS datatype
1760        let drop_right_as_hack = (op == &BinOper::As) && matches!(right, Expr::Custom(_));
1761
1762        let right_paren = !drop_right_higher_precedence
1763            && !drop_right_escape_hack
1764            && !drop_right_between_hack
1765            && !drop_right_as_hack;
1766        if right_paren {
1767            sql.write_str("(").unwrap();
1768        }
1769        self.prepare_expr(right, sql);
1770        if right_paren {
1771            sql.write_str(")").unwrap();
1772        }
1773    }
1774
1775    fn write_string_quoted(&self, string: &str, buffer: &mut impl Write) {
1776        buffer.write_str("'").unwrap();
1777        self.write_escaped(buffer, string);
1778        buffer.write_str("'").unwrap();
1779    }
1780
1781    #[doc(hidden)]
1782    /// Write bytes enclosed with engine specific byte syntax
1783    fn write_bytes(&self, bytes: &[u8], buffer: &mut impl Write) {
1784        buffer.write_str("x'").unwrap();
1785        for b in bytes {
1786            write!(buffer, "{b:02X}").unwrap()
1787        }
1788        buffer.write_str("'").unwrap();
1789    }
1790
1791    #[doc(hidden)]
1792    /// The name of the function that represents the "if null" condition.
1793    fn if_null_function(&self) -> &str {
1794        "IFNULL"
1795    }
1796
1797    #[doc(hidden)]
1798    /// The name of the function that represents the "greatest" function.
1799    fn greatest_function(&self) -> &str {
1800        "GREATEST"
1801    }
1802
1803    #[doc(hidden)]
1804    /// The name of the function that represents the "least" function.
1805    fn least_function(&self) -> &str {
1806        "LEAST"
1807    }
1808
1809    #[doc(hidden)]
1810    /// The name of the function that returns the char length.
1811    fn char_length_function(&self) -> &str {
1812        "CHAR_LENGTH"
1813    }
1814
1815    #[doc(hidden)]
1816    /// The name of the function that returns a random number
1817    fn random_function(&self) -> &str {
1818        // Returning it with parens as part of the name because the tuple preparer can't deal with empty lists
1819        "RANDOM"
1820    }
1821
1822    #[doc(hidden)]
1823    /// The name of the function that returns the lock phrase including the leading 'FOR'
1824    fn lock_phrase(&self, lock_type: LockType) -> &'static str {
1825        match lock_type {
1826            LockType::Update => "FOR UPDATE",
1827            LockType::NoKeyUpdate => "FOR NO KEY UPDATE",
1828            LockType::Share => "FOR SHARE",
1829            LockType::KeyShare => "FOR KEY SHARE",
1830        }
1831    }
1832
1833    /// The keywords for insert default row.
1834    fn insert_default_keyword(&self) -> &str {
1835        "(DEFAULT)"
1836    }
1837
1838    /// Write insert default rows expression.
1839    fn insert_default_values(&self, num_rows: u32, sql: &mut impl SqlWriter) {
1840        sql.write_str("VALUES ").unwrap();
1841        if num_rows > 0 {
1842            sql.write_str(self.insert_default_keyword()).unwrap();
1843
1844            for _ in 1..num_rows {
1845                sql.write_str(", ").unwrap();
1846                sql.write_str(self.insert_default_keyword()).unwrap();
1847            }
1848        }
1849    }
1850
1851    /// Write TRUE constant
1852    fn prepare_constant_true(&self, sql: &mut impl SqlWriter) {
1853        self.prepare_constant(&true.into(), sql);
1854    }
1855
1856    /// Write FALSE constant
1857    fn prepare_constant_false(&self, sql: &mut impl SqlWriter) {
1858        self.prepare_constant(&false.into(), sql);
1859    }
1860}
1861
1862impl SubQueryStatement {
1863    pub(crate) fn prepare_statement(
1864        &self,
1865        query_builder: &impl QueryBuilder,
1866        sql: &mut impl SqlWriter,
1867    ) {
1868        use SubQueryStatement::*;
1869        match self {
1870            SelectStatement(stmt) => query_builder.prepare_select_statement(stmt, sql),
1871            InsertStatement(stmt) => query_builder.prepare_insert_statement(stmt, sql),
1872            UpdateStatement(stmt) => query_builder.prepare_update_statement(stmt, sql),
1873            DeleteStatement(stmt) => query_builder.prepare_delete_statement(stmt, sql),
1874            WithStatement(stmt) => query_builder.prepare_with_query(stmt, sql),
1875        }
1876    }
1877}
1878
1879pub(crate) struct CommonSqlQueryBuilder;
1880
1881impl OperLeftAssocDecider for CommonSqlQueryBuilder {
1882    fn well_known_left_associative(&self, op: &BinOper) -> bool {
1883        common_well_known_left_associative(op)
1884    }
1885}
1886
1887impl PrecedenceDecider for CommonSqlQueryBuilder {
1888    fn inner_expr_well_known_greater_precedence(&self, inner: &Expr, outer_oper: &Oper) -> bool {
1889        common_inner_expr_well_known_greater_precedence(inner, outer_oper)
1890    }
1891}
1892
1893impl QueryBuilder for CommonSqlQueryBuilder {
1894    fn prepare_query_statement(&self, query: &SubQueryStatement, sql: &mut impl SqlWriter) {
1895        query.prepare_statement(self, sql);
1896    }
1897
1898    fn prepare_select_into(&self, _: &SelectInto, _: &mut impl SqlWriter) {}
1899
1900    fn prepare_value(&self, value: Value, sql: &mut impl SqlWriter) {
1901        sql.push_param(value, self as _);
1902    }
1903}
1904
1905impl QuotedBuilder for CommonSqlQueryBuilder {
1906    fn quote(&self) -> Quote {
1907        QUOTE
1908    }
1909}
1910
1911impl EscapeBuilder for CommonSqlQueryBuilder {}
1912
1913impl TableRefBuilder for CommonSqlQueryBuilder {}
1914
1915#[cfg_attr(
1916    feature = "option-more-parentheses",
1917    allow(unreachable_code, unused_variables)
1918)]
1919pub(crate) fn common_inner_expr_well_known_greater_precedence(
1920    inner: &Expr,
1921    outer_oper: &Oper,
1922) -> bool {
1923    match inner {
1924        // We only consider the case where an inner expression is contained in either a
1925        // unary or binary expression (with an outer_oper).
1926        // We do not need to wrap with parentheses:
1927        // Columns, tuples (already wrapped), constants, function calls, values,
1928        // keywords, subqueries (already wrapped), case (already wrapped)
1929        Expr::Column(_)
1930        | Expr::Tuple(_)
1931        | Expr::Constant(_)
1932        | Expr::FunctionCall(_)
1933        | Expr::Value(_)
1934        | Expr::Keyword(_)
1935        | Expr::Case(_)
1936        | Expr::SubQuery(_, _)
1937        | Expr::TypeName(_) => true,
1938        Expr::Binary(_, inner_oper, _) => {
1939            #[cfg(feature = "option-more-parentheses")]
1940            {
1941                return false;
1942            }
1943            let inner_oper: Oper = (*inner_oper).into();
1944            if inner_oper.is_arithmetic() || inner_oper.is_shift() {
1945                outer_oper.is_comparison()
1946                    || outer_oper.is_between()
1947                    || outer_oper.is_in()
1948                    || outer_oper.is_like()
1949                    || outer_oper.is_logical()
1950            } else if inner_oper.is_comparison()
1951                || inner_oper.is_in()
1952                || inner_oper.is_like()
1953                || inner_oper.is_is()
1954            {
1955                outer_oper.is_logical()
1956            } else {
1957                false
1958            }
1959        }
1960        _ => false,
1961    }
1962}
1963
1964pub(crate) fn common_well_known_left_associative(op: &BinOper) -> bool {
1965    matches!(
1966        op,
1967        BinOper::And | BinOper::Or | BinOper::Add | BinOper::Sub | BinOper::Mul | BinOper::Mod
1968    )
1969}
1970
1971macro_rules! join_io {
1972    ($iter:ident, $item:ident $(, first $first:expr)?, join $join:expr, do $do:expr $(, last $last:expr)?) => {
1973        if let Some($item) = $iter.next() {
1974            $($first)?
1975            $do
1976
1977            for $item in $iter {
1978                $join
1979                $do
1980            }
1981
1982            $($last)?
1983        }
1984    };
1985}
1986
1987pub(crate) use join_io;
1988
1989#[cfg(test)]
1990mod tests {
1991    #[cfg(feature = "with-chrono")]
1992    use chrono::{DateTime, FixedOffset, NaiveDate, NaiveDateTime, NaiveTime, Utc};
1993
1994    use crate::QueryBuilder;
1995
1996    /// [Postgresql reference](https://www.postgresql.org/docs/current/datatype-datetime.html#DATATYPE-DATETIME-INPUT-TIMES)
1997    ///
1998    /// [Mysql reference](https://dev.mysql.com/doc/refman/8.4/en/fractional-seconds.html)
1999    ///
2000    /// [Sqlite reference](https://sqlite.org/lang_datefunc.html)
2001    #[test]
2002    #[cfg(feature = "with-chrono")]
2003    fn format_time_constant() {
2004        use crate::{MysqlQueryBuilder, PostgresQueryBuilder, QueryBuilder, SqliteQueryBuilder};
2005
2006        let time = NaiveTime::from_hms_micro_opt(1, 2, 3, 123456)
2007            .unwrap()
2008            .into();
2009
2010        let mut string = String::new();
2011        macro_rules! compare {
2012            ($a:ident, $b:literal) => {
2013                PostgresQueryBuilder.prepare_constant(&$a, &mut string);
2014                assert_eq!(string, $b);
2015
2016                string.clear();
2017
2018                MysqlQueryBuilder.prepare_constant(&$a, &mut string);
2019                assert_eq!(string, $b);
2020
2021                string.clear();
2022
2023                SqliteQueryBuilder.prepare_constant(&$a, &mut string);
2024                assert_eq!(string, $b);
2025
2026                string.clear();
2027            };
2028        }
2029
2030        compare!(time, "'01:02:03.123456'");
2031
2032        let d = NaiveDate::from_ymd_opt(2015, 6, 3).unwrap();
2033        let t = NaiveTime::from_hms_micro_opt(12, 34, 56, 123456).unwrap();
2034
2035        let dt = NaiveDateTime::new(d, t);
2036
2037        let date_time = dt.into();
2038
2039        compare!(date_time, "'2015-06-03 12:34:56.123456'");
2040
2041        let date_time_utc = DateTime::<Utc>::from_naive_utc_and_offset(dt, Utc).into();
2042
2043        compare!(date_time_utc, "'2015-06-03 12:34:56.123456 +00:00'");
2044
2045        let date_time_tz = DateTime::<FixedOffset>::from_naive_utc_and_offset(
2046            dt,
2047            FixedOffset::east_opt(8 * 3600).unwrap(),
2048        )
2049        .into();
2050
2051        compare!(date_time_tz, "'2015-06-03 20:34:56.123456 +08:00'");
2052    }
2053
2054    #[test]
2055    fn prepare_type_ref_escape_array() {
2056        use crate::{PostgresQueryBuilder, TypeRef};
2057
2058        let mut buf = String::new();
2059        let test_cases = [
2060            ("text", r#""text""#),
2061            ("text[]", r#""text"[]"#),
2062            ("text[][]", r#""text"[][]"#),
2063            ("text[][][]", r#""text"[][][]"#),
2064            ("text[][][][]", r#""text"[][][][]"#),
2065            ("text[][][][][]", r#""text"[][][][][]"#),
2066        ];
2067        for (ty, expect) in test_cases {
2068            PostgresQueryBuilder.prepare_type_ref(&TypeRef::from(ty), &mut buf);
2069            assert_eq!(buf, expect);
2070            buf.clear();
2071        }
2072    }
2073}