Skip to main content

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