Skip to main content

fsqlite_parser/
token.rs

1// bd-2tu6: ยง10.1 SQL Token Types
2//
3// Every SQL token carries a discriminant and a byte-offset Span.
4// Keywords are their own variants for O(1) matching in the parser.
5
6use fsqlite_ast::Span;
7
8/// A single token produced by the lexer.
9#[derive(Debug, Clone, PartialEq)]
10pub struct Token {
11    /// The token discriminant.
12    pub kind: TokenKind,
13    /// Byte-offset span into the original source.
14    pub span: Span,
15    /// Line number (1-based) at the start of the token.
16    pub line: u32,
17    /// Column number (1-based) at the start of the token.
18    pub col: u32,
19}
20
21/// Token discriminant.
22///
23/// Organized by category: literals, identifiers, keywords (~120), operators,
24/// punctuation, and special tokens.
25#[derive(Debug, Clone, PartialEq)]
26pub enum TokenKind {
27    // === Literals ===
28    /// Integer literal: `42`, `-7`, `0xFF`.
29    Integer(i64),
30    /// Float literal: `3.14`, `1e10`, `.5`.
31    Float(f64),
32    /// String literal (single-quoted): `'hello'`.
33    String(String),
34    /// Blob literal: `X'CAFE'`.
35    Blob(Vec<u8>),
36
37    // === Identifiers ===
38    /// Unquoted identifier.
39    Id(String),
40    /// Quoted identifier (`"name"`, `[name]`, `` `name` ``).
41    /// The bool is the EP_DblQuoted flag (true if double-quoted).
42    QuotedId(String, bool),
43
44    // === Variables / bind parameters ===
45    /// `?` anonymous positional.
46    Question,
47    /// `?NNN` numbered positional.
48    QuestionNum(u32),
49    /// `:name` colon-prefixed named.
50    ColonParam(String),
51    /// `@name` at-prefixed named.
52    AtParam(String),
53    /// `$name` dollar-prefixed named.
54    DollarParam(String),
55
56    // === Operators ===
57    Plus,
58    Minus,
59    Star,
60    Slash,
61    Percent,
62    Ampersand,
63    Pipe,
64    Tilde,
65    ShiftLeft,
66    ShiftRight,
67    Eq,   // `=`
68    EqEq, // `==`
69    Ne,   // `!=`
70    LtGt, // `<>`
71    Lt,
72    Le,
73    Gt,
74    Ge,
75    Concat,      // `||`
76    Arrow,       // `->`
77    DoubleArrow, // `->>`
78
79    // === Punctuation ===
80    Dot,
81    Comma,
82    Semicolon,
83    LeftParen,
84    RightParen,
85
86    // === Keywords ===
87    KwAbort,
88    KwAction,
89    KwAdd,
90    KwAfter,
91    KwAll,
92    KwAlter,
93    KwAlways,
94    KwAnalyze,
95    KwAnd,
96    KwAs,
97    KwAsc,
98    KwAttach,
99    KwAutoincrement,
100    KwBefore,
101    KwBegin,
102    KwBetween,
103    KwBy,
104    KwCascade,
105    KwCase,
106    KwCast,
107    KwCheck,
108    KwCollate,
109    KwColumn,
110    KwCommit,
111    KwConcurrent,
112    KwConflict,
113    KwConstraint,
114    KwCreate,
115    KwCross,
116    KwCurrentDate,
117    KwCurrentTime,
118    KwCurrentTimestamp,
119    KwDatabase,
120    KwDefault,
121    KwDeferrable,
122    KwDeferred,
123    KwDelete,
124    KwDesc,
125    KwDetach,
126    KwDistinct,
127    KwDo,
128    KwDrop,
129    KwEach,
130    KwElse,
131    KwEnd,
132    KwEscape,
133    KwExcept,
134    KwExclude,
135    KwExclusive,
136    KwExists,
137    KwExplain,
138    KwFail,
139    KwFilter,
140    KwFirst,
141    KwFollowing,
142    KwFor,
143    KwForeign,
144    KwFrom,
145    KwFull,
146    KwGenerated,
147    KwGlob,
148    KwGroup,
149    KwGroups,
150    KwHaving,
151    KwIf,
152    KwIgnore,
153    KwImmediate,
154    KwIn,
155    KwIndex,
156    KwIndexed,
157    KwInitially,
158    KwInner,
159    KwInsert,
160    KwInstead,
161    KwIntersect,
162    KwInto,
163    KwIs,
164    KwIsnull,
165    KwJoin,
166    KwKey,
167    KwLast,
168    KwLeft,
169    KwLike,
170    KwLimit,
171    KwMatch,
172    KwMaterialized,
173    KwNatural,
174    KwNo,
175    KwNot,
176    KwNothing,
177    KwNotnull,
178    KwNull,
179    KwNulls,
180    KwOf,
181    KwOffset,
182    KwOn,
183    KwOr,
184    KwOrder,
185    KwOthers,
186    KwOuter,
187    KwOver,
188    KwPartition,
189    KwPlan,
190    KwPragma,
191    KwPreceding,
192    KwPrimary,
193    KwQuery,
194    KwRaise,
195    KwRange,
196    KwRecursive,
197    KwReferences,
198    KwRegexp,
199    KwReindex,
200    KwRelease,
201    KwRename,
202    KwReplace,
203    KwRestrict,
204    KwReturning,
205    KwRight,
206    KwRollback,
207    KwRow,
208    KwRows,
209    KwSavepoint,
210    KwSelect,
211    KwSet,
212    KwStored,
213    KwStrict,
214    KwTable,
215    KwTemp,
216    KwTemporary,
217    KwThen,
218    KwTies,
219    KwTo,
220    KwTransaction,
221    KwTrigger,
222    KwTrue,
223    KwFalse,
224    KwUnbounded,
225    KwUnion,
226    KwUnique,
227    KwUpdate,
228    KwUsing,
229    KwVacuum,
230    KwValues,
231    KwView,
232    KwVirtual,
233    KwWhen,
234    KwWhere,
235    KwWindow,
236    KwWith,
237    KwWithout,
238
239    // === Special ===
240    /// End of input.
241    Eof,
242    /// Lexer error (invalid input).
243    Error(String),
244}
245
246impl TokenKind {
247    /// Look up an identifier string to see if it's a keyword.
248    /// Returns the keyword variant if so, else `None`.
249    #[must_use]
250    #[allow(clippy::too_many_lines)]
251    pub fn lookup_keyword(s: &str) -> Option<Self> {
252        // Case-insensitive keyword matching.
253        // We uppercase for comparison since SQL keywords are case-insensitive.
254        match s.to_ascii_uppercase().as_str() {
255            "ABORT" => Some(Self::KwAbort),
256            "ACTION" => Some(Self::KwAction),
257            "ADD" => Some(Self::KwAdd),
258            "AFTER" => Some(Self::KwAfter),
259            "ALL" => Some(Self::KwAll),
260            "ALTER" => Some(Self::KwAlter),
261            "ALWAYS" => Some(Self::KwAlways),
262            "ANALYZE" => Some(Self::KwAnalyze),
263            "AND" => Some(Self::KwAnd),
264            "AS" => Some(Self::KwAs),
265            "ASC" => Some(Self::KwAsc),
266            "ATTACH" => Some(Self::KwAttach),
267            "AUTOINCREMENT" => Some(Self::KwAutoincrement),
268            "BEFORE" => Some(Self::KwBefore),
269            "BEGIN" => Some(Self::KwBegin),
270            "BETWEEN" => Some(Self::KwBetween),
271            "BY" => Some(Self::KwBy),
272            "CASCADE" => Some(Self::KwCascade),
273            "CASE" => Some(Self::KwCase),
274            "CAST" => Some(Self::KwCast),
275            "CHECK" => Some(Self::KwCheck),
276            "COLLATE" => Some(Self::KwCollate),
277            "COLUMN" => Some(Self::KwColumn),
278            "COMMIT" => Some(Self::KwCommit),
279            "CONCURRENT" => Some(Self::KwConcurrent),
280            "CONFLICT" => Some(Self::KwConflict),
281            "CONSTRAINT" => Some(Self::KwConstraint),
282            "CREATE" => Some(Self::KwCreate),
283            "CROSS" => Some(Self::KwCross),
284            "CURRENT_DATE" => Some(Self::KwCurrentDate),
285            "CURRENT_TIME" => Some(Self::KwCurrentTime),
286            "CURRENT_TIMESTAMP" => Some(Self::KwCurrentTimestamp),
287            "DATABASE" => Some(Self::KwDatabase),
288            "DEFAULT" => Some(Self::KwDefault),
289            "DEFERRABLE" => Some(Self::KwDeferrable),
290            "DEFERRED" => Some(Self::KwDeferred),
291            "DELETE" => Some(Self::KwDelete),
292            "DESC" => Some(Self::KwDesc),
293            "DETACH" => Some(Self::KwDetach),
294            "DISTINCT" => Some(Self::KwDistinct),
295            "DO" => Some(Self::KwDo),
296            "DROP" => Some(Self::KwDrop),
297            "EACH" => Some(Self::KwEach),
298            "ELSE" => Some(Self::KwElse),
299            "END" => Some(Self::KwEnd),
300            "ESCAPE" => Some(Self::KwEscape),
301            "EXCEPT" => Some(Self::KwExcept),
302            "EXCLUDE" => Some(Self::KwExclude),
303            "EXCLUSIVE" => Some(Self::KwExclusive),
304            "EXISTS" => Some(Self::KwExists),
305            "EXPLAIN" => Some(Self::KwExplain),
306            "FAIL" => Some(Self::KwFail),
307            "FILTER" => Some(Self::KwFilter),
308            "FIRST" => Some(Self::KwFirst),
309            "FOLLOWING" => Some(Self::KwFollowing),
310            "FOR" => Some(Self::KwFor),
311            "FOREIGN" => Some(Self::KwForeign),
312            "FROM" => Some(Self::KwFrom),
313            "FULL" => Some(Self::KwFull),
314            "GENERATED" => Some(Self::KwGenerated),
315            "GLOB" => Some(Self::KwGlob),
316            "GROUP" => Some(Self::KwGroup),
317            "GROUPS" => Some(Self::KwGroups),
318            "HAVING" => Some(Self::KwHaving),
319            "IF" => Some(Self::KwIf),
320            "IGNORE" => Some(Self::KwIgnore),
321            "IMMEDIATE" => Some(Self::KwImmediate),
322            "IN" => Some(Self::KwIn),
323            "INDEX" => Some(Self::KwIndex),
324            "INDEXED" => Some(Self::KwIndexed),
325            "INITIALLY" => Some(Self::KwInitially),
326            "INNER" => Some(Self::KwInner),
327            "INSERT" => Some(Self::KwInsert),
328            "INSTEAD" => Some(Self::KwInstead),
329            "INTERSECT" => Some(Self::KwIntersect),
330            "INTO" => Some(Self::KwInto),
331            "IS" => Some(Self::KwIs),
332            "ISNULL" => Some(Self::KwIsnull),
333            "JOIN" => Some(Self::KwJoin),
334            "KEY" => Some(Self::KwKey),
335            "LAST" => Some(Self::KwLast),
336            "LEFT" => Some(Self::KwLeft),
337            "LIKE" => Some(Self::KwLike),
338            "LIMIT" => Some(Self::KwLimit),
339            "MATCH" => Some(Self::KwMatch),
340            "MATERIALIZED" => Some(Self::KwMaterialized),
341            "NATURAL" => Some(Self::KwNatural),
342            "NO" => Some(Self::KwNo),
343            "NOT" => Some(Self::KwNot),
344            "NOTHING" => Some(Self::KwNothing),
345            "NOTNULL" => Some(Self::KwNotnull),
346            "NULL" => Some(Self::KwNull),
347            "NULLS" => Some(Self::KwNulls),
348            "OF" => Some(Self::KwOf),
349            "OFFSET" => Some(Self::KwOffset),
350            "ON" => Some(Self::KwOn),
351            "OR" => Some(Self::KwOr),
352            "ORDER" => Some(Self::KwOrder),
353            "OTHERS" => Some(Self::KwOthers),
354            "OUTER" => Some(Self::KwOuter),
355            "OVER" => Some(Self::KwOver),
356            "PARTITION" => Some(Self::KwPartition),
357            "PLAN" => Some(Self::KwPlan),
358            "PRAGMA" => Some(Self::KwPragma),
359            "PRECEDING" => Some(Self::KwPreceding),
360            "PRIMARY" => Some(Self::KwPrimary),
361            "QUERY" => Some(Self::KwQuery),
362            "RAISE" => Some(Self::KwRaise),
363            "RANGE" => Some(Self::KwRange),
364            "RECURSIVE" => Some(Self::KwRecursive),
365            "REFERENCES" => Some(Self::KwReferences),
366            "REGEXP" => Some(Self::KwRegexp),
367            "REINDEX" => Some(Self::KwReindex),
368            "RELEASE" => Some(Self::KwRelease),
369            "RENAME" => Some(Self::KwRename),
370            "REPLACE" => Some(Self::KwReplace),
371            "RESTRICT" => Some(Self::KwRestrict),
372            "RETURNING" => Some(Self::KwReturning),
373            "RIGHT" => Some(Self::KwRight),
374            "ROLLBACK" => Some(Self::KwRollback),
375            "ROW" => Some(Self::KwRow),
376            "ROWS" => Some(Self::KwRows),
377            "SAVEPOINT" => Some(Self::KwSavepoint),
378            "SELECT" => Some(Self::KwSelect),
379            "SET" => Some(Self::KwSet),
380            "STORED" => Some(Self::KwStored),
381            "STRICT" => Some(Self::KwStrict),
382            "TABLE" => Some(Self::KwTable),
383            "TEMP" => Some(Self::KwTemp),
384            "TEMPORARY" => Some(Self::KwTemporary),
385            "THEN" => Some(Self::KwThen),
386            "TIES" => Some(Self::KwTies),
387            "TO" => Some(Self::KwTo),
388            "TRANSACTION" => Some(Self::KwTransaction),
389            "TRIGGER" => Some(Self::KwTrigger),
390            "TRUE" => Some(Self::KwTrue),
391            "FALSE" => Some(Self::KwFalse),
392            "UNBOUNDED" => Some(Self::KwUnbounded),
393            "UNION" => Some(Self::KwUnion),
394            "UNIQUE" => Some(Self::KwUnique),
395            "UPDATE" => Some(Self::KwUpdate),
396            "USING" => Some(Self::KwUsing),
397            "VACUUM" => Some(Self::KwVacuum),
398            "VALUES" => Some(Self::KwValues),
399            "VIEW" => Some(Self::KwView),
400            "VIRTUAL" => Some(Self::KwVirtual),
401            "WHEN" => Some(Self::KwWhen),
402            "WHERE" => Some(Self::KwWhere),
403            "WINDOW" => Some(Self::KwWindow),
404            "WITH" => Some(Self::KwWith),
405            "WITHOUT" => Some(Self::KwWithout),
406            _ => None,
407        }
408    }
409
410    /// Returns true if this is a keyword that can start a statement.
411    /// Used by the parser for error recovery sync points.
412    #[must_use]
413    pub fn is_statement_start(&self) -> bool {
414        matches!(
415            self,
416            Self::KwSelect
417                | Self::KwInsert
418                | Self::KwUpdate
419                | Self::KwDelete
420                | Self::KwCreate
421                | Self::KwDrop
422                | Self::KwAlter
423                | Self::KwBegin
424                | Self::KwCommit
425                | Self::KwRollback
426                | Self::KwSavepoint
427                | Self::KwRelease
428                | Self::KwAttach
429                | Self::KwDetach
430                | Self::KwPragma
431                | Self::KwVacuum
432                | Self::KwReindex
433                | Self::KwAnalyze
434                | Self::KwExplain
435                | Self::KwWith
436                | Self::KwReplace
437        )
438    }
439
440    /// Reconstruct a SQL text fragment from this token kind.
441    ///
442    /// Used for opaque argument collection (e.g. virtual table args) where
443    /// the parser needs to produce readable SQL strings from tokenised input.
444    #[must_use]
445    #[allow(clippy::too_many_lines)]
446    pub fn to_sql(&self) -> String {
447        match self {
448            Self::Integer(i) => i.to_string(),
449            Self::Float(f) => format!("{f}"),
450            Self::String(s) => format!("'{}'", s.replace('\'', "''")),
451            Self::Blob(b) => {
452                use std::fmt::Write;
453                let mut hex = std::string::String::with_capacity(3 + b.len() * 2);
454                hex.push_str("X'");
455                for byte in b {
456                    let _ = write!(hex, "{byte:02X}");
457                }
458                hex.push('\'');
459                hex
460            }
461            Self::Id(s) | Self::Error(s) => s.clone(),
462            Self::QuotedId(s, _) => format!("\"{s}\""),
463            Self::Question => "?".to_owned(),
464            Self::QuestionNum(n) => format!("?{n}"),
465            Self::ColonParam(s) => format!(":{s}"),
466            Self::AtParam(s) => format!("@{s}"),
467            Self::DollarParam(s) => format!("${s}"),
468            Self::Plus => "+".to_owned(),
469            Self::Minus => "-".to_owned(),
470            Self::Star => "*".to_owned(),
471            Self::Slash => "/".to_owned(),
472            Self::Percent => "%".to_owned(),
473            Self::Ampersand => "&".to_owned(),
474            Self::Pipe => "|".to_owned(),
475            Self::Tilde => "~".to_owned(),
476            Self::ShiftLeft => "<<".to_owned(),
477            Self::ShiftRight => ">>".to_owned(),
478            Self::Eq => "=".to_owned(),
479            Self::EqEq => "==".to_owned(),
480            Self::Ne => "!=".to_owned(),
481            Self::LtGt => "<>".to_owned(),
482            Self::Lt => "<".to_owned(),
483            Self::Le => "<=".to_owned(),
484            Self::Gt => ">".to_owned(),
485            Self::Ge => ">=".to_owned(),
486            Self::Concat => "||".to_owned(),
487            Self::Arrow => "->".to_owned(),
488            Self::DoubleArrow => "->>".to_owned(),
489            Self::Dot => ".".to_owned(),
490            Self::Comma => ",".to_owned(),
491            Self::Semicolon => ";".to_owned(),
492            Self::LeftParen => "(".to_owned(),
493            Self::RightParen => ")".to_owned(),
494            Self::Eof => String::new(),
495            // Keywords: return the uppercase SQL keyword text.
496            kw => kw.keyword_str().unwrap_or_default().to_owned(),
497        }
498    }
499
500    /// Return the SQL keyword text for keyword variants.
501    #[must_use]
502    #[allow(clippy::too_many_lines)]
503    pub const fn keyword_str(&self) -> Option<&'static str> {
504        match self {
505            Self::KwAbort => Some("ABORT"),
506            Self::KwAction => Some("ACTION"),
507            Self::KwAdd => Some("ADD"),
508            Self::KwAfter => Some("AFTER"),
509            Self::KwAll => Some("ALL"),
510            Self::KwAlter => Some("ALTER"),
511            Self::KwAlways => Some("ALWAYS"),
512            Self::KwAnalyze => Some("ANALYZE"),
513            Self::KwAnd => Some("AND"),
514            Self::KwAs => Some("AS"),
515            Self::KwAsc => Some("ASC"),
516            Self::KwAttach => Some("ATTACH"),
517            Self::KwAutoincrement => Some("AUTOINCREMENT"),
518            Self::KwBefore => Some("BEFORE"),
519            Self::KwBegin => Some("BEGIN"),
520            Self::KwBetween => Some("BETWEEN"),
521            Self::KwBy => Some("BY"),
522            Self::KwCascade => Some("CASCADE"),
523            Self::KwCase => Some("CASE"),
524            Self::KwCast => Some("CAST"),
525            Self::KwCheck => Some("CHECK"),
526            Self::KwCollate => Some("COLLATE"),
527            Self::KwColumn => Some("COLUMN"),
528            Self::KwCommit => Some("COMMIT"),
529            Self::KwConcurrent => Some("CONCURRENT"),
530            Self::KwConflict => Some("CONFLICT"),
531            Self::KwConstraint => Some("CONSTRAINT"),
532            Self::KwCreate => Some("CREATE"),
533            Self::KwCross => Some("CROSS"),
534            Self::KwCurrentDate => Some("CURRENT_DATE"),
535            Self::KwCurrentTime => Some("CURRENT_TIME"),
536            Self::KwCurrentTimestamp => Some("CURRENT_TIMESTAMP"),
537            Self::KwDatabase => Some("DATABASE"),
538            Self::KwDefault => Some("DEFAULT"),
539            Self::KwDeferrable => Some("DEFERRABLE"),
540            Self::KwDeferred => Some("DEFERRED"),
541            Self::KwDelete => Some("DELETE"),
542            Self::KwDesc => Some("DESC"),
543            Self::KwDetach => Some("DETACH"),
544            Self::KwDistinct => Some("DISTINCT"),
545            Self::KwDo => Some("DO"),
546            Self::KwDrop => Some("DROP"),
547            Self::KwEach => Some("EACH"),
548            Self::KwElse => Some("ELSE"),
549            Self::KwEnd => Some("END"),
550            Self::KwEscape => Some("ESCAPE"),
551            Self::KwExcept => Some("EXCEPT"),
552            Self::KwExclude => Some("EXCLUDE"),
553            Self::KwExclusive => Some("EXCLUSIVE"),
554            Self::KwExists => Some("EXISTS"),
555            Self::KwExplain => Some("EXPLAIN"),
556            Self::KwFail => Some("FAIL"),
557            Self::KwFilter => Some("FILTER"),
558            Self::KwFirst => Some("FIRST"),
559            Self::KwFollowing => Some("FOLLOWING"),
560            Self::KwFor => Some("FOR"),
561            Self::KwForeign => Some("FOREIGN"),
562            Self::KwFrom => Some("FROM"),
563            Self::KwFull => Some("FULL"),
564            Self::KwGenerated => Some("GENERATED"),
565            Self::KwGlob => Some("GLOB"),
566            Self::KwGroup => Some("GROUP"),
567            Self::KwGroups => Some("GROUPS"),
568            Self::KwHaving => Some("HAVING"),
569            Self::KwIf => Some("IF"),
570            Self::KwIgnore => Some("IGNORE"),
571            Self::KwImmediate => Some("IMMEDIATE"),
572            Self::KwIn => Some("IN"),
573            Self::KwIndex => Some("INDEX"),
574            Self::KwIndexed => Some("INDEXED"),
575            Self::KwInitially => Some("INITIALLY"),
576            Self::KwInner => Some("INNER"),
577            Self::KwInsert => Some("INSERT"),
578            Self::KwInstead => Some("INSTEAD"),
579            Self::KwIntersect => Some("INTERSECT"),
580            Self::KwInto => Some("INTO"),
581            Self::KwIs => Some("IS"),
582            Self::KwIsnull => Some("ISNULL"),
583            Self::KwJoin => Some("JOIN"),
584            Self::KwKey => Some("KEY"),
585            Self::KwLast => Some("LAST"),
586            Self::KwLeft => Some("LEFT"),
587            Self::KwLike => Some("LIKE"),
588            Self::KwLimit => Some("LIMIT"),
589            Self::KwMatch => Some("MATCH"),
590            Self::KwMaterialized => Some("MATERIALIZED"),
591            Self::KwNatural => Some("NATURAL"),
592            Self::KwNo => Some("NO"),
593            Self::KwNot => Some("NOT"),
594            Self::KwNothing => Some("NOTHING"),
595            Self::KwNotnull => Some("NOTNULL"),
596            Self::KwNull => Some("NULL"),
597            Self::KwNulls => Some("NULLS"),
598            Self::KwOf => Some("OF"),
599            Self::KwOffset => Some("OFFSET"),
600            Self::KwOn => Some("ON"),
601            Self::KwOr => Some("OR"),
602            Self::KwOrder => Some("ORDER"),
603            Self::KwOthers => Some("OTHERS"),
604            Self::KwOuter => Some("OUTER"),
605            Self::KwOver => Some("OVER"),
606            Self::KwPartition => Some("PARTITION"),
607            Self::KwPlan => Some("PLAN"),
608            Self::KwPragma => Some("PRAGMA"),
609            Self::KwPreceding => Some("PRECEDING"),
610            Self::KwPrimary => Some("PRIMARY"),
611            Self::KwQuery => Some("QUERY"),
612            Self::KwRaise => Some("RAISE"),
613            Self::KwRange => Some("RANGE"),
614            Self::KwRecursive => Some("RECURSIVE"),
615            Self::KwReferences => Some("REFERENCES"),
616            Self::KwRegexp => Some("REGEXP"),
617            Self::KwReindex => Some("REINDEX"),
618            Self::KwRelease => Some("RELEASE"),
619            Self::KwRename => Some("RENAME"),
620            Self::KwReplace => Some("REPLACE"),
621            Self::KwRestrict => Some("RESTRICT"),
622            Self::KwReturning => Some("RETURNING"),
623            Self::KwRight => Some("RIGHT"),
624            Self::KwRollback => Some("ROLLBACK"),
625            Self::KwRow => Some("ROW"),
626            Self::KwRows => Some("ROWS"),
627            Self::KwSavepoint => Some("SAVEPOINT"),
628            Self::KwSelect => Some("SELECT"),
629            Self::KwSet => Some("SET"),
630            Self::KwStored => Some("STORED"),
631            Self::KwStrict => Some("STRICT"),
632            Self::KwTable => Some("TABLE"),
633            Self::KwTemp => Some("TEMP"),
634            Self::KwTemporary => Some("TEMPORARY"),
635            Self::KwThen => Some("THEN"),
636            Self::KwTies => Some("TIES"),
637            Self::KwTo => Some("TO"),
638            Self::KwTransaction => Some("TRANSACTION"),
639            Self::KwTrigger => Some("TRIGGER"),
640            Self::KwTrue => Some("TRUE"),
641            Self::KwFalse => Some("FALSE"),
642            Self::KwUnbounded => Some("UNBOUNDED"),
643            Self::KwUnion => Some("UNION"),
644            Self::KwUnique => Some("UNIQUE"),
645            Self::KwUpdate => Some("UPDATE"),
646            Self::KwUsing => Some("USING"),
647            Self::KwVacuum => Some("VACUUM"),
648            Self::KwValues => Some("VALUES"),
649            Self::KwView => Some("VIEW"),
650            Self::KwVirtual => Some("VIRTUAL"),
651            Self::KwWhen => Some("WHEN"),
652            Self::KwWhere => Some("WHERE"),
653            Self::KwWindow => Some("WINDOW"),
654            Self::KwWith => Some("WITH"),
655            Self::KwWithout => Some("WITHOUT"),
656            _ => None,
657        }
658    }
659}