sql_bridge/
ast.rs

1#![allow(unused)]
2
3use std::{
4    any::Any,
5    borrow::Cow,
6    io::{Cursor, Write},
7    ops::Deref,
8    path::Display,
9    slice,
10};
11
12use sqlparser::{
13    ast::{
14        Assignment, AssignmentTarget, BinaryOperator, CastKind, CharacterLength, ColumnDef,
15        ColumnOptionDef, CreateIndex, CreateTable as SqlParserCreateTable, CreateTableOptions,
16        Delete, ExactNumberInfo, Expr, FromTable, FunctionArguments, HiveDistributionStyle,
17        HiveFormat, Ident, IndexColumn, JoinConstraint, ObjectName, ObjectNamePart, ObjectType,
18        OrderByExpr, Query, ReferentialAction, SelectItem, SetExpr, SqliteOnConflict, Statement,
19        Table, TableConstraint, TableFactor, TableWithJoins, UpdateTableFromKind, Value,
20        ValueWithSpan,
21    },
22    dialect::{self, Dialect, MySqlDialect, PostgreSqlDialect, SQLiteDialect},
23    keywords::Keyword,
24    parser::Parser,
25    tokenizer::{Token, Word},
26};
27
28use crate::{Error, Result};
29
30/// Common datatypes which are supported across all databases
31#[derive(Debug, Clone, Copy, PartialEq)]
32pub enum DataType {
33    SmallSerial,
34    Serial,
35    BigSerial,
36    I16,
37    I32,
38    I64,
39    F32,
40    F64,
41    Bool,
42    String,
43    Char(u64),
44    VarChar(u64),
45    Bytes,
46    Json,
47    Uuid,
48    Decimal { precision: u64, scale: i64 },
49    Date,
50    Time,
51    Timestamp,
52}
53
54impl TryFrom<&sqlparser::ast::DataType> for DataType {
55    type Error = Error;
56
57    fn try_from(value: &sqlparser::ast::DataType) -> Result<Self, Self::Error> {
58        let dt = match value {
59            sqlparser::ast::DataType::SmallInt(_) => DataType::I16,
60            sqlparser::ast::DataType::Int(_) => DataType::I32,
61            sqlparser::ast::DataType::Integer(_) => DataType::I32,
62            sqlparser::ast::DataType::BigInt(_) => DataType::I64,
63            sqlparser::ast::DataType::Real => DataType::F32,
64            sqlparser::ast::DataType::Double(_) => DataType::F64,
65            sqlparser::ast::DataType::DoublePrecision => DataType::F64,
66            sqlparser::ast::DataType::Bool => DataType::Bool,
67            sqlparser::ast::DataType::Boolean => DataType::Bool,
68            sqlparser::ast::DataType::Text => DataType::String,
69            sqlparser::ast::DataType::Char(Some(CharacterLength::IntegerLength {
70                length, ..
71            })) => DataType::Char(*length),
72            sqlparser::ast::DataType::Varchar(Some(CharacterLength::IntegerLength {
73                length,
74                ..
75            })) => DataType::VarChar(*length),
76            sqlparser::ast::DataType::Bytea => DataType::Bytes,
77            sqlparser::ast::DataType::JSON => DataType::Json,
78            sqlparser::ast::DataType::Uuid => DataType::Uuid,
79            sqlparser::ast::DataType::Decimal(ExactNumberInfo::PrecisionAndScale(
80                precision,
81                scale,
82            )) => DataType::Decimal {
83                precision: *precision,
84                scale: *scale,
85            },
86            sqlparser::ast::DataType::Numeric(ExactNumberInfo::PrecisionAndScale(
87                precision,
88                scale,
89            )) => DataType::Decimal {
90                precision: *precision,
91                scale: *scale,
92            },
93            sqlparser::ast::DataType::Custom(ObjectName(name_parts), _) => {
94                match extract_serial(name_parts) {
95                    Some(dt) => dt,
96                    None => Err(Error::DataType {
97                        data_type: Box::new(value.clone()),
98                    })?,
99                }
100            }
101            sqlparser::ast::DataType::Date => DataType::Date,
102            sqlparser::ast::DataType::Time(_, _) => DataType::Time,
103            sqlparser::ast::DataType::Timestamp(_, _) => DataType::Timestamp,
104            sqlparser::ast::DataType::Datetime(_) => DataType::Timestamp,
105            _ => Err(Error::DataType {
106                data_type: Box::new(value.clone()),
107            })?,
108        };
109        Ok(dt)
110    }
111}
112
113fn extract_serial(name_parts: &[ObjectNamePart]) -> Option<DataType> {
114    let name = match name_parts.first() {
115        None => return None,
116        Some(ObjectNamePart::Function(_)) => return None,
117        Some(ObjectNamePart::Identifier(name)) => name,
118    };
119    let name = name.value.to_ascii_lowercase();
120    match name.as_str() {
121        "bigserial" => Some(DataType::BigSerial),
122        "serial" => Some(DataType::Serial),
123        "smallserial" => Some(DataType::SmallSerial),
124        _ => None,
125    }
126}
127
128#[derive(Debug, Clone, PartialEq)]
129pub struct Column {
130    pub name: String,
131    pub data_type: DataType,
132    pub options: ColumnOptions,
133}
134
135impl TryFrom<&ColumnDef> for Column {
136    type Error = Error;
137
138    fn try_from(value: &ColumnDef) -> std::result::Result<Self, Self::Error> {
139        let ColumnDef {
140            name,
141            data_type,
142            options,
143        } = value;
144        Ok(Self {
145            name: name.value.clone(),
146            data_type: data_type.try_into()?,
147            options: ColumnOptions::try_from(options.as_slice())?,
148        })
149    }
150}
151
152#[derive(Debug, Clone, Copy, PartialEq)]
153pub struct ColumnOptions(u32);
154
155#[derive(Debug, Clone, Copy, PartialEq)]
156#[repr(u32)]
157pub enum ColumnOption {
158    PrimaryKey = 1,
159    AutoInrement = 1 << 1,
160    Nullable = 1 << 2,
161    NotNull = 1 << 3,
162    Unique = 1 << 4,
163}
164
165impl ColumnOptions {
166    fn new() -> Self {
167        Self(0)
168    }
169
170    fn set_primary_key(mut self) -> Self {
171        self.0 |= ColumnOption::PrimaryKey as u32;
172        self
173    }
174
175    fn is_primary_key(self) -> bool {
176        self.0 & ColumnOption::PrimaryKey as u32 != 0
177    }
178
179    fn set_auto_increment(mut self) -> Self {
180        self.0 |= ColumnOption::AutoInrement as u32;
181        self
182    }
183
184    fn unset_auto_increment(mut self) -> Self {
185        self.0 &= !(ColumnOption::AutoInrement as u32);
186        self
187    }
188
189    fn is_auto_increment(self) -> bool {
190        self.0 & ColumnOption::AutoInrement as u32 != 0
191    }
192
193    fn set_nullable(mut self) -> Self {
194        self.0 |= ColumnOption::Nullable as u32;
195        self
196    }
197
198    fn is_nullable(self) -> bool {
199        self.0 & ColumnOption::Nullable as u32 != 0
200    }
201
202    fn set_not_null(mut self) -> Self {
203        self.0 |= ColumnOption::NotNull as u32;
204        self
205    }
206
207    fn is_not_null(self) -> bool {
208        self.0 & ColumnOption::NotNull as u32 != 0
209    }
210
211    fn set_unique(mut self) -> Self {
212        self.0 |= ColumnOption::Unique as u32;
213        self
214    }
215
216    fn is_unique(self) -> bool {
217        self.0 & ColumnOption::Unique as u32 != 0
218    }
219
220    #[allow(clippy::type_complexity)]
221    fn mapping() -> &'static [(ColumnOption, fn(Self) -> bool)] {
222        &[
223            (ColumnOption::PrimaryKey, ColumnOptions::is_primary_key),
224            (ColumnOption::AutoInrement, ColumnOptions::is_auto_increment),
225            (ColumnOption::Nullable, ColumnOptions::is_nullable),
226            (ColumnOption::NotNull, ColumnOptions::is_not_null),
227            (ColumnOption::Unique, ColumnOptions::is_unique),
228        ]
229    }
230}
231
232pub struct ColumnIterator {
233    column_options: ColumnOptions,
234    pos: usize,
235}
236
237impl Iterator for ColumnIterator {
238    type Item = ColumnOption;
239
240    fn next(&mut self) -> Option<Self::Item> {
241        let mapping = ColumnOptions::mapping();
242        loop {
243            if self.pos >= mapping.len() {
244                return None;
245            }
246            let (option, check) = mapping[self.pos];
247            self.pos += 1;
248            if check(self.column_options) {
249                return Some(option);
250            }
251        }
252    }
253}
254
255impl IntoIterator for ColumnOptions {
256    type Item = ColumnOption;
257    type IntoIter = ColumnIterator;
258
259    fn into_iter(self) -> Self::IntoIter {
260        ColumnIterator {
261            column_options: self,
262            pos: 0,
263        }
264    }
265}
266
267impl std::fmt::Display for ColumnOptions {
268    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
269        for option in self.into_iter() {
270            write!(f, "{option:?} ")?;
271        }
272        Ok(())
273    }
274}
275
276impl TryFrom<&[ColumnOptionDef]> for ColumnOptions {
277    type Error = Error;
278
279    fn try_from(values: &[ColumnOptionDef]) -> Result<Self, Self::Error> {
280        values.iter().try_fold(
281            ColumnOptions::new(),
282            |mut options, value| -> Result<_, Error> {
283                let options = match &value.option {
284                    sqlparser::ast::ColumnOption::Unique { is_primary, .. } if *is_primary => {
285                        options.set_primary_key()
286                    }
287                    sqlparser::ast::ColumnOption::NotNull => options.set_not_null(),
288                    sqlparser::ast::ColumnOption::Null => options.set_nullable(),
289                    option if is_auto_increment_option(option) => options.set_auto_increment(),
290                    option => Err(Error::ColumnOption {
291                        option: Box::new(option.clone()),
292                    })?,
293                };
294                Ok(options)
295            },
296        )
297    }
298}
299
300fn is_auto_increment_option(option: &sqlparser::ast::ColumnOption) -> bool {
301    match option {
302        sqlparser::ast::ColumnOption::DialectSpecific(tokens) if tokens.len() == 1 => tokens
303            .first()
304            .map(|token| match token {
305                Token::Word(Word { keyword, .. }) => {
306                    *keyword == Keyword::AUTOINCREMENT || *keyword == Keyword::AUTO_INCREMENT
307                }
308                _ => false,
309            })
310            .unwrap(),
311        _ => false,
312    }
313}
314
315#[derive(Debug, Clone, PartialEq)]
316pub enum Constraint {
317    PrimaryKey(Vec<String>),
318    ForeignKey {
319        columns: Vec<String>,
320        referred_columns: Vec<String>,
321        foreign_table: String,
322        on_delete: Option<OnDeleteAction>,
323    },
324}
325
326#[derive(Debug, Clone, PartialEq)]
327pub enum OnDeleteAction {
328    Cascade,
329    SetNull,
330    Restrict,
331}
332
333impl TryFrom<&ReferentialAction> for OnDeleteAction {
334    type Error = Error;
335
336    fn try_from(value: &ReferentialAction) -> Result<Self, Self::Error> {
337        match value {
338            ReferentialAction::Cascade => Ok(OnDeleteAction::Cascade),
339            ReferentialAction::Restrict => Ok(OnDeleteAction::Restrict),
340            ReferentialAction::SetNull => Ok(OnDeleteAction::SetNull),
341            other => Err(Error::OnDeleteConstrait {
342                referential_action: *other,
343            })?,
344        }
345    }
346}
347
348#[derive(Debug, Clone, PartialEq)]
349pub struct Constraints(Vec<Constraint>);
350
351impl Constraints {
352    fn len(&self) -> usize {
353        self.0.len()
354    }
355}
356
357#[derive(Debug)]
358pub struct ConstraintsIter<'a> {
359    constraints: &'a Constraints,
360    pos: usize,
361}
362
363impl<'a> Iterator for ConstraintsIter<'a> {
364    type Item = &'a Constraint;
365
366    fn next(&mut self) -> Option<Self::Item> {
367        if self.constraints.0.len() > self.pos {
368            let item = &self.constraints.0[self.pos];
369            self.pos += 1;
370            return Some(item);
371        }
372        None
373    }
374}
375
376impl<'a> IntoIterator for &'a Constraints {
377    type IntoIter = ConstraintsIter<'a>;
378    type Item = &'a Constraint;
379
380    fn into_iter(self) -> Self::IntoIter {
381        ConstraintsIter {
382            pos: 0,
383            constraints: self,
384        }
385    }
386}
387
388impl TryFrom<&[TableConstraint]> for Constraints {
389    type Error = Error;
390
391    fn try_from(value: &[TableConstraint]) -> Result<Self, Self::Error> {
392        let constraints = value
393            .iter()
394            .map(|constraint| -> Result<_> {
395                let res = match constraint {
396                    TableConstraint::PrimaryKey {
397                        columns,
398                        name,
399                        index_name,
400                        index_type,
401                        index_options,
402                        characteristics,
403                    } => {
404                        if name.is_some() {
405                            Err(Error::PrimaryKey { reason: "name" })?
406                        }
407                        if index_name.is_some() {
408                            Err(Error::PrimaryKey {
409                                reason: "index name",
410                            })?
411                        }
412                        if index_type.is_some() {
413                            Err(Error::PrimaryKey {
414                                reason: "index type",
415                            })?
416                        }
417                        if !index_options.is_empty() {
418                            Err(Error::PrimaryKey {
419                                reason: "index options",
420                            })?
421                        }
422                        if characteristics.is_some() {
423                            Err(Error::PrimaryKey {
424                                reason: "characteristics",
425                            })?
426                        }
427                        let columns = columns
428                            .iter()
429                            .map(
430                                |IndexColumn {
431                                     column,
432                                     operator_class,
433                                 }| {
434                                    if operator_class.is_some() {
435                                        Err(Error::PrimaryKey {
436                                            reason: "operator class",
437                                        })?
438                                    };
439                                    let OrderByExpr {
440                                        expr,
441                                        options,
442                                        with_fill,
443                                    } = column;
444                                    if with_fill.is_some() {
445                                        Err(Error::PrimaryKey {
446                                            reason: "`WITH FILL`",
447                                        })?
448                                    }
449                                    if options.nulls_first.is_some() || options.asc.is_some() {
450                                        Err(Error::PrimaryKey { reason: "options" })?
451                                    }
452                                    match expr {
453                                        Expr::Identifier(ident) => Ok(ident.value.clone()),
454                                        _ => Err(Error::PrimaryKeyWithExpression {
455                                            expr: Box::new(expr.clone()),
456                                        })?,
457                                    }
458                                },
459                            )
460                            .collect::<Result<Vec<_>>>()?;
461                        Constraint::PrimaryKey(columns)
462                    }
463                    TableConstraint::ForeignKey {
464                        name,
465                        columns,
466                        foreign_table,
467                        referred_columns,
468                        on_delete,
469                        on_update,
470                        characteristics,
471                        index_name,
472                    } => {
473                        if name.is_some() {
474                            Err(Error::ForeignKey {
475                                reason: "constraint",
476                            })?
477                        }
478                        if on_update.is_some() {
479                            Err(Error::ForeignKey {
480                                reason: "on update",
481                            })?
482                        }
483                        if characteristics.is_some() {
484                            Err(Error::ForeignKey {
485                                reason: "characteristics",
486                            })?
487                        }
488                        let on_delete = match on_delete {
489                            None => None,
490                            Some(action) => Some(action.try_into()?),
491                        };
492                        let columns = columns
493                            .iter()
494                            .map(|Ident { value, .. }| value.clone())
495                            .collect();
496                        let referred_columns = referred_columns
497                            .iter()
498                            .map(|Ident { value, .. }| value.clone())
499                            .collect();
500                        let foreign_table = Ast::parse_object_name(foreign_table)?;
501                        Constraint::ForeignKey {
502                            columns,
503                            referred_columns,
504                            foreign_table,
505                            on_delete,
506                        }
507                    }
508                    _ => Err(Error::TableConstraint {
509                        constraint: Box::new(constraint.clone()),
510                    })?,
511                };
512                Ok(res)
513            })
514            .collect::<Result<Vec<Constraint>, _>>()?;
515        Ok(Constraints(constraints))
516    }
517}
518
519#[derive(Debug, Clone, PartialEq)]
520pub enum Ast {
521    CreateTable {
522        if_not_exists: bool,
523        name: String,
524        columns: Vec<Column>,
525        constraints: Constraints,
526    },
527    AlterTable {
528        name: String,
529        operation: AlterTableOperation,
530    },
531    CreateIndex {
532        unique: bool,
533        name: String,
534        table: String,
535        columns: Vec<String>,
536    },
537    Select {
538        distinct: bool,
539        projections: Vec<Projection>,
540        from_clause: FromClause,
541        selection: Option<Selection>,
542        group_by: Vec<GroupByParameter>,
543        order_by: Vec<OrderByParameter>,
544    },
545    Insert {
546        table: String,
547        columns: Vec<String>,
548        source: Vec<Vec<InsertSource>>,
549    },
550    Update {
551        table: String,
552        assignments: Vec<UpdateAssignment>,
553        selection: Option<Selection>,
554    },
555    Delete {
556        from_clause: FromClause,
557        selection: Option<Selection>,
558    },
559    DropTable {
560        if_exists: bool,
561        name: String,
562    },
563    DropIndex {
564        if_exists: bool,
565        name: String,
566        table: String,
567    },
568}
569
570#[derive(Debug, Clone, PartialEq)]
571pub enum Projection {
572    WildCard,
573    Identifier(String),
574    CompoundIdentifier(CompoundIdentifier),
575    Function(Function),
576    NumericLiteral(String),
577    String(String),
578}
579
580#[derive(Debug, Clone, PartialEq)]
581pub struct CompoundIdentifier {
582    table: String,
583    column: String,
584}
585
586#[derive(Debug, Clone, PartialEq)]
587pub enum Function {
588    Count(FunctionArg),
589}
590
591#[derive(Debug, Clone, PartialEq)]
592pub enum FunctionArg {
593    Wildcard,
594    Ident(String),
595}
596
597#[derive(Debug, Clone, PartialEq)]
598pub enum Selection {
599    BinaryOp {
600        op: Op,
601        left: Box<Selection>,
602        right: Box<Selection>,
603    },
604    Ident(String),
605    CompoundIdentifier(CompoundIdentifier),
606    Number(String),
607    String(String),
608    Placeholder,
609    InList {
610        negated: bool,
611        ident: String,
612        list: Vec<Selection>,
613    },
614}
615
616impl TryFrom<&Expr> for Selection {
617    type Error = Error;
618
619    fn try_from(expr: &Expr) -> std::result::Result<Self, Self::Error> {
620        let selection = match expr {
621            Expr::BinaryOp { left, op, right } => Selection::BinaryOp {
622                op: op.try_into()?,
623                left: {
624                    let left: Selection = left.as_ref().try_into()?;
625                    Box::new(left)
626                },
627                right: {
628                    let right: Selection = right.as_ref().try_into()?;
629                    Box::new(right)
630                },
631            },
632            Expr::Identifier(id) => Selection::Ident(id.value.clone()),
633            Expr::CompoundIdentifier(ids) => {
634                // SQLite only supports table.column, not schema.table.column or database.table.column
635                if ids.len() != 2 {
636                    Err(Error::CompoundIdentifier { length: ids.len() })?
637                }
638                Selection::CompoundIdentifier(CompoundIdentifier {
639                    table: ids[0].value.clone(),
640                    column: ids[1].value.clone(),
641                })
642            }
643            Expr::Value(value) => match &value.value {
644                Value::Number(number, _) => Selection::Number(number.clone()),
645                Value::SingleQuotedString(string) => Selection::String(string.clone()),
646                Value::Placeholder(_) => Selection::Placeholder,
647                _ => Err(Error::SelectionValue {
648                    value: Box::new(value.value.clone()),
649                })?,
650            },
651            Expr::InList {
652                expr,
653                list,
654                negated,
655            } => {
656                let ident = match expr.as_ref().try_into()? {
657                    Selection::Ident(ident) => ident,
658                    selection => Err(Error::SelectionInList {
659                        selection: Box::new(selection.clone()),
660                    })?,
661                };
662                let list = list
663                    .iter()
664                    .map(|expr| {
665                        let ok = match expr.try_into()? {
666                            ok @ Selection::String(_) => ok,
667                            ok @ Selection::Number(_) => ok,
668                            ok @ Selection::Placeholder => ok,
669                            selection => Err(Error::SelectionInList {
670                                selection: Box::new(selection.clone()),
671                            })?,
672                        };
673                        Ok(ok)
674                    })
675                    .collect::<Result<Vec<Selection>>>()?;
676                Selection::InList {
677                    negated: *negated,
678                    ident,
679                    list,
680                }
681            }
682            expr => Err(Error::SelectionFromExpr {
683                expr: Box::new(expr.clone()),
684            })?,
685        };
686        Ok(selection)
687    }
688}
689
690#[derive(Debug, Clone, PartialEq)]
691pub enum GroupByParameter {
692    Ident(String),
693}
694
695#[derive(Debug, Clone, PartialEq)]
696pub struct OrderByParameter {
697    ident: String,
698    option: OrderOption,
699}
700
701#[derive(Debug, Clone, PartialEq)]
702pub enum OrderOption {
703    Asc,
704    Desc,
705    None,
706}
707
708#[derive(Debug, Clone, PartialEq)]
709pub enum InsertSource {
710    String(String),
711    Number(String),
712    Null,
713    Placeholder,
714    Cast {
715        cast: String,
716        source: Box<InsertSource>,
717    },
718}
719
720impl TryFrom<&Expr> for InsertSource {
721    type Error = Error;
722
723    fn try_from(value: &Expr) -> Result<Self, Self::Error> {
724        let value = match value {
725            Expr::Value(value) => &value.value,
726            Expr::Cast {
727                kind,
728                expr,
729                data_type,
730                format,
731            } if *kind == CastKind::DoubleColon && format.is_none() => match expr.as_ref() {
732                Expr::Value(_) => {
733                    return Ok(InsertSource::Cast {
734                        cast: data_type.to_string(),
735                        source: Box::new(expr.as_ref().try_into()?),
736                    });
737                }
738                _ => Err(Error::InsertSourceExpression { expr: expr.clone() })?,
739            },
740            value => Err(Error::InsertSourceExpression {
741                expr: Box::new(value.clone()),
742            })?,
743        };
744        let insert_source = match value {
745            Value::Null => InsertSource::Null,
746            Value::Number(number, _) => InsertSource::Number(number.clone()),
747            Value::SingleQuotedString(string) => InsertSource::String(string.clone()),
748            Value::Placeholder(_) => InsertSource::Placeholder,
749            value => Err(Error::InsertSourceValue {
750                value: Box::new(value.clone()),
751            })?,
752        };
753        Ok(insert_source)
754    }
755}
756
757#[derive(Debug, Clone, PartialEq)]
758pub struct UpdateAssignment {
759    target: String,
760    value: UpdateValue,
761}
762
763#[derive(Debug, Clone, PartialEq)]
764pub enum UpdateValue {
765    String(String),
766    Number(String),
767    Null,
768    Placeholder,
769}
770
771impl TryFrom<&Expr> for UpdateValue {
772    type Error = Error;
773
774    fn try_from(expr: &Expr) -> Result<Self, Self::Error> {
775        let value = match expr {
776            Expr::Value(value) => &value.value,
777            expr => Err(Error::UpdateExpression {
778                expr: Box::new(expr.clone()),
779            })?,
780        };
781        let update_value = match value {
782            Value::Null => UpdateValue::Null,
783            Value::Number(number, _) => UpdateValue::Number(number.clone()),
784            Value::SingleQuotedString(string) => UpdateValue::String(string.clone()),
785            Value::Placeholder(_) => UpdateValue::Placeholder,
786            value => Err(Error::UpdateValue {
787                value: Box::new(value.clone()),
788            })?,
789        };
790        Ok(update_value)
791    }
792}
793
794#[derive(Debug, Clone, Copy, PartialEq)]
795pub enum Op {
796    Eq,
797    And,
798    Or,
799}
800
801impl TryFrom<&BinaryOperator> for Op {
802    type Error = Error;
803
804    fn try_from(op: &BinaryOperator) -> std::result::Result<Self, Self::Error> {
805        let op = match op {
806            BinaryOperator::And => Op::And,
807            BinaryOperator::Eq => Op::Eq,
808            BinaryOperator::Or => Op::Or,
809            _ => Err(Error::BinaryOperator { op: op.clone() })?,
810        };
811        Ok(op)
812    }
813}
814
815#[derive(Debug, Clone, PartialEq)]
816pub enum FromClause {
817    Table(String),
818    TableWithJoin(TableJoin),
819    None,
820}
821
822#[derive(Debug, Clone, PartialEq)]
823pub struct TableJoin {
824    name: String,
825    join: Vec<Join>,
826}
827
828#[derive(Debug, Clone, PartialEq)]
829pub struct Join {
830    name: String,
831    operator: JoinOperator,
832}
833
834#[derive(Debug, Clone, PartialEq)]
835pub enum JoinOperator {
836    Join(Selection),
837    Inner(Selection),
838}
839
840impl TryFrom<&sqlparser::ast::Join> for Join {
841    type Error = Error;
842
843    fn try_from(table: &sqlparser::ast::Join) -> Result<Self, Self::Error> {
844        /// ClickHouse supports the optional `GLOBAL` keyword before the join operator.
845        /// See [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/select/join)
846        if table.global {
847            Err(Error::Keyword { keyword: "GLOBAL" })?
848        };
849
850        let name = table_relation_to_object_name(&table.relation)?;
851        let operator = match &table.join_operator {
852            sqlparser::ast::JoinOperator::Join(constraint) => match constraint {
853                JoinConstraint::On(expr) => JoinOperator::Join(expr.try_into()?),
854                other => Err(Error::JoinConstraint {
855                    constraint: Box::new(other.clone()),
856                })?,
857            },
858            sqlparser::ast::JoinOperator::Inner(constraint) => match constraint {
859                JoinConstraint::On(expr) => JoinOperator::Inner(expr.try_into()?),
860                other => Err(Error::JoinConstraint {
861                    constraint: Box::new(other.clone()),
862                })?,
863            },
864            other => Err(Error::JoinOperator {
865                op: Box::new(other.clone()),
866            })?,
867        };
868
869        Ok(Self { name, operator })
870    }
871}
872
873fn table_relation_to_object_name(relation: &TableFactor) -> Result<String> {
874    match relation {
875        TableFactor::Table {
876            name,
877            alias,
878            args,
879            with_hints,
880            version,
881            with_ordinality,
882            partitions,
883            json_path,
884            sample,
885            index_hints,
886        } => {
887            if alias.is_some() {
888                Err(Error::TableAlias)?
889            }
890            if args.is_some() {
891                Err(Error::TableValuedFunctions)?
892            }
893            if !with_hints.is_empty() {
894                Err(Error::TableWithHints)?
895            }
896            if version.is_some() {
897                Err(Error::TableVersioning)?
898            }
899            if *with_ordinality {
900                Err(Error::TableWithOrdinality)?
901            }
902            if !partitions.is_empty() {
903                Err(Error::TableWithPartitions)?
904            }
905            if json_path.is_some() {
906                Err(Error::TableWithJsonPath)?
907            }
908            if sample.is_some() {
909                Err(Error::TableWithSampleModifier)?
910            }
911            if !index_hints.is_empty() {
912                Err(Error::TableWithIndexHints)?
913            }
914            Ok(Ast::parse_object_name(name)?)
915        }
916        other => Err(Error::TableFactor {
917            factor: Box::new(other.clone()),
918        })?,
919    }
920}
921
922impl TryFrom<&[TableWithJoins]> for FromClause {
923    type Error = Error;
924
925    fn try_from(tables: &[TableWithJoins]) -> Result<Self, Self::Error> {
926        let from = match tables {
927            &[
928                TableWithJoins {
929                    ref relation,
930                    ref joins,
931                },
932            ] => {
933                let name = table_relation_to_object_name(relation)?;
934                if joins.is_empty() {
935                    Self::Table(name)
936                } else {
937                    Self::TableWithJoin(TableJoin {
938                        name,
939                        join: joins.iter().map(|t| t.try_into()).collect::<Result<_>>()?,
940                    })
941                }
942            }
943            &[] => Self::None,
944            other => Err(Error::TableJoins {
945                table_joins: other.iter().map(Clone::clone).collect(),
946            })?,
947        };
948        Ok(from)
949    }
950}
951
952#[derive(Debug, Clone, PartialEq)]
953pub enum AlterTableOperation {
954    AddColumn { column: Column },
955    RenameColumn { from: String, to: String },
956    DropColumn { name: String },
957    RenameTable { to: String },
958}
959
960impl TryFrom<&sqlparser::ast::AlterTableOperation> for AlterTableOperation {
961    type Error = Error;
962
963    fn try_from(
964        op: &sqlparser::ast::AlterTableOperation,
965    ) -> std::result::Result<Self, Self::Error> {
966        let op = match op {
967            sqlparser::ast::AlterTableOperation::AddColumn {
968                column_keyword,
969                if_not_exists,
970                column_def,
971                column_position,
972            } => {
973                let _ = column_keyword;
974                if *if_not_exists {
975                    Err(Error::AlterTable {
976                        reason: "if not exists",
977                    })?
978                }
979                if column_position.is_some() {
980                    Err(Error::AlterTable {
981                        reason: "column position",
982                    })?
983                }
984                let column = column_def.try_into()?;
985                AlterTableOperation::AddColumn { column }
986            }
987            sqlparser::ast::AlterTableOperation::RenameTable { table_name } => {
988                let table_name = match table_name {
989                    // only mysql
990                    sqlparser::ast::RenameTableNameKind::As(_) => Err(Error::AlterTable {
991                        reason: "as keyword",
992                    })?,
993                    sqlparser::ast::RenameTableNameKind::To(table_name) => table_name,
994                };
995                AlterTableOperation::RenameTable {
996                    to: Ast::parse_object_name(table_name)?,
997                }
998            }
999            sqlparser::ast::AlterTableOperation::RenameColumn {
1000                old_column_name,
1001                new_column_name,
1002            } => AlterTableOperation::RenameColumn {
1003                from: old_column_name.value.clone(),
1004                to: new_column_name.value.clone(),
1005            },
1006            sqlparser::ast::AlterTableOperation::DropColumn {
1007                if_exists,
1008                drop_behavior,
1009                has_column_keyword,
1010                column_names,
1011            } => {
1012                if *if_exists {
1013                    Err(Error::AlterTable {
1014                        reason: "if exists",
1015                    })?
1016                }
1017                if drop_behavior.is_some() {
1018                    Err(Error::AlterTable {
1019                        reason: "drop behaviour",
1020                    })?;
1021                }
1022                if column_names.len() > 1 {
1023                    Err(Error::AlterTable {
1024                        reason: "multiple columns names",
1025                    })?
1026                }
1027                AlterTableOperation::DropColumn {
1028                    name: column_names.first().unwrap().value.clone(),
1029                }
1030            }
1031            op => Err(Error::AlterTableOp {
1032                op: Box::new(op.clone()),
1033            })?,
1034        };
1035        Ok(op)
1036    }
1037}
1038
1039impl Ast {
1040    fn parse_object_name(name: &ObjectName) -> Result<String> {
1041        let name_parts = &name.0;
1042        if name_parts.len() > 1 {
1043            Err(Error::ObjectName {
1044                reason: "schema-qualified names are not supported",
1045            })?
1046        }
1047        match name_parts.first() {
1048            None => Err(Error::ObjectName {
1049                reason: "name parts are empty",
1050            })?,
1051            Some(ObjectNamePart::Identifier(ident)) => Ok(ident.value.clone()),
1052            Some(ObjectNamePart::Function(_)) => Err(Error::ObjectName {
1053                reason: "function names are not supported",
1054            })?,
1055        }
1056    }
1057
1058    fn parse_create_table(
1059        SqlParserCreateTable {
1060            or_replace,
1061            temporary,
1062            external,
1063            global,
1064            if_not_exists,
1065            transient,
1066            volatile,
1067            iceberg,
1068            name,
1069            columns,
1070            constraints,
1071            hive_distribution,
1072            hive_formats,
1073            file_format,
1074            location,
1075            query,
1076            without_rowid,
1077            like,
1078            clone,
1079            comment,
1080            on_commit,
1081            on_cluster,
1082            primary_key,
1083            order_by,
1084            partition_by,
1085            cluster_by,
1086            clustered_by,
1087            inherits,
1088            strict,
1089            copy_grants,
1090            enable_schema_evolution,
1091            change_tracking,
1092            data_retention_time_in_days,
1093            max_data_extension_time_in_days,
1094            default_ddl_collation,
1095            with_aggregation_policy,
1096            with_row_access_policy,
1097            with_tags,
1098            external_volume,
1099            base_location,
1100            catalog,
1101            catalog_sync,
1102            storage_serialization_policy,
1103            dynamic,
1104            table_options,
1105            version,
1106            target_lag,
1107            warehouse,
1108            refresh_mode,
1109            initialize,
1110            require_user,
1111        }: &SqlParserCreateTable,
1112    ) -> Result<Ast> {
1113        if *or_replace {
1114            Err(Error::CreateTable {
1115                reason: "or replace",
1116            })?
1117        }
1118        if *temporary {
1119            Err(Error::CreateTable {
1120                reason: "temporary",
1121            })?
1122        }
1123        if *external {
1124            Err(Error::CreateTable { reason: "external" })?
1125        }
1126        if global.is_some() {
1127            Err(Error::CreateTable { reason: "global" })?
1128        }
1129        if *transient {
1130            Err(Error::CreateTable {
1131                reason: "transient",
1132            })?
1133        }
1134        if *volatile {
1135            Err(Error::CreateTable { reason: "volatile" })?
1136        }
1137        if *iceberg {
1138            Err(Error::CreateTable { reason: "iceberg" })?
1139        }
1140        match hive_distribution {
1141            HiveDistributionStyle::NONE => {}
1142            _ => Err(Error::CreateTable {
1143                reason: "hive distribution style",
1144            })?,
1145        }
1146
1147        // Hive formats for some reason are always Some()
1148        if let Some(HiveFormat {
1149            row_format,
1150            serde_properties,
1151            storage,
1152            location,
1153        }) = hive_formats
1154            && (row_format.is_some()
1155                || serde_properties.is_some()
1156                || storage.is_some()
1157                || location.is_some())
1158        {
1159            Err(Error::CreateTable {
1160                reason: "hive formats",
1161            })?
1162        }
1163
1164        if file_format.is_some() {
1165            Err(Error::CreateTable {
1166                reason: "file format",
1167            })?
1168        }
1169        if location.is_some() {
1170            Err(Error::CreateTable { reason: "location" })?
1171        }
1172        if query.is_some() {
1173            Err(Error::CreateTable { reason: "query" })?
1174        }
1175        if *without_rowid {
1176            Err(Error::CreateTable {
1177                reason: "without rowid",
1178            })?
1179        }
1180        if like.is_some() {
1181            Err(Error::CreateTable { reason: "like" })?
1182        }
1183        if clone.is_some() {
1184            Err(Error::CreateTable { reason: "clone" })?
1185        }
1186        if comment.is_some() {
1187            Err(Error::CreateTable { reason: "comment" })?
1188        }
1189        if on_commit.is_some() {
1190            Err(Error::CreateTable {
1191                reason: "on commit",
1192            })?
1193        }
1194        // ClickHouse "ON CLUSTER" clause:
1195        if on_cluster.is_some() {
1196            Err(Error::CreateTable {
1197                reason: "on cluster",
1198            })?
1199        }
1200        // ClickHouse "PRIMARY KEY " clause.
1201        if primary_key.is_some() {
1202            Err(Error::CreateTable {
1203                reason: "primary key",
1204            })?
1205        }
1206        // ClickHouse "ORDER BY " clause.
1207        if order_by.is_some() {
1208            Err(Error::CreateTable { reason: "order by" })?
1209        }
1210        // BigQuery: A partition expression for the table.
1211        if partition_by.is_some() {
1212            Err(Error::CreateTable {
1213                reason: "partition by",
1214            })?
1215        }
1216        // BigQuery: Table clustering column list.
1217        if cluster_by.is_some() {
1218            Err(Error::CreateTable {
1219                reason: "cluster by",
1220            })?
1221        }
1222        // Hive: Table clustering column list.
1223        if clustered_by.is_some() {
1224            Err(Error::CreateTable {
1225                reason: "clustered by",
1226            })?
1227        }
1228        // Postgres `INHERITs` clause, which contains the list of tables from which the new table inherits.
1229        if inherits.is_some() {
1230            Err(Error::CreateTable { reason: "inherits" })?
1231        }
1232        // SQLite "STRICT" clause.
1233        if *strict {
1234            Err(Error::CreateTable { reason: "strict" })?
1235        }
1236        // Snowflake "COPY GRANTS" clause.
1237        if *copy_grants {
1238            Err(Error::CreateTable {
1239                reason: "copy grant",
1240            })?
1241        }
1242        // Snowflake "ENABLE_SCHEMA_EVOLUTION" clause.
1243        if enable_schema_evolution.is_some() {
1244            Err(Error::CreateTable {
1245                reason: "enable schema evolution",
1246            })?
1247        }
1248        // Snowflake "CHANGE_TRACKING" clause.
1249        if change_tracking.is_some() {
1250            Err(Error::CreateTable {
1251                reason: "change tracking",
1252            })?
1253        }
1254        // Snowflake "DATA_RETENTION_TIME_IN_DAYS" clause.
1255        if data_retention_time_in_days.is_some() {
1256            Err(Error::CreateTable {
1257                reason: "data retention time in days",
1258            })?
1259        }
1260        // Snowflake "MAX_DATA_EXTENSION_TIME_IN_DAYS" clause.
1261        if max_data_extension_time_in_days.is_some() {
1262            Err(Error::CreateTable {
1263                reason: "max data extension time in days",
1264            })?
1265        }
1266        // Snowflake "DEFAULT_DDL_COLLATION" clause.
1267        if default_ddl_collation.is_some() {
1268            Err(Error::CreateTable {
1269                reason: "default ddl collation",
1270            })?
1271        }
1272        // Snowflake "WITH AGGREGATION POLICY" clause.
1273        if with_aggregation_policy.is_some() {
1274            Err(Error::CreateTable {
1275                reason: "with aggragation policy",
1276            })?
1277        }
1278        // Snowflake "WITH ROW ACCESS POLICY" clause.
1279        if with_row_access_policy.is_some() {
1280            Err(Error::CreateTable {
1281                reason: "with row access policy",
1282            })?
1283        }
1284        // Snowflake "WITH TAG" clause.
1285        if with_tags.is_some() {
1286            Err(Error::CreateTable {
1287                reason: "with tags",
1288            })?
1289        }
1290        // Snowflake "EXTERNAL_VOLUME" clause for Iceberg tables
1291        if external_volume.is_some() {
1292            Err(Error::CreateTable {
1293                reason: "external volume",
1294            })?
1295        }
1296        // Snowflake "BASE_LOCATION" clause for Iceberg tables
1297        if base_location.is_some() {
1298            Err(Error::CreateTable {
1299                reason: "base location",
1300            })?
1301        }
1302        // Snowflake "CATALOG" clause for Iceberg tables
1303        if catalog.is_some() {
1304            Err(Error::CreateTable { reason: "catalog" })?
1305        }
1306        // Snowflake "CATALOG_SYNC" clause for Iceberg tables
1307        if catalog_sync.is_some() {
1308            Err(Error::CreateTable {
1309                reason: "catalog sync",
1310            })?
1311        }
1312        // Snowflake "STORAGE_SERIALIZATION_POLICY" clause for Iceberg tables
1313        if storage_serialization_policy.is_some() {
1314            Err(Error::CreateTable {
1315                reason: "storage serialization policy",
1316            })?
1317        }
1318        if *dynamic {
1319            Err(Error::CreateTable { reason: "dynamic" })?
1320        }
1321        match table_options {
1322            CreateTableOptions::None => (),
1323            _ => Err(Error::CreateTable {
1324                reason: "table options",
1325            })?,
1326        };
1327
1328        if version.is_some() {
1329            Err(Error::CreateTable { reason: "versions" })?
1330        }
1331
1332        // Snowflake "TARGET_LAG" clause for dybamic tables
1333        if target_lag.is_some() {
1334            Err(Error::CreateTable {
1335                reason: "target lag",
1336            })?
1337        }
1338        // Snowflake "WAREHOUSE" clause for dybamic tables
1339        if warehouse.is_some() {
1340            Err(Error::CreateTable {
1341                reason: "warehouse",
1342            })?
1343        }
1344        // Snowflake "REFRESH_MODE" clause for dybamic tables
1345        if refresh_mode.is_some() {
1346            Err(Error::CreateTable {
1347                reason: "refresh mode",
1348            })?
1349        }
1350        // Snowflake "INITIALIZE" clause for dybamic tables
1351        if initialize.is_some() {
1352            Err(Error::CreateTable {
1353                reason: "initialize",
1354            })?
1355        }
1356        // Snowflake "REQUIRE USER" clause for dybamic tables
1357        if *require_user {
1358            Err(Error::CreateTable {
1359                reason: "require user",
1360            })?
1361        }
1362
1363        let name = Self::parse_object_name(name)?;
1364        let columns = {
1365            columns
1366                .iter()
1367                .map(TryFrom::try_from)
1368                .collect::<Result<Vec<_>>>()?
1369        };
1370        Ok(Ast::CreateTable {
1371            if_not_exists: *if_not_exists,
1372            name,
1373            columns,
1374            constraints: Constraints::try_from(constraints.as_slice())?,
1375        })
1376    }
1377
1378    #[allow(clippy::too_many_arguments)]
1379    fn parse_alter_table(
1380        name: &ObjectName,
1381        if_exists: bool,
1382        only: bool,
1383        operations: &[sqlparser::ast::AlterTableOperation],
1384        location: Option<&sqlparser::ast::HiveSetLocation>,
1385        on_cluster: Option<&Ident>,
1386        iceberg: bool,
1387        _end_token: &sqlparser::ast::helpers::attached_token::AttachedToken,
1388    ) -> Result<Ast> {
1389        // sqlite doesn't support if exists in alter
1390        if if_exists {
1391            Err(Error::AlterTable {
1392                reason: "if exists",
1393            })?
1394        }
1395        // sqlite doesn't support `ON` clause in alter table
1396        if only {
1397            Err(Error::AlterTable { reason: "on" })?
1398        }
1399        // clickhouse syntax
1400        if on_cluster.is_some() {
1401            Err(Error::AlterTable {
1402                reason: "on cluster",
1403            })?
1404        }
1405        // hive syntax
1406        if location.is_some() {
1407            Err(Error::AlterTable { reason: "location" })?
1408        }
1409        // iceberg syntax
1410        if iceberg {
1411            Err(Error::AlterTable { reason: "iceberg" })?
1412        }
1413        let name = Self::parse_object_name(name)?;
1414        if operations.len() != 1 {
1415            Err(Error::AlterTable {
1416                reason: "only supports single operation",
1417            })?
1418        }
1419        let operation = operations.first().unwrap().try_into()?;
1420        Ok(Ast::AlterTable { name, operation })
1421    }
1422
1423    fn parse_function_args(args: &FunctionArguments) -> Result<Vec<FunctionArg>> {
1424        let args = match args {
1425            FunctionArguments::None => vec![],
1426            FunctionArguments::List(list) => {
1427                if !list.clauses.is_empty() {
1428                    Err(Error::FunctionArguments {
1429                        reason: "function clauses are not yet supported",
1430                        arguments: Box::new(args.clone()),
1431                    })?
1432                };
1433                if list.duplicate_treatment.is_some() {
1434                    Err(Error::FunctionArguments {
1435                        reason: "function duplicate treatment not supported",
1436                        arguments: Box::new(args.clone()),
1437                    })?
1438                }
1439                list.args
1440                    .iter()
1441                    .map(|arg| -> Result<_> {
1442                        // FIXME: move to TryFrom
1443                        let arg = match arg {
1444                            sqlparser::ast::FunctionArg::ExprNamed { .. } => {
1445                                Err(Error::FunctionArgument {
1446                                    reason: "named expressions",
1447                                    argument: Box::new(arg.clone()),
1448                                })?
1449                            }
1450                            sqlparser::ast::FunctionArg::Named { .. } => {
1451                                Err(Error::FunctionArgument {
1452                                    reason: "named columns",
1453                                    argument: Box::new(arg.clone()),
1454                                })?
1455                            }
1456                            sqlparser::ast::FunctionArg::Unnamed(expr) => match expr {
1457                                sqlparser::ast::FunctionArgExpr::Wildcard => FunctionArg::Wildcard,
1458                                sqlparser::ast::FunctionArgExpr::Expr(Expr::Identifier(ident)) => {
1459                                    FunctionArg::Ident(ident.value.clone())
1460                                }
1461                                _ => Err(Error::FunctionArgument {
1462                                    reason: "unnamed",
1463                                    argument: Box::new(arg.clone()),
1464                                })?,
1465                            },
1466                        };
1467                        Ok(arg)
1468                    })
1469                    .collect::<Result<_>>()?
1470            }
1471            FunctionArguments::Subquery(query) => Err(Error::FunctionArguments {
1472                reason: "subquery",
1473                arguments: Box::new(args.clone()),
1474            })?,
1475        };
1476        Ok(args)
1477    }
1478
1479    fn parse_create_index(
1480        CreateIndex {
1481            name,
1482            table_name,
1483            columns,
1484            if_not_exists,
1485            unique,
1486            concurrently,
1487            using,
1488            include,
1489            nulls_distinct,
1490            with,
1491            predicate,
1492            index_options,
1493            alter_options,
1494        }: &CreateIndex,
1495    ) -> Result<Self> {
1496        if *if_not_exists {
1497            Err(Error::CreateIndex {
1498                reason: "existance check",
1499            })?
1500        };
1501        if name.is_none() {
1502            Err(Error::CreateIndex { reason: "nameless" })?
1503        }
1504        if *concurrently {
1505            Err(Error::CreateIndex {
1506                reason: "concurrent",
1507            })?
1508        }
1509        if using.is_some() {
1510            Err(Error::CreateIndex { reason: "using" })?
1511        }
1512        if !include.is_empty() {
1513            Err(Error::CreateIndex { reason: "include" })?
1514        }
1515        if nulls_distinct.is_some() {
1516            Err(Error::CreateIndex {
1517                reason: "distinct nulls",
1518            })?
1519        }
1520        if !with.is_empty() {
1521            Err(Error::CreateIndex { reason: "with" })?
1522        }
1523        if predicate.is_some() {
1524            Err(Error::CreateIndex {
1525                reason: "predicate",
1526            })?
1527        }
1528        // PG only
1529        if !index_options.is_empty() {
1530            Err(Error::CreateIndex {
1531                reason: "index options",
1532            })?
1533        }
1534        // Mysql only
1535        if !alter_options.is_empty() {
1536            Err(Error::CreateIndex {
1537                reason: "alter options",
1538            })?
1539        }
1540        let columns = columns
1541            .iter()
1542            .map(
1543                |index_column @ IndexColumn { column, .. }| -> Result<String> {
1544                    match &column.expr {
1545                        Expr::Identifier(Ident { value, .. }) => Ok(value.clone()),
1546                        expr => Err(Error::CreateIndexColumn {
1547                            column: Box::new(index_column.clone()),
1548                        })?,
1549                    }
1550                },
1551            )
1552            .collect::<Result<Vec<String>>>()?;
1553        Ok(Ast::CreateIndex {
1554            unique: *unique,
1555            name: Self::parse_object_name(name.as_ref().unwrap())?,
1556            table: Self::parse_object_name(table_name)?,
1557            columns,
1558        })
1559    }
1560
1561    fn parse_query(query: &Query) -> Result<Ast> {
1562        // FIXME: support CTEs
1563        if query.with.is_some() {
1564            Err(Error::CTE)?
1565        }
1566        if query.fetch.is_some() {
1567            Err(Error::Fetch)?
1568        }
1569        // FIXME: support limits
1570        if query.limit_clause.is_some() {
1571            Err(Error::Limit)?
1572        }
1573        if !query.locks.is_empty() {
1574            Err(Error::Locks)?
1575        }
1576        if query.for_clause.is_some() {
1577            Err(Error::For)?
1578        }
1579        let select = match &*query.body {
1580            SetExpr::Select(select) => &**select,
1581            other => Err(Error::Select {
1582                set_expr: Box::new(other.clone()),
1583            })?,
1584        };
1585        if select.top.is_some() || select.top_before_distinct {
1586            Err(Error::Top)?;
1587        }
1588        if select.projection.is_empty() {
1589            Err(Error::EmptyProjections)?;
1590        }
1591        let projections = select
1592            .projection
1593            .iter()
1594            .map(|projection| -> Result<_> {
1595                match projection {
1596                    SelectItem::Wildcard(_) => Ok(Projection::WildCard),
1597                    SelectItem::UnnamedExpr(Expr::Identifier(ident)) => {
1598                        Ok(Projection::Identifier(ident.value.clone()))
1599                    }
1600                    SelectItem::UnnamedExpr(Expr::Function(function)) => {
1601                        let function_name = Self::parse_object_name(&function.name)?.to_lowercase();
1602                        match function_name.as_str() {
1603                            "count" => {
1604                                let mut args = Self::parse_function_args(&function.args)?;
1605                                if args.len() != 1 {
1606                                    Err(Error::Count {
1607                                        reason: "function can only have single argument",
1608                                        args: args.clone(),
1609                                    })?
1610                                }
1611                                let arg = args.pop().unwrap();
1612                                Ok(Projection::Function(Function::Count(arg)))
1613                            }
1614                            name => Err(Error::Function {
1615                                name: function_name,
1616                            })?,
1617                        }
1618                    }
1619                    SelectItem::UnnamedExpr(Expr::Value(value)) => match &value.value {
1620                        Value::Number(value, _) => Ok(Projection::NumericLiteral(value.clone())),
1621                        Value::SingleQuotedString(value) => Ok(Projection::String(value.clone())),
1622                        value => Err(Error::SelectionValue {
1623                            value: Box::new(value.clone()),
1624                        })?,
1625                    },
1626                    SelectItem::UnnamedExpr(Expr::CompoundIdentifier(values)) => {
1627                        // SQLite only supports table.column, not schema.table.column or database.table.column
1628                        if values.len() != 2 {
1629                            Err(Error::CompoundIdentifier {
1630                                length: values.len(),
1631                            })?
1632                        }
1633                        Ok(Projection::CompoundIdentifier(CompoundIdentifier {
1634                            table: values[0].value.clone(),
1635                            column: values[1].value.clone(),
1636                        }))
1637                    }
1638                    _ => Err(Error::Projection {
1639                        select_item: Box::new(projection.clone()),
1640                    })?,
1641                }
1642            })
1643            .collect::<Result<Vec<Projection>>>()?;
1644
1645        let from_clause = select.from.as_slice().try_into()?;
1646
1647        let selection = select
1648            .selection
1649            .as_ref()
1650            .map(|selection| selection.try_into())
1651            .transpose()?;
1652        let group_by = match &select.group_by {
1653            sqlparser::ast::GroupByExpr::Expressions(expr, modifier) if modifier.is_empty() => expr
1654                .iter()
1655                .map(|expr| match expr {
1656                    Expr::Identifier(ident) => Ok(GroupByParameter::Ident(ident.value.clone())),
1657                    _ => Err(Error::GroupBy {
1658                        reason: "unsupported expression in group by",
1659                    })?,
1660                })
1661                .collect::<Result<Vec<GroupByParameter>>>()?,
1662            expr => Err(Error::GroupBy {
1663                reason: "unsupported group by expression",
1664            })?,
1665        };
1666        let order_by = match query.order_by.as_ref() {
1667            Some(order_by) => {
1668                if order_by.interpolate.is_some() {
1669                    Err(Error::OrderBy {
1670                        reason: "order by interpolate is not supported",
1671                    })?;
1672                };
1673                match &order_by.kind {
1674                    sqlparser::ast::OrderByKind::All(_) => Err(Error::OrderBy {
1675                        reason: "order by all is not supported",
1676                    })?,
1677                    sqlparser::ast::OrderByKind::Expressions(expressions) => expressions
1678                        .iter()
1679                        .map(|expression| {
1680                            if expression.with_fill.is_some() {
1681                                Err(Error::OrderBy {
1682                                    reason: "with fill is not supported",
1683                                })?
1684                            }
1685                            let ident = match &expression.expr {
1686                                Expr::Identifier(ident) => ident.value.clone(),
1687                                expr => Err(Error::OrderBy {
1688                                    reason: "unsupported order by expression",
1689                                })?,
1690                            };
1691                            let option = match &expression.options {
1692                                sqlparser::ast::OrderByOptions { nulls_first, .. }
1693                                    if nulls_first.is_some() =>
1694                                {
1695                                    Err(Error::OrderBy {
1696                                        reason: "order by with nulls first not supported",
1697                                    })?
1698                                }
1699                                sqlparser::ast::OrderByOptions { asc, .. } => match asc {
1700                                    None => OrderOption::None,
1701                                    Some(true) => OrderOption::Asc,
1702                                    Some(false) => OrderOption::Desc,
1703                                },
1704                            };
1705                            Ok(OrderByParameter { ident, option })
1706                        })
1707                        .collect::<Result<Vec<_>>>()?,
1708                }
1709            }
1710            None => vec![],
1711        };
1712        let ast = Ast::Select {
1713            distinct: select.distinct.is_some(),
1714            projections,
1715            from_clause,
1716            selection,
1717            group_by,
1718            order_by,
1719        };
1720        Ok(ast)
1721    }
1722
1723    fn parse_insert(insert: &sqlparser::ast::Insert) -> Result<Ast> {
1724        let sqlparser::ast::Insert {
1725            or,
1726            ignore,
1727            into,
1728            table,
1729            table_alias,
1730            columns,
1731            overwrite,
1732            source,
1733            assignments,
1734            partitioned,
1735            after_columns,
1736            has_table_keyword,
1737            on,
1738            returning,
1739            replace_into,
1740            priority,
1741            insert_alias,
1742            settings,
1743            format_clause,
1744        } = insert;
1745        // FIXME:
1746        if or.is_some() {
1747            Err(Error::Insert { reason: "or" })?
1748        };
1749        // FIXME:
1750        if *ignore {
1751            Err(Error::Insert { reason: "ignore" })?
1752        }
1753        if !*into {
1754            Err(Error::Insert {
1755                reason: "missing into",
1756            })?
1757        }
1758        if table_alias.is_some() {
1759            Err(Error::Insert {
1760                reason: "table alias",
1761            })?
1762        }
1763        if *overwrite {
1764            Err(Error::Insert {
1765                reason: "overwrite",
1766            })?
1767        }
1768        if !assignments.is_empty() {
1769            Err(Error::Insert {
1770                reason: "assignments",
1771            })?
1772        }
1773        if partitioned.is_some() || !after_columns.is_empty() {
1774            Err(Error::Insert {
1775                reason: "partitioned",
1776            })?
1777        }
1778        if *has_table_keyword {
1779            Err(Error::Insert {
1780                reason: "table keyword",
1781            })?
1782        }
1783        // FIXME:
1784        if on.is_some() {
1785            Err(Error::Insert {
1786                reason: "on keyword",
1787            })?
1788        }
1789        if returning.is_some() {
1790            Err(Error::Insert {
1791                reason: "returning",
1792            })?
1793        }
1794        if *replace_into {
1795            Err(Error::Insert { reason: "replace" })?
1796        }
1797        if priority.is_some() {
1798            Err(Error::Insert { reason: "priority" })?
1799        }
1800        if insert_alias.is_some() {
1801            Err(Error::Insert {
1802                reason: "insert alias",
1803            })?
1804        }
1805        if settings.is_some() {
1806            Err(Error::Insert { reason: "settings" })?
1807        }
1808        if format_clause.is_some() {
1809            Err(Error::Insert {
1810                reason: "format clause",
1811            })?
1812        }
1813        let name = match &table {
1814            sqlparser::ast::TableObject::TableName(name) => Self::parse_object_name(name)?,
1815            _ => Err(Error::InsertTableObject)?,
1816        };
1817        let source = match source {
1818            Some(source) => source,
1819            None => Err(Error::InsertSourceEmpty)?,
1820        };
1821        Ok(Ast::Insert {
1822            table: name,
1823            columns: columns.iter().map(|ident| ident.value.clone()).collect(),
1824            source: Self::parse_insert_source(source)?,
1825        })
1826    }
1827
1828    fn parse_insert_source(values: &Query) -> Result<Vec<Vec<InsertSource>>> {
1829        let values = match values.body.as_ref() {
1830            SetExpr::Values(values) if !values.explicit_row => values
1831                .rows
1832                .iter()
1833                .map(|row| -> Result<Vec<InsertSource>> {
1834                    row.iter()
1835                        .map(|value| value.try_into())
1836                        .collect::<Result<_>>()
1837                })
1838                .collect::<Result<_>>()?,
1839            other => Err(Error::InsertSource {
1840                set_expr: Box::new(other.clone()),
1841            })?,
1842        };
1843        Ok(values)
1844    }
1845
1846    fn parse_update(
1847        table: &TableWithJoins,
1848        assignments: &[Assignment],
1849        from: Option<&UpdateTableFromKind>,
1850        selection: Option<&Expr>,
1851        returning: Option<&[SelectItem]>,
1852        or: Option<&SqliteOnConflict>,
1853        limit: Option<&Expr>,
1854    ) -> Result<Ast> {
1855        if from.is_some() {
1856            Err(Error::Update {
1857                reason: "from table",
1858            })?
1859        }
1860        if returning.is_some() {
1861            Err(Error::Update {
1862                reason: "returning",
1863            })?
1864        }
1865        if or.is_some() {
1866            Err(Error::Update {
1867                reason: "update with OR is not supported",
1868            })?
1869        }
1870        if limit.is_some() {
1871            Err(Error::Update {
1872                reason: "update with LIMIT is not supported",
1873            })?
1874        }
1875        let table = match &table.relation {
1876            TableFactor::Table { name, .. } => Self::parse_object_name(name)?,
1877            table_factor => Err(Error::UpdateTableType {
1878                table_factor: Box::new(table_factor.clone()),
1879            })?,
1880        };
1881        let assignments = assignments
1882            .iter()
1883            .map(|assigment| {
1884                let target = match &assigment.target {
1885                    AssignmentTarget::ColumnName(name) => Self::parse_object_name(name)?,
1886                    target => Err(Error::UpdateAssignmentTarget {
1887                        target: Box::new(target.clone()),
1888                    })?,
1889                };
1890                let value = (&assigment.value).try_into()?;
1891                Ok(UpdateAssignment { target, value })
1892            })
1893            .collect::<Result<Vec<UpdateAssignment>>>()?;
1894        let selection: Option<Selection> = selection
1895            .map(|selection| selection.try_into())
1896            .transpose()?;
1897        Ok(Ast::Update {
1898            table,
1899            assignments,
1900            selection,
1901        })
1902    }
1903
1904    fn parse_delete(delete: &Delete) -> Result<Ast> {
1905        if !delete.tables.is_empty() {
1906            Err(Error::Delete {
1907                reason: "multiple tables",
1908            })?
1909        }
1910        if delete.using.is_some() {
1911            Err(Error::Delete { reason: "using" })?
1912        }
1913        if delete.returning.is_some() {
1914            Err(Error::Delete {
1915                reason: "returning",
1916            })?
1917        }
1918        if !delete.order_by.is_empty() {
1919            Err(Error::Delete { reason: "order by" })?
1920        }
1921        if delete.limit.is_some() {
1922            Err(Error::Delete { reason: "limit" })?
1923        }
1924
1925        let tables = match &delete.from {
1926            FromTable::WithFromKeyword(tables) => tables,
1927            FromTable::WithoutKeyword(_) => Err(Error::Delete {
1928                reason: "without from",
1929            })?,
1930        };
1931        if tables.len() != 1 {
1932            Err(Error::Delete {
1933                reason: "multiple tables",
1934            })?
1935        }
1936
1937        let from_clause = tables.as_slice().try_into()?;
1938
1939        let selection = delete
1940            .selection
1941            .as_ref()
1942            .map(|selection| selection.try_into())
1943            .transpose()?;
1944        Ok(Ast::Delete {
1945            from_clause,
1946            selection,
1947        })
1948    }
1949
1950    fn parse_drop(
1951        object_type: &ObjectType,
1952        if_exists: bool,
1953        names: &[ObjectName],
1954        table: Option<&ObjectName>,
1955    ) -> Result<Self> {
1956        let name = match names {
1957            [table_name] => Self::parse_object_name(table_name)?,
1958            _ => Err(Error::Drop {
1959                reason: "multiple names",
1960                object_type: None,
1961            })?,
1962        };
1963        match object_type {
1964            ObjectType::Table => Ok(Ast::DropTable { if_exists, name }),
1965            ObjectType::Index => Self::parse_drop_index(if_exists, name, table),
1966            _ => Err(Error::Drop {
1967                reason: "object type",
1968                object_type: Some(*object_type),
1969            }),
1970        }
1971    }
1972
1973    fn parse_drop_index(if_exists: bool, name: String, table: Option<&ObjectName>) -> Result<Self> {
1974        let table = match table.map(Self::parse_object_name) {
1975            Some(name) => name?,
1976            None => Err(Error::DropIndex {
1977                reason: "table name required",
1978            })?,
1979        };
1980        Ok(Ast::DropIndex {
1981            if_exists,
1982            name,
1983            table,
1984        })
1985    }
1986
1987    pub fn parse(query: &str) -> Result<Vec<Ast>> {
1988        Parser::parse_sql(&dialect::GenericDialect {}, query)?
1989            .iter()
1990            .map(|statement| {
1991                let result = match statement {
1992                    Statement::CreateTable(create_table) => Self::parse_create_table(create_table)?,
1993                    Statement::AlterTable {
1994                        name,
1995                        if_exists,
1996                        only,
1997                        operations,
1998                        location,
1999                        on_cluster,
2000                        iceberg,
2001                        end_token,
2002                    } => Self::parse_alter_table(
2003                        name,
2004                        *if_exists,
2005                        *only,
2006                        operations.as_slice(),
2007                        location.as_ref(),
2008                        on_cluster.as_ref(),
2009                        *iceberg,
2010                        end_token,
2011                    )?,
2012                    Statement::CreateIndex(index) => Self::parse_create_index(index)?,
2013                    Statement::Query(query) => Self::parse_query(query)?,
2014                    Statement::Drop {
2015                        object_type,
2016                        if_exists,
2017                        names,
2018                        cascade,
2019                        restrict,
2020                        purge,
2021                        temporary,
2022                        table,
2023                    } => Self::parse_drop(object_type, *if_exists, names, table.as_ref())?,
2024                    Statement::Insert(insert) => Self::parse_insert(insert)?,
2025                    Statement::Update {
2026                        table,
2027                        assignments,
2028                        from,
2029                        selection,
2030                        returning,
2031                        or,
2032                        limit,
2033                    } => Self::parse_update(
2034                        table,
2035                        assignments.as_slice(),
2036                        from.as_ref(),
2037                        selection.as_ref(),
2038                        returning.as_deref(),
2039                        or.as_ref(),
2040                        limit.as_ref(),
2041                    )?,
2042                    Statement::Delete(delete) => Self::parse_delete(delete)?,
2043                    _ => Err(Error::Statement {
2044                        statement: Box::new(statement.clone()),
2045                    })?,
2046                };
2047                Ok(result)
2048            })
2049            .collect::<Result<Vec<_>>>()
2050    }
2051
2052    fn create_table_to_sql(
2053        dialect: &dyn ToQuery,
2054        buf: &mut dyn Write,
2055        if_not_exists: bool,
2056        name: &str,
2057        columns: &[Column],
2058        constraints: &Constraints,
2059    ) -> Result<()> {
2060        buf.write_all(b"CREATE TABLE ")?;
2061        if if_not_exists {
2062            buf.write_all(b"IF NOT EXISTS ")?;
2063        }
2064        Self::write_quoted(dialect, buf, name)?;
2065        buf.write_all(b" (\n")?;
2066        Self::table_columns_to_sql(dialect, buf, columns, "\n")?;
2067        if constraints.len() > 0 {
2068            buf.write_all(b",\n")?;
2069        }
2070        for (pos, constraint) in constraints.into_iter().enumerate() {
2071            match constraint {
2072                Constraint::PrimaryKey(fields) => {
2073                    buf.write_all(b"PRIMARY KEY (")?;
2074                    for (pos, field) in fields.iter().enumerate() {
2075                        Self::write_quoted(dialect, buf, field)?;
2076                        if pos != fields.len() - 1 {
2077                            buf.write_all(b", ")?;
2078                        }
2079                    }
2080                    buf.write_all(b")")?;
2081                }
2082                Constraint::ForeignKey {
2083                    columns,
2084                    referred_columns,
2085                    foreign_table,
2086                    on_delete,
2087                } => {
2088                    buf.write_all(b"FOREIGN KEY (")?;
2089                    for (pos, column) in columns.iter().enumerate() {
2090                        Self::write_quoted(dialect, buf, column)?;
2091                        if pos != columns.len() - 1 {
2092                            buf.write_all(b", ")?;
2093                        }
2094                    }
2095                    buf.write_all(b") REFERENCES ")?;
2096                    buf.write_all(foreign_table.as_bytes());
2097                    buf.write_all(b"(")?;
2098                    for (pos, column) in referred_columns.iter().enumerate() {
2099                        Self::write_quoted(dialect, buf, column)?;
2100                        if pos != columns.len() - 1 {
2101                            buf.write_all(b", ")?;
2102                        }
2103                    }
2104                    buf.write_all(b")")?;
2105
2106                    if let Some(delete_action) = on_delete {
2107                        buf.write_all(b" ON DELETE ")?;
2108                        match delete_action {
2109                            OnDeleteAction::Cascade => buf.write_all(b"CASCADE")?,
2110                            OnDeleteAction::SetNull => buf.write_all(b"SET NULL")?,
2111                            OnDeleteAction::Restrict => buf.write_all(b"RESTRICT")?,
2112                        }
2113                    }
2114                }
2115            }
2116            if pos != constraints.len() - 1 {
2117                buf.write_all(b",\n")?;
2118            }
2119        }
2120        buf.write_all(b"\n)")?;
2121        Ok(())
2122    }
2123
2124    fn table_columns_to_sql(
2125        dialect: &dyn ToQuery,
2126        buf: &mut dyn Write,
2127        columns: &[Column],
2128        separator: &str,
2129    ) -> Result<()> {
2130        for (pos, column) in columns.iter().enumerate() {
2131            Self::write_quoted(dialect, buf, &column.name)?;
2132            buf.write_all(b" ")?;
2133
2134            dialect.emit_column_spec(column, buf)?;
2135            if pos != columns.len() - 1 {
2136                buf.write_all(b",")?;
2137                buf.write_all(separator.as_bytes())?;
2138            }
2139        }
2140        Ok(())
2141    }
2142
2143    fn create_index_to_sql(
2144        dialect: &dyn ToQuery,
2145        buf: &mut dyn Write,
2146        unique: bool,
2147        name: &str,
2148        table: &str,
2149        columns: &[String],
2150    ) -> Result<()> {
2151        if unique {
2152            buf.write_all(b"CREATE UNIQUE INDEX ")?;
2153        } else {
2154            buf.write_all(b"CREATE INDEX ")?;
2155        }
2156        Self::write_quoted(dialect, buf, name)?;
2157        buf.write_all(b" ON ")?;
2158        Self::write_quoted(dialect, buf, table)?;
2159        buf.write_all(b" (")?;
2160        for (pos, column) in columns.iter().enumerate() {
2161            Self::write_quoted(dialect, buf, column)?;
2162            if pos != columns.len() - 1 {
2163                buf.write_all(b", ")?;
2164            }
2165        }
2166        buf.write_all(b")")?;
2167        Ok(())
2168    }
2169
2170    #[allow(clippy::too_many_arguments)]
2171    fn select_to_sql(
2172        dialect: &dyn ToQuery,
2173        buf: &mut dyn Write,
2174        distinct: bool,
2175        projections: &[Projection],
2176        from_clause: &FromClause,
2177        selection: Option<&Selection>,
2178        group_by: &[GroupByParameter],
2179        order_by: &[OrderByParameter],
2180    ) -> Result<()> {
2181        buf.write_all(b"SELECT ")?;
2182        if distinct {
2183            buf.write_all(b"DISTINCT ")?;
2184        }
2185        for (pos, projection) in projections.iter().enumerate() {
2186            match projection {
2187                Projection::WildCard => buf.write_all(b"*")?,
2188                Projection::Identifier(ident) => {
2189                    Self::write_quoted(dialect, buf, ident)?;
2190                }
2191                Projection::CompoundIdentifier(compound) => {
2192                    Self::write_quoted(dialect, buf, &compound.table)?;
2193                    buf.write_all(b".");
2194                    Self::write_quoted(dialect, buf, &compound.column)?;
2195                }
2196                Projection::Function(function) => match function {
2197                    Function::Count(FunctionArg::Wildcard) => buf.write_all(b"COUNT(*)")?,
2198                    Function::Count(FunctionArg::Ident(ident)) => {
2199                        buf.write_all(b"COUNT(")?;
2200                        Self::write_quoted(dialect, buf, ident)?;
2201                        buf.write_all(b")")?
2202                    }
2203                },
2204                Projection::NumericLiteral(value) => buf.write_all(value.as_bytes())?,
2205                Projection::String(value) => Self::write_single_quoted(dialect, buf, value)?,
2206            };
2207            if pos != projections.len() - 1 {
2208                buf.write_all(b", ")?;
2209            }
2210        }
2211
2212        match from_clause {
2213            FromClause::Table(name) => {
2214                buf.write_all(b" FROM ")?;
2215                Self::write_quoted(dialect, buf, name)?
2216            }
2217            FromClause::None => (),
2218            FromClause::TableWithJoin(table) => {
2219                buf.write_all(b" FROM ")?;
2220                Self::write_quoted(dialect, buf, &table.name)?;
2221                for table in table.join.iter() {
2222                    match &table.operator {
2223                        JoinOperator::Join(selection) => {
2224                            buf.write_all(b" JOIN ")?;
2225                            Self::write_quoted(dialect, buf, &table.name);
2226                            buf.write_all(b" ON ")?;
2227                            Self::selection_to_sql(dialect, buf, selection)?;
2228                        }
2229                        JoinOperator::Inner(selection) => {
2230                            buf.write_all(b" INNER JOIN ")?;
2231                            Self::write_quoted(dialect, buf, &table.name);
2232                            buf.write_all(b" ON ")?;
2233                            Self::selection_to_sql(dialect, buf, selection)?;
2234                        }
2235                    }
2236                }
2237            }
2238        }
2239        if let Some(selection) = selection.as_ref() {
2240            buf.write_all(b" WHERE ")?;
2241            Self::selection_to_sql(dialect, buf, selection)?;
2242        };
2243
2244        if !group_by.is_empty() {
2245            buf.write_all(b" GROUP BY (")?;
2246            for (pos, parameter) in group_by.iter().enumerate() {
2247                match parameter {
2248                    GroupByParameter::Ident(ident) => Self::write_quoted(dialect, buf, ident)?,
2249                }
2250                if pos != group_by.len() - 1 {
2251                    buf.write_all(b", ")?;
2252                }
2253            }
2254            buf.write_all(b")")?;
2255        }
2256        if !order_by.is_empty() {
2257            buf.write_all(b" ORDER BY ")?;
2258            for (pos, order_option) in order_by.iter().enumerate() {
2259                Self::write_quoted(dialect, buf, order_option.ident.as_str())?;
2260                match &order_option.option {
2261                    OrderOption::Asc => buf.write_all(b" ASC")?,
2262                    OrderOption::Desc => buf.write_all(b" DESC")?,
2263                    OrderOption::None => (),
2264                };
2265                if pos != order_by.len() - 1 {
2266                    buf.write_all(b", ")?;
2267                }
2268            }
2269        }
2270        Ok(())
2271    }
2272
2273    fn insert_source_to_sql(
2274        dialect: &dyn ToQuery,
2275        buf: &mut dyn Write,
2276        insert_source: &InsertSource,
2277        place_holder_num: usize,
2278    ) -> Result<()> {
2279        match insert_source {
2280            InsertSource::Null => buf.write_all(b"NULL")?,
2281            InsertSource::Number(num) => buf.write_all(num.as_bytes())?,
2282            InsertSource::String(string) => Self::write_single_quoted(dialect, buf, string)?,
2283            InsertSource::Placeholder => {
2284                buf.write_all(dialect.placeholder(place_holder_num).as_bytes())?;
2285            }
2286            InsertSource::Cast { cast, source } => {
2287                Self::insert_source_to_sql(dialect, buf, source, place_holder_num)?;
2288                if dialect.placeholder_supports_cast() {
2289                    buf.write_all(b"::")?;
2290                    buf.write_all(cast.as_bytes())?;
2291                }
2292            }
2293        };
2294        Ok(())
2295    }
2296
2297    fn insert_to_sql(
2298        dialect: &dyn ToQuery,
2299        buf: &mut dyn Write,
2300        table: &str,
2301        columns: &[String],
2302        values: &[Vec<InsertSource>],
2303    ) -> Result<()> {
2304        buf.write_all(b"INSERT INTO ")?;
2305        Self::write_quoted(dialect, buf, table)?;
2306        if !columns.is_empty() {
2307            buf.write_all(b"(")?;
2308            for (pos, column) in columns.iter().enumerate() {
2309                if pos != 0 {
2310                    buf.write_all(b", ")?;
2311                }
2312                Self::write_quoted(dialect, buf, column)?;
2313            }
2314            buf.write_all(b")")?;
2315        }
2316        buf.write_all(b" VALUES ")?;
2317        for (row_pos, row) in values.iter().enumerate() {
2318            if row_pos != 0 {
2319                buf.write_all(b", ")?;
2320            }
2321            buf.write_all(b"(")?;
2322            for (col_pos, insert_source) in row.iter().enumerate() {
2323                if col_pos != 0 {
2324                    buf.write_all(b", ")?;
2325                }
2326                Self::insert_source_to_sql(
2327                    dialect,
2328                    buf,
2329                    insert_source,
2330                    row_pos * row.len() + col_pos + 1,
2331                )?;
2332            }
2333            buf.write_all(b")")?;
2334        }
2335        Ok(())
2336    }
2337
2338    fn selection_to_sql(
2339        dialect: &dyn ToQuery,
2340        buf: &mut dyn Write,
2341        selection: &Selection,
2342    ) -> Result<()> {
2343        let mut placeholder_count = 0;
2344        Self::selection_to_sql_with_placeholder_count(
2345            dialect,
2346            buf,
2347            selection,
2348            &mut placeholder_count,
2349        )
2350    }
2351
2352    fn selection_to_sql_with_placeholder_count(
2353        dialect: &dyn ToQuery,
2354        buf: &mut dyn Write,
2355        selection: &Selection,
2356        placeholder_count: &mut usize,
2357    ) -> Result<()> {
2358        match selection {
2359            Selection::BinaryOp { op, left, right } => {
2360                Self::selection_to_sql_with_placeholder_count(
2361                    dialect,
2362                    buf,
2363                    left,
2364                    placeholder_count,
2365                )?;
2366                match op {
2367                    Op::And => buf.write_all(b" AND ")?,
2368                    Op::Eq => buf.write_all(b" = ")?,
2369                    Op::Or => buf.write_all(b" OR ")?,
2370                }
2371                Self::selection_to_sql_with_placeholder_count(
2372                    dialect,
2373                    buf,
2374                    right,
2375                    placeholder_count,
2376                )?;
2377            }
2378            Selection::Ident(ident) => Self::write_quoted(dialect, buf, ident)?,
2379            Selection::CompoundIdentifier(compound) => {
2380                Self::write_quoted(dialect, buf, &compound.table)?;
2381                buf.write_all(b".");
2382                Self::write_quoted(dialect, buf, &compound.column)?;
2383            }
2384            Selection::Number(number) => buf.write_all(number.as_bytes())?,
2385            Selection::String(string) => {
2386                for chunk in [b"'", string.as_bytes(), b"'"] {
2387                    buf.write_all(chunk)?;
2388                }
2389            }
2390            Selection::Placeholder => {
2391                *placeholder_count += 1;
2392                buf.write_all(dialect.placeholder(*placeholder_count).as_bytes())?;
2393            }
2394            Selection::InList {
2395                negated,
2396                ident,
2397                list,
2398            } => {
2399                Self::write_quoted(dialect, buf, ident)?;
2400                if *negated {
2401                    buf.write_all(b" NOT")?;
2402                }
2403                buf.write_all(b" IN ")?;
2404                buf.write_all(b"(")?;
2405                for (pos, selection) in list.iter().enumerate() {
2406                    if pos != 0 {
2407                        buf.write_all(b", ")?;
2408                    }
2409                    Self::selection_to_sql_with_placeholder_count(
2410                        dialect,
2411                        buf,
2412                        selection,
2413                        placeholder_count,
2414                    )?;
2415                }
2416                buf.write_all(b")")?;
2417            }
2418        };
2419        Ok(())
2420    }
2421
2422    fn update_to_sql(
2423        dialect: &dyn ToQuery,
2424        buf: &mut dyn Write,
2425        table: &str,
2426        assignments: &[UpdateAssignment],
2427        selection: Option<&Selection>,
2428    ) -> Result<()> {
2429        buf.write_all(b"UPDATE ")?;
2430        Self::write_quoted(dialect, buf, table)?;
2431        buf.write_all(b" SET ")?;
2432        for (pos, assignment) in assignments.iter().enumerate() {
2433            if pos != 0 {
2434                buf.write_all(b", ")?;
2435            }
2436            Self::write_quoted(dialect, buf, assignment.target.as_bytes())?;
2437            buf.write_all(b"=")?;
2438            match &assignment.value {
2439                UpdateValue::Null => buf.write_all(b"NULL")?,
2440                UpdateValue::String(string) => Self::write_single_quoted(dialect, buf, string)?,
2441                UpdateValue::Number(number) => buf.write_all(number.as_bytes())?,
2442                UpdateValue::Placeholder => {
2443                    buf.write_all(dialect.placeholder(pos + 1).as_bytes())?
2444                }
2445            }
2446        }
2447        if let Some(selection) = selection.as_ref() {
2448            buf.write_all(b" WHERE ")?;
2449            Self::selection_to_sql(dialect, buf, selection)?;
2450        };
2451        Ok(())
2452    }
2453
2454    fn delete_to_sql(
2455        dialect: &dyn ToQuery,
2456        buf: &mut dyn Write,
2457        from_clause: &FromClause,
2458        selection: Option<&Selection>,
2459    ) -> Result<()> {
2460        buf.write_all(b"DELETE FROM ")?;
2461        match from_clause {
2462            FromClause::Table(name) => Self::write_quoted(dialect, buf, name)?,
2463            FromClause::None => Err(Error::DeleteToSql {
2464                reason: "DELETE without FROM is not supported",
2465            })?,
2466            FromClause::TableWithJoin(_) => Err(Error::DeleteToSql {
2467                reason: "DELETE with joins is not supported",
2468            })?,
2469        }
2470        if let Some(selection) = selection.as_ref() {
2471            buf.write_all(b" WHERE ")?;
2472            Self::selection_to_sql(dialect, buf, selection)?;
2473        };
2474        Ok(())
2475    }
2476
2477    fn drop_table_to_sql(
2478        dialect: &dyn ToQuery,
2479        buf: &mut dyn Write,
2480        if_exists: bool,
2481        name: &str,
2482    ) -> Result<()> {
2483        buf.write_all(b"DROP TABLE ")?;
2484        if if_exists {
2485            buf.write_all(b"IF EXISTS ")?;
2486        }
2487        Self::write_quoted(dialect, buf, name);
2488        Ok(())
2489    }
2490
2491    fn drop_index_to_sql(
2492        dialect: &dyn ToQuery,
2493        buf: &mut dyn Write,
2494        if_exists: bool,
2495        name: &str,
2496        table: &str,
2497    ) -> Result<()> {
2498        buf.write_all(b"DROP INDEX ")?;
2499        if if_exists {
2500            buf.write_all(b"IF EXISTS ")?;
2501        }
2502        Self::write_quoted(dialect, buf, name);
2503        if dialect.drop_index_requires_table() {
2504            buf.write_all(b" ON ")?;
2505            Self::write_quoted(dialect, buf, table)?;
2506        }
2507        Ok(())
2508    }
2509
2510    fn write_quoted(
2511        dialect: &dyn ToQuery,
2512        buf: &mut dyn Write,
2513        input: impl AsRef<[u8]>,
2514    ) -> Result<()> {
2515        buf.write_all(dialect.quote())?;
2516        buf.write_all(input.as_ref())?;
2517        buf.write_all(dialect.quote())?;
2518        Ok(())
2519    }
2520
2521    fn write_single_quoted(
2522        dialect: &dyn ToQuery,
2523        buf: &mut dyn Write,
2524        input: impl AsRef<[u8]>,
2525    ) -> Result<()> {
2526        buf.write_all(b"'")?;
2527        buf.write_all(input.as_ref())?;
2528        buf.write_all(b"'")?;
2529        Ok(())
2530    }
2531
2532    fn alter_table_to_sql(
2533        dialect: &dyn ToQuery,
2534        buf: &mut dyn Write,
2535        table_name: &str,
2536        operation: &AlterTableOperation,
2537    ) -> Result<()> {
2538        buf.write_all(b"ALTER TABLE ")?;
2539        Self::write_quoted(dialect, buf, table_name)?;
2540        match operation {
2541            AlterTableOperation::AddColumn { column } => {
2542                buf.write_all(b" ADD COLUMN ")?;
2543                let columns: &[Column] = slice::from_ref(column);
2544                Self::table_columns_to_sql(dialect, buf, columns, "")?;
2545            }
2546            AlterTableOperation::RenameColumn { from, to } => {
2547                buf.write_all(b" RENAME COLUMN ")?;
2548                Self::write_quoted(dialect, buf, from)?;
2549                buf.write_all(b" TO ")?;
2550                Self::write_quoted(dialect, buf, to)?;
2551            }
2552            AlterTableOperation::DropColumn { name } => {
2553                buf.write_all(b" DROP COLUMN ")?;
2554                Self::write_quoted(dialect, buf, name)?;
2555            }
2556            AlterTableOperation::RenameTable { to } => {
2557                buf.write_all(b" RENAME TO ")?;
2558                Self::write_quoted(dialect, buf, to)?;
2559            }
2560        }
2561        Ok(())
2562    }
2563
2564    pub fn to_sql(&self, dialect: &dyn ToQuery) -> Result<String> {
2565        let buf = &mut Cursor::new(Vec::with_capacity(1));
2566        match self {
2567            Ast::CreateTable {
2568                if_not_exists,
2569                name,
2570                columns,
2571                constraints,
2572            } => {
2573                Self::create_table_to_sql(dialect, buf, *if_not_exists, name, columns, constraints)?
2574            }
2575            Ast::AlterTable { name, operation } => {
2576                Self::alter_table_to_sql(dialect, buf, name.as_str(), operation)?
2577            }
2578            Ast::CreateIndex {
2579                unique,
2580                name,
2581                table,
2582                columns,
2583            } => Self::create_index_to_sql(dialect, buf, *unique, name, table, columns)?,
2584            Ast::Select {
2585                distinct,
2586                projections,
2587                from_clause,
2588                selection,
2589                group_by,
2590                order_by,
2591            } => Self::select_to_sql(
2592                dialect,
2593                buf,
2594                *distinct,
2595                projections,
2596                from_clause,
2597                selection.as_ref(),
2598                group_by,
2599                order_by,
2600            )?,
2601            Ast::Insert {
2602                table,
2603                columns,
2604                source,
2605            } => Self::insert_to_sql(
2606                dialect,
2607                buf,
2608                table.as_str(),
2609                columns.as_slice(),
2610                source.as_slice(),
2611            )?,
2612            Ast::Update {
2613                table,
2614                assignments,
2615                selection,
2616            } => Self::update_to_sql(
2617                dialect,
2618                buf,
2619                table.as_str(),
2620                assignments.as_slice(),
2621                selection.as_ref(),
2622            )?,
2623            Ast::Delete {
2624                from_clause,
2625                selection,
2626            } => Self::delete_to_sql(dialect, buf, from_clause, selection.as_ref())?,
2627            Ast::DropTable { if_exists, name } => {
2628                Self::drop_table_to_sql(dialect, buf, *if_exists, name)?
2629            }
2630            Ast::DropIndex {
2631                if_exists,
2632                name,
2633                table,
2634            } => Self::drop_index_to_sql(dialect, buf, *if_exists, name, table)?,
2635        };
2636        let buf = std::mem::replace(buf, Cursor::new(Vec::new()));
2637        Ok(String::from_utf8(buf.into_inner())?)
2638    }
2639}
2640
2641pub trait ToQuery {
2642    fn quote(&self) -> &'static [u8];
2643
2644    fn placeholder(&self, pos: usize) -> Cow<'static, str>;
2645
2646    fn placeholder_supports_cast(&self) -> bool {
2647        false
2648    }
2649
2650    fn emit_column_spec(&self, column: &Column, buf: &mut dyn Write) -> Result<()>;
2651
2652    fn drop_index_requires_table(&self) -> bool {
2653        false
2654    }
2655}
2656
2657impl ToQuery for MySqlDialect {
2658    fn quote(&self) -> &'static [u8] {
2659        b"`"
2660    }
2661
2662    fn placeholder(&self, _: usize) -> Cow<'static, str> {
2663        Cow::Borrowed("?")
2664    }
2665
2666    fn emit_column_spec(
2667        &self,
2668        Column {
2669            name,
2670            data_type,
2671            options,
2672        }: &Column,
2673        buf: &mut dyn Write,
2674    ) -> Result<()> {
2675        let mut options = *options;
2676        let spec = match data_type {
2677            DataType::SmallSerial if options.is_primary_key() => {
2678                options = options.set_auto_increment();
2679                Cow::Borrowed("SMALLINT")
2680            }
2681            DataType::Serial if options.is_primary_key() => {
2682                options = options.set_auto_increment();
2683                Cow::Borrowed("INT")
2684            }
2685            DataType::BigSerial if options.is_primary_key() => {
2686                options = options.set_auto_increment();
2687                Cow::Borrowed("BIGINT")
2688            }
2689            DataType::SmallSerial | DataType::Serial | DataType::BigSerial => Err(Error::Serial)?,
2690            DataType::I16 => Cow::Borrowed("SMALLLINT"),
2691            DataType::I32 => Cow::Borrowed("INT"),
2692            DataType::I64 => Cow::Borrowed("BIGINT"),
2693            DataType::F32 => Cow::Borrowed("REAL"),
2694            DataType::F64 => Cow::Borrowed("DOUBLE"),
2695            DataType::Bool => Cow::Borrowed("BOOLEAN"),
2696            DataType::String => Cow::Borrowed("TEXT"),
2697            DataType::Char(len) => Cow::Owned(format!("CHAR({len})")),
2698            DataType::VarChar(len) => Cow::Owned(format!("VARCHAR({len})")),
2699            DataType::Bytes => Cow::Borrowed("BLOB"),
2700            DataType::Json => Cow::Borrowed("JSON"),
2701            DataType::Uuid => Cow::Borrowed("CHAR(36)"),
2702            DataType::Decimal { precision, scale } => {
2703                Cow::Owned(format!("DECIMAL({precision}, {scale})"))
2704            }
2705            DataType::Date => Cow::Borrowed("DATE"),
2706            DataType::Time => Cow::Borrowed("TIME"),
2707            DataType::Timestamp => Cow::Borrowed("DATETIME"),
2708        };
2709
2710        buf.write_all(spec.as_bytes())?;
2711        let options = options
2712            .into_iter()
2713            .map(|option| match option {
2714                ColumnOption::PrimaryKey => "PRIMARY KEY",
2715                ColumnOption::AutoInrement => "AUTO_INCREMENT",
2716                ColumnOption::NotNull => "NOT NULL",
2717                ColumnOption::Nullable => "NULL",
2718                ColumnOption::Unique => "UNIQUE",
2719            })
2720            .collect::<Vec<_>>()
2721            .join(" ");
2722        if !options.is_empty() {
2723            buf.write_all(b" ")?;
2724            buf.write_all(options.as_bytes())?;
2725        }
2726        Ok(())
2727    }
2728
2729    fn drop_index_requires_table(&self) -> bool {
2730        true
2731    }
2732}
2733
2734impl ToQuery for PostgreSqlDialect {
2735    fn quote(&self) -> &'static [u8] {
2736        b"\""
2737    }
2738
2739    fn placeholder(&self, pos: usize) -> Cow<'static, str> {
2740        Cow::Owned(format!("${pos}"))
2741    }
2742
2743    fn placeholder_supports_cast(&self) -> bool {
2744        true
2745    }
2746
2747    fn emit_column_spec(
2748        &self,
2749        Column {
2750            name,
2751            data_type,
2752            options,
2753        }: &Column,
2754        buf: &mut dyn Write,
2755    ) -> Result<()> {
2756        let mut options = *options;
2757        let spec = match data_type {
2758            DataType::SmallSerial if options.is_primary_key() => Cow::Borrowed("SMALLSERIAL"),
2759            DataType::Serial if options.is_primary_key() => Cow::Borrowed("SERIAL"),
2760            DataType::BigSerial if options.is_primary_key() => Cow::Borrowed("BIGSERIAL"),
2761            DataType::SmallSerial | DataType::Serial | DataType::BigSerial => Err(Error::Serial)?,
2762            DataType::I16 if options.is_primary_key() && options.is_auto_increment() => {
2763                Cow::Borrowed("SMALLSERIAL")
2764            }
2765            DataType::I32 if options.is_primary_key() && options.is_auto_increment() => {
2766                Cow::Borrowed("SERIAL")
2767            }
2768            DataType::I64 if options.is_primary_key() && options.is_auto_increment() => {
2769                Cow::Borrowed("BIGSERIAL")
2770            }
2771            DataType::I16 => Cow::Borrowed("SMALLLINT"),
2772            DataType::I32 => Cow::Borrowed("INT"),
2773            DataType::I64 => Cow::Borrowed("BIGINT"),
2774            DataType::F32 => Cow::Borrowed("REAL"),
2775            DataType::F64 => Cow::Borrowed("DOUBLE"),
2776            DataType::Bool => Cow::Borrowed("BOOLEAN"),
2777            DataType::String => Cow::Borrowed("TEXT"),
2778            DataType::Char(len) => Cow::Owned(format!("CHAR({len})")),
2779            DataType::VarChar(len) => Cow::Owned(format!("VARCHAR({len})")),
2780            DataType::Bytes => Cow::Borrowed("BYTEA"),
2781            DataType::Json => Cow::Borrowed("JSON"),
2782            DataType::Uuid => Cow::Borrowed("UUID"),
2783            DataType::Decimal { precision, scale } => {
2784                Cow::Owned(format!("DECIMAL({precision}, {scale})"))
2785            }
2786            DataType::Date => Cow::Borrowed("DATE"),
2787            DataType::Time => Cow::Borrowed("TIME"),
2788            DataType::Timestamp => Cow::Borrowed("TIMESTAMP"),
2789        };
2790        buf.write_all(spec.as_bytes())?;
2791        let options = options
2792            .into_iter()
2793            .filter_map(|option| match option {
2794                ColumnOption::PrimaryKey => Some("PRIMARY KEY"),
2795                ColumnOption::AutoInrement => None,
2796                ColumnOption::NotNull => Some("NOT NULL"),
2797                ColumnOption::Nullable => Some("NULL"),
2798                ColumnOption::Unique => Some("UNIQUE"),
2799            })
2800            .collect::<Vec<_>>()
2801            .join(" ");
2802        if !options.is_empty() {
2803            buf.write_all(b" ")?;
2804            buf.write_all(options.as_bytes())?;
2805        }
2806        Ok(())
2807    }
2808}
2809
2810impl ToQuery for SQLiteDialect {
2811    fn quote(&self) -> &'static [u8] {
2812        b"`"
2813    }
2814
2815    fn placeholder(&self, _: usize) -> Cow<'static, str> {
2816        Cow::Borrowed("?")
2817    }
2818
2819    fn emit_column_spec(
2820        &self,
2821        Column {
2822            name,
2823            data_type,
2824            options,
2825        }: &Column,
2826        buf: &mut dyn Write,
2827    ) -> Result<()> {
2828        let mut options = *options;
2829        let spec = match data_type {
2830            DataType::SmallSerial | DataType::Serial | DataType::BigSerial
2831                if options.is_primary_key() =>
2832            {
2833                Cow::Borrowed("INTEGER")
2834            }
2835            DataType::SmallSerial | DataType::Serial | DataType::BigSerial => Err(Error::Serial)?,
2836            DataType::I16 | DataType::I32 | DataType::I64 if options.is_primary_key() => {
2837                // Sqlite doesn't need auto increment for integer primary key, since it's already auto incremented
2838                // in nature
2839                options = options.unset_auto_increment();
2840                Cow::Borrowed("INTEGER")
2841            }
2842            DataType::I32 => Cow::Borrowed("INTEGER"),
2843            DataType::I64 => Cow::Borrowed("INTEGER"),
2844            DataType::I16 => Cow::Borrowed("INTEGER"),
2845            DataType::I32 => Cow::Borrowed("INTEGER"),
2846            DataType::I64 => Cow::Borrowed("INTEGER"),
2847            DataType::F32 => Cow::Borrowed("FLOAT"),
2848            DataType::F64 => Cow::Borrowed("DOUBLE"),
2849            DataType::Bool => Cow::Borrowed("BOOLEAN"),
2850            DataType::String => Cow::Borrowed("TEXT"),
2851            DataType::Char(len) => Cow::Owned(format!("CHAR({len})")),
2852            DataType::VarChar(len) => Cow::Owned(format!("VARCHAR({len})")),
2853            DataType::Bytes => Cow::Borrowed("BLOB"),
2854            DataType::Json => Cow::Borrowed("JSON"),
2855            DataType::Uuid => Cow::Borrowed("UUID"),
2856            DataType::Decimal { precision, scale } => {
2857                Cow::Owned(format!("DECIMAL({precision}, {scale})"))
2858            }
2859            DataType::Date => Cow::Borrowed("TEXT"),
2860            DataType::Time => Cow::Borrowed("TEXT"),
2861            DataType::Timestamp => Cow::Borrowed("TEXT"),
2862        };
2863        buf.write_all(spec.as_bytes())?;
2864        let options = options
2865            .into_iter()
2866            .map(|option| match option {
2867                ColumnOption::PrimaryKey => "PRIMARY KEY",
2868                ColumnOption::AutoInrement => "AUTOINCREMENT",
2869                ColumnOption::NotNull => "NOT NULL",
2870                ColumnOption::Nullable => "NULL",
2871                ColumnOption::Unique => "UNIQUE",
2872            })
2873            .collect::<Vec<_>>()
2874            .join(" ");
2875        if !options.is_empty() {
2876            buf.write_all(b" ")?;
2877            buf.write_all(options.as_bytes())?;
2878        }
2879        Ok(())
2880    }
2881}