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