libsql_sqlite3_parser/parser/ast/
mod.rs

1//! Abstract Syntax Tree
2
3use std::fmt::{self, Display, Formatter, Write};
4use std::num::ParseIntError;
5use std::str::FromStr;
6
7use indexmap::IndexSet;
8
9use crate::dialect::TokenType::{self, *};
10use crate::dialect::{from_token, is_identifier, Token};
11use crate::parser::{parse::YYCODETYPE, ParserError};
12
13struct FmtTokenStream<'a, 'b> {
14    f: &'a mut Formatter<'b>,
15    spaced: bool,
16}
17impl<'a, 'b> TokenStream for FmtTokenStream<'a, 'b> {
18    type Error = fmt::Error;
19
20    fn append(&mut self, ty: TokenType, value: Option<&str>) -> fmt::Result {
21        if !self.spaced {
22            match ty {
23                TK_COMMA | TK_SEMI | TK_RP | TK_DOT => {}
24                _ => {
25                    self.f.write_char(' ')?;
26                    self.spaced = true;
27                }
28            };
29        }
30        if ty == TK_BLOB {
31            self.f.write_char('X')?;
32            self.f.write_char('\'')?;
33            if let Some(str) = value {
34                self.f.write_str(str)?;
35            }
36            return self.f.write_char('\'');
37        } else if let Some(str) = ty.as_str() {
38            self.f.write_str(str)?;
39            self.spaced = ty == TK_LP || ty == TK_DOT; // str should not be whitespace
40        }
41        if let Some(str) = value {
42            // trick for pretty-print
43            self.spaced = str.bytes().all(|b| b.is_ascii_whitespace());
44            /*if !self.spaced {
45                self.f.write_char(' ')?;
46            }*/
47            self.f.write_str(str)
48        } else {
49            Ok(())
50        }
51    }
52}
53
54#[derive(Default)]
55pub struct ParameterInfo {
56    pub count: u32,
57    pub names: IndexSet<String>,
58}
59
60// https://sqlite.org/lang_expr.html#parameters
61impl TokenStream for ParameterInfo {
62    type Error = ParseIntError;
63
64    fn append(&mut self, ty: TokenType, value: Option<&str>) -> Result<(), Self::Error> {
65        if ty == TK_VARIABLE {
66            if let Some(variable) = value {
67                if variable == "?" {
68                    self.count = self.count.saturating_add(1);
69                } else if variable.as_bytes()[0] == b'?' {
70                    let n = u32::from_str(&variable[1..])?;
71                    if n > self.count {
72                        self.count = n;
73                    }
74                } else if self.names.insert(variable.to_owned()) {
75                    self.count = self.count.saturating_add(1);
76                }
77            }
78        }
79        Ok(())
80    }
81}
82
83pub trait TokenStream {
84    type Error;
85
86    fn append(&mut self, ty: TokenType, value: Option<&str>) -> Result<(), Self::Error>;
87}
88
89pub trait ToTokens {
90    fn to_tokens<S: TokenStream>(&self, s: &mut S) -> Result<(), S::Error>;
91
92    fn to_fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
93        let mut s = FmtTokenStream { f, spaced: true };
94        self.to_tokens(&mut s)
95    }
96}
97
98impl<T: ?Sized + ToTokens> ToTokens for &T {
99    fn to_tokens<S: TokenStream>(&self, s: &mut S) -> Result<(), S::Error> {
100        ToTokens::to_tokens(&**self, s)
101    }
102}
103
104impl ToTokens for String {
105    fn to_tokens<S: TokenStream>(&self, s: &mut S) -> Result<(), S::Error> {
106        s.append(TK_ANY, Some(self.as_ref()))
107    }
108}
109
110/* FIXME: does not work, find why
111impl Display for dyn ToTokens {
112    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
113        let mut s = FmtTokenStream { f, spaced: true };
114        match self.to_tokens(&mut s) {
115            Err(_) => Err(fmt::Error),
116            Ok(()) => Ok(()),
117        }
118    }
119}
120*/
121
122// https://sqlite.org/syntax/sql-stmt.html
123#[derive(Clone, Debug, PartialEq, Eq)]
124pub enum Cmd {
125    Explain(Stmt),
126    ExplainQueryPlan(Stmt),
127    Stmt(Stmt),
128}
129
130impl ToTokens for Cmd {
131    fn to_tokens<S: TokenStream>(&self, s: &mut S) -> Result<(), S::Error> {
132        match self {
133            Cmd::Explain(stmt) => {
134                s.append(TK_EXPLAIN, None)?;
135                stmt.to_tokens(s)?;
136            }
137            Cmd::ExplainQueryPlan(stmt) => {
138                s.append(TK_EXPLAIN, None)?;
139                s.append(TK_QUERY, None)?;
140                s.append(TK_PLAN, None)?;
141                stmt.to_tokens(s)?;
142            }
143            Cmd::Stmt(stmt) => {
144                stmt.to_tokens(s)?;
145            }
146        }
147        s.append(TK_SEMI, None)
148    }
149}
150
151impl Display for Cmd {
152    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
153        self.to_fmt(f)
154    }
155}
156
157pub(crate) enum ExplainKind {
158    Explain,
159    QueryPlan,
160}
161
162// https://sqlite.org/syntax/sql-stmt.html
163#[derive(Clone, Debug, PartialEq, Eq)]
164pub enum Stmt {
165    // table name, body
166    AlterTable(QualifiedName, AlterTableBody),
167    // object name
168    Analyze(Option<QualifiedName>),
169    Attach {
170        // TODO distinction between ATTACH and ATTACH DATABASE
171        expr: Expr,
172        db_name: Expr,
173        key: Option<Expr>,
174    },
175    // tx type, tx name
176    Begin(Option<TransactionType>, Option<Name>),
177    // tx name
178    Commit(Option<Name>), // TODO distinction between COMMIT and END
179    CreateIndex {
180        unique: bool,
181        if_not_exists: bool,
182        idx_name: QualifiedName,
183        tbl_name: Name,
184        columns: Vec<SortedColumn>,
185        where_clause: Option<Expr>,
186    },
187    CreateTable {
188        temporary: bool, // TODO distinction between TEMP and TEMPORARY
189        if_not_exists: bool,
190        tbl_name: QualifiedName,
191        body: CreateTableBody,
192    },
193    CreateTrigger {
194        temporary: bool,
195        if_not_exists: bool,
196        trigger_name: QualifiedName,
197        time: Option<TriggerTime>,
198        event: TriggerEvent,
199        tbl_name: QualifiedName,
200        for_each_row: bool,
201        when_clause: Option<Expr>,
202        commands: Vec<TriggerCmd>,
203    },
204    CreateView {
205        temporary: bool,
206        if_not_exists: bool,
207        view_name: QualifiedName,
208        columns: Option<Vec<IndexedColumn>>,
209        select: Select,
210    },
211    CreateVirtualTable {
212        if_not_exists: bool,
213        tbl_name: QualifiedName,
214        module_name: Name,
215        args: Option<Vec<String>>, // TODO smol str
216    },
217    Delete {
218        with: Option<With>,
219        tbl_name: QualifiedName,
220        indexed: Option<Indexed>,
221        where_clause: Option<Expr>,
222        returning: Option<Vec<ResultColumn>>,
223        order_by: Option<Vec<SortedColumn>>,
224        limit: Option<Limit>,
225    },
226    // db name
227    Detach(Expr), // TODO distinction between DETACH and DETACH DATABASE
228    DropIndex {
229        if_exists: bool,
230        idx_name: QualifiedName,
231    },
232    DropTable {
233        if_exists: bool,
234        tbl_name: QualifiedName,
235    },
236    DropTrigger {
237        if_exists: bool,
238        trigger_name: QualifiedName,
239    },
240    DropView {
241        if_exists: bool,
242        view_name: QualifiedName,
243    },
244    Insert {
245        with: Option<With>,
246        or_conflict: Option<ResolveType>, // TODO distinction between REPLACE and INSERT OR REPLACE
247        tbl_name: QualifiedName,
248        columns: Option<Vec<Name>>,
249        body: InsertBody,
250        returning: Option<Vec<ResultColumn>>,
251    },
252    // pragma name, body
253    Pragma(QualifiedName, Option<PragmaBody>),
254    Reindex {
255        obj_name: Option<QualifiedName>,
256    },
257    // savepoint name
258    Release(Name), // TODO distinction between RELEASE and RELEASE SAVEPOINT
259    Rollback {
260        tx_name: Option<Name>,
261        savepoint_name: Option<Name>, // TODO distinction between TO and TO SAVEPOINT
262    },
263    // savepoint name
264    Savepoint(Name),
265    Select(Select),
266    Update {
267        with: Option<With>,
268        or_conflict: Option<ResolveType>,
269        tbl_name: QualifiedName,
270        indexed: Option<Indexed>,
271        sets: Vec<Set>,
272        from: Option<FromClause>,
273        where_clause: Option<Expr>,
274        returning: Option<Vec<ResultColumn>>,
275        order_by: Option<Vec<SortedColumn>>,
276        limit: Option<Limit>,
277    },
278    // database name, into expr
279    Vacuum(Option<Name>, Option<Expr>),
280}
281
282impl ToTokens for Stmt {
283    fn to_tokens<S: TokenStream>(&self, s: &mut S) -> Result<(), S::Error> {
284        match self {
285            Stmt::AlterTable(tbl_name, body) => {
286                s.append(TK_ALTER, None)?;
287                s.append(TK_TABLE, None)?;
288                tbl_name.to_tokens(s)?;
289                body.to_tokens(s)
290            }
291            Stmt::Analyze(obj_name) => {
292                s.append(TK_ANALYZE, None)?;
293                if let Some(obj_name) = obj_name {
294                    obj_name.to_tokens(s)?;
295                }
296                Ok(())
297            }
298            Stmt::Attach { expr, db_name, key } => {
299                s.append(TK_ATTACH, None)?;
300                expr.to_tokens(s)?;
301                s.append(TK_AS, None)?;
302                db_name.to_tokens(s)?;
303                if let Some(key) = key {
304                    s.append(TK_KEY, None)?;
305                    key.to_tokens(s)?;
306                }
307                Ok(())
308            }
309            Stmt::Begin(tx_type, tx_name) => {
310                s.append(TK_BEGIN, None)?;
311                if let Some(tx_type) = tx_type {
312                    tx_type.to_tokens(s)?;
313                }
314                if let Some(tx_name) = tx_name {
315                    s.append(TK_TRANSACTION, None)?;
316                    tx_name.to_tokens(s)?;
317                }
318                Ok(())
319            }
320            Stmt::Commit(tx_name) => {
321                s.append(TK_COMMIT, None)?;
322                if let Some(tx_name) = tx_name {
323                    s.append(TK_TRANSACTION, None)?;
324                    tx_name.to_tokens(s)?;
325                }
326                Ok(())
327            }
328            Stmt::CreateIndex {
329                unique,
330                if_not_exists,
331                idx_name,
332                tbl_name,
333                columns,
334                where_clause,
335            } => {
336                s.append(TK_CREATE, None)?;
337                if *unique {
338                    s.append(TK_UNIQUE, None)?;
339                }
340                s.append(TK_INDEX, None)?;
341                if *if_not_exists {
342                    s.append(TK_IF, None)?;
343                    s.append(TK_NOT, None)?;
344                    s.append(TK_EXISTS, None)?;
345                }
346                idx_name.to_tokens(s)?;
347                s.append(TK_ON, None)?;
348                tbl_name.to_tokens(s)?;
349                s.append(TK_LP, None)?;
350                comma(columns, s)?;
351                s.append(TK_RP, None)?;
352                if let Some(where_clause) = where_clause {
353                    s.append(TK_WHERE, None)?;
354                    where_clause.to_tokens(s)?;
355                }
356                Ok(())
357            }
358            Stmt::CreateTable {
359                temporary,
360                if_not_exists,
361                tbl_name,
362                body,
363            } => {
364                s.append(TK_CREATE, None)?;
365                if *temporary {
366                    s.append(TK_TEMP, None)?;
367                }
368                s.append(TK_TABLE, None)?;
369                if *if_not_exists {
370                    s.append(TK_IF, None)?;
371                    s.append(TK_NOT, None)?;
372                    s.append(TK_EXISTS, None)?;
373                }
374                tbl_name.to_tokens(s)?;
375                body.to_tokens(s)
376            }
377            Stmt::CreateTrigger {
378                temporary,
379                if_not_exists,
380                trigger_name,
381                time,
382                event,
383                tbl_name,
384                for_each_row,
385                when_clause,
386                commands,
387            } => {
388                s.append(TK_CREATE, None)?;
389                if *temporary {
390                    s.append(TK_TEMP, None)?;
391                }
392                s.append(TK_TRIGGER, None)?;
393                if *if_not_exists {
394                    s.append(TK_IF, None)?;
395                    s.append(TK_NOT, None)?;
396                    s.append(TK_EXISTS, None)?;
397                }
398                trigger_name.to_tokens(s)?;
399                if let Some(time) = time {
400                    time.to_tokens(s)?;
401                }
402                event.to_tokens(s)?;
403                s.append(TK_ON, None)?;
404                tbl_name.to_tokens(s)?;
405                if *for_each_row {
406                    s.append(TK_FOR, None)?;
407                    s.append(TK_EACH, None)?;
408                    s.append(TK_ROW, None)?;
409                }
410                if let Some(when_clause) = when_clause {
411                    s.append(TK_WHEN, None)?;
412                    when_clause.to_tokens(s)?;
413                }
414                s.append(TK_BEGIN, Some("\n"))?;
415                for command in commands {
416                    command.to_tokens(s)?;
417                    s.append(TK_SEMI, Some("\n"))?;
418                }
419                s.append(TK_END, None)
420            }
421            Stmt::CreateView {
422                temporary,
423                if_not_exists,
424                view_name,
425                columns,
426                select,
427            } => {
428                s.append(TK_CREATE, None)?;
429                if *temporary {
430                    s.append(TK_TEMP, None)?;
431                }
432                s.append(TK_VIEW, None)?;
433                if *if_not_exists {
434                    s.append(TK_IF, None)?;
435                    s.append(TK_NOT, None)?;
436                    s.append(TK_EXISTS, None)?;
437                }
438                view_name.to_tokens(s)?;
439                if let Some(columns) = columns {
440                    s.append(TK_LP, None)?;
441                    comma(columns, s)?;
442                    s.append(TK_RP, None)?;
443                }
444                s.append(TK_AS, None)?;
445                select.to_tokens(s)
446            }
447            Stmt::CreateVirtualTable {
448                if_not_exists,
449                tbl_name,
450                module_name,
451                args,
452            } => {
453                s.append(TK_CREATE, None)?;
454                s.append(TK_VIRTUAL, None)?;
455                s.append(TK_TABLE, None)?;
456                if *if_not_exists {
457                    s.append(TK_IF, None)?;
458                    s.append(TK_NOT, None)?;
459                    s.append(TK_EXISTS, None)?;
460                }
461                tbl_name.to_tokens(s)?;
462                s.append(TK_USING, None)?;
463                module_name.to_tokens(s)?;
464                s.append(TK_LP, None)?;
465                if let Some(args) = args {
466                    comma(args, s)?;
467                }
468                s.append(TK_RP, None)
469            }
470            Stmt::Delete {
471                with,
472                tbl_name,
473                indexed,
474                where_clause,
475                returning,
476                order_by,
477                limit,
478            } => {
479                if let Some(with) = with {
480                    with.to_tokens(s)?;
481                }
482                s.append(TK_DELETE, None)?;
483                s.append(TK_FROM, None)?;
484                tbl_name.to_tokens(s)?;
485                if let Some(indexed) = indexed {
486                    indexed.to_tokens(s)?;
487                }
488                if let Some(where_clause) = where_clause {
489                    s.append(TK_WHERE, None)?;
490                    where_clause.to_tokens(s)?;
491                }
492                if let Some(returning) = returning {
493                    s.append(TK_RETURNING, None)?;
494                    comma(returning, s)?;
495                }
496                if let Some(order_by) = order_by {
497                    s.append(TK_ORDER, None)?;
498                    s.append(TK_BY, None)?;
499                    comma(order_by, s)?;
500                }
501                if let Some(limit) = limit {
502                    limit.to_tokens(s)?;
503                }
504                Ok(())
505            }
506            Stmt::Detach(expr) => {
507                s.append(TK_DETACH, None)?;
508                expr.to_tokens(s)
509            }
510            Stmt::DropIndex {
511                if_exists,
512                idx_name,
513            } => {
514                s.append(TK_DROP, None)?;
515                s.append(TK_INDEX, None)?;
516                if *if_exists {
517                    s.append(TK_IF, None)?;
518                    s.append(TK_EXISTS, None)?;
519                }
520                idx_name.to_tokens(s)
521            }
522            Stmt::DropTable {
523                if_exists,
524                tbl_name,
525            } => {
526                s.append(TK_DROP, None)?;
527                s.append(TK_TABLE, None)?;
528                if *if_exists {
529                    s.append(TK_IF, None)?;
530                    s.append(TK_EXISTS, None)?;
531                }
532                tbl_name.to_tokens(s)
533            }
534            Stmt::DropTrigger {
535                if_exists,
536                trigger_name,
537            } => {
538                s.append(TK_DROP, None)?;
539                s.append(TK_TRIGGER, None)?;
540                if *if_exists {
541                    s.append(TK_IF, None)?;
542                    s.append(TK_EXISTS, None)?;
543                }
544                trigger_name.to_tokens(s)
545            }
546            Stmt::DropView {
547                if_exists,
548                view_name,
549            } => {
550                s.append(TK_DROP, None)?;
551                s.append(TK_VIEW, None)?;
552                if *if_exists {
553                    s.append(TK_IF, None)?;
554                    s.append(TK_EXISTS, None)?;
555                }
556                view_name.to_tokens(s)
557            }
558            Stmt::Insert {
559                with,
560                or_conflict,
561                tbl_name,
562                columns,
563                body,
564                returning,
565            } => {
566                if let Some(with) = with {
567                    with.to_tokens(s)?;
568                }
569                if let Some(ResolveType::Replace) = or_conflict {
570                    s.append(TK_REPLACE, None)?;
571                } else {
572                    s.append(TK_INSERT, None)?;
573                    if let Some(or_conflict) = or_conflict {
574                        s.append(TK_OR, None)?;
575                        or_conflict.to_tokens(s)?;
576                    }
577                }
578                s.append(TK_INTO, None)?;
579                tbl_name.to_tokens(s)?;
580                if let Some(columns) = columns {
581                    s.append(TK_LP, None)?;
582                    comma(columns, s)?;
583                    s.append(TK_RP, None)?;
584                }
585                body.to_tokens(s)?;
586                if let Some(returning) = returning {
587                    s.append(TK_RETURNING, None)?;
588                    comma(returning, s)?;
589                }
590                Ok(())
591            }
592            Stmt::Pragma(name, value) => {
593                s.append(TK_PRAGMA, None)?;
594                name.to_tokens(s)?;
595                if let Some(value) = value {
596                    value.to_tokens(s)?;
597                }
598                Ok(())
599            }
600            Stmt::Reindex { obj_name } => {
601                s.append(TK_REINDEX, None)?;
602                if let Some(obj_name) = obj_name {
603                    obj_name.to_tokens(s)?;
604                }
605                Ok(())
606            }
607            Stmt::Release(name) => {
608                s.append(TK_RELEASE, None)?;
609                name.to_tokens(s)
610            }
611            Stmt::Rollback {
612                tx_name,
613                savepoint_name,
614            } => {
615                s.append(TK_ROLLBACK, None)?;
616                if let Some(tx_name) = tx_name {
617                    s.append(TK_TRANSACTION, None)?;
618                    tx_name.to_tokens(s)?;
619                }
620                if let Some(savepoint_name) = savepoint_name {
621                    s.append(TK_TO, None)?;
622                    savepoint_name.to_tokens(s)?;
623                }
624                Ok(())
625            }
626            Stmt::Savepoint(name) => {
627                s.append(TK_SAVEPOINT, None)?;
628                name.to_tokens(s)
629            }
630            Stmt::Select(select) => select.to_tokens(s),
631            Stmt::Update {
632                with,
633                or_conflict,
634                tbl_name,
635                indexed,
636                sets,
637                from,
638                where_clause,
639                returning,
640                order_by,
641                limit,
642            } => {
643                if let Some(with) = with {
644                    with.to_tokens(s)?;
645                }
646                s.append(TK_UPDATE, None)?;
647                if let Some(or_conflict) = or_conflict {
648                    s.append(TK_OR, None)?;
649                    or_conflict.to_tokens(s)?;
650                }
651                tbl_name.to_tokens(s)?;
652                if let Some(indexed) = indexed {
653                    indexed.to_tokens(s)?;
654                }
655                s.append(TK_SET, None)?;
656                comma(sets, s)?;
657                if let Some(from) = from {
658                    s.append(TK_FROM, None)?;
659                    from.to_tokens(s)?;
660                }
661                if let Some(where_clause) = where_clause {
662                    s.append(TK_WHERE, None)?;
663                    where_clause.to_tokens(s)?;
664                }
665                if let Some(returning) = returning {
666                    s.append(TK_RETURNING, None)?;
667                    comma(returning, s)?;
668                }
669                if let Some(order_by) = order_by {
670                    s.append(TK_ORDER, None)?;
671                    s.append(TK_BY, None)?;
672                    comma(order_by, s)?;
673                }
674                if let Some(limit) = limit {
675                    limit.to_tokens(s)?;
676                }
677                Ok(())
678            }
679            Stmt::Vacuum(name, expr) => {
680                s.append(TK_VACUUM, None)?;
681                if let Some(ref name) = name {
682                    name.to_tokens(s)?;
683                }
684                if let Some(ref expr) = expr {
685                    s.append(TK_INTO, None)?;
686                    expr.to_tokens(s)?;
687                }
688                Ok(())
689            }
690        }
691    }
692}
693
694// https://sqlite.org/syntax/expr.html
695#[derive(Clone, Debug, PartialEq, Eq)]
696pub enum Expr {
697    Between {
698        lhs: Box<Expr>,
699        not: bool,
700        start: Box<Expr>,
701        end: Box<Expr>,
702    },
703    Binary(Box<Expr>, Operator, Box<Expr>),
704    // CASE expression
705    Case {
706        base: Option<Box<Expr>>,
707        when_then_pairs: Vec<(Expr, Expr)>,
708        else_expr: Option<Box<Expr>>,
709    },
710    // CAST expression
711    Cast {
712        expr: Box<Expr>,
713        type_name: Type,
714    },
715    // COLLATE expression
716    Collate(Box<Expr>, String),
717    // schema-name.table-name.column-name
718    DoublyQualified(Name, Name, Name),
719    // EXISTS subquery
720    Exists(Box<Select>),
721    // call to a built-in function
722    FunctionCall {
723        name: Id,
724        distinctness: Option<Distinctness>,
725        args: Option<Vec<Expr>>,
726        filter_over: Option<FunctionTail>,
727    },
728    // Function call expression with '*' as arg
729    FunctionCallStar {
730        name: Id,
731        filter_over: Option<FunctionTail>,
732    },
733    // Identifier
734    Id(Id),
735    InList {
736        lhs: Box<Expr>,
737        not: bool,
738        rhs: Option<Vec<Expr>>,
739    },
740    InSelect {
741        lhs: Box<Expr>,
742        not: bool,
743        rhs: Box<Select>,
744    },
745    InTable {
746        lhs: Box<Expr>,
747        not: bool,
748        rhs: QualifiedName,
749        args: Option<Vec<Expr>>,
750    },
751    IsNull(Box<Expr>),
752    Like {
753        lhs: Box<Expr>,
754        not: bool,
755        op: LikeOperator,
756        rhs: Box<Expr>,
757        escape: Option<Box<Expr>>,
758    },
759    // Literal expression
760    Literal(Literal),
761    Name(Name),
762    // "NOT NULL" or "NOTNULL"
763    NotNull(Box<Expr>),
764    // Parenthesized subexpression
765    Parenthesized(Vec<Expr>),
766    Qualified(Name, Name),
767    // RAISE function call
768    Raise(ResolveType, Option<Name>),
769    // Subquery expression
770    Subquery(Box<Select>),
771    // Unary expression
772    Unary(UnaryOperator, Box<Expr>),
773    // Parameters
774    Variable(String),
775}
776
777impl Expr {
778    pub fn parenthesized(x: Expr) -> Expr {
779        Expr::Parenthesized(vec![x])
780    }
781    pub fn id(xt: YYCODETYPE, x: Token) -> Expr {
782        Expr::Id(Id::from_token(xt, x))
783    }
784    pub fn collate(x: Expr, ct: YYCODETYPE, c: Token) -> Expr {
785        Expr::Collate(Box::new(x), from_token(ct, c))
786    }
787    pub fn cast(x: Expr, type_name: Type) -> Expr {
788        Expr::Cast {
789            expr: Box::new(x),
790            type_name,
791        }
792    }
793    pub fn binary(left: Expr, op: YYCODETYPE, right: Expr) -> Expr {
794        Expr::Binary(Box::new(left), Operator::from(op), Box::new(right))
795    }
796    pub fn ptr(left: Expr, op: Token, right: Expr) -> Expr {
797        let mut ptr = Operator::ArrowRight;
798        if let Some(ref op) = op.1 {
799            if op == "->>" {
800                ptr = Operator::ArrowRightShift;
801            }
802        }
803        Expr::Binary(Box::new(left), ptr, Box::new(right))
804    }
805    pub fn like(lhs: Expr, not: bool, op: LikeOperator, rhs: Expr, escape: Option<Expr>) -> Expr {
806        Expr::Like {
807            lhs: Box::new(lhs),
808            not,
809            op,
810            rhs: Box::new(rhs),
811            escape: escape.map(Box::new),
812        }
813    }
814    pub fn not_null(x: Expr, op: YYCODETYPE) -> Expr {
815        if op == TK_ISNULL as YYCODETYPE {
816            Expr::IsNull(Box::new(x))
817        } else if op == TK_NOTNULL as YYCODETYPE {
818            Expr::NotNull(Box::new(x))
819        } else {
820            unreachable!()
821        }
822    }
823    pub fn unary(op: UnaryOperator, x: Expr) -> Expr {
824        Expr::Unary(op, Box::new(x))
825    }
826    pub fn between(lhs: Expr, not: bool, start: Expr, end: Expr) -> Expr {
827        Expr::Between {
828            lhs: Box::new(lhs),
829            not,
830            start: Box::new(start),
831            end: Box::new(end),
832        }
833    }
834    pub fn in_list(lhs: Expr, not: bool, rhs: Option<Vec<Expr>>) -> Expr {
835        Expr::InList {
836            lhs: Box::new(lhs),
837            not,
838            rhs,
839        }
840    }
841    pub fn in_select(lhs: Expr, not: bool, rhs: Select) -> Expr {
842        Expr::InSelect {
843            lhs: Box::new(lhs),
844            not,
845            rhs: Box::new(rhs),
846        }
847    }
848    pub fn in_table(lhs: Expr, not: bool, rhs: QualifiedName, args: Option<Vec<Expr>>) -> Expr {
849        Expr::InTable {
850            lhs: Box::new(lhs),
851            not,
852            rhs,
853            args,
854        }
855    }
856    pub fn sub_query(query: Select) -> Expr {
857        Expr::Subquery(Box::new(query))
858    }
859}
860impl ToTokens for Expr {
861    fn to_tokens<S: TokenStream>(&self, s: &mut S) -> Result<(), S::Error> {
862        match self {
863            Expr::Between {
864                lhs,
865                not,
866                start,
867                end,
868            } => {
869                lhs.to_tokens(s)?;
870                if *not {
871                    s.append(TK_NOT, None)?;
872                }
873                s.append(TK_BETWEEN, None)?;
874                start.to_tokens(s)?;
875                s.append(TK_AND, None)?;
876                end.to_tokens(s)
877            }
878            Expr::Binary(lhs, op, rhs) => {
879                lhs.to_tokens(s)?;
880                op.to_tokens(s)?;
881                rhs.to_tokens(s)
882            }
883            Expr::Case {
884                base,
885                when_then_pairs,
886                else_expr,
887            } => {
888                s.append(TK_CASE, None)?;
889                if let Some(ref base) = base {
890                    base.to_tokens(s)?;
891                }
892                for (when, then) in when_then_pairs {
893                    s.append(TK_WHEN, None)?;
894                    when.to_tokens(s)?;
895                    s.append(TK_THEN, None)?;
896                    then.to_tokens(s)?;
897                }
898                if let Some(ref else_expr) = else_expr {
899                    s.append(TK_ELSE, None)?;
900                    else_expr.to_tokens(s)?;
901                }
902                s.append(TK_END, None)
903            }
904            Expr::Cast { expr, type_name } => {
905                s.append(TK_CAST, None)?;
906                s.append(TK_LP, None)?;
907                expr.to_tokens(s)?;
908                s.append(TK_AS, None)?;
909                type_name.to_tokens(s)?;
910                s.append(TK_RP, None)
911            }
912            Expr::Collate(expr, collation) => {
913                expr.to_tokens(s)?;
914                s.append(TK_COLLATE, None)?;
915                double_quote(collation, s)
916            }
917            Expr::DoublyQualified(db_name, tbl_name, col_name) => {
918                db_name.to_tokens(s)?;
919                s.append(TK_DOT, None)?;
920                tbl_name.to_tokens(s)?;
921                s.append(TK_DOT, None)?;
922                col_name.to_tokens(s)
923            }
924            Expr::Exists(subquery) => {
925                s.append(TK_EXISTS, None)?;
926                s.append(TK_LP, None)?;
927                subquery.to_tokens(s)?;
928                s.append(TK_RP, None)
929            }
930            Expr::FunctionCall {
931                name,
932                distinctness,
933                args,
934                filter_over,
935            } => {
936                name.to_tokens(s)?;
937                s.append(TK_LP, None)?;
938                if let Some(distinctness) = distinctness {
939                    distinctness.to_tokens(s)?;
940                }
941                if let Some(args) = args {
942                    comma(args, s)?;
943                }
944                s.append(TK_RP, None)?;
945                if let Some(filter_over) = filter_over {
946                    filter_over.to_tokens(s)?;
947                }
948                Ok(())
949            }
950            Expr::FunctionCallStar { name, filter_over } => {
951                name.to_tokens(s)?;
952                s.append(TK_LP, None)?;
953                s.append(TK_STAR, None)?;
954                s.append(TK_RP, None)?;
955                if let Some(filter_over) = filter_over {
956                    filter_over.to_tokens(s)?;
957                }
958                Ok(())
959            }
960            Expr::Id(id) => id.to_tokens(s),
961            Expr::InList { lhs, not, rhs } => {
962                lhs.to_tokens(s)?;
963                if *not {
964                    s.append(TK_NOT, None)?;
965                }
966                s.append(TK_IN, None)?;
967                s.append(TK_LP, None)?;
968                if let Some(rhs) = rhs {
969                    comma(rhs, s)?;
970                }
971                s.append(TK_RP, None)
972            }
973            Expr::InSelect { lhs, not, rhs } => {
974                lhs.to_tokens(s)?;
975                if *not {
976                    s.append(TK_NOT, None)?;
977                }
978                s.append(TK_IN, None)?;
979                s.append(TK_LP, None)?;
980                rhs.to_tokens(s)?;
981                s.append(TK_RP, None)
982            }
983            Expr::InTable {
984                lhs,
985                not,
986                rhs,
987                args,
988            } => {
989                lhs.to_tokens(s)?;
990                if *not {
991                    s.append(TK_NOT, None)?;
992                }
993                s.append(TK_IN, None)?;
994                rhs.to_tokens(s)?;
995                if let Some(args) = args {
996                    s.append(TK_LP, None)?;
997                    comma(args, s)?;
998                    s.append(TK_RP, None)?;
999                }
1000                Ok(())
1001            }
1002            Expr::IsNull(sub_expr) => {
1003                sub_expr.to_tokens(s)?;
1004                s.append(TK_ISNULL, None)
1005            }
1006            Expr::Like {
1007                lhs,
1008                not,
1009                op,
1010                rhs,
1011                escape,
1012            } => {
1013                lhs.to_tokens(s)?;
1014                if *not {
1015                    s.append(TK_NOT, None)?;
1016                }
1017                op.to_tokens(s)?;
1018                rhs.to_tokens(s)?;
1019                if let Some(escape) = escape {
1020                    s.append(TK_ESCAPE, None)?;
1021                    escape.to_tokens(s)?;
1022                }
1023                Ok(())
1024            }
1025            Expr::Literal(lit) => lit.to_tokens(s),
1026            Expr::Name(name) => name.to_tokens(s),
1027            Expr::NotNull(sub_expr) => {
1028                sub_expr.to_tokens(s)?;
1029                s.append(TK_NOTNULL, None)
1030            }
1031            Expr::Parenthesized(exprs) => {
1032                s.append(TK_LP, None)?;
1033                comma(exprs, s)?;
1034                s.append(TK_RP, None)
1035            }
1036            Expr::Qualified(qualifier, qualified) => {
1037                qualifier.to_tokens(s)?;
1038                s.append(TK_DOT, None)?;
1039                qualified.to_tokens(s)
1040            }
1041            Expr::Raise(rt, err) => {
1042                s.append(TK_RAISE, None)?;
1043                s.append(TK_LP, None)?;
1044                rt.to_tokens(s)?;
1045                if let Some(err) = err {
1046                    s.append(TK_COMMA, None)?;
1047                    err.to_tokens(s)?;
1048                }
1049                s.append(TK_RP, None)
1050            }
1051            Expr::Subquery(query) => {
1052                s.append(TK_LP, None)?;
1053                query.to_tokens(s)?;
1054                s.append(TK_RP, None)
1055            }
1056            Expr::Unary(op, sub_expr) => {
1057                op.to_tokens(s)?;
1058                sub_expr.to_tokens(s)
1059            }
1060            Expr::Variable(var) => match var.chars().next() {
1061                Some(c) if c == '$' || c == '@' || c == '#' || c == ':' => {
1062                    s.append(TK_VARIABLE, Some(var))
1063                }
1064                Some(_) => s.append(TK_VARIABLE, Some(&("?".to_owned() + var))),
1065                None => s.append(TK_VARIABLE, Some("?")),
1066            },
1067        }
1068    }
1069}
1070
1071impl Display for Expr {
1072    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1073        self.to_fmt(f)
1074    }
1075}
1076
1077#[derive(Clone, Debug, PartialEq, Eq)]
1078pub enum Literal {
1079    Numeric(String),
1080    // TODO Check that string is already quoted and correctly escaped
1081    String(String),
1082    // TODO Check that string is valid (only hexa)
1083    Blob(String),
1084    Keyword(String),
1085    Null,
1086    CurrentDate,
1087    CurrentTime,
1088    CurrentTimestamp,
1089}
1090
1091impl Literal {
1092    pub fn from_ctime_kw(token: Token) -> Literal {
1093        if let Some(ref token) = token.1 {
1094            if "CURRENT_DATE".eq_ignore_ascii_case(token) {
1095                Literal::CurrentDate
1096            } else if "CURRENT_TIME".eq_ignore_ascii_case(token) {
1097                Literal::CurrentTime
1098            } else if "CURRENT_TIMESTAMP".eq_ignore_ascii_case(token) {
1099                Literal::CurrentTimestamp
1100            } else {
1101                unreachable!()
1102            }
1103        } else {
1104            unreachable!()
1105        }
1106    }
1107}
1108impl ToTokens for Literal {
1109    fn to_tokens<S: TokenStream>(&self, s: &mut S) -> Result<(), S::Error> {
1110        match self {
1111            Literal::Numeric(ref num) => s.append(TK_FLOAT, Some(num)), // TODO Validate TK_FLOAT
1112            Literal::String(ref str) => s.append(TK_STRING, Some(str)),
1113            Literal::Blob(ref blob) => s.append(TK_BLOB, Some(blob)),
1114            Literal::Keyword(ref str) => s.append(TK_ID, Some(str)), // TODO Validate TK_ID
1115            Literal::Null => s.append(TK_NULL, None),
1116            Literal::CurrentDate => s.append(TK_CTIME_KW, Some("CURRENT_DATE")),
1117            Literal::CurrentTime => s.append(TK_CTIME_KW, Some("CURRENT_TIME")),
1118            Literal::CurrentTimestamp => s.append(TK_CTIME_KW, Some("CURRENT_TIMESTAMP")),
1119        }
1120    }
1121}
1122
1123#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1124pub enum LikeOperator {
1125    Glob,
1126    Like,
1127    Match,
1128    Regexp,
1129}
1130
1131impl LikeOperator {
1132    pub fn from_token(token_type: YYCODETYPE, token: Token) -> LikeOperator {
1133        if token_type == TK_MATCH as YYCODETYPE {
1134            return LikeOperator::Match;
1135        } else if token_type == TK_LIKE_KW as YYCODETYPE {
1136            if let Some(ref token) = token.1 {
1137                if "LIKE".eq_ignore_ascii_case(token) {
1138                    return LikeOperator::Like;
1139                } else if "GLOB".eq_ignore_ascii_case(token) {
1140                    return LikeOperator::Glob;
1141                } else if "REGEXP".eq_ignore_ascii_case(token) {
1142                    return LikeOperator::Regexp;
1143                }
1144            }
1145        }
1146        unreachable!()
1147    }
1148}
1149impl ToTokens for LikeOperator {
1150    fn to_tokens<S: TokenStream>(&self, s: &mut S) -> Result<(), S::Error> {
1151        s.append(
1152            TK_LIKE_KW,
1153            Some(match self {
1154                LikeOperator::Glob => "GLOB",
1155                LikeOperator::Like => "LIKE",
1156                LikeOperator::Match => "MATCH",
1157                LikeOperator::Regexp => "REGEXP",
1158            }),
1159        )
1160    }
1161}
1162
1163#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1164pub enum Operator {
1165    Add,
1166    And,
1167    ArrowRight,      // ->
1168    ArrowRightShift, // ->>
1169    BitwiseAnd,
1170    BitwiseOr,
1171    Concat, // String concatenation (||)
1172    Equals, // = or ==
1173    Divide,
1174    Greater,
1175    GreaterEquals,
1176    Is,
1177    IsNot,
1178    LeftShift,
1179    Less,
1180    LessEquals,
1181    Modulus,
1182    Multiply,
1183    NotEquals, // != or <>
1184    Or,
1185    RightShift,
1186    Substract,
1187}
1188
1189impl From<YYCODETYPE> for Operator {
1190    fn from(token_type: YYCODETYPE) -> Operator {
1191        match token_type {
1192            x if x == TK_AND as YYCODETYPE => Operator::And,
1193            x if x == TK_OR as YYCODETYPE => Operator::Or,
1194            x if x == TK_LT as YYCODETYPE => Operator::Less,
1195            x if x == TK_GT as YYCODETYPE => Operator::Greater,
1196            x if x == TK_GE as YYCODETYPE => Operator::GreaterEquals,
1197            x if x == TK_LE as YYCODETYPE => Operator::LessEquals,
1198            x if x == TK_EQ as YYCODETYPE => Operator::Equals,
1199            x if x == TK_NE as YYCODETYPE => Operator::NotEquals,
1200            x if x == TK_BITAND as YYCODETYPE => Operator::BitwiseAnd,
1201            x if x == TK_BITOR as YYCODETYPE => Operator::BitwiseOr,
1202            x if x == TK_LSHIFT as YYCODETYPE => Operator::LeftShift,
1203            x if x == TK_RSHIFT as YYCODETYPE => Operator::RightShift,
1204            x if x == TK_PLUS as YYCODETYPE => Operator::Add,
1205            x if x == TK_MINUS as YYCODETYPE => Operator::Substract,
1206            x if x == TK_STAR as YYCODETYPE => Operator::Multiply,
1207            x if x == TK_SLASH as YYCODETYPE => Operator::Divide,
1208            x if x == TK_REM as YYCODETYPE => Operator::Modulus,
1209            x if x == TK_CONCAT as YYCODETYPE => Operator::Concat,
1210            x if x == TK_IS as YYCODETYPE => Operator::Is,
1211            x if x == TK_NOT as YYCODETYPE => Operator::IsNot,
1212            _ => unreachable!(),
1213        }
1214    }
1215}
1216impl ToTokens for Operator {
1217    fn to_tokens<S: TokenStream>(&self, s: &mut S) -> Result<(), S::Error> {
1218        match self {
1219            Operator::Add => s.append(TK_PLUS, None),
1220            Operator::And => s.append(TK_AND, None),
1221            Operator::ArrowRight => s.append(TK_PTR, Some("->")),
1222            Operator::ArrowRightShift => s.append(TK_PTR, Some("->>")),
1223            Operator::BitwiseAnd => s.append(TK_BITAND, None),
1224            Operator::BitwiseOr => s.append(TK_BITOR, None),
1225            Operator::Concat => s.append(TK_CONCAT, None),
1226            Operator::Equals => s.append(TK_EQ, None),
1227            Operator::Divide => s.append(TK_SLASH, None),
1228            Operator::Greater => s.append(TK_GT, None),
1229            Operator::GreaterEquals => s.append(TK_GE, None),
1230            Operator::Is => s.append(TK_IS, None),
1231            Operator::IsNot => {
1232                s.append(TK_IS, None)?;
1233                s.append(TK_NOT, None)
1234            }
1235            Operator::LeftShift => s.append(TK_LSHIFT, None),
1236            Operator::Less => s.append(TK_LT, None),
1237            Operator::LessEquals => s.append(TK_LE, None),
1238            Operator::Modulus => s.append(TK_REM, None),
1239            Operator::Multiply => s.append(TK_STAR, None),
1240            Operator::NotEquals => s.append(TK_NE, None),
1241            Operator::Or => s.append(TK_OR, None),
1242            Operator::RightShift => s.append(TK_RSHIFT, None),
1243            Operator::Substract => s.append(TK_MINUS, None),
1244        }
1245    }
1246}
1247
1248#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1249pub enum UnaryOperator {
1250    // bitwise negation (~)
1251    BitwiseNot,
1252    // negative-sign
1253    Negative,
1254    // "NOT"
1255    Not,
1256    // positive-sign
1257    Positive,
1258}
1259
1260impl From<YYCODETYPE> for UnaryOperator {
1261    fn from(token_type: YYCODETYPE) -> UnaryOperator {
1262        match token_type {
1263            x if x == TK_BITNOT as YYCODETYPE => UnaryOperator::BitwiseNot,
1264            x if x == TK_MINUS as YYCODETYPE => UnaryOperator::Negative,
1265            x if x == TK_NOT as YYCODETYPE => UnaryOperator::Not,
1266            x if x == TK_PLUS as YYCODETYPE => UnaryOperator::Positive,
1267            _ => unreachable!(),
1268        }
1269    }
1270}
1271impl ToTokens for UnaryOperator {
1272    fn to_tokens<S: TokenStream>(&self, s: &mut S) -> Result<(), S::Error> {
1273        s.append(
1274            match self {
1275                UnaryOperator::BitwiseNot => TK_BITNOT,
1276                UnaryOperator::Negative => TK_MINUS,
1277                UnaryOperator::Not => TK_NOT,
1278                UnaryOperator::Positive => TK_PLUS,
1279            },
1280            None,
1281        )
1282    }
1283}
1284
1285// https://sqlite.org/lang_select.html
1286// https://sqlite.org/syntax/factored-select-stmt.html
1287#[derive(Clone, Debug, PartialEq, Eq)]
1288pub struct Select {
1289    pub with: Option<With>,
1290    pub body: SelectBody,
1291    pub order_by: Option<Vec<SortedColumn>>,
1292    pub limit: Option<Limit>,
1293}
1294impl ToTokens for Select {
1295    fn to_tokens<S: TokenStream>(&self, s: &mut S) -> Result<(), S::Error> {
1296        if let Some(ref with) = self.with {
1297            with.to_tokens(s)?;
1298        }
1299        self.body.to_tokens(s)?;
1300        if let Some(ref order_by) = self.order_by {
1301            s.append(TK_ORDER, None)?;
1302            s.append(TK_BY, None)?;
1303            comma(order_by, s)?;
1304        }
1305        if let Some(ref limit) = self.limit {
1306            limit.to_tokens(s)?;
1307        }
1308        Ok(())
1309    }
1310}
1311
1312#[derive(Clone, Debug, PartialEq, Eq)]
1313pub struct SelectBody {
1314    pub select: OneSelect,
1315    pub compounds: Option<Vec<CompoundSelect>>,
1316}
1317
1318impl SelectBody {
1319    pub(crate) fn push(&mut self, cs: CompoundSelect) {
1320        if let Some(ref mut v) = self.compounds {
1321            v.push(cs);
1322        } else {
1323            self.compounds = Some(vec![cs]);
1324        }
1325    }
1326}
1327impl ToTokens for SelectBody {
1328    fn to_tokens<S: TokenStream>(&self, s: &mut S) -> Result<(), S::Error> {
1329        self.select.to_tokens(s)?;
1330        if let Some(ref compounds) = self.compounds {
1331            for compound in compounds {
1332                compound.to_tokens(s)?;
1333            }
1334        }
1335        Ok(())
1336    }
1337}
1338
1339#[derive(Clone, Debug, PartialEq, Eq)]
1340pub struct CompoundSelect {
1341    pub operator: CompoundOperator,
1342    pub select: OneSelect,
1343}
1344impl ToTokens for CompoundSelect {
1345    fn to_tokens<S: TokenStream>(&self, s: &mut S) -> Result<(), S::Error> {
1346        self.operator.to_tokens(s)?;
1347        self.select.to_tokens(s)
1348    }
1349}
1350
1351// https://sqlite.org/syntax/compound-operator.html
1352#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1353pub enum CompoundOperator {
1354    Union,
1355    UnionAll,
1356    Except,
1357    Intersect,
1358}
1359impl ToTokens for CompoundOperator {
1360    fn to_tokens<S: TokenStream>(&self, s: &mut S) -> Result<(), S::Error> {
1361        match self {
1362            CompoundOperator::Union => s.append(TK_UNION, None),
1363            CompoundOperator::UnionAll => {
1364                s.append(TK_UNION, None)?;
1365                s.append(TK_ALL, None)
1366            }
1367            CompoundOperator::Except => s.append(TK_EXCEPT, None),
1368            CompoundOperator::Intersect => s.append(TK_INTERSECT, None),
1369        }
1370    }
1371}
1372
1373// https://sqlite.org/syntax/select-core.html
1374#[derive(Clone, Debug, PartialEq, Eq)]
1375pub enum OneSelect {
1376    Select {
1377        distinctness: Option<Distinctness>,
1378        columns: Vec<ResultColumn>,
1379        from: Option<FromClause>,
1380        where_clause: Option<Expr>,
1381        group_by: Option<GroupBy>,
1382        window_clause: Option<Vec<WindowDef>>,
1383    },
1384    Values(Vec<Vec<Expr>>),
1385}
1386impl ToTokens for OneSelect {
1387    fn to_tokens<S: TokenStream>(&self, s: &mut S) -> Result<(), S::Error> {
1388        match self {
1389            OneSelect::Select {
1390                distinctness,
1391                columns,
1392                from,
1393                where_clause,
1394                group_by,
1395                window_clause,
1396            } => {
1397                s.append(TK_SELECT, None)?;
1398                if let Some(ref distinctness) = distinctness {
1399                    distinctness.to_tokens(s)?;
1400                }
1401                comma(columns, s)?;
1402                if let Some(ref from) = from {
1403                    s.append(TK_FROM, None)?;
1404                    from.to_tokens(s)?;
1405                }
1406                if let Some(ref where_clause) = where_clause {
1407                    s.append(TK_WHERE, None)?;
1408                    where_clause.to_tokens(s)?;
1409                }
1410                if let Some(ref group_by) = group_by {
1411                    group_by.to_tokens(s)?;
1412                }
1413                if let Some(ref window_clause) = window_clause {
1414                    s.append(TK_WINDOW, None)?;
1415                    comma(window_clause, s)?;
1416                }
1417                Ok(())
1418            }
1419            OneSelect::Values(values) => {
1420                for (i, vals) in values.iter().enumerate() {
1421                    if i == 0 {
1422                        s.append(TK_VALUES, None)?;
1423                    } else {
1424                        s.append(TK_COMMA, None)?;
1425                    }
1426                    s.append(TK_LP, None)?;
1427                    comma(vals, s)?;
1428                    s.append(TK_RP, None)?;
1429                }
1430                Ok(())
1431            }
1432        }
1433    }
1434}
1435
1436// https://sqlite.org/syntax/join-clause.html
1437#[derive(Clone, Debug, PartialEq, Eq)]
1438pub struct FromClause {
1439    pub select: Option<Box<SelectTable>>, // FIXME mandatory
1440    pub joins: Option<Vec<JoinedSelectTable>>,
1441    op: Option<JoinOperator>, // FIXME transient
1442}
1443impl FromClause {
1444    pub(crate) fn empty() -> FromClause {
1445        FromClause {
1446            select: None,
1447            joins: None,
1448            op: None,
1449        }
1450    }
1451
1452    pub(crate) fn push(
1453        &mut self,
1454        table: SelectTable,
1455        jc: Option<JoinConstraint>,
1456    ) -> Result<(), ParserError> {
1457        let op = self.op.take();
1458        if let Some(op) = op {
1459            let jst = JoinedSelectTable {
1460                operator: op,
1461                table,
1462                constraint: jc,
1463            };
1464            if let Some(ref mut joins) = self.joins {
1465                joins.push(jst);
1466            } else {
1467                self.joins = Some(vec![jst]);
1468            }
1469        } else {
1470            if jc.is_some() {
1471                return Err(ParserError::Custom(
1472                    "a JOIN clause is required before ON".to_string(),
1473                ));
1474            }
1475            debug_assert!(self.select.is_none());
1476            debug_assert!(self.joins.is_none());
1477            self.select = Some(Box::new(table));
1478        }
1479
1480        Ok(())
1481    }
1482
1483    pub(crate) fn push_op(&mut self, op: JoinOperator) {
1484        self.op = Some(op);
1485    }
1486}
1487impl ToTokens for FromClause {
1488    fn to_tokens<S: TokenStream>(&self, s: &mut S) -> Result<(), S::Error> {
1489        self.select.as_ref().unwrap().to_tokens(s)?;
1490        if let Some(ref joins) = self.joins {
1491            for join in joins {
1492                join.to_tokens(s)?;
1493            }
1494        }
1495        Ok(())
1496    }
1497}
1498
1499#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1500pub enum Distinctness {
1501    Distinct,
1502    All,
1503}
1504impl ToTokens for Distinctness {
1505    fn to_tokens<S: TokenStream>(&self, s: &mut S) -> Result<(), S::Error> {
1506        s.append(
1507            match self {
1508                Distinctness::Distinct => TK_DISTINCT,
1509                Distinctness::All => TK_ALL,
1510            },
1511            None,
1512        )
1513    }
1514}
1515
1516// https://sqlite.org/syntax/result-column.html
1517#[derive(Clone, Debug, PartialEq, Eq)]
1518pub enum ResultColumn {
1519    Expr(Expr, Option<As>),
1520    Star,
1521    // table name
1522    TableStar(Name),
1523}
1524impl ToTokens for ResultColumn {
1525    fn to_tokens<S: TokenStream>(&self, s: &mut S) -> Result<(), S::Error> {
1526        match self {
1527            ResultColumn::Expr(expr, alias) => {
1528                expr.to_tokens(s)?;
1529                if let Some(alias) = alias {
1530                    alias.to_tokens(s)?;
1531                }
1532                Ok(())
1533            }
1534            ResultColumn::Star => s.append(TK_STAR, None),
1535            ResultColumn::TableStar(tbl_name) => {
1536                tbl_name.to_tokens(s)?;
1537                s.append(TK_DOT, None)?;
1538                s.append(TK_STAR, None)
1539            }
1540        }
1541    }
1542}
1543
1544#[derive(Clone, Debug, PartialEq, Eq)]
1545pub enum As {
1546    As(Name),
1547    Elided(Name), // FIXME Ids
1548}
1549impl ToTokens for As {
1550    fn to_tokens<S: TokenStream>(&self, s: &mut S) -> Result<(), S::Error> {
1551        match self {
1552            As::As(ref name) => {
1553                s.append(TK_AS, None)?;
1554                name.to_tokens(s)
1555            }
1556            As::Elided(ref name) => name.to_tokens(s),
1557        }
1558    }
1559}
1560
1561// https://sqlite.org/syntax/join-clause.html
1562#[derive(Clone, Debug, PartialEq, Eq)]
1563pub struct JoinedSelectTable {
1564    pub operator: JoinOperator,
1565    pub table: SelectTable,
1566    pub constraint: Option<JoinConstraint>,
1567}
1568impl ToTokens for JoinedSelectTable {
1569    fn to_tokens<S: TokenStream>(&self, s: &mut S) -> Result<(), S::Error> {
1570        self.operator.to_tokens(s)?;
1571        self.table.to_tokens(s)?;
1572        if let Some(ref constraint) = self.constraint {
1573            constraint.to_tokens(s)?;
1574        }
1575        Ok(())
1576    }
1577}
1578
1579// https://sqlite.org/syntax/table-or-subquery.html
1580#[derive(Clone, Debug, PartialEq, Eq)]
1581pub enum SelectTable {
1582    Table(QualifiedName, Option<As>, Option<Indexed>),
1583    TableCall(QualifiedName, Option<Vec<Expr>>, Option<As>),
1584    Select(Select, Option<As>),
1585    Sub(FromClause, Option<As>),
1586}
1587impl ToTokens for SelectTable {
1588    fn to_tokens<S: TokenStream>(&self, s: &mut S) -> Result<(), S::Error> {
1589        match self {
1590            SelectTable::Table(name, alias, indexed) => {
1591                name.to_tokens(s)?;
1592                if let Some(alias) = alias {
1593                    alias.to_tokens(s)?;
1594                }
1595                if let Some(indexed) = indexed {
1596                    indexed.to_tokens(s)?;
1597                }
1598                Ok(())
1599            }
1600            SelectTable::TableCall(name, exprs, alias) => {
1601                name.to_tokens(s)?;
1602                s.append(TK_LP, None)?;
1603                if let Some(exprs) = exprs {
1604                    comma(exprs, s)?;
1605                }
1606                s.append(TK_RP, None)?;
1607                if let Some(alias) = alias {
1608                    alias.to_tokens(s)?;
1609                }
1610                Ok(())
1611            }
1612            SelectTable::Select(select, alias) => {
1613                s.append(TK_LP, None)?;
1614                select.to_tokens(s)?;
1615                s.append(TK_RP, None)?;
1616                if let Some(alias) = alias {
1617                    alias.to_tokens(s)?;
1618                }
1619                Ok(())
1620            }
1621            SelectTable::Sub(from, alias) => {
1622                s.append(TK_LP, None)?;
1623                from.to_tokens(s)?;
1624                s.append(TK_RP, None)?;
1625                if let Some(alias) = alias {
1626                    alias.to_tokens(s)?;
1627                }
1628                Ok(())
1629            }
1630        }
1631    }
1632}
1633
1634// https://sqlite.org/syntax/join-operator.html
1635#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1636pub enum JoinOperator {
1637    Comma,
1638    TypedJoin {
1639        natural: bool,
1640        join_type: Option<JoinType>,
1641    },
1642}
1643
1644impl JoinOperator {
1645    pub(crate) fn from_single(token: Token) -> Result<JoinOperator, ParserError> {
1646        Ok(if let Some(ref jt) = token.1 {
1647            if "CROSS".eq_ignore_ascii_case(jt) {
1648                JoinOperator::TypedJoin {
1649                    natural: false,
1650                    join_type: Some(JoinType::Cross),
1651                }
1652            } else if "INNER".eq_ignore_ascii_case(jt) {
1653                JoinOperator::TypedJoin {
1654                    natural: false,
1655                    join_type: Some(JoinType::Inner),
1656                }
1657            } else if "LEFT".eq_ignore_ascii_case(jt) {
1658                JoinOperator::TypedJoin {
1659                    natural: false,
1660                    join_type: Some(JoinType::Left),
1661                }
1662            } else if "RIGHT".eq_ignore_ascii_case(jt) {
1663                JoinOperator::TypedJoin {
1664                    natural: false,
1665                    join_type: Some(JoinType::Right),
1666                }
1667            } else if "FULL".eq_ignore_ascii_case(jt) {
1668                JoinOperator::TypedJoin {
1669                    natural: false,
1670                    join_type: Some(JoinType::Full),
1671                }
1672            } else if "NATURAL".eq_ignore_ascii_case(jt) {
1673                JoinOperator::TypedJoin {
1674                    natural: true,
1675                    join_type: None,
1676                }
1677            } else {
1678                return Err(ParserError::Custom(format!(
1679                    "unsupported JOIN type: {}",
1680                    jt
1681                )));
1682            }
1683        } else {
1684            unreachable!()
1685        })
1686    }
1687    pub(crate) fn from_couple(token: Token, name: Name) -> Result<JoinOperator, ParserError> {
1688        Ok(if let Some(ref jt) = token.1 {
1689            if "NATURAL".eq_ignore_ascii_case(jt) {
1690                let join_type = if "INNER".eq_ignore_ascii_case(&name.0) {
1691                    JoinType::Inner
1692                } else if "LEFT".eq_ignore_ascii_case(&name.0) {
1693                    JoinType::Left
1694                } else if "RIGHT".eq_ignore_ascii_case(&name.0) {
1695                    JoinType::Right
1696                } else if "FULL".eq_ignore_ascii_case(&name.0) {
1697                    JoinType::Full
1698                } else if "CROSS".eq_ignore_ascii_case(&name.0) {
1699                    JoinType::Cross
1700                } else {
1701                    return Err(ParserError::Custom(format!(
1702                        "unsupported JOIN type: {} {}",
1703                        jt, &name.0
1704                    )));
1705                };
1706                JoinOperator::TypedJoin {
1707                    natural: true,
1708                    join_type: Some(join_type),
1709                }
1710            } else if "OUTER".eq_ignore_ascii_case(&name.0) {
1711                // If "OUTER" is present then there must also be one of "LEFT", "RIGHT", or "FULL"
1712                let join_type = if "LEFT".eq_ignore_ascii_case(jt) {
1713                    JoinType::LeftOuter
1714                } else if "RIGHT".eq_ignore_ascii_case(jt) {
1715                    JoinType::RightOuter
1716                } else if "FULL".eq_ignore_ascii_case(jt) {
1717                    JoinType::FullOuter
1718                } else {
1719                    return Err(ParserError::Custom(format!(
1720                        "unsupported JOIN type: {} {}",
1721                        jt, &name.0
1722                    )));
1723                };
1724                JoinOperator::TypedJoin {
1725                    natural: false,
1726                    join_type: Some(join_type),
1727                }
1728            } else if "LEFT".eq_ignore_ascii_case(jt) && "RIGHT".eq_ignore_ascii_case(&name.0) {
1729                JoinOperator::TypedJoin {
1730                    natural: false,
1731                    join_type: Some(JoinType::Full),
1732                }
1733            } else if "OUTER".eq_ignore_ascii_case(jt) && "LEFT".eq_ignore_ascii_case(&name.0) {
1734                // OUTER LEFT JOIN         ->   same as LEFT JOIN
1735                JoinOperator::TypedJoin {
1736                    natural: false,
1737                    join_type: Some(JoinType::LeftOuter),
1738                }
1739            } else {
1740                return Err(ParserError::Custom(format!(
1741                    "unsupported JOIN type: {} {}",
1742                    jt, &name.0
1743                )));
1744            }
1745        } else {
1746            unreachable!()
1747        })
1748    }
1749    pub(crate) fn from_triple(
1750        token: Token,
1751        n1: Name,
1752        n2: Name,
1753    ) -> Result<JoinOperator, ParserError> {
1754        Ok(if let Some(ref jt) = token.1 {
1755            if "NATURAL".eq_ignore_ascii_case(jt) && "OUTER".eq_ignore_ascii_case(&n2.0) {
1756                // If "OUTER" is present then there must also be one of "LEFT", "RIGHT", or "FULL"
1757                let join_type = if "LEFT".eq_ignore_ascii_case(&n1.0) {
1758                    JoinType::LeftOuter
1759                } else if "RIGHT".eq_ignore_ascii_case(&n1.0) {
1760                    JoinType::RightOuter
1761                } else if "FULL".eq_ignore_ascii_case(&n1.0) {
1762                    JoinType::FullOuter
1763                } else {
1764                    return Err(ParserError::Custom(format!(
1765                        "unsupported JOIN type: {} {} {}",
1766                        jt, &n1.0, &n2.0
1767                    )));
1768                };
1769                JoinOperator::TypedJoin {
1770                    natural: true,
1771                    join_type: Some(join_type),
1772                }
1773            } else if "OUTER".eq_ignore_ascii_case(jt)
1774                && "LEFT".eq_ignore_ascii_case(&n1.0)
1775                && "NATURAL".eq_ignore_ascii_case(&n2.0)
1776            {
1777                JoinOperator::TypedJoin {
1778                    natural: true,
1779                    join_type: Some(JoinType::LeftOuter),
1780                }
1781            } else {
1782                return Err(ParserError::Custom(format!(
1783                    "unsupported JOIN type: {} {} {}",
1784                    jt, &n1.0, &n2.0
1785                )));
1786            }
1787        } else {
1788            unreachable!()
1789        })
1790    }
1791}
1792impl ToTokens for JoinOperator {
1793    fn to_tokens<S: TokenStream>(&self, s: &mut S) -> Result<(), S::Error> {
1794        match self {
1795            JoinOperator::Comma => s.append(TK_COMMA, None),
1796            JoinOperator::TypedJoin { natural, join_type } => {
1797                if *natural {
1798                    s.append(TK_JOIN_KW, Some("NATURAL"))?;
1799                }
1800                if let Some(ref join_type) = join_type {
1801                    join_type.to_tokens(s)?;
1802                }
1803                s.append(TK_JOIN, None)
1804            }
1805        }
1806    }
1807}
1808
1809#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1810pub enum JoinType {
1811    Left, // same as LeftOuter
1812    LeftOuter,
1813    Inner,
1814    Cross,
1815    Right, // same as RightOuter
1816    RightOuter,
1817    Full, // same as FullOuter
1818    FullOuter,
1819}
1820impl ToTokens for JoinType {
1821    fn to_tokens<S: TokenStream>(&self, s: &mut S) -> Result<(), S::Error> {
1822        s.append(
1823            TK_JOIN_KW,
1824            match self {
1825                JoinType::Left => Some("LEFT"),
1826                JoinType::LeftOuter => Some("LEFT OUTER"),
1827                JoinType::Inner => Some("INNER"),
1828                JoinType::Cross => Some("CROSS"),
1829                JoinType::Right => Some("RIGHT"),
1830                JoinType::RightOuter => Some("RIGHT OUTER"),
1831                JoinType::Full => Some("FULL"),
1832                JoinType::FullOuter => Some("FULL OUTER"),
1833            },
1834        )
1835    }
1836}
1837
1838#[derive(Clone, Debug, PartialEq, Eq)]
1839pub enum JoinConstraint {
1840    On(Expr),
1841    // col names
1842    Using(Vec<Name>),
1843}
1844
1845impl ToTokens for JoinConstraint {
1846    fn to_tokens<S: TokenStream>(&self, s: &mut S) -> Result<(), S::Error> {
1847        match self {
1848            JoinConstraint::On(expr) => {
1849                s.append(TK_ON, None)?;
1850                expr.to_tokens(s)
1851            }
1852            JoinConstraint::Using(col_names) => {
1853                s.append(TK_USING, None)?;
1854                s.append(TK_LP, None)?;
1855                comma(col_names, s)?;
1856                s.append(TK_RP, None)
1857            }
1858        }
1859    }
1860}
1861
1862#[derive(Clone, Debug, PartialEq, Eq)]
1863pub struct GroupBy {
1864    pub exprs: Vec<Expr>,
1865    pub having: Option<Expr>,
1866}
1867impl ToTokens for GroupBy {
1868    fn to_tokens<S: TokenStream>(&self, s: &mut S) -> Result<(), S::Error> {
1869        s.append(TK_GROUP, None)?;
1870        s.append(TK_BY, None)?;
1871        comma(&self.exprs, s)?;
1872        if let Some(ref having) = self.having {
1873            s.append(TK_HAVING, None)?;
1874            having.to_tokens(s)?;
1875        }
1876        Ok(())
1877    }
1878}
1879
1880/// identifier or one of several keywords or `INDEXED`
1881#[derive(Clone, Debug, PartialEq, Eq)]
1882pub struct Id(pub String);
1883
1884impl Id {
1885    pub fn from_token(ty: YYCODETYPE, token: Token) -> Id {
1886        Id(from_token(ty, token))
1887    }
1888}
1889impl ToTokens for Id {
1890    fn to_tokens<S: TokenStream>(&self, s: &mut S) -> Result<(), S::Error> {
1891        double_quote(&self.0, s)
1892    }
1893}
1894
1895// TODO ids (identifier or string)
1896
1897/// identifier or string or `CROSS` or `FULL` or `INNER` or `LEFT` or `NATURAL` or `OUTER` or `RIGHT`.
1898#[derive(Clone, Debug, PartialEq, Eq)]
1899pub struct Name(pub String); // TODO distinction between Name and "Name"/[Name]/`Name`
1900
1901impl Name {
1902    pub fn from_token(ty: YYCODETYPE, token: Token) -> Name {
1903        Name(from_token(ty, token))
1904    }
1905}
1906impl ToTokens for Name {
1907    fn to_tokens<S: TokenStream>(&self, s: &mut S) -> Result<(), S::Error> {
1908        double_quote(&self.0, s)
1909    }
1910}
1911
1912impl Display for Name {
1913    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1914        self.to_fmt(f)
1915    }
1916}
1917
1918#[derive(Clone, Debug, PartialEq, Eq)]
1919pub struct QualifiedName {
1920    pub db_name: Option<Name>,
1921    pub name: Name,
1922    pub alias: Option<Name>, // FIXME restrict alias usage (fullname vs xfullname)
1923}
1924
1925impl QualifiedName {
1926    pub fn single(name: Name) -> Self {
1927        QualifiedName {
1928            db_name: None,
1929            name,
1930            alias: None,
1931        }
1932    }
1933    pub fn fullname(db_name: Name, name: Name) -> Self {
1934        QualifiedName {
1935            db_name: Some(db_name),
1936            name,
1937            alias: None,
1938        }
1939    }
1940    pub fn xfullname(db_name: Name, name: Name, alias: Name) -> Self {
1941        QualifiedName {
1942            db_name: Some(db_name),
1943            name,
1944            alias: Some(alias),
1945        }
1946    }
1947    pub fn alias(name: Name, alias: Name) -> Self {
1948        QualifiedName {
1949            db_name: None,
1950            name,
1951            alias: Some(alias),
1952        }
1953    }
1954}
1955impl ToTokens for QualifiedName {
1956    fn to_tokens<S: TokenStream>(&self, s: &mut S) -> Result<(), S::Error> {
1957        if let Some(ref db_name) = self.db_name {
1958            db_name.to_tokens(s)?;
1959            s.append(TK_DOT, None)?;
1960        }
1961        self.name.to_tokens(s)?;
1962        if let Some(ref alias) = self.alias {
1963            s.append(TK_AS, None)?;
1964            alias.to_tokens(s)?;
1965        }
1966        Ok(())
1967    }
1968}
1969
1970// https://sqlite.org/lang_altertable.html
1971#[derive(Clone, Debug, PartialEq, Eq)]
1972pub enum AlterTableBody {
1973    // new table name
1974    RenameTo(Name),
1975    AddColumn(ColumnDefinition), // TODO distinction between ADD and ADD COLUMN
1976    RenameColumn { old: Name, new: Name },
1977    DropColumn(Name), // TODO distinction between DROP and DROP COLUMN
1978    AlterColumn { old: Name, cd: ColumnDefinition },
1979}
1980impl ToTokens for AlterTableBody {
1981    fn to_tokens<S: TokenStream>(&self, s: &mut S) -> Result<(), S::Error> {
1982        match self {
1983            AlterTableBody::RenameTo(name) => {
1984                s.append(TK_RENAME, None)?;
1985                s.append(TK_TO, None)?;
1986                name.to_tokens(s)
1987            }
1988            AlterTableBody::AddColumn(def) => {
1989                s.append(TK_ADD, None)?;
1990                s.append(TK_COLUMNKW, None)?;
1991                def.to_tokens(s)
1992            }
1993            AlterTableBody::RenameColumn { old, new } => {
1994                s.append(TK_RENAME, None)?;
1995                old.to_tokens(s)?;
1996                s.append(TK_TO, None)?;
1997                new.to_tokens(s)
1998            }
1999            AlterTableBody::DropColumn(name) => {
2000                s.append(TK_DROP, None)?;
2001                s.append(TK_COLUMNKW, None)?;
2002                name.to_tokens(s)
2003            }
2004            AlterTableBody::AlterColumn { old, cd } => {
2005                s.append(TK_ALTER, None)?;
2006                s.append(TK_COLUMNKW, None)?;
2007                old.to_tokens(s)?;
2008                s.append(TK_TO, None)?;
2009                cd.to_tokens(s)
2010            }
2011        }
2012    }
2013}
2014
2015// https://sqlite.org/lang_createtable.html
2016// https://sqlite.org/syntax/create-table-stmt.html
2017#[derive(Clone, Debug, PartialEq, Eq)]
2018pub enum CreateTableBody {
2019    ColumnsAndConstraints {
2020        columns: Vec<ColumnDefinition>,
2021        constraints: Option<Vec<NamedTableConstraint>>,
2022        options: TableOptions,
2023    },
2024    AsSelect(Select),
2025}
2026
2027impl CreateTableBody {
2028    pub fn columns_and_constraints(
2029        columns: Vec<ColumnDefinition>,
2030        constraints: Option<Vec<NamedTableConstraint>>,
2031        options: TableOptions,
2032    ) -> Result<CreateTableBody, ParserError> {
2033        Ok(CreateTableBody::ColumnsAndConstraints {
2034            columns,
2035            constraints,
2036            options,
2037        })
2038    }
2039}
2040
2041impl ToTokens for CreateTableBody {
2042    fn to_tokens<S: TokenStream>(&self, s: &mut S) -> Result<(), S::Error> {
2043        match self {
2044            CreateTableBody::ColumnsAndConstraints {
2045                columns,
2046                constraints,
2047                options,
2048            } => {
2049                s.append(TK_LP, None)?;
2050                comma(columns, s)?;
2051                if let Some(constraints) = constraints {
2052                    s.append(TK_COMMA, None)?;
2053                    comma(constraints, s)?;
2054                }
2055                s.append(TK_RP, None)?;
2056                if options.contains(TableOptions::WITHOUT_ROWID) {
2057                    s.append(TK_WITHOUT, None)?;
2058                    s.append(TK_ID, Some("ROWID"))?;
2059                } else if options.contains(TableOptions::RANDOM_ROWID) {
2060                    s.append(TK_ID, Some("RANDOM"))?;
2061                    s.append(TK_ID, Some("ROWID"))?;
2062                }
2063                if options.contains(TableOptions::STRICT) {
2064                    s.append(TK_ID, Some("STRICT"))?;
2065                }
2066                Ok(())
2067            }
2068            CreateTableBody::AsSelect(select) => {
2069                s.append(TK_AS, None)?;
2070                select.to_tokens(s)
2071            }
2072        }
2073    }
2074}
2075
2076// https://sqlite.org/syntax/column-def.html
2077#[derive(Clone, Debug, PartialEq, Eq)]
2078pub struct ColumnDefinition {
2079    pub col_name: Name,
2080    pub col_type: Option<Type>,
2081    pub constraints: Vec<NamedColumnConstraint>,
2082}
2083impl ToTokens for ColumnDefinition {
2084    fn to_tokens<S: TokenStream>(&self, s: &mut S) -> Result<(), S::Error> {
2085        self.col_name.to_tokens(s)?;
2086        if let Some(ref col_type) = self.col_type {
2087            col_type.to_tokens(s)?;
2088        }
2089        for constraint in self.constraints.iter() {
2090            constraint.to_tokens(s)?;
2091        }
2092        Ok(())
2093    }
2094}
2095impl ColumnDefinition {
2096    pub fn add_column(
2097        columns: &mut Vec<ColumnDefinition>,
2098        cd: ColumnDefinition,
2099    ) -> Result<(), ParserError> {
2100        if columns
2101            .iter()
2102            .any(|c| c.col_name.0.eq_ignore_ascii_case(&cd.col_name.0))
2103        {
2104            return Err(ParserError::Custom(format!(
2105                "duplicate column name: {}",
2106                cd.col_name
2107            )));
2108        }
2109        columns.push(cd);
2110        Ok(())
2111    }
2112}
2113
2114// https://sqlite.org/syntax/column-constraint.html
2115#[derive(Clone, Debug, PartialEq, Eq)]
2116pub struct NamedColumnConstraint {
2117    pub name: Option<Name>,
2118    pub constraint: ColumnConstraint,
2119}
2120impl ToTokens for NamedColumnConstraint {
2121    fn to_tokens<S: TokenStream>(&self, s: &mut S) -> Result<(), S::Error> {
2122        if let Some(ref name) = self.name {
2123            s.append(TK_CONSTRAINT, None)?;
2124            name.to_tokens(s)?;
2125        }
2126        self.constraint.to_tokens(s)
2127    }
2128}
2129
2130// https://sqlite.org/syntax/column-constraint.html
2131#[derive(Clone, Debug, PartialEq, Eq)]
2132pub enum ColumnConstraint {
2133    PrimaryKey {
2134        order: Option<SortOrder>,
2135        conflict_clause: Option<ResolveType>,
2136        auto_increment: bool,
2137    },
2138    NotNull {
2139        nullable: bool,
2140        conflict_clause: Option<ResolveType>,
2141    },
2142    Unique(Option<ResolveType>),
2143    Check(Expr),
2144    Default(Expr),
2145    Defer(DeferSubclause), // FIXME
2146    Collate {
2147        collation_name: Name, // FIXME Ids
2148    },
2149    ForeignKey {
2150        clause: ForeignKeyClause,
2151        deref_clause: Option<DeferSubclause>,
2152    },
2153    Generated {
2154        expr: Expr,
2155        typ: Option<Id>,
2156    },
2157}
2158impl ToTokens for ColumnConstraint {
2159    fn to_tokens<S: TokenStream>(&self, s: &mut S) -> Result<(), S::Error> {
2160        match self {
2161            ColumnConstraint::PrimaryKey {
2162                order,
2163                conflict_clause,
2164                auto_increment,
2165            } => {
2166                s.append(TK_PRIMARY, None)?;
2167                s.append(TK_KEY, None)?;
2168                if let Some(order) = order {
2169                    order.to_tokens(s)?;
2170                }
2171                if let Some(conflict_clause) = conflict_clause {
2172                    s.append(TK_ON, None)?;
2173                    s.append(TK_CONFLICT, None)?;
2174                    conflict_clause.to_tokens(s)?;
2175                }
2176                if *auto_increment {
2177                    s.append(TK_AUTOINCR, None)?;
2178                }
2179                Ok(())
2180            }
2181            ColumnConstraint::NotNull {
2182                nullable,
2183                conflict_clause,
2184            } => {
2185                if !nullable {
2186                    s.append(TK_NOT, None)?;
2187                }
2188                s.append(TK_NULL, None)?;
2189                if let Some(conflict_clause) = conflict_clause {
2190                    s.append(TK_ON, None)?;
2191                    s.append(TK_CONFLICT, None)?;
2192                    conflict_clause.to_tokens(s)?;
2193                }
2194                Ok(())
2195            }
2196            ColumnConstraint::Unique(conflict_clause) => {
2197                s.append(TK_UNIQUE, None)?;
2198                if let Some(conflict_clause) = conflict_clause {
2199                    s.append(TK_ON, None)?;
2200                    s.append(TK_CONFLICT, None)?;
2201                    conflict_clause.to_tokens(s)?;
2202                }
2203                Ok(())
2204            }
2205            ColumnConstraint::Check(expr) => {
2206                s.append(TK_CHECK, None)?;
2207                s.append(TK_LP, None)?;
2208                expr.to_tokens(s)?;
2209                s.append(TK_RP, None)
2210            }
2211            ColumnConstraint::Default(expr) => {
2212                s.append(TK_DEFAULT, None)?;
2213                expr.to_tokens(s)
2214            }
2215            ColumnConstraint::Defer(deref_clause) => deref_clause.to_tokens(s),
2216            ColumnConstraint::Collate { collation_name } => {
2217                s.append(TK_COLLATE, None)?;
2218                collation_name.to_tokens(s)
2219            }
2220            ColumnConstraint::ForeignKey {
2221                clause,
2222                deref_clause,
2223            } => {
2224                s.append(TK_REFERENCES, None)?;
2225                clause.to_tokens(s)?;
2226                if let Some(deref_clause) = deref_clause {
2227                    deref_clause.to_tokens(s)?;
2228                }
2229                Ok(())
2230            }
2231            ColumnConstraint::Generated { expr, typ } => {
2232                s.append(TK_AS, None)?;
2233                s.append(TK_LP, None)?;
2234                expr.to_tokens(s)?;
2235                s.append(TK_RP, None)?;
2236                if let Some(typ) = typ {
2237                    typ.to_tokens(s)?;
2238                }
2239                Ok(())
2240            }
2241        }
2242    }
2243}
2244
2245// https://sqlite.org/syntax/table-constraint.html
2246#[derive(Clone, Debug, PartialEq, Eq)]
2247pub struct NamedTableConstraint {
2248    pub name: Option<Name>,
2249    pub constraint: TableConstraint,
2250}
2251impl ToTokens for NamedTableConstraint {
2252    fn to_tokens<S: TokenStream>(&self, s: &mut S) -> Result<(), S::Error> {
2253        if let Some(ref name) = self.name {
2254            s.append(TK_CONSTRAINT, None)?;
2255            name.to_tokens(s)?;
2256        }
2257        self.constraint.to_tokens(s)
2258    }
2259}
2260
2261// https://sqlite.org/syntax/table-constraint.html
2262#[derive(Clone, Debug, PartialEq, Eq)]
2263pub enum TableConstraint {
2264    PrimaryKey {
2265        columns: Vec<SortedColumn>,
2266        auto_increment: bool,
2267        conflict_clause: Option<ResolveType>,
2268    },
2269    Unique {
2270        columns: Vec<SortedColumn>,
2271        conflict_clause: Option<ResolveType>,
2272    },
2273    Check(Expr),
2274    ForeignKey {
2275        columns: Vec<IndexedColumn>,
2276        clause: ForeignKeyClause,
2277        deref_clause: Option<DeferSubclause>,
2278    },
2279}
2280impl ToTokens for TableConstraint {
2281    fn to_tokens<S: TokenStream>(&self, s: &mut S) -> Result<(), S::Error> {
2282        match self {
2283            TableConstraint::PrimaryKey {
2284                columns,
2285                auto_increment,
2286                conflict_clause,
2287            } => {
2288                s.append(TK_PRIMARY, None)?;
2289                s.append(TK_KEY, None)?;
2290                s.append(TK_LP, None)?;
2291                comma(columns, s)?;
2292                if *auto_increment {
2293                    s.append(TK_AUTOINCR, None)?;
2294                }
2295                s.append(TK_RP, None)?;
2296                if let Some(conflict_clause) = conflict_clause {
2297                    s.append(TK_ON, None)?;
2298                    s.append(TK_CONFLICT, None)?;
2299                    conflict_clause.to_tokens(s)?;
2300                }
2301                Ok(())
2302            }
2303            TableConstraint::Unique {
2304                columns,
2305                conflict_clause,
2306            } => {
2307                s.append(TK_UNIQUE, None)?;
2308                s.append(TK_LP, None)?;
2309                comma(columns, s)?;
2310                s.append(TK_RP, None)?;
2311                if let Some(conflict_clause) = conflict_clause {
2312                    s.append(TK_ON, None)?;
2313                    s.append(TK_CONFLICT, None)?;
2314                    conflict_clause.to_tokens(s)?;
2315                }
2316                Ok(())
2317            }
2318            TableConstraint::Check(expr) => {
2319                s.append(TK_CHECK, None)?;
2320                s.append(TK_LP, None)?;
2321                expr.to_tokens(s)?;
2322                s.append(TK_RP, None)
2323            }
2324            TableConstraint::ForeignKey {
2325                columns,
2326                clause,
2327                deref_clause,
2328            } => {
2329                s.append(TK_FOREIGN, None)?;
2330                s.append(TK_KEY, None)?;
2331                s.append(TK_LP, None)?;
2332                comma(columns, s)?;
2333                s.append(TK_RP, None)?;
2334                s.append(TK_REFERENCES, None)?;
2335                clause.to_tokens(s)?;
2336                if let Some(deref_clause) = deref_clause {
2337                    deref_clause.to_tokens(s)?;
2338                }
2339                Ok(())
2340            }
2341        }
2342    }
2343}
2344
2345bitflags::bitflags! {
2346    #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
2347    pub struct TableOptions: u8 {
2348        const NONE = 0;
2349        const WITHOUT_ROWID = 1;
2350        const STRICT = 2;
2351        const RANDOM_ROWID = 3;
2352    }
2353}
2354
2355#[derive(Copy, Clone, Debug, PartialEq, Eq)]
2356pub enum SortOrder {
2357    Asc,
2358    Desc,
2359}
2360impl ToTokens for SortOrder {
2361    fn to_tokens<S: TokenStream>(&self, s: &mut S) -> Result<(), S::Error> {
2362        s.append(
2363            match self {
2364                SortOrder::Asc => TK_ASC,
2365                SortOrder::Desc => TK_DESC,
2366            },
2367            None,
2368        )
2369    }
2370}
2371
2372#[derive(Copy, Clone, Debug, PartialEq, Eq)]
2373pub enum NullsOrder {
2374    First,
2375    Last,
2376}
2377impl ToTokens for NullsOrder {
2378    fn to_tokens<S: TokenStream>(&self, s: &mut S) -> Result<(), S::Error> {
2379        s.append(TK_NULLS, None)?;
2380        s.append(
2381            match self {
2382                NullsOrder::First => TK_FIRST,
2383                NullsOrder::Last => TK_LAST,
2384            },
2385            None,
2386        )
2387    }
2388}
2389
2390// https://sqlite.org/syntax/foreign-key-clause.html
2391#[derive(Clone, Debug, PartialEq, Eq)]
2392pub struct ForeignKeyClause {
2393    pub tbl_name: Name,
2394    pub columns: Option<Vec<IndexedColumn>>,
2395    pub args: Vec<RefArg>,
2396}
2397impl ToTokens for ForeignKeyClause {
2398    fn to_tokens<S: TokenStream>(&self, s: &mut S) -> Result<(), S::Error> {
2399        self.tbl_name.to_tokens(s)?;
2400        if let Some(ref columns) = self.columns {
2401            s.append(TK_LP, None)?;
2402            comma(columns, s)?;
2403            s.append(TK_RP, None)?;
2404        }
2405        for arg in self.args.iter() {
2406            arg.to_tokens(s)?;
2407        }
2408        Ok(())
2409    }
2410}
2411
2412#[derive(Clone, Debug, PartialEq, Eq)]
2413pub enum RefArg {
2414    OnDelete(RefAct),
2415    OnInsert(RefAct),
2416    OnUpdate(RefAct),
2417    Match(Name),
2418}
2419impl ToTokens for RefArg {
2420    fn to_tokens<S: TokenStream>(&self, s: &mut S) -> Result<(), S::Error> {
2421        match self {
2422            RefArg::OnDelete(ref action) => {
2423                s.append(TK_ON, None)?;
2424                s.append(TK_DELETE, None)?;
2425                action.to_tokens(s)
2426            }
2427            RefArg::OnInsert(ref action) => {
2428                s.append(TK_ON, None)?;
2429                s.append(TK_INSERT, None)?;
2430                action.to_tokens(s)
2431            }
2432            RefArg::OnUpdate(ref action) => {
2433                s.append(TK_ON, None)?;
2434                s.append(TK_UPDATE, None)?;
2435                action.to_tokens(s)
2436            }
2437            RefArg::Match(ref name) => {
2438                s.append(TK_MATCH, None)?;
2439                name.to_tokens(s)
2440            }
2441        }
2442    }
2443}
2444
2445#[derive(Copy, Clone, Debug, PartialEq, Eq)]
2446pub enum RefAct {
2447    SetNull,
2448    SetDefault,
2449    Cascade,
2450    Restrict,
2451    NoAction,
2452}
2453impl ToTokens for RefAct {
2454    fn to_tokens<S: TokenStream>(&self, s: &mut S) -> Result<(), S::Error> {
2455        match self {
2456            RefAct::SetNull => {
2457                s.append(TK_SET, None)?;
2458                s.append(TK_NULL, None)
2459            }
2460            RefAct::SetDefault => {
2461                s.append(TK_SET, None)?;
2462                s.append(TK_DEFAULT, None)
2463            }
2464            RefAct::Cascade => s.append(TK_CASCADE, None),
2465            RefAct::Restrict => s.append(TK_RESTRICT, None),
2466            RefAct::NoAction => {
2467                s.append(TK_NO, None)?;
2468                s.append(TK_ACTION, None)
2469            }
2470        }
2471    }
2472}
2473
2474#[derive(Clone, Debug, PartialEq, Eq)]
2475pub struct DeferSubclause {
2476    pub deferrable: bool,
2477    pub init_deferred: Option<InitDeferredPred>,
2478}
2479impl ToTokens for DeferSubclause {
2480    fn to_tokens<S: TokenStream>(&self, s: &mut S) -> Result<(), S::Error> {
2481        if !self.deferrable {
2482            s.append(TK_NOT, None)?;
2483        }
2484        s.append(TK_DEFERRABLE, None)?;
2485        if let Some(init_deferred) = self.init_deferred {
2486            init_deferred.to_tokens(s)?;
2487        }
2488        Ok(())
2489    }
2490}
2491
2492#[derive(Copy, Clone, Debug, PartialEq, Eq)]
2493pub enum InitDeferredPred {
2494    InitiallyDeferred,
2495    InitiallyImmediate, // default
2496}
2497impl ToTokens for InitDeferredPred {
2498    fn to_tokens<S: TokenStream>(&self, s: &mut S) -> Result<(), S::Error> {
2499        s.append(TK_INITIALLY, None)?;
2500        s.append(
2501            match self {
2502                InitDeferredPred::InitiallyDeferred => TK_DEFERRED,
2503                InitDeferredPred::InitiallyImmediate => TK_IMMEDIATE,
2504            },
2505            None,
2506        )
2507    }
2508}
2509
2510// https://sqlite.org/syntax/indexed-column.html
2511#[derive(Clone, Debug, PartialEq, Eq)]
2512pub struct IndexedColumn {
2513    pub col_name: Name,
2514    pub collation_name: Option<Name>, // FIXME Ids
2515    pub order: Option<SortOrder>,
2516}
2517impl ToTokens for IndexedColumn {
2518    fn to_tokens<S: TokenStream>(&self, s: &mut S) -> Result<(), S::Error> {
2519        self.col_name.to_tokens(s)?;
2520        if let Some(ref collation_name) = self.collation_name {
2521            s.append(TK_COLLATE, None)?;
2522            collation_name.to_tokens(s)?;
2523        }
2524        if let Some(order) = self.order {
2525            order.to_tokens(s)?;
2526        }
2527        Ok(())
2528    }
2529}
2530
2531#[derive(Clone, Debug, PartialEq, Eq)]
2532pub enum Indexed {
2533    // idx name
2534    IndexedBy(Name),
2535    NotIndexed,
2536}
2537impl ToTokens for Indexed {
2538    fn to_tokens<S: TokenStream>(&self, s: &mut S) -> Result<(), S::Error> {
2539        match self {
2540            Indexed::IndexedBy(ref name) => {
2541                s.append(TK_INDEXED, None)?;
2542                s.append(TK_BY, None)?;
2543                name.to_tokens(s)
2544            }
2545            Indexed::NotIndexed => {
2546                s.append(TK_NOT, None)?;
2547                s.append(TK_INDEXED, None)
2548            }
2549        }
2550    }
2551}
2552
2553#[derive(Clone, Debug, PartialEq, Eq)]
2554pub struct SortedColumn {
2555    pub expr: Expr,
2556    pub order: Option<SortOrder>,
2557    pub nulls: Option<NullsOrder>,
2558}
2559impl ToTokens for SortedColumn {
2560    fn to_tokens<S: TokenStream>(&self, s: &mut S) -> Result<(), S::Error> {
2561        self.expr.to_tokens(s)?;
2562        if let Some(ref order) = self.order {
2563            order.to_tokens(s)?;
2564        }
2565        if let Some(ref nulls) = self.nulls {
2566            nulls.to_tokens(s)?;
2567        }
2568        Ok(())
2569    }
2570}
2571
2572#[derive(Clone, Debug, PartialEq, Eq)]
2573pub struct Limit {
2574    pub expr: Expr,
2575    pub offset: Option<Expr>, // TODO distinction between LIMIT offset, count and LIMIT count OFFSET offset
2576}
2577impl ToTokens for Limit {
2578    fn to_tokens<S: TokenStream>(&self, s: &mut S) -> Result<(), S::Error> {
2579        s.append(TK_LIMIT, None)?;
2580        self.expr.to_tokens(s)?;
2581        if let Some(ref offset) = self.offset {
2582            s.append(TK_OFFSET, None)?;
2583            offset.to_tokens(s)?;
2584        }
2585        Ok(())
2586    }
2587}
2588
2589// https://sqlite.org/lang_insert.html
2590// https://sqlite.org/syntax/insert-stmt.html
2591#[derive(Clone, Debug, PartialEq, Eq)]
2592pub enum InsertBody {
2593    Select(Select, Option<Upsert>),
2594    DefaultValues,
2595}
2596impl ToTokens for InsertBody {
2597    fn to_tokens<S: TokenStream>(&self, s: &mut S) -> Result<(), S::Error> {
2598        match self {
2599            InsertBody::Select(select, upsert) => {
2600                select.to_tokens(s)?;
2601                if let Some(upsert) = upsert {
2602                    upsert.to_tokens(s)?;
2603                }
2604                Ok(())
2605            }
2606            InsertBody::DefaultValues => {
2607                s.append(TK_DEFAULT, None)?;
2608                s.append(TK_VALUES, None)
2609            }
2610        }
2611    }
2612}
2613
2614#[derive(Clone, Debug, PartialEq, Eq)]
2615pub struct Set {
2616    pub col_names: Vec<Name>,
2617    pub expr: Expr,
2618}
2619impl ToTokens for Set {
2620    fn to_tokens<S: TokenStream>(&self, s: &mut S) -> Result<(), S::Error> {
2621        if self.col_names.len() == 1 {
2622            comma(&self.col_names, s)?;
2623        } else {
2624            s.append(TK_LP, None)?;
2625            comma(&self.col_names, s)?;
2626            s.append(TK_RP, None)?;
2627        }
2628        s.append(TK_EQ, None)?;
2629        self.expr.to_tokens(s)
2630    }
2631}
2632
2633// https://sqlite.org/syntax/pragma-stmt.html
2634#[derive(Clone, Debug, PartialEq, Eq)]
2635pub enum PragmaBody {
2636    Equals(PragmaValue),
2637    Call(PragmaValue),
2638}
2639impl ToTokens for PragmaBody {
2640    fn to_tokens<S: TokenStream>(&self, s: &mut S) -> Result<(), S::Error> {
2641        match self {
2642            PragmaBody::Equals(value) => {
2643                s.append(TK_EQ, None)?;
2644                value.to_tokens(s)
2645            }
2646            PragmaBody::Call(value) => {
2647                s.append(TK_LP, None)?;
2648                value.to_tokens(s)?;
2649                s.append(TK_RP, None)
2650            }
2651        }
2652    }
2653}
2654
2655// https://sqlite.org/syntax/pragma-value.html
2656pub type PragmaValue = Expr; // TODO
2657
2658#[derive(Copy, Clone, Debug, PartialEq, Eq)]
2659pub enum TriggerTime {
2660    Before, // default
2661    After,
2662    InsteadOf,
2663}
2664impl ToTokens for TriggerTime {
2665    fn to_tokens<S: TokenStream>(&self, s: &mut S) -> Result<(), S::Error> {
2666        match self {
2667            TriggerTime::Before => s.append(TK_BEFORE, None),
2668            TriggerTime::After => s.append(TK_AFTER, None),
2669            TriggerTime::InsteadOf => {
2670                s.append(TK_INSTEAD, None)?;
2671                s.append(TK_OF, None)
2672            }
2673        }
2674    }
2675}
2676
2677#[derive(Clone, Debug, PartialEq, Eq)]
2678pub enum TriggerEvent {
2679    Delete,
2680    Insert,
2681    Update,
2682    // col names
2683    UpdateOf(Vec<Name>),
2684}
2685impl ToTokens for TriggerEvent {
2686    fn to_tokens<S: TokenStream>(&self, s: &mut S) -> Result<(), S::Error> {
2687        match self {
2688            TriggerEvent::Delete => s.append(TK_DELETE, None),
2689            TriggerEvent::Insert => s.append(TK_INSERT, None),
2690            TriggerEvent::Update => s.append(TK_UPDATE, None),
2691            TriggerEvent::UpdateOf(ref col_names) => {
2692                s.append(TK_UPDATE, None)?;
2693                s.append(TK_OF, None)?;
2694                comma(col_names, s)
2695            }
2696        }
2697    }
2698}
2699
2700// https://sqlite.org/lang_createtrigger.html
2701// https://sqlite.org/syntax/create-trigger-stmt.html
2702#[derive(Clone, Debug, PartialEq, Eq)]
2703pub enum TriggerCmd {
2704    Update {
2705        or_conflict: Option<ResolveType>,
2706        tbl_name: Name,
2707        sets: Vec<Set>,
2708        from: Option<FromClause>,
2709        where_clause: Option<Expr>,
2710    },
2711    Insert {
2712        or_conflict: Option<ResolveType>,
2713        tbl_name: Name,
2714        col_names: Option<Vec<Name>>,
2715        select: Select,
2716        upsert: Option<Upsert>,
2717        returning: Option<Vec<ResultColumn>>,
2718    },
2719    Delete {
2720        tbl_name: Name,
2721        where_clause: Option<Expr>,
2722    },
2723    Select(Select),
2724}
2725impl ToTokens for TriggerCmd {
2726    fn to_tokens<S: TokenStream>(&self, s: &mut S) -> Result<(), S::Error> {
2727        match self {
2728            TriggerCmd::Update {
2729                or_conflict,
2730                tbl_name,
2731                sets,
2732                from,
2733                where_clause,
2734            } => {
2735                s.append(TK_UPDATE, None)?;
2736                if let Some(or_conflict) = or_conflict {
2737                    s.append(TK_OR, None)?;
2738                    or_conflict.to_tokens(s)?;
2739                }
2740                tbl_name.to_tokens(s)?;
2741                s.append(TK_SET, None)?;
2742                comma(sets, s)?;
2743                if let Some(from) = from {
2744                    s.append(TK_FROM, None)?;
2745                    from.to_tokens(s)?;
2746                }
2747                if let Some(where_clause) = where_clause {
2748                    s.append(TK_WHERE, None)?;
2749                    where_clause.to_tokens(s)?;
2750                }
2751                Ok(())
2752            }
2753            TriggerCmd::Insert {
2754                or_conflict,
2755                tbl_name,
2756                col_names,
2757                select,
2758                upsert,
2759                returning,
2760            } => {
2761                if let Some(ResolveType::Replace) = or_conflict {
2762                    s.append(TK_REPLACE, None)?;
2763                } else {
2764                    s.append(TK_INSERT, None)?;
2765                    if let Some(or_conflict) = or_conflict {
2766                        s.append(TK_OR, None)?;
2767                        or_conflict.to_tokens(s)?;
2768                    }
2769                }
2770                s.append(TK_INTO, None)?;
2771                tbl_name.to_tokens(s)?;
2772                if let Some(col_names) = col_names {
2773                    s.append(TK_LP, None)?;
2774                    comma(col_names, s)?;
2775                    s.append(TK_RP, None)?;
2776                }
2777                select.to_tokens(s)?;
2778                if let Some(upsert) = upsert {
2779                    upsert.to_tokens(s)?;
2780                }
2781                if let Some(returning) = returning {
2782                    s.append(TK_RETURNING, None)?;
2783                    comma(returning, s)?;
2784                }
2785                Ok(())
2786            }
2787            TriggerCmd::Delete {
2788                tbl_name,
2789                where_clause,
2790            } => {
2791                s.append(TK_DELETE, None)?;
2792                s.append(TK_FROM, None)?;
2793                tbl_name.to_tokens(s)?;
2794                if let Some(where_clause) = where_clause {
2795                    s.append(TK_WHERE, None)?;
2796                    where_clause.to_tokens(s)?;
2797                }
2798                Ok(())
2799            }
2800            TriggerCmd::Select(select) => select.to_tokens(s),
2801        }
2802    }
2803}
2804
2805#[derive(Copy, Clone, Debug, PartialEq, Eq)]
2806pub enum ResolveType {
2807    Rollback,
2808    Abort, // default
2809    Fail,
2810    Ignore,
2811    Replace,
2812}
2813impl ToTokens for ResolveType {
2814    fn to_tokens<S: TokenStream>(&self, s: &mut S) -> Result<(), S::Error> {
2815        s.append(
2816            match self {
2817                ResolveType::Rollback => TK_ROLLBACK,
2818                ResolveType::Abort => TK_ABORT,
2819                ResolveType::Fail => TK_FAIL,
2820                ResolveType::Ignore => TK_IGNORE,
2821                ResolveType::Replace => TK_REPLACE,
2822            },
2823            None,
2824        )
2825    }
2826}
2827
2828// https://sqlite.org/lang_with.html
2829// https://sqlite.org/syntax/with-clause.html
2830#[derive(Clone, Debug, PartialEq, Eq)]
2831pub struct With {
2832    pub recursive: bool,
2833    pub ctes: Vec<CommonTableExpr>,
2834}
2835impl ToTokens for With {
2836    fn to_tokens<S: TokenStream>(&self, s: &mut S) -> Result<(), S::Error> {
2837        s.append(TK_WITH, None)?;
2838        if self.recursive {
2839            s.append(TK_RECURSIVE, None)?;
2840        }
2841        comma(&self.ctes, s)
2842    }
2843}
2844
2845#[derive(Clone, Debug, PartialEq, Eq)]
2846pub enum Materialized {
2847    Any,
2848    Yes,
2849    No,
2850}
2851
2852// https://sqlite.org/syntax/common-table-expression.html
2853#[derive(Clone, Debug, PartialEq, Eq)]
2854pub struct CommonTableExpr {
2855    pub tbl_name: Name,
2856    pub columns: Option<Vec<IndexedColumn>>,
2857    pub materialized: Materialized,
2858    pub select: Select,
2859}
2860
2861impl ToTokens for CommonTableExpr {
2862    fn to_tokens<S: TokenStream>(&self, s: &mut S) -> Result<(), S::Error> {
2863        self.tbl_name.to_tokens(s)?;
2864        if let Some(ref columns) = self.columns {
2865            s.append(TK_LP, None)?;
2866            comma(columns, s)?;
2867            s.append(TK_RP, None)?;
2868        }
2869        s.append(TK_AS, None)?;
2870        match self.materialized {
2871            Materialized::Any => {}
2872            Materialized::Yes => {
2873                s.append(TK_MATERIALIZED, None)?;
2874            }
2875            Materialized::No => {
2876                s.append(TK_NOT, None)?;
2877                s.append(TK_MATERIALIZED, None)?;
2878            }
2879        };
2880        s.append(TK_LP, None)?;
2881        self.select.to_tokens(s)?;
2882        s.append(TK_RP, None)
2883    }
2884}
2885
2886impl CommonTableExpr {
2887    pub fn add_cte(
2888        ctes: &mut Vec<CommonTableExpr>,
2889        cte: CommonTableExpr,
2890    ) -> Result<(), ParserError> {
2891        if ctes
2892            .iter()
2893            .any(|c| c.tbl_name.0.eq_ignore_ascii_case(&cte.tbl_name.0))
2894        {
2895            return Err(ParserError::Custom(format!(
2896                "duplicate WITH table name: {}",
2897                cte.tbl_name
2898            )));
2899        }
2900        ctes.push(cte);
2901        Ok(())
2902    }
2903}
2904
2905// https://sqlite.org/syntax/type-name.html
2906#[derive(Clone, Debug, PartialEq, Eq)]
2907pub struct Type {
2908    pub name: String, // TODO Validate: Ids+
2909    pub size: Option<TypeSize>,
2910}
2911impl ToTokens for Type {
2912    fn to_tokens<S: TokenStream>(&self, s: &mut S) -> Result<(), S::Error> {
2913        match self.size {
2914            None => s.append(TK_ID, Some(&self.name)),
2915            Some(ref size) => {
2916                s.append(TK_ID, Some(&self.name))?; // TODO check there is no forbidden chars
2917                s.append(TK_LP, None)?;
2918                size.to_tokens(s)?;
2919                s.append(TK_RP, None)
2920            }
2921        }
2922    }
2923}
2924
2925// https://sqlite.org/syntax/type-name.html
2926#[derive(Clone, Debug, PartialEq, Eq)]
2927pub enum TypeSize {
2928    MaxSize(Box<Expr>),
2929    TypeSize(Box<Expr>, Box<Expr>),
2930}
2931
2932impl ToTokens for TypeSize {
2933    fn to_tokens<S: TokenStream>(&self, s: &mut S) -> Result<(), S::Error> {
2934        match self {
2935            TypeSize::MaxSize(size) => size.to_tokens(s),
2936            TypeSize::TypeSize(size1, size2) => {
2937                size1.to_tokens(s)?;
2938                s.append(TK_COMMA, None)?;
2939                size2.to_tokens(s)
2940            }
2941        }
2942    }
2943}
2944
2945#[derive(Copy, Clone, Debug, PartialEq, Eq)]
2946pub enum TransactionType {
2947    Deferred, // default
2948    Immediate,
2949    Exclusive,
2950    ReadOnly,
2951}
2952impl ToTokens for TransactionType {
2953    fn to_tokens<S: TokenStream>(&self, s: &mut S) -> Result<(), S::Error> {
2954        s.append(
2955            match self {
2956                TransactionType::Deferred => TK_DEFERRED,
2957                TransactionType::Immediate => TK_IMMEDIATE,
2958                TransactionType::Exclusive => TK_EXCLUSIVE,
2959                TransactionType::ReadOnly => TK_READONLY,
2960            },
2961            None,
2962        )
2963    }
2964}
2965
2966// https://sqlite.org/lang_upsert.html
2967// https://sqlite.org/syntax/upsert-clause.html
2968#[derive(Clone, Debug, PartialEq, Eq)]
2969pub struct Upsert {
2970    pub index: Option<UpsertIndex>,
2971    pub do_clause: UpsertDo,
2972    pub next: Option<Box<Upsert>>,
2973}
2974
2975impl ToTokens for Upsert {
2976    fn to_tokens<S: TokenStream>(&self, s: &mut S) -> Result<(), S::Error> {
2977        s.append(TK_ON, None)?;
2978        s.append(TK_CONFLICT, None)?;
2979        if let Some(ref index) = self.index {
2980            index.to_tokens(s)?;
2981        }
2982        self.do_clause.to_tokens(s)?;
2983        if let Some(ref next) = self.next {
2984            next.to_tokens(s)?;
2985        }
2986        Ok(())
2987    }
2988}
2989
2990#[derive(Clone, Debug, PartialEq, Eq)]
2991pub struct UpsertIndex {
2992    pub targets: Vec<SortedColumn>,
2993    pub where_clause: Option<Expr>,
2994}
2995
2996impl ToTokens for UpsertIndex {
2997    fn to_tokens<S: TokenStream>(&self, s: &mut S) -> Result<(), S::Error> {
2998        s.append(TK_LP, None)?;
2999        comma(&self.targets, s)?;
3000        s.append(TK_RP, None)?;
3001        if let Some(ref where_clause) = self.where_clause {
3002            s.append(TK_WHERE, None)?;
3003            where_clause.to_tokens(s)?;
3004        }
3005        Ok(())
3006    }
3007}
3008
3009#[derive(Clone, Debug, PartialEq, Eq)]
3010pub enum UpsertDo {
3011    Set {
3012        sets: Vec<Set>,
3013        where_clause: Option<Expr>,
3014    },
3015    Nothing,
3016}
3017
3018impl ToTokens for UpsertDo {
3019    fn to_tokens<S: TokenStream>(&self, s: &mut S) -> Result<(), S::Error> {
3020        match self {
3021            UpsertDo::Set { sets, where_clause } => {
3022                s.append(TK_DO, None)?;
3023                s.append(TK_UPDATE, None)?;
3024                s.append(TK_SET, None)?;
3025                comma(sets, s)?;
3026                if let Some(where_clause) = where_clause {
3027                    s.append(TK_WHERE, None)?;
3028                    where_clause.to_tokens(s)?;
3029                }
3030                Ok(())
3031            }
3032            UpsertDo::Nothing => {
3033                s.append(TK_DO, None)?;
3034                s.append(TK_NOTHING, None)
3035            }
3036        }
3037    }
3038}
3039
3040#[derive(Clone, Debug, PartialEq, Eq)]
3041pub struct FunctionTail {
3042    pub filter_clause: Option<Box<Expr>>,
3043    pub over_clause: Option<Box<Over>>,
3044}
3045impl ToTokens for FunctionTail {
3046    fn to_tokens<S: TokenStream>(&self, s: &mut S) -> Result<(), S::Error> {
3047        if let Some(ref filter_clause) = self.filter_clause {
3048            s.append(TK_FILTER, None)?;
3049            s.append(TK_LP, None)?;
3050            s.append(TK_WHERE, None)?;
3051            filter_clause.to_tokens(s)?;
3052            s.append(TK_RP, None)?;
3053        }
3054        if let Some(ref over_clause) = self.over_clause {
3055            s.append(TK_OVER, None)?;
3056            over_clause.to_tokens(s)?;
3057        }
3058        Ok(())
3059    }
3060}
3061
3062// https://sqlite.org/syntax/over-clause.html
3063#[derive(Clone, Debug, PartialEq, Eq)]
3064pub enum Over {
3065    Window(Window),
3066    Name(Name),
3067}
3068
3069impl ToTokens for Over {
3070    fn to_tokens<S: TokenStream>(&self, s: &mut S) -> Result<(), S::Error> {
3071        match self {
3072            Over::Window(ref window) => window.to_tokens(s),
3073            Over::Name(ref name) => name.to_tokens(s),
3074        }
3075    }
3076}
3077
3078#[derive(Clone, Debug, PartialEq, Eq)]
3079pub struct WindowDef {
3080    pub name: Name,
3081    pub window: Window,
3082}
3083impl ToTokens for WindowDef {
3084    fn to_tokens<S: TokenStream>(&self, s: &mut S) -> Result<(), S::Error> {
3085        self.name.to_tokens(s)?;
3086        s.append(TK_AS, None)?;
3087        self.window.to_tokens(s)
3088    }
3089}
3090
3091// https://sqlite.org/syntax/window-defn.html
3092#[derive(Clone, Debug, PartialEq, Eq)]
3093pub struct Window {
3094    pub base: Option<Name>,
3095    pub partition_by: Option<Vec<Expr>>,
3096    pub order_by: Option<Vec<SortedColumn>>,
3097    pub frame_clause: Option<FrameClause>,
3098}
3099
3100impl ToTokens for Window {
3101    fn to_tokens<S: TokenStream>(&self, s: &mut S) -> Result<(), S::Error> {
3102        s.append(TK_LP, None)?;
3103        if let Some(ref base) = self.base {
3104            base.to_tokens(s)?;
3105        }
3106        if let Some(ref partition_by) = self.partition_by {
3107            s.append(TK_PARTITION, None)?;
3108            s.append(TK_BY, None)?;
3109            comma(partition_by, s)?;
3110        }
3111        if let Some(ref order_by) = self.order_by {
3112            s.append(TK_ORDER, None)?;
3113            s.append(TK_BY, None)?;
3114            comma(order_by, s)?;
3115        }
3116        if let Some(ref frame_clause) = self.frame_clause {
3117            frame_clause.to_tokens(s)?;
3118        }
3119        s.append(TK_RP, None)
3120    }
3121}
3122
3123// https://sqlite.org/syntax/frame-spec.html
3124#[derive(Clone, Debug, PartialEq, Eq)]
3125pub struct FrameClause {
3126    pub mode: FrameMode,
3127    pub start: FrameBound,
3128    pub end: Option<FrameBound>,
3129    pub exclude: Option<FrameExclude>,
3130}
3131
3132impl ToTokens for FrameClause {
3133    fn to_tokens<S: TokenStream>(&self, s: &mut S) -> Result<(), S::Error> {
3134        self.mode.to_tokens(s)?;
3135        if let Some(ref end) = self.end {
3136            s.append(TK_BETWEEN, None)?;
3137            self.start.to_tokens(s)?;
3138            s.append(TK_AND, None)?;
3139            end.to_tokens(s)?;
3140        } else {
3141            self.start.to_tokens(s)?;
3142        }
3143        if let Some(ref exclude) = self.exclude {
3144            s.append(TK_EXCLUDE, None)?;
3145            exclude.to_tokens(s)?;
3146        }
3147        Ok(())
3148    }
3149}
3150
3151#[derive(Copy, Clone, Debug, PartialEq, Eq)]
3152pub enum FrameMode {
3153    Groups,
3154    Range,
3155    Rows,
3156}
3157
3158impl ToTokens for FrameMode {
3159    fn to_tokens<S: TokenStream>(&self, s: &mut S) -> Result<(), S::Error> {
3160        s.append(
3161            match self {
3162                FrameMode::Groups => TK_GROUPS,
3163                FrameMode::Range => TK_RANGE,
3164                FrameMode::Rows => TK_ROWS,
3165            },
3166            None,
3167        )
3168    }
3169}
3170
3171#[derive(Clone, Debug, PartialEq, Eq)]
3172pub enum FrameBound {
3173    CurrentRow,
3174    Following(Expr),
3175    Preceding(Expr),
3176    UnboundedFollowing,
3177    UnboundedPreceding,
3178}
3179
3180impl ToTokens for FrameBound {
3181    fn to_tokens<S: TokenStream>(&self, s: &mut S) -> Result<(), S::Error> {
3182        match self {
3183            FrameBound::CurrentRow => {
3184                s.append(TK_CURRENT, None)?;
3185                s.append(TK_ROW, None)
3186            }
3187            FrameBound::Following(value) => {
3188                value.to_tokens(s)?;
3189                s.append(TK_FOLLOWING, None)
3190            }
3191            FrameBound::Preceding(value) => {
3192                value.to_tokens(s)?;
3193                s.append(TK_PRECEDING, None)
3194            }
3195            FrameBound::UnboundedFollowing => {
3196                s.append(TK_UNBOUNDED, None)?;
3197                s.append(TK_FOLLOWING, None)
3198            }
3199            FrameBound::UnboundedPreceding => {
3200                s.append(TK_UNBOUNDED, None)?;
3201                s.append(TK_PRECEDING, None)
3202            }
3203        }
3204    }
3205}
3206
3207#[derive(Clone, Debug, PartialEq, Eq)]
3208pub enum FrameExclude {
3209    NoOthers,
3210    CurrentRow,
3211    Group,
3212    Ties,
3213}
3214
3215impl ToTokens for FrameExclude {
3216    fn to_tokens<S: TokenStream>(&self, s: &mut S) -> Result<(), S::Error> {
3217        match self {
3218            FrameExclude::NoOthers => {
3219                s.append(TK_NO, None)?;
3220                s.append(TK_OTHERS, None)
3221            }
3222            FrameExclude::CurrentRow => {
3223                s.append(TK_CURRENT, None)?;
3224                s.append(TK_ROW, None)
3225            }
3226            FrameExclude::Group => s.append(TK_GROUP, None),
3227            FrameExclude::Ties => s.append(TK_TIES, None),
3228        }
3229    }
3230}
3231
3232fn comma<I, S: TokenStream>(items: I, s: &mut S) -> Result<(), S::Error>
3233where
3234    I: IntoIterator,
3235    I::Item: ToTokens,
3236{
3237    let iter = items.into_iter();
3238    for (i, item) in iter.enumerate() {
3239        if i != 0 {
3240            s.append(TK_COMMA, None)?;
3241        }
3242        item.to_tokens(s)?;
3243    }
3244    Ok(())
3245}
3246
3247// TK_ID: [...] / `...` / "..." / some keywords / non keywords
3248fn double_quote<S: TokenStream>(name: &str, s: &mut S) -> Result<(), S::Error> {
3249    if name.is_empty() {
3250        return s.append(TK_ID, Some("\"\""));
3251    }
3252    if is_identifier(name) {
3253        // identifier must be quoted when they match a keyword...
3254        /*if is_keyword(name) {
3255            f.write_char('`')?;
3256            f.write_str(name)?;
3257            return f.write_char('`');
3258        }*/
3259        return s.append(TK_ID, Some(name));
3260    }
3261    /*f.write_char('"')?;
3262    for c in name.chars() {
3263        if c == '"' {
3264            f.write_char(c)?;
3265        }
3266        f.write_char(c)?;
3267    }
3268    f.write_char('"')*/
3269    s.append(TK_ID, Some(name))
3270}