sqlite3_parser/parser/ast/
mod.rs

1//! Abstract Syntax Tree
2
3pub mod check;
4pub mod fmt;
5
6use std::num::ParseIntError;
7use std::ops::Deref;
8use std::str::{self, Bytes, FromStr};
9
10use fmt::{ToTokens, TokenStream};
11use indexmap::{IndexMap, IndexSet};
12
13use crate::custom_err;
14use crate::dialect::TokenType::{self, *};
15use crate::dialect::{from_token, is_identifier, Token};
16use crate::parser::{parse::YYCODETYPE, ParserError};
17
18/// `?` or `$` Prepared statement arg placeholder(s)
19#[derive(Default)]
20pub struct ParameterInfo {
21    /// Number of SQL parameters in a prepared statement, like `sqlite3_bind_parameter_count`
22    pub count: u32,
23    /// Parameter name(s) if any
24    pub names: IndexSet<String>,
25}
26
27// https://sqlite.org/lang_expr.html#parameters
28impl TokenStream for ParameterInfo {
29    type Error = ParseIntError;
30
31    fn append(&mut self, ty: TokenType, value: Option<&str>) -> Result<(), Self::Error> {
32        if ty == TK_VARIABLE {
33            if let Some(variable) = value {
34                if variable == "?" {
35                    self.count = self.count.saturating_add(1);
36                } else if variable.as_bytes()[0] == b'?' {
37                    let n = u32::from_str(&variable[1..])?;
38                    if n > self.count {
39                        self.count = n;
40                    }
41                } else if self.names.insert(variable.to_owned()) {
42                    self.count = self.count.saturating_add(1);
43                }
44            }
45        }
46        Ok(())
47    }
48}
49
50/// Statement or Explain statement
51// https://sqlite.org/syntax/sql-stmt.html
52#[derive(Clone, Debug, PartialEq, Eq)]
53pub enum Cmd {
54    /// `EXPLAIN` statement
55    Explain(Stmt),
56    /// `EXPLAIN QUERY PLAN` statement
57    ExplainQueryPlan(Stmt),
58    /// statement
59    Stmt(Stmt),
60}
61
62pub(crate) enum ExplainKind {
63    Explain,
64    QueryPlan,
65}
66
67/// SQL statement
68// https://sqlite.org/syntax/sql-stmt.html
69#[derive(Clone, Debug, PartialEq, Eq)]
70pub enum Stmt {
71    /// `ALTER TABLE`: table name, body
72    AlterTable(QualifiedName, AlterTableBody),
73    /// `ANALYSE`: object name
74    Analyze(Option<QualifiedName>),
75    /// `ATTACH DATABASE`
76    Attach {
77        /// filename
78        // TODO distinction between ATTACH and ATTACH DATABASE
79        expr: Expr,
80        /// schema name
81        db_name: Expr,
82        /// password
83        key: Option<Expr>,
84    },
85    /// `BEGIN`: tx type, tx name
86    Begin(Option<TransactionType>, Option<Name>),
87    /// `COMMIT`/`END`: tx name
88    Commit(Option<Name>), // TODO distinction between COMMIT and END
89    /// `CREATE INDEX`
90    CreateIndex {
91        /// `UNIQUE`
92        unique: bool,
93        /// `IF NOT EXISTS`
94        if_not_exists: bool,
95        /// index name
96        idx_name: QualifiedName,
97        /// table name
98        tbl_name: Name,
99        /// indexed columns or expressions
100        columns: Vec<SortedColumn>,
101        /// partial index
102        where_clause: Option<Expr>,
103    },
104    /// `CREATE TABLE`
105    CreateTable {
106        /// `TEMPORARY`
107        temporary: bool, // TODO distinction between TEMP and TEMPORARY
108        /// `IF NOT EXISTS`
109        if_not_exists: bool,
110        /// table name
111        tbl_name: QualifiedName,
112        /// table body
113        body: CreateTableBody,
114    },
115    /// `CREATE TRIGGER`
116    CreateTrigger {
117        /// `TEMPORARY`
118        temporary: bool,
119        /// `IF NOT EXISTS`
120        if_not_exists: bool,
121        /// trigger name
122        trigger_name: QualifiedName,
123        /// `BEFORE`/`AFTER`/`INSTEAD OF`
124        time: Option<TriggerTime>,
125        /// `DELETE`/`INSERT`/`UPDATE`
126        event: TriggerEvent,
127        /// table name
128        tbl_name: QualifiedName,
129        /// `FOR EACH ROW`
130        for_each_row: bool,
131        /// `WHEN`
132        when_clause: Option<Expr>,
133        /// statements
134        commands: Vec<TriggerCmd>,
135    },
136    /// `CREATE VIEW`
137    CreateView {
138        /// `TEMPORARY`
139        temporary: bool,
140        /// `IF NOT EXISTS`
141        if_not_exists: bool,
142        /// view name
143        view_name: QualifiedName,
144        /// columns
145        columns: Option<Vec<IndexedColumn>>,
146        /// query
147        select: Box<Select>,
148    },
149    /// `CREATE VIRTUAL TABLE`
150    CreateVirtualTable {
151        /// `IF NOT EXISTS`
152        if_not_exists: bool,
153        /// table name
154        tbl_name: QualifiedName,
155        /// module
156        module_name: Name,
157        /// args
158        args: Option<Vec<String>>, // TODO smol str
159    },
160    /// `DELETE`
161    Delete {
162        /// CTE
163        with: Option<With>,
164        /// `FROM` table name
165        tbl_name: QualifiedName,
166        /// `INDEXED`
167        indexed: Option<Indexed>,
168        /// `WHERE` clause
169        where_clause: Option<Expr>,
170        /// `RETURNING`
171        returning: Option<Vec<ResultColumn>>,
172        /// `ORDER BY`
173        order_by: Option<Vec<SortedColumn>>,
174        /// `LIMIT`
175        limit: Option<Limit>,
176    },
177    /// `DETACH DATABASE`: db name
178    Detach(Expr), // TODO distinction between DETACH and DETACH DATABASE
179    /// `DROP INDEX`
180    DropIndex {
181        /// `IF EXISTS`
182        if_exists: bool,
183        /// index name
184        idx_name: QualifiedName,
185    },
186    /// `DROP TABLE`
187    DropTable {
188        /// `IF EXISTS`
189        if_exists: bool,
190        /// table name
191        tbl_name: QualifiedName,
192    },
193    /// `DROP TRIGGER`
194    DropTrigger {
195        /// `IF EXISTS`
196        if_exists: bool,
197        /// trigger name
198        trigger_name: QualifiedName,
199    },
200    /// `DROP VIEW`
201    DropView {
202        /// `IF EXISTS`
203        if_exists: bool,
204        /// view name
205        view_name: QualifiedName,
206    },
207    /// `INSERT`
208    Insert {
209        /// CTE
210        with: Option<With>,
211        /// `OR`
212        or_conflict: Option<ResolveType>, // TODO distinction between REPLACE and INSERT OR REPLACE
213        /// table name
214        tbl_name: QualifiedName,
215        /// `COLUMNS`
216        columns: Option<DistinctNames>,
217        /// `VALUES` or `SELECT`
218        body: InsertBody,
219        /// `RETURNING`
220        returning: Option<Vec<ResultColumn>>,
221    },
222    /// `PRAGMA`: pragma name, body
223    Pragma(QualifiedName, Option<PragmaBody>),
224    /// `REINDEX`
225    Reindex {
226        /// collation or index or table name
227        obj_name: Option<QualifiedName>,
228    },
229    /// `RELEASE`: savepoint name
230    Release(Name), // TODO distinction between RELEASE and RELEASE SAVEPOINT
231    /// `ROLLBACK`
232    Rollback {
233        /// transaction name
234        tx_name: Option<Name>,
235        /// savepoint name
236        savepoint_name: Option<Name>, // TODO distinction between TO and TO SAVEPOINT
237    },
238    /// `SAVEPOINT`: savepoint name
239    Savepoint(Name),
240    /// `SELECT`
241    Select(Box<Select>),
242    /// `UPDATE`
243    Update {
244        /// CTE
245        with: Option<With>,
246        /// `OR`
247        or_conflict: Option<ResolveType>,
248        /// table name
249        tbl_name: QualifiedName,
250        /// `INDEXED`
251        indexed: Option<Indexed>,
252        /// `SET` assignments
253        sets: Vec<Set>,
254        /// `FROM`
255        from: Option<FromClause>,
256        /// `WHERE` clause
257        where_clause: Option<Expr>,
258        /// `RETURNING`
259        returning: Option<Vec<ResultColumn>>,
260        /// `ORDER BY`
261        order_by: Option<Vec<SortedColumn>>,
262        /// `LIMIT`
263        limit: Option<Limit>,
264    },
265    /// `VACUUM`: database name, into expr
266    Vacuum(Option<Name>, Option<Expr>),
267}
268
269/// SQL expression
270// https://sqlite.org/syntax/expr.html
271#[derive(Clone, Debug, PartialEq, Eq)]
272pub enum Expr {
273    /// `BETWEEN`
274    Between {
275        /// expression
276        lhs: Box<Expr>,
277        /// `NOT`
278        not: bool,
279        /// start
280        start: Box<Expr>,
281        /// end
282        end: Box<Expr>,
283    },
284    /// binary expression
285    Binary(Box<Expr>, Operator, Box<Expr>),
286    /// `CASE` expression
287    Case {
288        /// operand
289        base: Option<Box<Expr>>,
290        /// `WHEN` condition `THEN` result
291        when_then_pairs: Vec<(Expr, Expr)>,
292        /// `ELSE` result
293        else_expr: Option<Box<Expr>>,
294    },
295    /// CAST expression
296    Cast {
297        /// expression
298        expr: Box<Expr>,
299        /// `AS` type name
300        type_name: Option<Type>,
301    },
302    /// `COLLATE`: expression
303    Collate(Box<Expr>, String),
304    /// schema-name.table-name.column-name
305    DoublyQualified(Name, Name, Name),
306    /// `EXISTS` subquery
307    Exists(Box<Select>),
308    /// call to a built-in function
309    FunctionCall {
310        /// function name
311        name: Id,
312        /// `DISTINCT`
313        distinctness: Option<Distinctness>,
314        /// arguments
315        args: Option<Vec<Expr>>,
316        /// `ORDER BY`
317        order_by: Option<Vec<SortedColumn>>,
318        /// `FILTER`
319        filter_over: Option<FunctionTail>,
320    },
321    /// Function call expression with '*' as arg
322    FunctionCallStar {
323        /// function name
324        name: Id,
325        /// `FILTER`
326        filter_over: Option<FunctionTail>,
327    },
328    /// Identifier
329    Id(Id),
330    /// `IN`
331    InList {
332        /// expression
333        lhs: Box<Expr>,
334        /// `NOT`
335        not: bool,
336        /// values
337        rhs: Option<Vec<Expr>>,
338    },
339    /// `IN` subselect
340    InSelect {
341        /// expression
342        lhs: Box<Expr>,
343        /// `NOT`
344        not: bool,
345        /// subquery
346        rhs: Box<Select>,
347    },
348    /// `IN` table name / function
349    InTable {
350        /// expression
351        lhs: Box<Expr>,
352        /// `NOT`
353        not: bool,
354        /// table name
355        rhs: QualifiedName,
356        /// table function arguments
357        args: Option<Vec<Expr>>,
358    },
359    /// `IS NULL`
360    IsNull(Box<Expr>),
361    /// `LIKE`
362    Like {
363        /// expression
364        lhs: Box<Expr>,
365        /// `NOT`
366        not: bool,
367        /// operator
368        op: LikeOperator,
369        /// pattern
370        rhs: Box<Expr>,
371        /// `ESCAPE` char
372        escape: Option<Box<Expr>>,
373    },
374    /// Literal expression
375    Literal(Literal),
376    /// Name
377    Name(Name),
378    /// `NOT NULL` or `NOTNULL`
379    NotNull(Box<Expr>),
380    /// Parenthesized subexpression
381    Parenthesized(Vec<Expr>),
382    /// Qualified name
383    Qualified(Name, Name),
384    /// `RAISE` function call
385    Raise(ResolveType, Option<Box<Expr>>),
386    /// Subquery expression
387    Subquery(Box<Select>),
388    /// Unary expression
389    Unary(UnaryOperator, Box<Expr>),
390    /// Parameters
391    Variable(String),
392}
393
394impl Expr {
395    /// Constructor
396    pub fn parenthesized(x: Self) -> Self {
397        Self::Parenthesized(vec![x])
398    }
399    /// Constructor
400    pub fn id(xt: YYCODETYPE, x: Token) -> Self {
401        Self::Id(Id::from_token(xt, x))
402    }
403    /// Constructor
404    pub fn collate(x: Self, ct: YYCODETYPE, c: Token) -> Self {
405        Self::Collate(Box::new(x), from_token(ct, c))
406    }
407    /// Constructor
408    pub fn cast(x: Self, type_name: Option<Type>) -> Self {
409        Self::Cast {
410            expr: Box::new(x),
411            type_name,
412        }
413    }
414    /// Constructor
415    pub fn binary(left: Self, op: YYCODETYPE, right: Self) -> Self {
416        Self::Binary(Box::new(left), Operator::from(op), Box::new(right))
417    }
418    /// Constructor
419    pub fn ptr(left: Self, op: Token, right: Self) -> Self {
420        let mut ptr = Operator::ArrowRight;
421        if op.1 == b"->>" {
422            ptr = Operator::ArrowRightShift;
423        }
424        Self::Binary(Box::new(left), ptr, Box::new(right))
425    }
426    /// Constructor
427    pub fn like(lhs: Self, not: bool, op: LikeOperator, rhs: Self, escape: Option<Self>) -> Self {
428        Self::Like {
429            lhs: Box::new(lhs),
430            not,
431            op,
432            rhs: Box::new(rhs),
433            escape: escape.map(Box::new),
434        }
435    }
436    /// Constructor
437    pub fn not_null(x: Self, op: YYCODETYPE) -> Self {
438        if op == TK_ISNULL as YYCODETYPE {
439            Self::IsNull(Box::new(x))
440        } else if op == TK_NOTNULL as YYCODETYPE {
441            Self::NotNull(Box::new(x))
442        } else {
443            unreachable!()
444        }
445    }
446    /// Constructor
447    pub fn unary(op: UnaryOperator, x: Self) -> Self {
448        Self::Unary(op, Box::new(x))
449    }
450    /// Constructor
451    pub fn between(lhs: Self, not: bool, start: Self, end: Self) -> Self {
452        Self::Between {
453            lhs: Box::new(lhs),
454            not,
455            start: Box::new(start),
456            end: Box::new(end),
457        }
458    }
459    /// Constructor
460    pub fn in_list(lhs: Self, not: bool, rhs: Option<Vec<Self>>) -> Self {
461        Self::InList {
462            lhs: Box::new(lhs),
463            not,
464            rhs,
465        }
466    }
467    /// Constructor
468    pub fn in_select(lhs: Self, not: bool, rhs: Select) -> Self {
469        Self::InSelect {
470            lhs: Box::new(lhs),
471            not,
472            rhs: Box::new(rhs),
473        }
474    }
475    /// Constructor
476    pub fn in_table(lhs: Self, not: bool, rhs: QualifiedName, args: Option<Vec<Self>>) -> Self {
477        Self::InTable {
478            lhs: Box::new(lhs),
479            not,
480            rhs,
481            args,
482        }
483    }
484    /// Constructor
485    pub fn sub_query(query: Select) -> Self {
486        Self::Subquery(Box::new(query))
487    }
488}
489
490/// SQL literal
491#[derive(Clone, Debug, PartialEq, Eq)]
492pub enum Literal {
493    /// Number
494    Numeric(String),
495    /// String
496    // TODO Check that string is already quoted and correctly escaped
497    String(String),
498    /// BLOB
499    // TODO Check that string is valid (only hexa)
500    Blob(String),
501    /// Keyword
502    Keyword(String),
503    /// `NULL`
504    Null,
505    /// `CURRENT_DATE`
506    CurrentDate,
507    /// `CURRENT_TIME`
508    CurrentTime,
509    /// `CURRENT_TIMESTAMP`
510    CurrentTimestamp,
511}
512
513impl Literal {
514    /// Constructor
515    pub fn from_ctime_kw(token: Token) -> Self {
516        if b"CURRENT_DATE".eq_ignore_ascii_case(token.1) {
517            Self::CurrentDate
518        } else if b"CURRENT_TIME".eq_ignore_ascii_case(token.1) {
519            Self::CurrentTime
520        } else if b"CURRENT_TIMESTAMP".eq_ignore_ascii_case(token.1) {
521            Self::CurrentTimestamp
522        } else {
523            unreachable!()
524        }
525    }
526}
527
528/// Textual comparison operator in an expression
529#[derive(Copy, Clone, Debug, PartialEq, Eq)]
530pub enum LikeOperator {
531    /// `GLOB`
532    Glob,
533    /// `LIKE`
534    Like,
535    /// `MATCH`
536    Match,
537    /// `REGEXP`
538    Regexp,
539}
540
541impl LikeOperator {
542    /// Constructor
543    pub fn from_token(token_type: YYCODETYPE, token: Token) -> Self {
544        if token_type == TK_MATCH as YYCODETYPE {
545            return Self::Match;
546        } else if token_type == TK_LIKE_KW as YYCODETYPE {
547            let token = token.1;
548            if b"LIKE".eq_ignore_ascii_case(token) {
549                return Self::Like;
550            } else if b"GLOB".eq_ignore_ascii_case(token) {
551                return Self::Glob;
552            } else if b"REGEXP".eq_ignore_ascii_case(token) {
553                return Self::Regexp;
554            }
555        }
556        unreachable!()
557    }
558}
559
560/// SQL operators
561#[derive(Copy, Clone, Debug, PartialEq, Eq)]
562pub enum Operator {
563    /// `+`
564    Add,
565    /// `AND`
566    And,
567    /// `->`
568    ArrowRight,
569    /// `->>`
570    ArrowRightShift,
571    /// `&`
572    BitwiseAnd,
573    /// `|`
574    BitwiseOr,
575    /// String concatenation (`||`)
576    Concat,
577    /// `=` or `==`
578    Equals,
579    /// `/`
580    Divide,
581    /// `>`
582    Greater,
583    /// `>=`
584    GreaterEquals,
585    /// `IS`
586    Is,
587    /// `IS NOT`
588    IsNot,
589    /// `<<`
590    LeftShift,
591    /// `<`
592    Less,
593    /// `<=`
594    LessEquals,
595    /// `%`
596    Modulus,
597    /// `*`
598    Multiply,
599    /// `!=` or `<>`
600    NotEquals,
601    /// `OR`
602    Or,
603    /// `>>`
604    RightShift,
605    /// `-`
606    Subtract,
607}
608
609impl From<YYCODETYPE> for Operator {
610    fn from(token_type: YYCODETYPE) -> Self {
611        match token_type {
612            x if x == TK_AND as YYCODETYPE => Self::And,
613            x if x == TK_OR as YYCODETYPE => Self::Or,
614            x if x == TK_LT as YYCODETYPE => Self::Less,
615            x if x == TK_GT as YYCODETYPE => Self::Greater,
616            x if x == TK_GE as YYCODETYPE => Self::GreaterEquals,
617            x if x == TK_LE as YYCODETYPE => Self::LessEquals,
618            x if x == TK_EQ as YYCODETYPE => Self::Equals,
619            x if x == TK_NE as YYCODETYPE => Self::NotEquals,
620            x if x == TK_BITAND as YYCODETYPE => Self::BitwiseAnd,
621            x if x == TK_BITOR as YYCODETYPE => Self::BitwiseOr,
622            x if x == TK_LSHIFT as YYCODETYPE => Self::LeftShift,
623            x if x == TK_RSHIFT as YYCODETYPE => Self::RightShift,
624            x if x == TK_PLUS as YYCODETYPE => Self::Add,
625            x if x == TK_MINUS as YYCODETYPE => Self::Subtract,
626            x if x == TK_STAR as YYCODETYPE => Self::Multiply,
627            x if x == TK_SLASH as YYCODETYPE => Self::Divide,
628            x if x == TK_REM as YYCODETYPE => Self::Modulus,
629            x if x == TK_CONCAT as YYCODETYPE => Self::Concat,
630            x if x == TK_IS as YYCODETYPE => Self::Is,
631            x if x == TK_NOT as YYCODETYPE => Self::IsNot,
632            _ => unreachable!(),
633        }
634    }
635}
636
637/// Unary operators
638#[derive(Copy, Clone, Debug, PartialEq, Eq)]
639pub enum UnaryOperator {
640    /// bitwise negation (`~`)
641    BitwiseNot,
642    /// negative-sign
643    Negative,
644    /// `NOT`
645    Not,
646    /// positive-sign
647    Positive,
648}
649
650impl From<YYCODETYPE> for UnaryOperator {
651    fn from(token_type: YYCODETYPE) -> Self {
652        match token_type {
653            x if x == TK_BITNOT as YYCODETYPE => Self::BitwiseNot,
654            x if x == TK_MINUS as YYCODETYPE => Self::Negative,
655            x if x == TK_NOT as YYCODETYPE => Self::Not,
656            x if x == TK_PLUS as YYCODETYPE => Self::Positive,
657            _ => unreachable!(),
658        }
659    }
660}
661
662/// `SELECT` statement
663// https://sqlite.org/lang_select.html
664// https://sqlite.org/syntax/factored-select-stmt.html
665#[derive(Clone, Debug, PartialEq, Eq)]
666pub struct Select {
667    /// CTE
668    pub with: Option<With>,
669    /// body
670    pub body: SelectBody,
671    /// `ORDER BY`
672    pub order_by: Option<Vec<SortedColumn>>, // ORDER BY term does not match any column in the result set
673    /// `LIMIT`
674    pub limit: Option<Limit>,
675}
676
677/// `SELECT` body
678#[derive(Clone, Debug, PartialEq, Eq)]
679pub struct SelectBody {
680    /// first select
681    pub select: OneSelect,
682    /// compounds
683    pub compounds: Option<Vec<CompoundSelect>>,
684}
685
686impl SelectBody {
687    pub(crate) fn push(&mut self, cs: CompoundSelect) -> Result<(), ParserError> {
688        use crate::ast::check::ColumnCount;
689        if let ColumnCount::Fixed(n) = self.select.column_count() {
690            if let ColumnCount::Fixed(m) = cs.select.column_count() {
691                if n != m {
692                    return Err(custom_err!(
693                        "SELECTs to the left and right of {} do not have the same number of result columns",
694                        cs.operator
695                    ));
696                }
697            }
698        }
699        if let Some(ref mut v) = self.compounds {
700            v.push(cs);
701        } else {
702            self.compounds = Some(vec![cs]);
703        }
704        Ok(())
705    }
706}
707
708/// Compound select
709#[derive(Clone, Debug, PartialEq, Eq)]
710pub struct CompoundSelect {
711    /// operator
712    pub operator: CompoundOperator,
713    /// select
714    pub select: OneSelect,
715}
716
717/// Compound operators
718// https://sqlite.org/syntax/compound-operator.html
719#[derive(Copy, Clone, Debug, PartialEq, Eq)]
720pub enum CompoundOperator {
721    /// `UNION`
722    Union,
723    /// `UNION ALL`
724    UnionAll,
725    /// `EXCEPT`
726    Except,
727    /// `INTERSECT`
728    Intersect,
729}
730
731/// `SELECT` core
732// https://sqlite.org/syntax/select-core.html
733#[derive(Clone, Debug, PartialEq, Eq)]
734pub enum OneSelect {
735    /// `SELECT`
736    Select {
737        /// `DISTINCT`
738        distinctness: Option<Distinctness>,
739        /// columns
740        columns: Vec<ResultColumn>,
741        /// `FROM` clause
742        from: Option<FromClause>,
743        /// `WHERE` clause
744        where_clause: Option<Expr>,
745        /// `GROUP BY`
746        group_by: Option<GroupBy>,
747        /// `WINDOW` definition
748        window_clause: Option<Vec<WindowDef>>,
749    },
750    /// `VALUES`
751    Values(Vec<Vec<Expr>>),
752}
753
754/// `SELECT` ... `FROM` clause
755// https://sqlite.org/syntax/join-clause.html
756#[derive(Clone, Debug, PartialEq, Eq)]
757pub struct FromClause {
758    /// table
759    pub select: Option<Box<SelectTable>>, // FIXME mandatory
760    /// `JOIN`ed tabled
761    pub joins: Option<Vec<JoinedSelectTable>>,
762    op: Option<JoinOperator>, // FIXME transient
763}
764impl FromClause {
765    pub(crate) fn empty() -> Self {
766        Self {
767            select: None,
768            joins: None,
769            op: None,
770        }
771    }
772
773    pub(crate) fn push(
774        &mut self,
775        table: SelectTable,
776        jc: Option<JoinConstraint>,
777    ) -> Result<(), ParserError> {
778        let op = self.op.take();
779        if let Some(op) = op {
780            let jst = JoinedSelectTable {
781                operator: op,
782                table,
783                constraint: jc,
784            };
785            if jst.operator.is_natural() && jst.constraint.is_some() {
786                return Err(custom_err!(
787                    "a NATURAL join may not have an ON or USING clause"
788                ));
789            }
790            if let Some(ref mut joins) = self.joins {
791                joins.push(jst);
792            } else {
793                self.joins = Some(vec![jst]);
794            }
795        } else {
796            if jc.is_some() {
797                return Err(custom_err!("a JOIN clause is required before ON"));
798            }
799            debug_assert!(self.select.is_none());
800            debug_assert!(self.joins.is_none());
801            self.select = Some(Box::new(table));
802        }
803        Ok(())
804    }
805
806    pub(crate) fn push_op(&mut self, op: JoinOperator) {
807        self.op = Some(op);
808    }
809}
810
811/// `SELECT` distinctness
812#[derive(Copy, Clone, Debug, PartialEq, Eq)]
813pub enum Distinctness {
814    /// `DISTINCT`
815    Distinct,
816    /// `ALL`
817    All,
818}
819
820/// `SELECT` or `RETURNING` result column
821// https://sqlite.org/syntax/result-column.html
822#[derive(Clone, Debug, PartialEq, Eq)]
823pub enum ResultColumn {
824    /// expression
825    Expr(Expr, Option<As>),
826    /// `*`
827    Star,
828    /// table name.`*`
829    TableStar(Name),
830}
831
832/// Alias
833#[derive(Clone, Debug, PartialEq, Eq)]
834pub enum As {
835    /// `AS`
836    As(Name),
837    /// no `AS`
838    Elided(Name), // FIXME Ids
839}
840
841/// `JOIN` clause
842// https://sqlite.org/syntax/join-clause.html
843#[derive(Clone, Debug, PartialEq, Eq)]
844pub struct JoinedSelectTable {
845    /// operator
846    pub operator: JoinOperator,
847    /// table
848    pub table: SelectTable,
849    /// constraint
850    pub constraint: Option<JoinConstraint>,
851}
852
853/// Table or subquery
854// https://sqlite.org/syntax/table-or-subquery.html
855#[derive(Clone, Debug, PartialEq, Eq)]
856pub enum SelectTable {
857    /// table
858    Table(QualifiedName, Option<As>, Option<Indexed>),
859    /// table function call
860    TableCall(QualifiedName, Option<Vec<Expr>>, Option<As>),
861    /// `SELECT` subquery
862    Select(Box<Select>, Option<As>),
863    /// subquery
864    Sub(FromClause, Option<As>),
865}
866
867/// Join operators
868// https://sqlite.org/syntax/join-operator.html
869#[derive(Copy, Clone, Debug, PartialEq, Eq)]
870pub enum JoinOperator {
871    /// `,`
872    Comma,
873    /// `JOIN`
874    TypedJoin(Option<JoinType>),
875}
876
877impl JoinOperator {
878    pub(crate) fn from(
879        token: Token,
880        n1: Option<Name>,
881        n2: Option<Name>,
882    ) -> Result<Self, ParserError> {
883        Ok({
884            let mut jt = JoinType::try_from(token.1)?;
885            for n in [&n1, &n2].into_iter().flatten() {
886                jt |= JoinType::try_from(n.0.as_ref())?;
887            }
888            if (jt & (JoinType::INNER | JoinType::OUTER)) == (JoinType::INNER | JoinType::OUTER)
889                || (jt & (JoinType::OUTER | JoinType::LEFT | JoinType::RIGHT)) == JoinType::OUTER
890            {
891                return Err(custom_err!(
892                    "unsupported JOIN type: {:?} {:?} {:?}",
893                    str::from_utf8(token.1),
894                    n1,
895                    n2
896                ));
897            }
898            Self::TypedJoin(Some(jt))
899        })
900    }
901    fn is_natural(&self) -> bool {
902        match self {
903            Self::TypedJoin(Some(jt)) => jt.contains(JoinType::NATURAL),
904            _ => false,
905        }
906    }
907}
908
909// https://github.com/sqlite/sqlite/blob/80511f32f7e71062026edd471913ef0455563964/src/select.c#L197-L257
910bitflags::bitflags! {
911    /// `JOIN` types
912    #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
913    pub struct JoinType: u8 {
914        /// `INNER`
915        const INNER   = 0x01;
916        /// `CROSS` => INNER|CROSS
917        const CROSS   = 0x02;
918        /// `NATURAL`
919        const NATURAL = 0x04;
920        /// `LEFT` => LEFT|OUTER
921        const LEFT    = 0x08;
922        /// `RIGHT` => RIGHT|OUTER
923        const RIGHT   = 0x10;
924        /// `OUTER`
925        const OUTER   = 0x20;
926    }
927}
928
929impl TryFrom<&[u8]> for JoinType {
930    type Error = ParserError;
931    fn try_from(s: &[u8]) -> Result<Self, ParserError> {
932        if b"CROSS".eq_ignore_ascii_case(s) {
933            Ok(Self::INNER | Self::CROSS)
934        } else if b"FULL".eq_ignore_ascii_case(s) {
935            Ok(Self::LEFT | Self::RIGHT | Self::OUTER)
936        } else if b"INNER".eq_ignore_ascii_case(s) {
937            Ok(Self::INNER)
938        } else if b"LEFT".eq_ignore_ascii_case(s) {
939            Ok(Self::LEFT | Self::OUTER)
940        } else if b"NATURAL".eq_ignore_ascii_case(s) {
941            Ok(Self::NATURAL)
942        } else if b"RIGHT".eq_ignore_ascii_case(s) {
943            Ok(Self::RIGHT | Self::OUTER)
944        } else if b"OUTER".eq_ignore_ascii_case(s) {
945            Ok(Self::OUTER)
946        } else {
947            Err(custom_err!(
948                "unsupported JOIN type: {:?}",
949                str::from_utf8(s)
950            ))
951        }
952    }
953}
954
955/// `JOIN` constraint
956#[derive(Clone, Debug, PartialEq, Eq)]
957pub enum JoinConstraint {
958    /// `ON`
959    On(Expr),
960    /// `USING`: col names
961    Using(DistinctNames),
962}
963
964/// `GROUP BY`
965#[derive(Clone, Debug, PartialEq, Eq)]
966pub struct GroupBy {
967    /// expressions
968    pub exprs: Vec<Expr>,
969    /// `HAVING`
970    pub having: Option<Expr>, // HAVING clause on a non-aggregate query
971}
972
973/// identifier or one of several keywords or `INDEXED`
974#[derive(Clone, Debug, PartialEq, Eq)]
975pub struct Id(pub String);
976
977impl Id {
978    /// Constructor
979    pub fn from_token(ty: YYCODETYPE, token: Token) -> Self {
980        Self(from_token(ty, token))
981    }
982}
983
984// TODO ids (identifier or string)
985
986/// identifier or string or `CROSS` or `FULL` or `INNER` or `LEFT` or `NATURAL` or `OUTER` or `RIGHT`.
987#[derive(Clone, Debug, Eq)]
988pub struct Name(pub String); // TODO distinction between Name and "Name"/[Name]/`Name`
989
990impl Name {
991    /// Constructor
992    pub fn from_token(ty: YYCODETYPE, token: Token) -> Self {
993        Self(from_token(ty, token))
994    }
995
996    fn as_bytes(&self) -> QuotedIterator<'_> {
997        if self.0.is_empty() {
998            return QuotedIterator(self.0.bytes(), 0);
999        }
1000        let bytes = self.0.as_bytes();
1001        let mut quote = bytes[0];
1002        if quote != b'"' && quote != b'`' && quote != b'\'' && quote != b'[' {
1003            return QuotedIterator(self.0.bytes(), 0);
1004        } else if quote == b'[' {
1005            quote = b']';
1006        }
1007        debug_assert!(bytes.len() > 1);
1008        debug_assert_eq!(quote, bytes[bytes.len() - 1]);
1009        let sub = &self.0.as_str()[1..bytes.len() - 1];
1010        if quote == b']' {
1011            return QuotedIterator(sub.bytes(), 0); // no escape
1012        }
1013        QuotedIterator(sub.bytes(), quote)
1014    }
1015}
1016
1017struct QuotedIterator<'s>(Bytes<'s>, u8);
1018impl Iterator for QuotedIterator<'_> {
1019    type Item = u8;
1020
1021    fn next(&mut self) -> Option<u8> {
1022        match self.0.next() {
1023            x @ Some(b) => {
1024                if b == self.1 && self.0.next() != Some(self.1) {
1025                    panic!("Malformed string literal: {:?}", self.0);
1026                }
1027                x
1028            }
1029            x => x,
1030        }
1031    }
1032
1033    fn size_hint(&self) -> (usize, Option<usize>) {
1034        if self.1 == 0 {
1035            return self.0.size_hint();
1036        }
1037        (0, None)
1038    }
1039}
1040
1041fn eq_ignore_case_and_quote(mut it: QuotedIterator<'_>, mut other: QuotedIterator<'_>) -> bool {
1042    loop {
1043        match (it.next(), other.next()) {
1044            (Some(b1), Some(b2)) => {
1045                if !b1.eq_ignore_ascii_case(&b2) {
1046                    return false;
1047                }
1048            }
1049            (None, None) => break,
1050            _ => return false,
1051        }
1052    }
1053    true
1054}
1055
1056/// Ignore case and quote
1057impl std::hash::Hash for Name {
1058    fn hash<H: std::hash::Hasher>(&self, hasher: &mut H) {
1059        self.as_bytes()
1060            .for_each(|b| hasher.write_u8(b.to_ascii_lowercase()));
1061    }
1062}
1063/// Ignore case and quote
1064impl PartialEq for Name {
1065    fn eq(&self, other: &Self) -> bool {
1066        eq_ignore_case_and_quote(self.as_bytes(), other.as_bytes())
1067    }
1068}
1069/// Ignore case and quote
1070impl PartialEq<str> for Name {
1071    fn eq(&self, other: &str) -> bool {
1072        eq_ignore_case_and_quote(self.as_bytes(), QuotedIterator(other.bytes(), 0u8))
1073    }
1074}
1075/// Ignore case and quote
1076impl PartialEq<&str> for Name {
1077    fn eq(&self, other: &&str) -> bool {
1078        eq_ignore_case_and_quote(self.as_bytes(), QuotedIterator(other.bytes(), 0u8))
1079    }
1080}
1081
1082/// Qualified name
1083#[derive(Clone, Debug, PartialEq, Eq)]
1084pub struct QualifiedName {
1085    /// schema
1086    pub db_name: Option<Name>,
1087    /// object name
1088    pub name: Name,
1089    /// alias
1090    pub alias: Option<Name>, // FIXME restrict alias usage (fullname vs xfullname)
1091}
1092
1093impl QualifiedName {
1094    /// Constructor
1095    pub fn single(name: Name) -> Self {
1096        Self {
1097            db_name: None,
1098            name,
1099            alias: None,
1100        }
1101    }
1102    /// Constructor
1103    pub fn fullname(db_name: Name, name: Name) -> Self {
1104        Self {
1105            db_name: Some(db_name),
1106            name,
1107            alias: None,
1108        }
1109    }
1110    /// Constructor
1111    pub fn xfullname(db_name: Name, name: Name, alias: Name) -> Self {
1112        Self {
1113            db_name: Some(db_name),
1114            name,
1115            alias: Some(alias),
1116        }
1117    }
1118    /// Constructor
1119    pub fn alias(name: Name, alias: Name) -> Self {
1120        Self {
1121            db_name: None,
1122            name,
1123            alias: Some(alias),
1124        }
1125    }
1126}
1127
1128/// Ordered set of distinct column names
1129#[derive(Clone, Debug, PartialEq, Eq)]
1130pub struct DistinctNames(IndexSet<Name>);
1131
1132impl DistinctNames {
1133    /// Initialize
1134    pub fn new(name: Name) -> Self {
1135        let mut dn = Self(IndexSet::new());
1136        dn.0.insert(name);
1137        dn
1138    }
1139    /// Single column name
1140    pub fn single(name: Name) -> Self {
1141        let mut dn = Self(IndexSet::with_capacity(1));
1142        dn.0.insert(name);
1143        dn
1144    }
1145    /// Push a distinct name or fail
1146    pub fn insert(&mut self, name: Name) -> Result<(), ParserError> {
1147        if self.0.contains(&name) {
1148            return Err(custom_err!("column \"{}\" specified more than once", name));
1149        }
1150        self.0.insert(name);
1151        Ok(())
1152    }
1153}
1154impl Deref for DistinctNames {
1155    type Target = IndexSet<Name>;
1156
1157    fn deref(&self) -> &IndexSet<Name> {
1158        &self.0
1159    }
1160}
1161
1162/// `ALTER TABLE` body
1163// https://sqlite.org/lang_altertable.html
1164#[derive(Clone, Debug, PartialEq, Eq)]
1165pub enum AlterTableBody {
1166    /// `RENAME TO`: new table name
1167    RenameTo(Name),
1168    /// `ADD COLUMN`
1169    AddColumn(ColumnDefinition), // TODO distinction between ADD and ADD COLUMN
1170    /// `RENAME COLUMN`
1171    RenameColumn {
1172        /// old name
1173        old: Name,
1174        /// new name
1175        new: Name,
1176    },
1177    /// `DROP COLUMN`
1178    DropColumn(Name), // TODO distinction between DROP and DROP COLUMN
1179}
1180
1181/// `CREATE TABLE` body
1182// https://sqlite.org/lang_createtable.html
1183// https://sqlite.org/syntax/create-table-stmt.html
1184#[derive(Clone, Debug, PartialEq, Eq)]
1185pub enum CreateTableBody {
1186    /// columns and constraints
1187    ColumnsAndConstraints {
1188        /// table column definitions
1189        columns: IndexMap<Name, ColumnDefinition>,
1190        /// table constraints
1191        constraints: Option<Vec<NamedTableConstraint>>,
1192        /// table options
1193        options: TableOptions,
1194    },
1195    /// `AS` select
1196    AsSelect(Box<Select>),
1197}
1198
1199impl CreateTableBody {
1200    /// Constructor
1201    pub fn columns_and_constraints(
1202        columns: IndexMap<Name, ColumnDefinition>,
1203        constraints: Option<Vec<NamedTableConstraint>>,
1204        options: TableOptions,
1205    ) -> Result<Self, ParserError> {
1206        Ok(Self::ColumnsAndConstraints {
1207            columns,
1208            constraints,
1209            options,
1210        })
1211    }
1212}
1213
1214/// Table column definition
1215// https://sqlite.org/syntax/column-def.html
1216#[derive(Clone, Debug, PartialEq, Eq)]
1217pub struct ColumnDefinition {
1218    /// column name
1219    pub col_name: Name,
1220    /// column type
1221    pub col_type: Option<Type>,
1222    /// column constraints
1223    pub constraints: Vec<NamedColumnConstraint>,
1224}
1225
1226impl ColumnDefinition {
1227    /// Constructor
1228    pub fn add_column(columns: &mut IndexMap<Name, Self>, mut cd: Self) -> Result<(), ParserError> {
1229        let col_name = &cd.col_name;
1230        if columns.contains_key(col_name) {
1231            // TODO unquote
1232            return Err(custom_err!("duplicate column name: {}", col_name));
1233        }
1234        // https://github.com/sqlite/sqlite/blob/e452bf40a14aca57fd9047b330dff282f3e4bbcc/src/build.c#L1511-L1514
1235        if let Some(ref mut col_type) = cd.col_type {
1236            let mut split = col_type.name.split_ascii_whitespace();
1237            let truncate = if split
1238                .next_back()
1239                .is_some_and(|s| s.eq_ignore_ascii_case("ALWAYS"))
1240                && split
1241                    .next_back()
1242                    .is_some_and(|s| s.eq_ignore_ascii_case("GENERATED"))
1243            {
1244                let mut generated = false;
1245                for constraint in &cd.constraints {
1246                    if let ColumnConstraint::Generated { .. } = constraint.constraint {
1247                        generated = true;
1248                        break;
1249                    }
1250                }
1251                generated
1252            } else {
1253                false
1254            };
1255            if truncate {
1256                // str_split_whitespace_remainder
1257                let new_type: Vec<&str> = split.collect();
1258                col_type.name = new_type.join(" ");
1259            }
1260        }
1261        for constraint in &cd.constraints {
1262            if let ColumnConstraint::ForeignKey {
1263                clause:
1264                    ForeignKeyClause {
1265                        tbl_name, columns, ..
1266                    },
1267                ..
1268            } = &constraint.constraint
1269            {
1270                // The child table may reference the primary key of the parent without specifying the primary key column
1271                if columns.as_ref().map_or(0, Vec::len) > 1 {
1272                    return Err(custom_err!(
1273                        "foreign key on {} should reference only one column of table {}",
1274                        col_name,
1275                        tbl_name
1276                    ));
1277                }
1278            }
1279        }
1280        columns.insert(col_name.clone(), cd);
1281        Ok(())
1282    }
1283}
1284
1285/// Named column constraint
1286// https://sqlite.org/syntax/column-constraint.html
1287#[derive(Clone, Debug, PartialEq, Eq)]
1288pub struct NamedColumnConstraint {
1289    /// constraint name
1290    pub name: Option<Name>,
1291    /// constraint
1292    pub constraint: ColumnConstraint,
1293}
1294
1295/// Column constraint
1296// https://sqlite.org/syntax/column-constraint.html
1297#[derive(Clone, Debug, PartialEq, Eq)]
1298pub enum ColumnConstraint {
1299    /// `PRIMARY KEY`
1300    PrimaryKey {
1301        /// `ASC` / `DESC`
1302        order: Option<SortOrder>,
1303        /// `ON CONFLICT` clause
1304        conflict_clause: Option<ResolveType>,
1305        /// `AUTOINCREMENT`
1306        auto_increment: bool,
1307    },
1308    /// `NULL`
1309    NotNull {
1310        /// `NOT`
1311        nullable: bool,
1312        /// `ON CONFLICT` clause
1313        conflict_clause: Option<ResolveType>,
1314    },
1315    /// `UNIQUE`
1316    Unique(Option<ResolveType>),
1317    /// `CHECK`
1318    Check(Expr),
1319    /// `DEFAULT`
1320    Default(Expr),
1321    /// `DEFERRABLE`
1322    Defer(DeferSubclause), // FIXME
1323    /// `COLLATE`
1324    Collate {
1325        /// collation name
1326        collation_name: Name, // FIXME Ids
1327    },
1328    /// `REFERENCES` foreign-key clause
1329    ForeignKey {
1330        /// clause
1331        clause: ForeignKeyClause,
1332        /// `DEFERRABLE`
1333        deref_clause: Option<DeferSubclause>,
1334    },
1335    /// `GENERATED`
1336    Generated {
1337        /// expression
1338        expr: Expr,
1339        /// `STORED` / `VIRTUAL`
1340        typ: Option<Id>,
1341    },
1342}
1343
1344/// Named table constraint
1345// https://sqlite.org/syntax/table-constraint.html
1346#[derive(Clone, Debug, PartialEq, Eq)]
1347pub struct NamedTableConstraint {
1348    /// constraint name
1349    pub name: Option<Name>,
1350    /// constraint
1351    pub constraint: TableConstraint,
1352}
1353
1354/// Table constraint
1355// https://sqlite.org/syntax/table-constraint.html
1356#[derive(Clone, Debug, PartialEq, Eq)]
1357pub enum TableConstraint {
1358    /// `PRIMARY KEY`
1359    PrimaryKey {
1360        /// columns
1361        columns: Vec<SortedColumn>,
1362        /// `AUTOINCREMENT`
1363        auto_increment: bool,
1364        /// `ON CONFLICT` clause
1365        conflict_clause: Option<ResolveType>,
1366    },
1367    /// `UNIQUE`
1368    Unique {
1369        /// columns
1370        columns: Vec<SortedColumn>,
1371        /// `ON CONFLICT` clause
1372        conflict_clause: Option<ResolveType>,
1373    },
1374    /// `CHECK`
1375    Check(Expr),
1376    /// `FOREIGN KEY`
1377    ForeignKey {
1378        /// columns
1379        columns: Vec<IndexedColumn>,
1380        /// `REFERENCES`
1381        clause: ForeignKeyClause,
1382        /// `DEFERRABLE`
1383        deref_clause: Option<DeferSubclause>,
1384    },
1385}
1386
1387bitflags::bitflags! {
1388    /// `CREATE TABLE` options
1389    #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
1390    pub struct TableOptions: u8 {
1391        /// None
1392        const NONE = 0;
1393        /// `WITHOUT ROWID`
1394        const WITHOUT_ROWID = 1;
1395        /// `STRICT`
1396        const STRICT = 2;
1397    }
1398}
1399
1400/// Sort orders
1401#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1402pub enum SortOrder {
1403    /// `ASC`
1404    Asc,
1405    /// `DESC`
1406    Desc,
1407}
1408
1409/// `NULLS FIRST` or `NULLS LAST`
1410#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1411pub enum NullsOrder {
1412    /// `NULLS FIRST`
1413    First,
1414    /// `NULLS LAST`
1415    Last,
1416}
1417
1418/// `REFERENCES` clause
1419// https://sqlite.org/syntax/foreign-key-clause.html
1420#[derive(Clone, Debug, PartialEq, Eq)]
1421pub struct ForeignKeyClause {
1422    /// foreign table name
1423    pub tbl_name: Name,
1424    /// foreign table columns
1425    pub columns: Option<Vec<IndexedColumn>>,
1426    /// referential action(s) / deferrable option(s)
1427    pub args: Vec<RefArg>,
1428}
1429
1430/// foreign-key reference args
1431#[derive(Clone, Debug, PartialEq, Eq)]
1432pub enum RefArg {
1433    /// `ON DELETE`
1434    OnDelete(RefAct),
1435    /// `ON INSERT`
1436    OnInsert(RefAct),
1437    /// `ON UPDATE`
1438    OnUpdate(RefAct),
1439    /// `MATCH`
1440    Match(Name),
1441}
1442
1443/// foreign-key reference actions
1444#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1445pub enum RefAct {
1446    /// `SET NULL`
1447    SetNull,
1448    /// `SET DEFAULT`
1449    SetDefault,
1450    /// `CASCADE`
1451    Cascade,
1452    /// `RESTRICT`
1453    Restrict,
1454    /// `NO ACTION`
1455    NoAction,
1456}
1457
1458/// foreign-key defer clause
1459#[derive(Clone, Debug, PartialEq, Eq)]
1460pub struct DeferSubclause {
1461    /// `DEFERRABLE`
1462    pub deferrable: bool,
1463    /// `INITIALLY` `DEFERRED` / `IMMEDIATE`
1464    pub init_deferred: Option<InitDeferredPred>,
1465}
1466
1467/// `INITIALLY` `DEFERRED` / `IMMEDIATE`
1468#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1469pub enum InitDeferredPred {
1470    /// `INITIALLY DEFERRED`
1471    InitiallyDeferred,
1472    /// `INITIALLY IMMEDIATE`
1473    InitiallyImmediate, // default
1474}
1475
1476/// Indexed column
1477// https://sqlite.org/syntax/indexed-column.html
1478#[derive(Clone, Debug, PartialEq, Eq)]
1479pub struct IndexedColumn {
1480    /// column name
1481    pub col_name: Name,
1482    /// `COLLATE`
1483    pub collation_name: Option<Name>, // FIXME Ids
1484    /// `ORDER BY`
1485    pub order: Option<SortOrder>,
1486}
1487
1488/// `INDEXED BY` / `NOT INDEXED`
1489#[derive(Clone, Debug, PartialEq, Eq)]
1490pub enum Indexed {
1491    /// `INDEXED BY`: idx name
1492    IndexedBy(Name),
1493    /// `NOT INDEXED`
1494    NotIndexed,
1495}
1496
1497/// Sorted column
1498#[derive(Clone, Debug, PartialEq, Eq)]
1499pub struct SortedColumn {
1500    /// expression
1501    pub expr: Expr,
1502    /// `ASC` / `DESC`
1503    pub order: Option<SortOrder>,
1504    /// `NULLS FIRST` / `NULLS LAST`
1505    pub nulls: Option<NullsOrder>,
1506}
1507
1508/// `LIMIT`
1509#[derive(Clone, Debug, PartialEq, Eq)]
1510pub struct Limit {
1511    /// count
1512    pub expr: Expr,
1513    /// `OFFSET`
1514    pub offset: Option<Expr>, // TODO distinction between LIMIT offset, count and LIMIT count OFFSET offset
1515}
1516
1517/// `INSERT` body
1518// https://sqlite.org/lang_insert.html
1519// https://sqlite.org/syntax/insert-stmt.html
1520#[derive(Clone, Debug, PartialEq, Eq)]
1521pub enum InsertBody {
1522    /// `SELECT` or `VALUES`
1523    Select(Box<Select>, Option<Upsert>),
1524    /// `DEFAULT VALUES`
1525    DefaultValues,
1526}
1527
1528/// `UPDATE ... SET`
1529#[derive(Clone, Debug, PartialEq, Eq)]
1530pub struct Set {
1531    /// column name(s)
1532    pub col_names: DistinctNames,
1533    /// expression
1534    pub expr: Expr,
1535}
1536
1537/// `PRAGMA` body
1538// https://sqlite.org/syntax/pragma-stmt.html
1539#[derive(Clone, Debug, PartialEq, Eq)]
1540pub enum PragmaBody {
1541    /// `=`
1542    Equals(PragmaValue),
1543    /// function call
1544    Call(PragmaValue),
1545}
1546
1547/// `PRAGMA` value
1548// https://sqlite.org/syntax/pragma-value.html
1549pub type PragmaValue = Expr; // TODO
1550
1551/// `CREATE TRIGGER` time
1552#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1553pub enum TriggerTime {
1554    /// `BEFORE`
1555    Before, // default
1556    /// `AFTER`
1557    After,
1558    /// `INSTEAD OF`
1559    InsteadOf,
1560}
1561
1562/// `CREATE TRIGGER` event
1563#[derive(Clone, Debug, PartialEq, Eq)]
1564pub enum TriggerEvent {
1565    /// `DELETE`
1566    Delete,
1567    /// `INSERT`
1568    Insert,
1569    /// `UPDATE`
1570    Update,
1571    /// `UPDATE OF`: col names
1572    UpdateOf(DistinctNames),
1573}
1574
1575/// `CREATE TRIGGER` command
1576// https://sqlite.org/lang_createtrigger.html
1577// https://sqlite.org/syntax/create-trigger-stmt.html
1578#[derive(Clone, Debug, PartialEq, Eq)]
1579pub enum TriggerCmd {
1580    /// `UPDATE`
1581    Update {
1582        /// `OR`
1583        or_conflict: Option<ResolveType>,
1584        /// table name
1585        tbl_name: Name,
1586        /// `SET` assignments
1587        sets: Vec<Set>,
1588        /// `FROM`
1589        from: Option<FromClause>,
1590        /// `WHERE` clause
1591        where_clause: Option<Expr>,
1592    },
1593    /// `INSERT`
1594    Insert {
1595        /// `OR`
1596        or_conflict: Option<ResolveType>,
1597        /// table name
1598        tbl_name: Name,
1599        /// `COLUMNS`
1600        col_names: Option<DistinctNames>,
1601        /// `SELECT` or `VALUES`
1602        select: Box<Select>,
1603        /// `ON CONLICT` clause
1604        upsert: Option<Upsert>,
1605        /// `RETURNING`
1606        returning: Option<Vec<ResultColumn>>,
1607    },
1608    /// `DELETE`
1609    Delete {
1610        /// table name
1611        tbl_name: Name,
1612        /// `WHERE` clause
1613        where_clause: Option<Expr>,
1614    },
1615    /// `SELECT`
1616    Select(Box<Select>),
1617}
1618
1619/// Conflict resolution types
1620#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1621pub enum ResolveType {
1622    /// `ROLLBACK`
1623    Rollback,
1624    /// `ABORT`
1625    Abort, // default
1626    /// `FAIL`
1627    Fail,
1628    /// `IGNORE`
1629    Ignore,
1630    /// `REPLACE`
1631    Replace,
1632}
1633
1634/// `WITH` clause
1635// https://sqlite.org/lang_with.html
1636// https://sqlite.org/syntax/with-clause.html
1637#[derive(Clone, Debug, PartialEq, Eq)]
1638pub struct With {
1639    /// `RECURSIVE`
1640    pub recursive: bool,
1641    /// CTEs
1642    pub ctes: Vec<CommonTableExpr>,
1643}
1644
1645/// CTE materialization
1646#[derive(Clone, Debug, PartialEq, Eq)]
1647pub enum Materialized {
1648    /// No hint
1649    Any,
1650    /// `MATERIALIZED`
1651    Yes,
1652    /// `NOT MATERIALIZED`
1653    No,
1654}
1655
1656/// CTE
1657// https://sqlite.org/syntax/common-table-expression.html
1658#[derive(Clone, Debug, PartialEq, Eq)]
1659pub struct CommonTableExpr {
1660    /// table name
1661    pub tbl_name: Name,
1662    /// table columns
1663    pub columns: Option<Vec<IndexedColumn>>, // check no duplicate
1664    /// `MATERIALIZED`
1665    pub materialized: Materialized,
1666    /// query
1667    pub select: Box<Select>,
1668}
1669
1670impl CommonTableExpr {
1671    /// Constructor
1672    pub fn add_cte(ctes: &mut Vec<Self>, cte: Self) -> Result<(), ParserError> {
1673        if ctes.iter().any(|c| c.tbl_name == cte.tbl_name) {
1674            return Err(custom_err!("duplicate WITH table name: {}", cte.tbl_name));
1675        }
1676        ctes.push(cte);
1677        Ok(())
1678    }
1679}
1680
1681/// Column type
1682// https://sqlite.org/syntax/type-name.html
1683#[derive(Clone, Debug, PartialEq, Eq)]
1684pub struct Type {
1685    /// type name
1686    pub name: String, // TODO Validate: Ids+
1687    /// type size
1688    pub size: Option<TypeSize>,
1689}
1690
1691/// Column type size limit(s)
1692// https://sqlite.org/syntax/type-name.html
1693#[derive(Clone, Debug, PartialEq, Eq)]
1694pub enum TypeSize {
1695    /// maximum size
1696    MaxSize(Box<Expr>),
1697    /// precision
1698    TypeSize(Box<Expr>, Box<Expr>),
1699}
1700
1701/// Transaction types
1702#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1703pub enum TransactionType {
1704    /// `DEFERRED`
1705    Deferred, // default
1706    /// `IMMEDIATE`
1707    Immediate,
1708    /// `EXCLUSIVE`
1709    Exclusive,
1710}
1711
1712/// Upsert clause
1713// https://sqlite.org/lang_upsert.html
1714// https://sqlite.org/syntax/upsert-clause.html
1715#[derive(Clone, Debug, PartialEq, Eq)]
1716pub struct Upsert {
1717    /// conflict targets
1718    pub index: Option<UpsertIndex>,
1719    /// `DO` clause
1720    pub do_clause: UpsertDo,
1721    /// next upsert
1722    pub next: Option<Box<Upsert>>,
1723}
1724
1725/// Upsert conflict targets
1726#[derive(Clone, Debug, PartialEq, Eq)]
1727pub struct UpsertIndex {
1728    /// columns
1729    pub targets: Vec<SortedColumn>,
1730    /// `WHERE` clause
1731    pub where_clause: Option<Expr>,
1732}
1733
1734/// Upsert `DO` action
1735#[derive(Clone, Debug, PartialEq, Eq)]
1736pub enum UpsertDo {
1737    /// `SET`
1738    Set {
1739        /// assignments
1740        sets: Vec<Set>,
1741        /// `WHERE` clause
1742        where_clause: Option<Expr>,
1743    },
1744    /// `NOTHING`
1745    Nothing,
1746}
1747
1748/// Function call tail
1749#[derive(Clone, Debug, PartialEq, Eq)]
1750pub struct FunctionTail {
1751    /// `FILTER` clause
1752    pub filter_clause: Option<Box<Expr>>,
1753    /// `OVER` clause
1754    pub over_clause: Option<Box<Over>>,
1755}
1756
1757/// Function call `OVER` clause
1758// https://sqlite.org/syntax/over-clause.html
1759#[derive(Clone, Debug, PartialEq, Eq)]
1760pub enum Over {
1761    /// Window definition
1762    Window(Window),
1763    /// Window name
1764    Name(Name),
1765}
1766
1767/// `OVER` window definition
1768#[derive(Clone, Debug, PartialEq, Eq)]
1769pub struct WindowDef {
1770    /// window name
1771    pub name: Name,
1772    /// window definition
1773    pub window: Window,
1774}
1775
1776/// Window definition
1777// https://sqlite.org/syntax/window-defn.html
1778#[derive(Clone, Debug, PartialEq, Eq)]
1779pub struct Window {
1780    /// base window name
1781    pub base: Option<Name>,
1782    /// `PARTITION BY`
1783    pub partition_by: Option<Vec<Expr>>,
1784    /// `ORDER BY`
1785    pub order_by: Option<Vec<SortedColumn>>,
1786    /// frame spec
1787    pub frame_clause: Option<FrameClause>,
1788}
1789
1790/// Frame specification
1791// https://sqlite.org/syntax/frame-spec.html
1792#[derive(Clone, Debug, PartialEq, Eq)]
1793pub struct FrameClause {
1794    /// unit
1795    pub mode: FrameMode,
1796    /// start bound
1797    pub start: FrameBound,
1798    /// end bound
1799    pub end: Option<FrameBound>,
1800    /// `EXCLUDE`
1801    pub exclude: Option<FrameExclude>,
1802}
1803
1804/// Frame modes
1805#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1806pub enum FrameMode {
1807    /// `GROUPS`
1808    Groups,
1809    /// `RANGE`
1810    Range,
1811    /// `ROWS`
1812    Rows,
1813}
1814
1815/// Frame bounds
1816#[derive(Clone, Debug, PartialEq, Eq)]
1817pub enum FrameBound {
1818    /// `CURRENT ROW`
1819    CurrentRow,
1820    /// `FOLLOWING`
1821    Following(Expr),
1822    /// `PRECEDING`
1823    Preceding(Expr),
1824    /// `UNBOUNDED FOLLOWING`
1825    UnboundedFollowing,
1826    /// `UNBOUNDED PRECEDING`
1827    UnboundedPreceding,
1828}
1829
1830/// Frame exclusions
1831#[derive(Clone, Debug, PartialEq, Eq)]
1832pub enum FrameExclude {
1833    /// `NO OTHERS`
1834    NoOthers,
1835    /// `CURRENT ROW`
1836    CurrentRow,
1837    /// `GROUP`
1838    Group,
1839    /// `TIES`
1840    Ties,
1841}
1842
1843#[cfg(test)]
1844mod test {
1845    use super::Name;
1846
1847    #[test]
1848    fn test_dequote() {
1849        assert_eq!(name("x"), "x");
1850        assert_eq!(name("`x`"), "x");
1851        assert_eq!(name("`x``y`"), "x`y");
1852        assert_eq!(name(r#""x""#), "x");
1853        assert_eq!(name(r#""x""y""#), "x\"y");
1854        assert_eq!(name("[x]"), "x");
1855    }
1856
1857    fn name(s: &'static str) -> Name {
1858        Name(s.to_owned())
1859    }
1860}