sqlite3_parser/parser/ast/
mod.rs

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