vibesql_parser/
keywords.rs

1use std::fmt;
2
3/// SQL Keywords supported by the parser.
4#[derive(Debug, Clone, Copy, PartialEq, Eq)]
5pub enum Keyword {
6    Select,
7    Distinct,
8    From,
9    Where,
10    Insert,
11    Into,
12    Replace,
13    Ignore,
14    Update,
15    Delete,
16    Duplicate,
17    Create,
18    Table,
19    Truncate,
20    Drop,
21    Alter,
22    And,
23    Or,
24    Not,
25    Null,
26    True,
27    False,
28    Unknown,
29    As,
30    Join,
31    Left,
32    Right,
33    Inner,
34    Outer,
35    Cross,
36    Full,
37    Natural,
38    On,
39    Group,
40    Groups,
41    By,
42    // OLAP extensions for GROUP BY
43    Rollup,
44    Cube,
45    Sets,
46    Grouping,
47    GroupingId,
48    Having,
49    Order,
50    Asc,
51    Desc,
52    Nulls,
53    Limit,
54    Offset,
55    Set,
56    Values,
57    In,
58    Between,
59    Asymmetric,
60    Symmetric,
61    Like,
62    Glob,
63    Escape,
64    Exists,
65    If,
66    All,
67    Any,
68    Some,
69    Union,
70    Intersect,
71    Except,
72    With,
73    Recursive,
74    // CTE materialization hints (SQL:1999)
75    Materialized,
76    Date,
77    Time,
78    Timestamp,
79    Interval,
80    Cast,
81    // CASE expression keywords
82    Case,
83    When,
84    Then,
85    Else,
86    End,
87    // Window function keywords
88    Over,
89    Partition,
90    Rows,
91    Range,
92    Preceding,
93    Following,
94    Unbounded,
95    Current,
96    Filter,
97    Exclude,
98    Others,
99    Ties,
100    // Note: Window function names (ROW_NUMBER, RANK, etc.) are identifiers, not keywords
101    // Constraint keywords
102    Primary,
103    Foreign,
104    Key,
105    Unique,
106    Check,
107    References,
108    // IS NULL keywords
109    Is,
110    // SQLite ISNULL/NOTNULL postfix operators
111    Isnull,
112    Notnull,
113    // Transaction keywords
114    Begin,
115    Commit,
116    Rollback,
117    // SCHEMA keywords
118    Cascade,
119    Restrict,
120    Schema,
121    Start,
122    Transaction,
123    // ALTER TABLE keywords
124    Add,
125    Column,
126    Constraint,
127    Default,
128    Rename,
129    Modify,
130    Change,
131    // SAVEPOINT keywords
132    Savepoint,
133    Release,
134    To,
135    // Role management keywords
136    Role,
137    // TRIM function keywords
138    Both,
139    Leading,
140    Trailing,
141    // MySQL arithmetic operators
142    Div,
143    // Data type keywords
144    Varying,
145    Characters,
146    Octets,
147    Using,
148    // SUBSTRING function keywords
149    For,
150    // Current date/time function keywords
151    CurrentDate,
152    CurrentTime,
153    CurrentTimestamp,
154    // GRANT keywords
155    Grant,
156    Privileges,
157    Usage,
158    Option,
159    // REVOKE keywords
160    Revoke,
161    Granted,
162    // Advanced privilege keywords
163    Execute,
164    Trigger,
165    Under,
166    // Advanced SQL object keywords
167    Domain,
168    Sequence,
169    Type,
170    Collation,
171    Character,
172    Translation,
173    View,
174    Index,
175    Analyze,
176    Reindex,
177    Explain,
178    Assertion,
179    Specific,
180    // Trigger-specific keywords
181    Before,
182    After,
183    Instead,
184    Of,
185    Each,
186    Row,
187    Statement,
188    Enable,
189    Disable,
190    // SEQUENCE specific keywords
191    Increment,
192    Minvalue,
193    Maxvalue,
194    Cycle,
195    No,
196    Restart,
197    Next,
198    // Referential action keywords
199    Action,
200    // Constraint deferral keywords (SQL:1999)
201    Deferrable,
202    Deferred,
203    Immediate,
204    Initially,
205    // Session configuration keywords (SQL:1999)
206    Catalog,
207    Names,
208    Zone,
209    Local,
210    Session,
211    Global,
212    // Interval unit keywords
213    Year,
214    Quarter,
215    Month,
216    Week,
217    Day,
218    Hour,
219    Minute,
220    Second,
221    Microsecond,
222    // Callable object keywords (functions, procedures, methods)
223    Function,
224    Procedure,
225    Call,
226    Routine,
227    Method,
228    Constructor,
229    Static,
230    Instance,
231    // Procedure/Function parameter modes
232    Out,
233    InOut,
234    // Procedure/Function keywords
235    Returns,
236    While,
237    Do,
238    Loop,
239    Repeat,
240    Until,
241    Return,
242    Leave,
243    Iterate,
244    // Procedure/Function characteristics (Phase 6)
245    Deterministic,
246    Language,
247    Sql,
248    Security,
249    Definer,
250    Invoker,
251    // Internationalization keywords (SQL:1999)
252    Get,
253    Pad,
254    Space,
255    Collate,
256    // Generated column keywords (SQLite)
257    Generated,
258    Always,
259    Stored,
260    Virtual,
261    // CURSOR keywords
262    Declare,
263    Cursor,
264    Insensitive,
265    // Prepared statement keywords
266    Prepare,
267    Deallocate,
268    Scroll,
269    Hold,
270    Without,
271    Read,
272    Only,
273    Oids,
274    Rowid,
275    Open,
276    Fetch,
277    Close,
278    Prior,
279    First,
280    Last,
281    Absolute,
282    Relative,
283    Serializable,
284    Isolation,
285    Level,
286    Write,
287    Comment,
288    // MySQL table option keywords
289    KeyBlockSize,
290    Connection,
291    InsertMethod,
292    RowFormat,
293    DelayKeyWrite,
294    TableChecksum,
295    Checksum,
296    StatsSamplePages,
297    Password,
298    AvgRowLength,
299    MinRows,
300    MaxRows,
301    SecondaryEngine,
302    // MySQL table option values
303    Dynamic,
304    Fixed,
305    Compressed,
306    Redundant,
307    Compact,
308    // Full-text search keywords
309    Fulltext,
310    Match,
311    Against,
312    Boolean,
313    Expansion,
314    Mode,
315    Query,
316    Plan,
317    // Spatial index keywords
318    Spatial,
319    // Vector index keywords (IVFFlat, HNSW)
320    Ivfflat,
321    Hnsw,
322    Lists,
323    Probes,
324    EfConstruction,
325    EfSearch,
326    M,
327    // Database introspection keywords
328    Show,
329    Describe,
330    Databases,
331    Tables,
332    Columns,
333    Fields,
334    Indexes,
335    Keys,
336    // Auto-increment keywords (MySQL and SQLite)
337    AutoIncrement,
338    // Temporary object keywords (SQLite)
339    Temp,
340    Temporary,
341    // VibeSQL storage format keywords
342    Storage,
343    Columnar,
344    // Transaction durability hint keywords
345    Durability,
346    Lazy,
347    Durable,
348    Volatile,
349    // SQLite compatibility keywords
350    Pragma,
351    // SQLite conflict resolution keywords
352    Abort,
353    Fail,
354    Conflict,
355    Nothing,
356}
357
358impl Keyword {
359    /// Returns true if this keyword can be used as an unquoted column or table name.
360    /// These are "unreserved" keywords that are only treated as keywords in specific contexts.
361    ///
362    /// This follows SQLite's behavior where temporal type keywords (TIMESTAMP, DATE, TIME,
363    /// INTERVAL) and interval unit keywords (YEAR, MONTH, DAY, etc.) can be used as identifiers
364    /// without quoting.
365    ///
366    /// TYPE and SQL are also unreserved to match SQLite compatibility (neither is in SQLite's
367    /// 147-keyword reserved list). They work safely because:
368    /// - TYPE: Parser uses peek_next_keyword() for CREATE TYPE dispatch
369    /// - SQL: Only consumed after explicit LANGUAGE keyword in routines
370    pub fn can_be_identifier(&self) -> bool {
371        matches!(
372            self,
373            // Temporal type keywords
374            Keyword::Timestamp | Keyword::Date | Keyword::Time | Keyword::Interval |
375            // Interval unit keywords (used in EXTRACT, DATE_ADD, etc. but also valid as identifiers)
376            Keyword::Year | Keyword::Quarter | Keyword::Month | Keyword::Week |
377            Keyword::Day | Keyword::Hour | Keyword::Minute | Keyword::Second |
378            Keyword::Microsecond |
379            // SQLite compatibility: TYPE and SQL are not reserved in SQLite
380            // (allows unquoted access to sqlite_master.type and sqlite_master.sql columns)
381            // ROWID is the pseudo-column for implicit row IDs in SQLite tables
382            Keyword::Type | Keyword::Sql | Keyword::Rowid |
383            // Vector index parameter: M is only contextual in HNSW WITH clause
384            // SQLite TCL tests commonly use 'm' as a column name
385            Keyword::M |
386            // NULLS is only contextual in ORDER BY (NULLS FIRST/LAST)
387            // Can be used as identifier for table/column/CTE names
388            Keyword::Nulls |
389            // SQLite schema keywords: TEMP/TEMPORARY are valid schema names
390            // Allows three-part qualified names like temp.t1.column
391            Keyword::Temp | Keyword::Temporary |
392            // Procedure parameter direction keywords: OUT/INOUT are only meaningful
393            // in stored procedure contexts, safe to use as identifiers elsewhere
394            // SQLite TCL tests use 'out' as a CTE name
395            Keyword::Out | Keyword::InOut |
396            // Join keywords: SQLite allows these as identifiers (table/column/function names)
397            // when not in a join context. SQLite TCL tests (func8.test) use these extensively.
398            Keyword::Cross | Keyword::Full | Keyword::Inner | Keyword::Left |
399            Keyword::Natural | Keyword::Outer | Keyword::Right
400        )
401    }
402}
403
404impl fmt::Display for Keyword {
405    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
406        let keyword_str = match self {
407            Keyword::Select => "SELECT",
408            Keyword::Distinct => "DISTINCT",
409            Keyword::From => "FROM",
410            Keyword::Where => "WHERE",
411            Keyword::Insert => "INSERT",
412            Keyword::Into => "INTO",
413            Keyword::Replace => "REPLACE",
414            Keyword::Ignore => "IGNORE",
415            Keyword::Update => "UPDATE",
416            Keyword::Delete => "DELETE",
417            Keyword::Duplicate => "DUPLICATE",
418            Keyword::Create => "CREATE",
419            Keyword::Table => "TABLE",
420            Keyword::Truncate => "TRUNCATE",
421            Keyword::Drop => "DROP",
422            Keyword::Alter => "ALTER",
423            Keyword::And => "AND",
424            Keyword::Or => "OR",
425            Keyword::Not => "NOT",
426            Keyword::Null => "NULL",
427            Keyword::True => "TRUE",
428            Keyword::False => "FALSE",
429            Keyword::Unknown => "UNKNOWN",
430            Keyword::As => "AS",
431            Keyword::Join => "JOIN",
432            Keyword::Left => "LEFT",
433            Keyword::Right => "RIGHT",
434            Keyword::Inner => "INNER",
435            Keyword::Outer => "OUTER",
436            Keyword::Cross => "CROSS",
437            Keyword::Full => "FULL",
438            Keyword::Natural => "NATURAL",
439            Keyword::On => "ON",
440            Keyword::Group => "GROUP",
441            Keyword::Groups => "GROUPS",
442            Keyword::By => "BY",
443            Keyword::Rollup => "ROLLUP",
444            Keyword::Cube => "CUBE",
445            Keyword::Sets => "SETS",
446            Keyword::Grouping => "GROUPING",
447            Keyword::GroupingId => "GROUPING_ID",
448            Keyword::Having => "HAVING",
449            Keyword::Order => "ORDER",
450            Keyword::Asc => "ASC",
451            Keyword::Desc => "DESC",
452            Keyword::Nulls => "NULLS",
453            Keyword::Limit => "LIMIT",
454            Keyword::Offset => "OFFSET",
455            Keyword::Set => "SET",
456            Keyword::Values => "VALUES",
457            Keyword::In => "IN",
458            Keyword::Between => "BETWEEN",
459            Keyword::Asymmetric => "ASYMMETRIC",
460            Keyword::Symmetric => "SYMMETRIC",
461            Keyword::Like => "LIKE",
462            Keyword::Glob => "GLOB",
463            Keyword::Escape => "ESCAPE",
464            Keyword::Exists => "EXISTS",
465            Keyword::If => "IF",
466            Keyword::All => "ALL",
467            Keyword::Any => "ANY",
468            Keyword::Some => "SOME",
469            Keyword::Union => "UNION",
470            Keyword::Intersect => "INTERSECT",
471            Keyword::Except => "EXCEPT",
472            Keyword::With => "WITH",
473            Keyword::Recursive => "RECURSIVE",
474            Keyword::Materialized => "MATERIALIZED",
475            Keyword::Date => "DATE",
476            Keyword::Time => "TIME",
477            Keyword::Timestamp => "TIMESTAMP",
478            Keyword::Interval => "INTERVAL",
479            Keyword::Cast => "CAST",
480            Keyword::Case => "CASE",
481            Keyword::When => "WHEN",
482            Keyword::Then => "THEN",
483            Keyword::Else => "ELSE",
484            Keyword::End => "END",
485            Keyword::Over => "OVER",
486            Keyword::Partition => "PARTITION",
487            Keyword::Rows => "ROWS",
488            Keyword::Range => "RANGE",
489            Keyword::Preceding => "PRECEDING",
490            Keyword::Following => "FOLLOWING",
491            Keyword::Unbounded => "UNBOUNDED",
492            Keyword::Current => "CURRENT",
493            Keyword::Filter => "FILTER",
494            Keyword::Exclude => "EXCLUDE",
495            Keyword::Others => "OTHERS",
496            Keyword::Ties => "TIES",
497            Keyword::Primary => "PRIMARY",
498            Keyword::Foreign => "FOREIGN",
499            Keyword::Key => "KEY",
500            Keyword::Unique => "UNIQUE",
501            Keyword::Check => "CHECK",
502            Keyword::References => "REFERENCES",
503            Keyword::Is => "IS",
504            Keyword::Isnull => "ISNULL",
505            Keyword::Notnull => "NOTNULL",
506            Keyword::Begin => "BEGIN",
507            Keyword::Commit => "COMMIT",
508            Keyword::Rollback => "ROLLBACK",
509            Keyword::Cascade => "CASCADE",
510            Keyword::Restrict => "RESTRICT",
511            Keyword::Schema => "SCHEMA",
512            Keyword::Start => "START",
513            Keyword::Transaction => "TRANSACTION",
514            Keyword::Add => "ADD",
515            Keyword::Column => "COLUMN",
516            Keyword::Constraint => "CONSTRAINT",
517            Keyword::Default => "DEFAULT",
518            Keyword::Rename => "RENAME",
519            Keyword::Modify => "MODIFY",
520            Keyword::Change => "CHANGE",
521            Keyword::Savepoint => "SAVEPOINT",
522            Keyword::Release => "RELEASE",
523            Keyword::To => "TO",
524            Keyword::Role => "ROLE",
525            Keyword::Both => "BOTH",
526            Keyword::Leading => "LEADING",
527            Keyword::Trailing => "TRAILING",
528            Keyword::Div => "DIV",
529            Keyword::Varying => "VARYING",
530            Keyword::Characters => "CHARACTERS",
531            Keyword::Octets => "OCTETS",
532            Keyword::Using => "USING",
533            Keyword::For => "FOR",
534            Keyword::CurrentDate => "CURRENT_DATE",
535            Keyword::CurrentTime => "CURRENT_TIME",
536            Keyword::CurrentTimestamp => "CURRENT_TIMESTAMP",
537            Keyword::Grant => "GRANT",
538            Keyword::Privileges => "PRIVILEGES",
539            Keyword::Usage => "USAGE",
540            Keyword::Option => "OPTION",
541            Keyword::Revoke => "REVOKE",
542            Keyword::Granted => "GRANTED",
543            Keyword::Execute => "EXECUTE",
544            Keyword::Trigger => "TRIGGER",
545            Keyword::Under => "UNDER",
546            Keyword::Domain => "DOMAIN",
547            Keyword::Sequence => "SEQUENCE",
548            Keyword::Type => "TYPE",
549            Keyword::Collation => "COLLATION",
550            Keyword::Character => "CHARACTER",
551            Keyword::Translation => "TRANSLATION",
552            Keyword::View => "VIEW",
553            Keyword::Index => "INDEX",
554            Keyword::Analyze => "ANALYZE",
555            Keyword::Reindex => "REINDEX",
556            Keyword::Explain => "EXPLAIN",
557            Keyword::Assertion => "ASSERTION",
558            Keyword::Specific => "SPECIFIC",
559            Keyword::Before => "BEFORE",
560            Keyword::After => "AFTER",
561            Keyword::Instead => "INSTEAD",
562            Keyword::Of => "OF",
563            Keyword::Each => "EACH",
564            Keyword::Row => "ROW",
565            Keyword::Statement => "STATEMENT",
566            Keyword::Enable => "ENABLE",
567            Keyword::Disable => "DISABLE",
568            Keyword::Increment => "INCREMENT",
569            Keyword::Minvalue => "MINVALUE",
570            Keyword::Maxvalue => "MAXVALUE",
571            Keyword::Cycle => "CYCLE",
572            Keyword::No => "NO",
573            Keyword::Restart => "RESTART",
574            Keyword::Next => "NEXT",
575            Keyword::Action => "ACTION",
576            Keyword::Deferrable => "DEFERRABLE",
577            Keyword::Deferred => "DEFERRED",
578            Keyword::Immediate => "IMMEDIATE",
579            Keyword::Initially => "INITIALLY",
580            Keyword::Catalog => "CATALOG",
581            Keyword::Names => "NAMES",
582            Keyword::Zone => "ZONE",
583            Keyword::Local => "LOCAL",
584            Keyword::Session => "SESSION",
585            Keyword::Global => "GLOBAL",
586            Keyword::Year => "YEAR",
587            Keyword::Quarter => "QUARTER",
588            Keyword::Month => "MONTH",
589            Keyword::Week => "WEEK",
590            Keyword::Day => "DAY",
591            Keyword::Hour => "HOUR",
592            Keyword::Minute => "MINUTE",
593            Keyword::Second => "SECOND",
594            Keyword::Microsecond => "MICROSECOND",
595            Keyword::Function => "FUNCTION",
596            Keyword::Procedure => "PROCEDURE",
597            Keyword::Call => "CALL",
598            Keyword::Routine => "ROUTINE",
599            Keyword::Method => "METHOD",
600            Keyword::Constructor => "CONSTRUCTOR",
601            Keyword::Static => "STATIC",
602            Keyword::Instance => "INSTANCE",
603            Keyword::Out => "OUT",
604            Keyword::InOut => "INOUT",
605            Keyword::Returns => "RETURNS",
606            Keyword::While => "WHILE",
607            Keyword::Do => "DO",
608            Keyword::Loop => "LOOP",
609            Keyword::Repeat => "REPEAT",
610            Keyword::Until => "UNTIL",
611            Keyword::Return => "RETURN",
612            Keyword::Leave => "LEAVE",
613            Keyword::Iterate => "ITERATE",
614            Keyword::Deterministic => "DETERMINISTIC",
615            Keyword::Language => "LANGUAGE",
616            Keyword::Sql => "SQL",
617            Keyword::Security => "SECURITY",
618            Keyword::Definer => "DEFINER",
619            Keyword::Invoker => "INVOKER",
620            Keyword::Comment => "COMMENT",
621            Keyword::Get => "GET",
622            Keyword::Pad => "PAD",
623            Keyword::Space => "SPACE",
624            Keyword::Collate => "COLLATE",
625            Keyword::Generated => "GENERATED",
626            Keyword::Always => "ALWAYS",
627            Keyword::Stored => "STORED",
628            Keyword::Virtual => "VIRTUAL",
629            Keyword::Declare => "DECLARE",
630            Keyword::Cursor => "CURSOR",
631            Keyword::Insensitive => "INSENSITIVE",
632            Keyword::Prepare => "PREPARE",
633            Keyword::Deallocate => "DEALLOCATE",
634            Keyword::Scroll => "SCROLL",
635            Keyword::Hold => "HOLD",
636            Keyword::Without => "WITHOUT",
637            Keyword::Read => "READ",
638            Keyword::Only => "ONLY",
639            Keyword::Oids => "OIDS",
640            Keyword::Rowid => "ROWID",
641            Keyword::Open => "OPEN",
642            Keyword::Fetch => "FETCH",
643            Keyword::Close => "CLOSE",
644            Keyword::Prior => "PRIOR",
645            Keyword::First => "FIRST",
646            Keyword::Last => "LAST",
647            Keyword::Absolute => "ABSOLUTE",
648            Keyword::Relative => "RELATIVE",
649            Keyword::Serializable => "SERIALIZABLE",
650            Keyword::Isolation => "ISOLATION",
651            Keyword::Level => "LEVEL",
652            Keyword::Write => "WRITE",
653            // MySQL table option keywords
654            Keyword::KeyBlockSize => "KEY_BLOCK_SIZE",
655            Keyword::Connection => "CONNECTION",
656            Keyword::InsertMethod => "INSERT_METHOD",
657            Keyword::RowFormat => "ROW_FORMAT",
658            Keyword::DelayKeyWrite => "DELAY_KEY_WRITE",
659            Keyword::TableChecksum => "TABLE_CHECKSUM",
660            Keyword::Checksum => "CHECKSUM",
661            Keyword::StatsSamplePages => "STATS_SAMPLE_PAGES",
662            Keyword::Password => "PASSWORD",
663            Keyword::AvgRowLength => "AVG_ROW_LENGTH",
664            Keyword::MinRows => "MIN_ROWS",
665            Keyword::MaxRows => "MAX_ROWS",
666            Keyword::SecondaryEngine => "SECONDARY_ENGINE",
667            // MySQL table option values
668            Keyword::Dynamic => "DYNAMIC",
669            Keyword::Fixed => "FIXED",
670            Keyword::Compressed => "COMPRESSED",
671            Keyword::Redundant => "REDUNDANT",
672            Keyword::Compact => "COMPACT",
673            // Full-text search keywords
674            Keyword::Fulltext => "FULLTEXT",
675            Keyword::Match => "MATCH",
676            Keyword::Against => "AGAINST",
677            Keyword::Boolean => "BOOLEAN",
678            Keyword::Expansion => "EXPANSION",
679            Keyword::Mode => "MODE",
680            Keyword::Query => "QUERY",
681            Keyword::Plan => "PLAN",
682            // Spatial index keywords
683            Keyword::Spatial => "SPATIAL",
684            // Vector index keywords (IVFFlat, HNSW)
685            Keyword::Ivfflat => "IVFFLAT",
686            Keyword::Hnsw => "HNSW",
687            Keyword::Lists => "LISTS",
688            Keyword::Probes => "PROBES",
689            Keyword::EfConstruction => "EF_CONSTRUCTION",
690            Keyword::EfSearch => "EF_SEARCH",
691            Keyword::M => "M",
692            // Database introspection keywords
693            Keyword::Show => "SHOW",
694            Keyword::Describe => "DESCRIBE",
695            Keyword::Databases => "DATABASES",
696            Keyword::Tables => "TABLES",
697            Keyword::Columns => "COLUMNS",
698            Keyword::Fields => "FIELDS",
699            Keyword::Indexes => "INDEXES",
700            Keyword::Keys => "KEYS",
701            // Auto-increment keywords
702            Keyword::AutoIncrement => "AUTO_INCREMENT",
703            // Temporary object keywords
704            Keyword::Temp => "TEMP",
705            Keyword::Temporary => "TEMPORARY",
706            // VibeSQL storage format keywords
707            Keyword::Storage => "STORAGE",
708            Keyword::Columnar => "COLUMNAR",
709            // Transaction durability hint keywords
710            Keyword::Durability => "DURABILITY",
711            Keyword::Lazy => "LAZY",
712            Keyword::Durable => "DURABLE",
713            Keyword::Volatile => "VOLATILE",
714            // SQLite compatibility keywords
715            Keyword::Pragma => "PRAGMA",
716            // SQLite conflict resolution keywords
717            Keyword::Abort => "ABORT",
718            Keyword::Fail => "FAIL",
719            Keyword::Conflict => "CONFLICT",
720            Keyword::Nothing => "NOTHING",
721        };
722        write!(f, "{}", keyword_str)
723    }
724}