Skip to main content

sochdb_query/sql/
parser.rs

1// SPDX-License-Identifier: AGPL-3.0-or-later
2// SochDB - LLM-Optimized Embedded Database
3// Copyright (C) 2026 Sushanth Reddy Vanagala (https://github.com/sushanthpy)
4//
5// This program is free software: you can redistribute it and/or modify
6// it under the terms of the GNU Affero General Public License as published by
7// the Free Software Foundation, either version 3 of the License, or
8// (at your option) any later version.
9//
10// This program is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13// GNU Affero General Public License for more details.
14//
15// You should have received a copy of the GNU Affero General Public License
16// along with this program. If not, see <https://www.gnu.org/licenses/>.
17
18//! SQL Parser
19//!
20//! Recursive descent parser for SQL grammar.
21//! Produces AST from token stream.
22
23use super::ast::*;
24use super::lexer::Lexer;
25use super::token::{Span, Token, TokenKind};
26
27/// Parser errors
28#[derive(Debug, Clone)]
29pub struct ParseError {
30    pub message: String,
31    pub span: Span,
32    pub expected: Vec<String>,
33}
34
35impl ParseError {
36    pub fn new(message: impl Into<String>, span: Span) -> Self {
37        Self {
38            message: message.into(),
39            span,
40            expected: Vec::new(),
41        }
42    }
43
44    pub fn expected(mut self, expected: impl Into<String>) -> Self {
45        self.expected.push(expected.into());
46        self
47    }
48}
49
50impl std::fmt::Display for ParseError {
51    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
52        write!(
53            f,
54            "Parse error at line {}, column {}: {}",
55            self.span.line, self.span.column, self.message
56        )?;
57        if !self.expected.is_empty() {
58            write!(f, " (expected: {})", self.expected.join(", "))?;
59        }
60        Ok(())
61    }
62}
63
64impl std::error::Error for ParseError {}
65
66/// Maximum expression nesting depth. Recursive-descent expression parsing
67/// (`parse_expr` → … → `parse_primary_expr` → `parse_expr` on `(`, subscript,
68/// CASE, etc.) has no natural bound, so a pathological input like
69/// `((((((…))))))` or `NOT NOT NOT …` would recurse until the thread stack
70/// overflows and the process aborts (SIGABRT) — a DoS on attacker-controlled
71/// SQL. We cap depth and return a parse error instead. 256 is far deeper than
72/// any legitimate query yet leaves ample stack headroom.
73const MAX_EXPR_DEPTH: usize = 256;
74
75/// SQL Parser
76pub struct Parser<'a> {
77    tokens: Vec<Token<'a>>,
78    pos: usize,
79    /// Current expression-recursion depth (see [`MAX_EXPR_DEPTH`]).
80    depth: usize,
81}
82
83impl<'a> Parser<'a> {
84    /// Create a new parser from tokens
85    pub fn new(tokens: Vec<Token<'a>>) -> Self {
86        Self {
87            tokens,
88            pos: 0,
89            depth: 0,
90        }
91    }
92
93    /// Parse a SQL string into a statement
94    pub fn parse(sql: &str) -> Result<Statement, Vec<ParseError>> {
95        let tokens = Lexer::new(sql).tokenize().map_err(|lex_errors| {
96            lex_errors
97                .into_iter()
98                .map(|e| ParseError::new(e.message, e.span))
99                .collect::<Vec<_>>()
100        })?;
101
102        let mut parser = Parser::new(tokens);
103        parser.parse_statement()
104    }
105
106    /// Parse multiple statements (semicolon-separated)
107    pub fn parse_statements(sql: &str) -> Result<Vec<Statement>, Vec<ParseError>> {
108        let tokens = Lexer::new(sql).tokenize().map_err(|lex_errors| {
109            lex_errors
110                .into_iter()
111                .map(|e| ParseError::new(e.message, e.span))
112                .collect::<Vec<_>>()
113        })?;
114
115        let mut parser = Parser::new(tokens);
116        let mut statements = Vec::new();
117
118        while !parser.is_at_end() {
119            match parser.parse_statement() {
120                Ok(stmt) => {
121                    statements.push(stmt);
122                    // Consume optional semicolon
123                    parser.match_token(&TokenKind::Semicolon);
124                }
125                Err(errors) => return Err(errors),
126            }
127        }
128
129        Ok(statements)
130    }
131
132    // ========== Helper Methods ==========
133
134    fn is_at_end(&self) -> bool {
135        matches!(self.peek().kind, TokenKind::Eof)
136    }
137
138    fn peek(&self) -> &Token<'a> {
139        self.tokens
140            .get(self.pos)
141            .unwrap_or(&self.tokens[self.tokens.len() - 1])
142    }
143
144    fn peek_nth(&self, n: usize) -> &Token<'a> {
145        self.tokens
146            .get(self.pos + n)
147            .unwrap_or(&self.tokens[self.tokens.len() - 1])
148    }
149
150    fn advance(&mut self) -> Token<'a> {
151        if !self.is_at_end() {
152            self.pos += 1;
153        }
154        self.tokens.get(self.pos - 1).cloned().unwrap()
155    }
156
157    fn check(&self, kind: &TokenKind<'a>) -> bool {
158        std::mem::discriminant(&self.peek().kind) == std::mem::discriminant(kind)
159    }
160
161    fn check_keyword(&self, kw: &TokenKind<'a>) -> bool {
162        self.peek().kind == *kw
163    }
164
165    fn match_token(&mut self, kind: &TokenKind<'a>) -> bool {
166        if self.check(kind) {
167            self.advance();
168            true
169        } else {
170            false
171        }
172    }
173
174    fn expect(&mut self, kind: &TokenKind<'a>, message: &str) -> Result<Token<'a>, ParseError> {
175        if self.check(kind) {
176            Ok(self.advance())
177        } else {
178            Err(ParseError::new(message, self.peek().span).expected(format!("{:?}", kind)))
179        }
180    }
181
182    fn expect_identifier(&mut self, message: &str) -> Result<String, ParseError> {
183        match &self.peek().kind {
184            TokenKind::Identifier(name) => {
185                let name = name.to_string();
186                self.advance();
187                Ok(name)
188            }
189            TokenKind::QuotedIdentifier(name) => {
190                let name = name.to_string();
191                self.advance();
192                Ok(name)
193            }
194            _ => Err(ParseError::new(message, self.peek().span).expected("identifier")),
195        }
196    }
197
198    fn current_span(&self) -> Span {
199        self.peek().span
200    }
201
202    // ========== Statement Parsing ==========
203
204    fn parse_statement(&mut self) -> Result<Statement, Vec<ParseError>> {
205        let result = match &self.peek().kind {
206            TokenKind::Select => self.parse_select().map(Statement::Select),
207            TokenKind::Insert => self.parse_insert().map(Statement::Insert),
208            TokenKind::Update => self.parse_update().map(Statement::Update),
209            TokenKind::Delete => self.parse_delete().map(Statement::Delete),
210            TokenKind::Create => self.parse_create(),
211            TokenKind::Drop => self.parse_drop(),
212            TokenKind::Alter => self.parse_alter(),
213            TokenKind::Define => self.parse_define(),
214            TokenKind::Remove => self.parse_remove(),
215            TokenKind::Begin => self.parse_begin().map(Statement::Begin),
216            TokenKind::Commit => {
217                self.advance();
218                Ok(Statement::Commit)
219            }
220            TokenKind::Rollback => self.parse_rollback(),
221            TokenKind::Savepoint => self.parse_savepoint(),
222            TokenKind::Release => self.parse_release(),
223            // Graph & Real-Time
224            TokenKind::Relate => self.parse_relate().map(Statement::Relate),
225            TokenKind::Live => self.parse_live_select().map(Statement::LiveSelect),
226            _ => Err(ParseError::new(
227                format!("Unexpected token: {:?}", self.peek().kind),
228                self.peek().span,
229            )),
230        };
231
232        result.map_err(|e| vec![e])
233    }
234
235    // ========== SELECT Parsing ==========
236
237    fn parse_select(&mut self) -> Result<SelectStmt, ParseError> {
238        let start_span = self.current_span();
239        self.expect(&TokenKind::Select, "Expected SELECT")?;
240
241        // DISTINCT?
242        let distinct = self.match_token(&TokenKind::Distinct);
243        if !distinct {
244            self.match_token(&TokenKind::All);
245        }
246
247        // Select list
248        let columns = self.parse_select_list()?;
249
250        // FROM clause (optional for SELECT 1+1 style queries)
251        let from = if self.match_token(&TokenKind::From) {
252            Some(self.parse_from_clause()?)
253        } else {
254            None
255        };
256
257        // WHERE clause
258        let where_clause = if self.match_token(&TokenKind::Where) {
259            Some(self.parse_expr()?)
260        } else {
261            None
262        };
263
264        // GROUP BY clause
265        let group_by = if self.check_keyword(&TokenKind::Group) {
266            self.advance();
267            self.expect(&TokenKind::By, "Expected BY after GROUP")?;
268            self.parse_expr_list()?
269        } else {
270            Vec::new()
271        };
272
273        // HAVING clause
274        let having = if self.match_token(&TokenKind::Having) {
275            Some(self.parse_expr()?)
276        } else {
277            None
278        };
279
280        // ORDER BY clause
281        let order_by = if self.check_keyword(&TokenKind::Order) {
282            self.advance();
283            self.expect(&TokenKind::By, "Expected BY after ORDER")?;
284            self.parse_order_by_list()?
285        } else {
286            Vec::new()
287        };
288
289        // LIMIT clause
290        let limit = if self.match_token(&TokenKind::Limit) {
291            Some(self.parse_expr()?)
292        } else {
293            None
294        };
295
296        // OFFSET clause
297        let offset = if self.match_token(&TokenKind::Offset) {
298            Some(self.parse_expr()?)
299        } else {
300            None
301        };
302
303        // Set operations (UNION, INTERSECT, EXCEPT)
304        let mut unions = Vec::new();
305        loop {
306            let set_op = if self.match_token(&TokenKind::Union) {
307                if self.match_token(&TokenKind::All) {
308                    SetOp::UnionAll
309                } else {
310                    SetOp::Union
311                }
312            } else if self.match_token(&TokenKind::Intersect) {
313                if self.match_token(&TokenKind::All) {
314                    SetOp::IntersectAll
315                } else {
316                    SetOp::Intersect
317                }
318            } else if self.match_token(&TokenKind::Except) {
319                if self.match_token(&TokenKind::All) {
320                    SetOp::ExceptAll
321                } else {
322                    SetOp::Except
323                }
324            } else {
325                break;
326            };
327
328            let right = self.parse_select()?;
329            unions.push((set_op, Box::new(right)));
330        }
331
332        Ok(SelectStmt {
333            span: start_span.merge(self.current_span()),
334            distinct,
335            columns,
336            from,
337            where_clause,
338            group_by,
339            having,
340            order_by,
341            limit,
342            offset,
343            unions,
344        })
345    }
346
347    fn parse_select_list(&mut self) -> Result<Vec<SelectItem>, ParseError> {
348        let mut items = Vec::new();
349
350        loop {
351            items.push(self.parse_select_item()?);
352
353            if !self.match_token(&TokenKind::Comma) {
354                break;
355            }
356        }
357
358        Ok(items)
359    }
360
361    fn parse_select_item(&mut self) -> Result<SelectItem, ParseError> {
362        // Check for *
363        if self.match_token(&TokenKind::Star) {
364            return Ok(SelectItem::Wildcard);
365        }
366
367        // Check for table.*
368        if let TokenKind::Identifier(name) = &self.peek().kind
369            && self.peek_nth(1).kind == TokenKind::Dot
370            && self.peek_nth(2).kind == TokenKind::Star
371        {
372            let table = name.to_string();
373            self.advance(); // identifier
374            self.advance(); // .
375            self.advance(); // *
376            return Ok(SelectItem::QualifiedWildcard(table));
377        }
378
379        // Expression with optional alias
380        let expr = self.parse_expr()?;
381
382        let alias = if self.match_token(&TokenKind::As) {
383            Some(self.expect_identifier("Expected alias after AS")?)
384        } else if let TokenKind::Identifier(name) = &self.peek().kind {
385            // Implicit alias (without AS)
386            if !self.check_keyword(&TokenKind::From)
387                && !self.check_keyword(&TokenKind::Where)
388                && !self.check(&TokenKind::Comma)
389                && !self.check_keyword(&TokenKind::Order)
390                && !self.check_keyword(&TokenKind::Group)
391                && !self.check_keyword(&TokenKind::Limit)
392                && !self.is_at_end()
393            {
394                let name = name.to_string();
395                self.advance();
396                Some(name)
397            } else {
398                None
399            }
400        } else {
401            None
402        };
403
404        Ok(SelectItem::Expr { expr, alias })
405    }
406
407    fn parse_from_clause(&mut self) -> Result<FromClause, ParseError> {
408        let mut tables = vec![self.parse_table_ref()?];
409
410        while self.match_token(&TokenKind::Comma) {
411            tables.push(self.parse_table_ref()?);
412        }
413
414        Ok(FromClause { tables })
415    }
416
417    fn parse_table_ref(&mut self) -> Result<TableRef, ParseError> {
418        let mut table = self.parse_table_primary()?;
419
420        // Parse joins
421        loop {
422            let join_type = if self.match_token(&TokenKind::Cross) {
423                self.expect(&TokenKind::Join, "Expected JOIN after CROSS")?;
424                JoinType::Cross
425            } else if self.match_token(&TokenKind::Inner) {
426                self.expect(&TokenKind::Join, "Expected JOIN after INNER")?;
427                JoinType::Inner
428            } else if self.match_token(&TokenKind::Left) {
429                self.match_token(&TokenKind::Outer);
430                self.expect(&TokenKind::Join, "Expected JOIN after LEFT")?;
431                JoinType::Left
432            } else if self.match_token(&TokenKind::Right) {
433                self.match_token(&TokenKind::Outer);
434                self.expect(&TokenKind::Join, "Expected JOIN after RIGHT")?;
435                JoinType::Right
436            } else if self.match_token(&TokenKind::Join) {
437                JoinType::Inner // Default join is INNER
438            } else {
439                break;
440            };
441
442            let right = self.parse_table_primary()?;
443
444            let condition = if join_type == JoinType::Cross {
445                None
446            } else if self.match_token(&TokenKind::On) {
447                Some(JoinCondition::On(self.parse_expr()?))
448            } else if self.match_token(&TokenKind::Using) {
449                self.expect(&TokenKind::LParen, "Expected '(' after USING")?;
450                let columns = self.parse_identifier_list()?;
451                self.expect(&TokenKind::RParen, "Expected ')' after USING columns")?;
452                Some(JoinCondition::Using(columns))
453            } else {
454                return Err(ParseError::new(
455                    "Expected ON or USING clause for JOIN",
456                    self.current_span(),
457                ));
458            };
459
460            table = TableRef::Join {
461                left: Box::new(table),
462                join_type,
463                right: Box::new(right),
464                condition,
465            };
466        }
467
468        Ok(table)
469    }
470
471    fn parse_table_primary(&mut self) -> Result<TableRef, ParseError> {
472        // Subquery: (SELECT ...)
473        if self.match_token(&TokenKind::LParen) {
474            let query = self.parse_select()?;
475            self.expect(&TokenKind::RParen, "Expected ')' after subquery")?;
476
477            self.match_token(&TokenKind::As);
478            let alias = self.expect_identifier("Subquery requires an alias")?;
479
480            return Ok(TableRef::Subquery {
481                query: Box::new(query),
482                alias,
483            });
484        }
485
486        // Table name
487        let name = self.parse_object_name()?;
488
489        // Optional alias
490        let alias = if self.match_token(&TokenKind::As) {
491            Some(self.expect_identifier("Expected alias after AS")?)
492        } else if let TokenKind::Identifier(id) = &self.peek().kind {
493            // Check it's not a keyword
494            if !self.peek().kind.is_keyword() {
495                let alias = id.to_string();
496                self.advance();
497                Some(alias)
498            } else {
499                None
500            }
501        } else {
502            None
503        };
504
505        Ok(TableRef::Table { name, alias })
506    }
507
508    // ========== INSERT Parsing ==========
509
510    fn parse_insert(&mut self) -> Result<InsertStmt, ParseError> {
511        let start_span = self.current_span();
512        self.expect(&TokenKind::Insert, "Expected INSERT")?;
513
514        // Check for MySQL-style INSERT IGNORE
515        let mysql_ignore = self.match_token(&TokenKind::Ignore);
516
517        // Check for SQLite-style INSERT OR {IGNORE|REPLACE|ABORT|FAIL}
518        let sqlite_conflict_action = if self.match_token(&TokenKind::Or) {
519            if self.match_token(&TokenKind::Ignore) {
520                Some(ConflictAction::DoNothing)
521            } else if self.match_token(&TokenKind::Replace) {
522                Some(ConflictAction::DoReplace)
523            } else if self.match_token(&TokenKind::Abort) {
524                Some(ConflictAction::DoAbort)
525            } else if self.match_token(&TokenKind::Fail) {
526                Some(ConflictAction::DoFail)
527            } else {
528                return Err(ParseError::new(
529                    "Expected IGNORE, REPLACE, ABORT, or FAIL after OR",
530                    self.current_span(),
531                ));
532            }
533        } else {
534            None
535        };
536
537        self.expect(&TokenKind::Into, "Expected INTO")?;
538
539        let table = self.parse_object_name()?;
540
541        // Optional column list
542        let columns = if self.match_token(&TokenKind::LParen) {
543            let cols = self.parse_identifier_list()?;
544            self.expect(&TokenKind::RParen, "Expected ')' after column list")?;
545            Some(cols)
546        } else {
547            None
548        };
549
550        // VALUES or SELECT
551        let source = if self.match_token(&TokenKind::Values) {
552            InsertSource::Values(self.parse_values_list()?)
553        } else if self.check_keyword(&TokenKind::Select) {
554            InsertSource::Query(Box::new(self.parse_select()?))
555        } else if self.match_token(&TokenKind::Default) {
556            self.expect(&TokenKind::Values, "Expected VALUES after DEFAULT")?;
557            InsertSource::Default
558        } else {
559            return Err(ParseError::new(
560                "Expected VALUES or SELECT",
561                self.current_span(),
562            ));
563        };
564
565        // Parse ON CONFLICT (PostgreSQL) or ON DUPLICATE KEY UPDATE (MySQL)
566        let on_conflict = if self.match_token(&TokenKind::On) {
567            if self.match_token(&TokenKind::Conflict) {
568                // PostgreSQL: ON CONFLICT [target] DO {NOTHING | UPDATE SET ...}
569                Some(self.parse_on_conflict()?)
570            } else if self.match_token(&TokenKind::Duplicate) {
571                // MySQL: ON DUPLICATE KEY UPDATE ...
572                self.expect(&TokenKind::Key, "Expected KEY after DUPLICATE")?;
573                self.expect(&TokenKind::Update, "Expected UPDATE after KEY")?;
574                let assignments = self.parse_assignments()?;
575                Some(OnConflict {
576                    target: None,
577                    action: ConflictAction::DoUpdate(assignments),
578                })
579            } else {
580                return Err(ParseError::new(
581                    "Expected CONFLICT or DUPLICATE after ON",
582                    self.current_span(),
583                ));
584            }
585        } else if mysql_ignore {
586            // MySQL INSERT IGNORE normalizes to DoNothing
587            Some(OnConflict {
588                target: None,
589                action: ConflictAction::DoNothing,
590            })
591        } else {
592            // SQLite conflict action from OR clause
593            sqlite_conflict_action.map(|action| OnConflict {
594                target: None,
595                action,
596            })
597        };
598
599        // RETURNING clause (PostgreSQL/SQLite)
600        let returning = if self.match_token(&TokenKind::Returning) {
601            Some(self.parse_select_list()?)
602        } else {
603            None
604        };
605
606        Ok(InsertStmt {
607            span: start_span.merge(self.current_span()),
608            table,
609            columns,
610            source,
611            on_conflict,
612            returning,
613        })
614    }
615
616    /// Parse ON CONFLICT clause (PostgreSQL style)
617    fn parse_on_conflict(&mut self) -> Result<OnConflict, ParseError> {
618        // Optional conflict target: (columns) or ON CONSTRAINT name
619        let target = if self.match_token(&TokenKind::LParen) {
620            let cols = self.parse_identifier_list()?;
621            self.expect(&TokenKind::RParen, "Expected ')' after conflict columns")?;
622            Some(ConflictTarget::Columns(cols))
623        } else if self.match_token(&TokenKind::On) {
624            // ON CONSTRAINT name (though this is a bit unusual syntax)
625            // Actually PostgreSQL uses just ON CONFLICT ON CONSTRAINT name
626            // Let's handle the standard case
627            None
628        } else {
629            None
630        };
631
632        // DO {NOTHING | UPDATE SET ...}
633        self.expect(&TokenKind::Do, "Expected DO after ON CONFLICT")?;
634
635        let action = if self.match_token(&TokenKind::Nothing) {
636            ConflictAction::DoNothing
637        } else if self.match_token(&TokenKind::Update) {
638            self.expect(&TokenKind::Set, "Expected SET after UPDATE")?;
639            let assignments = self.parse_assignments()?;
640            ConflictAction::DoUpdate(assignments)
641        } else {
642            return Err(ParseError::new(
643                "Expected NOTHING or UPDATE after DO",
644                self.current_span(),
645            ));
646        };
647
648        Ok(OnConflict { target, action })
649    }
650
651    fn parse_values_list(&mut self) -> Result<Vec<Vec<Expr>>, ParseError> {
652        let mut rows = Vec::new();
653
654        loop {
655            self.expect(&TokenKind::LParen, "Expected '(' for VALUES row")?;
656            let row = self.parse_expr_list()?;
657            self.expect(&TokenKind::RParen, "Expected ')' after VALUES row")?;
658            rows.push(row);
659
660            if !self.match_token(&TokenKind::Comma) {
661                break;
662            }
663        }
664
665        Ok(rows)
666    }
667
668    // ========== UPDATE Parsing ==========
669
670    fn parse_update(&mut self) -> Result<UpdateStmt, ParseError> {
671        let start_span = self.current_span();
672        self.expect(&TokenKind::Update, "Expected UPDATE")?;
673
674        let table = self.parse_object_name()?;
675
676        let alias = if self.match_token(&TokenKind::As) {
677            Some(self.expect_identifier("Expected alias after AS")?)
678        } else {
679            None
680        };
681
682        self.expect(&TokenKind::Set, "Expected SET")?;
683
684        let assignments = self.parse_assignments()?;
685
686        let from = if self.match_token(&TokenKind::From) {
687            Some(self.parse_from_clause()?)
688        } else {
689            None
690        };
691
692        let where_clause = if self.match_token(&TokenKind::Where) {
693            Some(self.parse_expr()?)
694        } else {
695            None
696        };
697
698        let returning = None; // TODO
699
700        Ok(UpdateStmt {
701            span: start_span.merge(self.current_span()),
702            table,
703            alias,
704            assignments,
705            from,
706            where_clause,
707            returning,
708        })
709    }
710
711    fn parse_assignments(&mut self) -> Result<Vec<Assignment>, ParseError> {
712        let mut assignments = Vec::new();
713
714        loop {
715            let column = self.expect_identifier("Expected column name")?;
716            self.expect(&TokenKind::Eq, "Expected '=' after column name")?;
717            let value = self.parse_expr()?;
718
719            assignments.push(Assignment { column, value });
720
721            if !self.match_token(&TokenKind::Comma) {
722                break;
723            }
724        }
725
726        Ok(assignments)
727    }
728
729    // ========== DELETE Parsing ==========
730
731    fn parse_delete(&mut self) -> Result<DeleteStmt, ParseError> {
732        let start_span = self.current_span();
733        self.expect(&TokenKind::Delete, "Expected DELETE")?;
734        self.expect(&TokenKind::From, "Expected FROM")?;
735
736        let table = self.parse_object_name()?;
737
738        let alias = if self.match_token(&TokenKind::As) {
739            Some(self.expect_identifier("Expected alias after AS")?)
740        } else {
741            None
742        };
743
744        let using = None; // TODO: Parse USING clause
745
746        let where_clause = if self.match_token(&TokenKind::Where) {
747            Some(self.parse_expr()?)
748        } else {
749            None
750        };
751
752        Ok(DeleteStmt {
753            span: start_span.merge(self.current_span()),
754            table,
755            alias,
756            using,
757            where_clause,
758            returning: None,
759        })
760    }
761
762    // ========== DDL Parsing ==========
763
764    fn parse_create(&mut self) -> Result<Statement, ParseError> {
765        self.expect(&TokenKind::Create, "Expected CREATE")?;
766
767        // Check for CREATE UNIQUE INDEX
768        let unique = self.match_token(&TokenKind::Unique);
769
770        if self.match_token(&TokenKind::Table) {
771            self.parse_create_table().map(Statement::CreateTable)
772        } else if self.match_token(&TokenKind::Index) {
773            self.parse_create_index(unique).map(Statement::CreateIndex)
774        } else if unique {
775            // After UNIQUE, must be INDEX
776            Err(ParseError::new(
777                "Expected INDEX after UNIQUE",
778                self.current_span(),
779            ))
780        } else {
781            Err(ParseError::new(
782                "Expected TABLE or INDEX after CREATE",
783                self.current_span(),
784            ))
785        }
786    }
787
788    fn parse_create_index(&mut self, unique: bool) -> Result<CreateIndexStmt, ParseError> {
789        let start_span = self.current_span();
790
791        // IF NOT EXISTS
792        let if_not_exists = if self.match_token(&TokenKind::If) {
793            self.expect(&TokenKind::Not, "Expected NOT after IF")?;
794            self.expect(&TokenKind::Exists, "Expected EXISTS after IF NOT")?;
795            true
796        } else {
797            false
798        };
799
800        // Index name
801        let name = self.expect_identifier("Expected index name")?;
802
803        self.expect(&TokenKind::On, "Expected ON after index name")?;
804
805        // Table name
806        let table = self.parse_object_name()?;
807
808        // Column list
809        self.expect(&TokenKind::LParen, "Expected '(' after table name")?;
810        let mut columns = Vec::new();
811        loop {
812            let col_name = self.expect_identifier("Expected column name")?;
813
814            // Optional ASC/DESC
815            let asc = if self.match_token(&TokenKind::Desc) {
816                false
817            } else {
818                self.match_token(&TokenKind::Asc);
819                true
820            };
821
822            columns.push(IndexColumn {
823                name: col_name,
824                asc,
825                nulls_first: None,
826            });
827
828            if !self.match_token(&TokenKind::Comma) {
829                break;
830            }
831        }
832        self.expect(&TokenKind::RParen, "Expected ')' after column list")?;
833
834        // Optional WHERE clause for partial indexes
835        let where_clause = if self.match_token(&TokenKind::Where) {
836            Some(self.parse_expr()?)
837        } else {
838            None
839        };
840
841        Ok(CreateIndexStmt {
842            span: start_span.merge(self.current_span()),
843            unique,
844            if_not_exists,
845            name,
846            table,
847            columns,
848            where_clause,
849            index_type: None,
850        })
851    }
852
853    fn parse_create_table(&mut self) -> Result<CreateTableStmt, ParseError> {
854        let start_span = self.current_span();
855
856        let if_not_exists = if self.match_token(&TokenKind::If) {
857            self.expect(&TokenKind::Not, "Expected NOT after IF")?;
858            self.expect(&TokenKind::Exists, "Expected EXISTS after IF NOT")?;
859            true
860        } else {
861            false
862        };
863
864        let name = self.parse_object_name()?;
865
866        self.expect(&TokenKind::LParen, "Expected '(' after table name")?;
867
868        let mut columns = Vec::new();
869        let constraints = Vec::new();
870
871        loop {
872            // Check for table constraint keywords
873            if self.check_keyword(&TokenKind::Primary)
874                || self.check_keyword(&TokenKind::Foreign)
875                || self.check_keyword(&TokenKind::Unique)
876            {
877                // TODO: Parse table constraints
878                break;
879            }
880
881            // Check for end of column list
882            if self.check(&TokenKind::RParen) {
883                break;
884            }
885
886            // Parse column definition
887            columns.push(self.parse_column_def()?);
888
889            if !self.match_token(&TokenKind::Comma) {
890                break;
891            }
892        }
893
894        self.expect(&TokenKind::RParen, "Expected ')' after column definitions")?;
895
896        Ok(CreateTableStmt {
897            span: start_span.merge(self.current_span()),
898            if_not_exists,
899            name,
900            columns,
901            constraints,
902            options: Vec::new(),
903        })
904    }
905
906    fn parse_column_def(&mut self) -> Result<ColumnDef, ParseError> {
907        let name = self.expect_identifier("Expected column name")?;
908        let data_type = self.parse_data_type()?;
909
910        let mut constraints = Vec::new();
911
912        // Parse column constraints
913        loop {
914            if self.match_token(&TokenKind::Primary) {
915                self.expect(&TokenKind::Key, "Expected KEY after PRIMARY")?;
916                constraints.push(ColumnConstraint::PrimaryKey);
917            } else if self.match_token(&TokenKind::Not) {
918                self.expect(&TokenKind::Null, "Expected NULL after NOT")?;
919                constraints.push(ColumnConstraint::NotNull);
920            } else if self.match_token(&TokenKind::Null) {
921                constraints.push(ColumnConstraint::Null);
922            } else if self.match_token(&TokenKind::Unique) {
923                constraints.push(ColumnConstraint::Unique);
924            } else if self.match_token(&TokenKind::Default) {
925                constraints.push(ColumnConstraint::Default(self.parse_expr()?));
926            } else if self.match_token(&TokenKind::AutoIncrement) {
927                constraints.push(ColumnConstraint::AutoIncrement);
928            } else {
929                break;
930            }
931        }
932
933        Ok(ColumnDef {
934            name,
935            data_type,
936            constraints,
937        })
938    }
939
940    fn parse_data_type(&mut self) -> Result<DataType, ParseError> {
941        let type_name = match &self.peek().kind {
942            TokenKind::Int | TokenKind::IntegerKw => {
943                self.advance();
944                DataType::Int
945            }
946            TokenKind::Bigint => {
947                self.advance();
948                DataType::BigInt
949            }
950            TokenKind::Smallint => {
951                self.advance();
952                DataType::SmallInt
953            }
954            TokenKind::Tinyint => {
955                self.advance();
956                DataType::TinyInt
957            }
958            TokenKind::FloatKw | TokenKind::Real => {
959                self.advance();
960                DataType::Float
961            }
962            TokenKind::Double => {
963                self.advance();
964                DataType::Double
965            }
966            TokenKind::Varchar => {
967                self.advance();
968                let len = self.parse_type_length()?;
969                DataType::Varchar(len)
970            }
971            TokenKind::Char => {
972                self.advance();
973                let len = self.parse_type_length()?;
974                DataType::Char(len)
975            }
976            TokenKind::Text => {
977                self.advance();
978                DataType::Text
979            }
980            TokenKind::BlobKw => {
981                self.advance();
982                DataType::Blob
983            }
984            TokenKind::Boolean | TokenKind::Bool => {
985                self.advance();
986                DataType::Boolean
987            }
988            TokenKind::Date => {
989                self.advance();
990                DataType::Date
991            }
992            TokenKind::Time => {
993                self.advance();
994                DataType::Time
995            }
996            TokenKind::Timestamp | TokenKind::Datetime => {
997                self.advance();
998                DataType::Timestamp
999            }
1000            TokenKind::Vector => {
1001                self.advance();
1002                let dims = self.parse_type_length()?.unwrap_or(128);
1003                DataType::Vector(dims)
1004            }
1005            TokenKind::Embedding => {
1006                self.advance();
1007                let dims = self.parse_type_length()?.unwrap_or(1536);
1008                DataType::Embedding(dims)
1009            }
1010            TokenKind::Identifier(name) => {
1011                let name = name.to_string();
1012                self.advance();
1013                DataType::Custom(name)
1014            }
1015            _ => {
1016                return Err(ParseError::new(
1017                    format!("Expected data type, got {:?}", self.peek().kind),
1018                    self.current_span(),
1019                ));
1020            }
1021        };
1022
1023        Ok(type_name)
1024    }
1025
1026    fn parse_type_length(&mut self) -> Result<Option<u32>, ParseError> {
1027        if self.match_token(&TokenKind::LParen) {
1028            let len = match &self.peek().kind {
1029                TokenKind::Integer(n) => {
1030                    let n = *n as u32;
1031                    self.advance();
1032                    n
1033                }
1034                _ => return Err(ParseError::new("Expected integer", self.current_span())),
1035            };
1036            self.expect(&TokenKind::RParen, "Expected ')'")?;
1037            Ok(Some(len))
1038        } else {
1039            Ok(None)
1040        }
1041    }
1042
1043    fn parse_drop(&mut self) -> Result<Statement, ParseError> {
1044        let start_span = self.current_span();
1045        self.expect(&TokenKind::Drop, "Expected DROP")?;
1046
1047        if self.match_token(&TokenKind::Table) {
1048            let if_exists = if self.match_token(&TokenKind::If) {
1049                self.expect(&TokenKind::Exists, "Expected EXISTS after IF")?;
1050                true
1051            } else {
1052                false
1053            };
1054
1055            let name = self.parse_object_name()?;
1056            let cascade = false; // TODO: Parse CASCADE
1057
1058            Ok(Statement::DropTable(DropTableStmt {
1059                span: start_span.merge(self.current_span()),
1060                if_exists,
1061                names: vec![name],
1062                cascade,
1063            }))
1064        } else if self.match_token(&TokenKind::Index) {
1065            let if_exists = if self.match_token(&TokenKind::If) {
1066                self.expect(&TokenKind::Exists, "Expected EXISTS after IF")?;
1067                true
1068            } else {
1069                false
1070            };
1071
1072            let name = self.expect_identifier("Expected index name")?;
1073
1074            // Optional ON table_name (PostgreSQL style)
1075            let table = if self.match_token(&TokenKind::On) {
1076                Some(self.parse_object_name()?)
1077            } else {
1078                None
1079            };
1080
1081            Ok(Statement::DropIndex(DropIndexStmt {
1082                span: start_span.merge(self.current_span()),
1083                if_exists,
1084                name,
1085                table,
1086                cascade: false,
1087            }))
1088        } else {
1089            Err(ParseError::new(
1090                "Expected TABLE or INDEX after DROP",
1091                self.current_span(),
1092            ))
1093        }
1094    }
1095
1096    fn parse_alter(&mut self) -> Result<Statement, ParseError> {
1097        let start_span = self.current_span();
1098        self.expect(&TokenKind::Alter, "Expected ALTER")?;
1099        self.expect(&TokenKind::Table, "Expected TABLE after ALTER")?;
1100
1101        let name = self.parse_object_name()?;
1102        let mut operations = Vec::new();
1103
1104        loop {
1105            let op = self.parse_alter_table_op()?;
1106            operations.push(op);
1107
1108            if !self.match_token(&TokenKind::Comma) {
1109                break;
1110            }
1111        }
1112
1113        Ok(Statement::AlterTable(AlterTableStmt {
1114            span: start_span.merge(self.current_span()),
1115            name,
1116            operations,
1117        }))
1118    }
1119
1120    fn parse_alter_table_op(&mut self) -> Result<AlterTableOp, ParseError> {
1121        if self.match_token(&TokenKind::Add) {
1122            // ADD [COLUMN] column_def
1123            self.match_token(&TokenKind::Column); // optional COLUMN keyword
1124            let col_def = self.parse_column_def()?;
1125            Ok(AlterTableOp::AddColumn(col_def))
1126        } else if self.match_token(&TokenKind::Drop) {
1127            // DROP [COLUMN] name [CASCADE]
1128            self.match_token(&TokenKind::Column); // optional COLUMN keyword
1129            let col_name = self.expect_identifier("Expected column name after DROP")?;
1130            let cascade = self.match_token(&TokenKind::Cascade);
1131            Ok(AlterTableOp::DropColumn {
1132                name: col_name,
1133                cascade,
1134            })
1135        } else if self.match_token(&TokenKind::Rename) {
1136            if self.match_token(&TokenKind::Column) {
1137                // RENAME COLUMN old_name TO new_name
1138                let old_name = self.expect_identifier("Expected old column name")?;
1139                self.expect(&TokenKind::To, "Expected TO after column name")?;
1140                let new_name = self.expect_identifier("Expected new column name")?;
1141                Ok(AlterTableOp::RenameColumn { old_name, new_name })
1142            } else if self.match_token(&TokenKind::To) {
1143                // RENAME TO new_table_name
1144                let new_name = self.parse_object_name()?;
1145                Ok(AlterTableOp::RenameTable(new_name))
1146            } else {
1147                // RENAME old_name TO new_name (shorthand for RENAME COLUMN)
1148                let old_name = self.expect_identifier("Expected column name or TO")?;
1149                self.expect(&TokenKind::To, "Expected TO after column name")?;
1150                let new_name = self.expect_identifier("Expected new column name")?;
1151                Ok(AlterTableOp::RenameColumn { old_name, new_name })
1152            }
1153        } else if self.match_token(&TokenKind::Alter) {
1154            // ALTER [COLUMN] name SET/DROP ...
1155            self.match_token(&TokenKind::Column); // optional COLUMN keyword
1156            let col_name = self.expect_identifier("Expected column name after ALTER COLUMN")?;
1157
1158            let operation = if self.match_token(&TokenKind::Set) {
1159                if self.match_token(&TokenKind::Not) {
1160                    self.expect(&TokenKind::Null, "Expected NULL after SET NOT")?;
1161                    AlterColumnOp::SetNotNull
1162                } else if self.match_token(&TokenKind::Default) {
1163                    let expr = self.parse_expr()?;
1164                    AlterColumnOp::SetDefault(expr)
1165                } else {
1166                    // SET DATA TYPE / TYPE
1167                    // Accept optional DATA keyword
1168                    if self.check_keyword(&TokenKind::Identifier("TYPE")) {
1169                        self.advance(); // consume TYPE
1170                    }
1171                    let data_type = self.parse_data_type()?;
1172                    AlterColumnOp::SetType(data_type)
1173                }
1174            } else if self.match_token(&TokenKind::Drop) {
1175                if self.match_token(&TokenKind::Not) {
1176                    self.expect(&TokenKind::Null, "Expected NULL after DROP NOT")?;
1177                    AlterColumnOp::DropNotNull
1178                } else if self.match_token(&TokenKind::Default) {
1179                    AlterColumnOp::DropDefault
1180                } else {
1181                    return Err(ParseError::new(
1182                        "Expected NOT NULL or DEFAULT after DROP",
1183                        self.current_span(),
1184                    ));
1185                }
1186            } else {
1187                // Bare type change: ALTER COLUMN name TYPE
1188                if self.check_keyword(&TokenKind::Identifier("TYPE")) {
1189                    self.advance(); // consume TYPE
1190                }
1191                let data_type = self.parse_data_type()?;
1192                AlterColumnOp::SetType(data_type)
1193            };
1194
1195            Ok(AlterTableOp::AlterColumn {
1196                name: col_name,
1197                operation,
1198            })
1199        } else {
1200            Err(ParseError::new(
1201                "Expected ADD, DROP, RENAME, or ALTER after ALTER TABLE <name>",
1202                self.current_span(),
1203            ))
1204        }
1205    }
1206
1207    // ========== Graph & Real-Time Parsing (P1 — Multi-Model) ==========
1208
1209    /// Parse RELATE statement.
1210    ///
1211    /// ```sql
1212    /// RELATE person:1 -> knows -> person:2 SET since = '2024-01-01';
1213    /// RELATE person:1 -> knows -> person:2 CONTENT { "since": "2024-01-01" };
1214    /// ```
1215    fn parse_relate(&mut self) -> Result<RelateStmt, ParseError> {
1216        let start_span = self.current_span();
1217        self.expect(&TokenKind::Relate, "Expected RELATE")?;
1218
1219        // Parse source record expression (e.g., person:1)
1220        // Use additive_expr so we don't consume -> as graph traversal
1221        let from = self.parse_additive_expr()?;
1222
1223        // Expect -> edge -> to
1224        self.expect(&TokenKind::Arrow, "Expected '->' after source record")?;
1225        let edge = self.parse_object_name()?;
1226        self.expect(&TokenKind::Arrow, "Expected '->' after edge table")?;
1227
1228        let to = self.parse_additive_expr()?;
1229
1230        // Parse optional SET or CONTENT
1231        let mut set = Vec::new();
1232        let mut content = None;
1233        let mut returning = None;
1234
1235        if self.match_token(&TokenKind::Set) {
1236            set = self.parse_assignments()?;
1237        } else if self.match_token(&TokenKind::Content) {
1238            content = Some(self.parse_expr()?);
1239        }
1240
1241        // Optional RETURNING
1242        if self.match_token(&TokenKind::Returning) {
1243            returning = Some(self.parse_select_list()?);
1244        }
1245
1246        Ok(RelateStmt {
1247            span: start_span.merge(self.current_span()),
1248            from,
1249            edge,
1250            to,
1251            set,
1252            content,
1253            returning,
1254        })
1255    }
1256
1257    /// Parse LIVE SELECT statement.
1258    ///
1259    /// ```sql
1260    /// LIVE SELECT * FROM person WHERE age > 18;
1261    /// LIVE SELECT DIFF FROM person;
1262    /// ```
1263    fn parse_live_select(&mut self) -> Result<LiveSelectStmt, ParseError> {
1264        let start_span = self.current_span();
1265        self.expect(&TokenKind::Live, "Expected LIVE")?;
1266
1267        // Check for DIFF before SELECT
1268        let diff = self.match_token(&TokenKind::Diff);
1269
1270        // Parse the underlying SELECT statement
1271        let select = self.parse_select()?;
1272
1273        Ok(LiveSelectStmt {
1274            span: start_span.merge(self.current_span()),
1275            select,
1276            diff,
1277        })
1278    }
1279
1280    // ========== Security DDL Parsing (P2 — Scope-Based Auth) ==========
1281
1282    /// Parse DEFINE statement.
1283    ///
1284    /// Supports:
1285    /// - `DEFINE SCOPE <name> [SESSION <duration>] [SIGNIN (<expr>)] [SIGNUP (<expr>)]`
1286    /// - `DEFINE TABLE <name> PERMISSIONS FOR <op> WHERE <expr> [, ...]`
1287    fn parse_define(&mut self) -> Result<Statement, ParseError> {
1288        self.expect(&TokenKind::Define, "Expected DEFINE")?;
1289
1290        if self.match_token(&TokenKind::Scope) {
1291            self.parse_define_scope()
1292        } else if self.match_token(&TokenKind::Table) {
1293            self.parse_define_table_permissions()
1294        } else if self.match_token(&TokenKind::Event) {
1295            self.parse_define_event()
1296        } else {
1297            Err(ParseError::new(
1298                "Expected SCOPE, TABLE, or EVENT after DEFINE",
1299                self.current_span(),
1300            ))
1301        }
1302    }
1303
1304    /// Parse DEFINE SCOPE <name> [SESSION <duration>] [SIGNIN (<expr>)] [SIGNUP (<expr>)]
1305    fn parse_define_scope(&mut self) -> Result<Statement, ParseError> {
1306        let name = self.expect_identifier("Expected scope name after DEFINE SCOPE")?;
1307
1308        let mut session_duration_secs = None;
1309        let mut signin = None;
1310        let mut signup = None;
1311
1312        // Parse optional clauses in any order
1313        loop {
1314            if self.match_token(&TokenKind::Session) {
1315                // Parse duration: integer literal interpreted as seconds,
1316                // or identifier like "24h", "7d"
1317                match &self.peek().kind {
1318                    TokenKind::Integer(n) => {
1319                        session_duration_secs = Some(*n as u64);
1320                        self.advance();
1321                    }
1322                    TokenKind::Identifier(s) => {
1323                        session_duration_secs = Some(parse_duration_string(s));
1324                        self.advance();
1325                    }
1326                    TokenKind::String(s) => {
1327                        session_duration_secs = Some(parse_duration_string(s.as_ref()));
1328                        self.advance();
1329                    }
1330                    _ => {
1331                        return Err(ParseError::new(
1332                            "Expected duration after SESSION",
1333                            self.current_span(),
1334                        ));
1335                    }
1336                }
1337            } else if self.match_token(&TokenKind::Signin) {
1338                self.expect(&TokenKind::LParen, "Expected '(' after SIGNIN")?;
1339                let expr = self.parse_expr()?;
1340                self.expect(&TokenKind::RParen, "Expected ')' after SIGNIN expression")?;
1341                signin = Some(Box::new(expr));
1342            } else if self.match_token(&TokenKind::Signup) {
1343                self.expect(&TokenKind::LParen, "Expected '(' after SIGNUP")?;
1344                let expr = self.parse_expr()?;
1345                self.expect(&TokenKind::RParen, "Expected ')' after SIGNUP expression")?;
1346                signup = Some(Box::new(expr));
1347            } else {
1348                break;
1349            }
1350        }
1351
1352        Ok(Statement::DefineScope(DefineScopeStmt {
1353            name,
1354            session_duration_secs,
1355            signin,
1356            signup,
1357        }))
1358    }
1359
1360    /// Parse DEFINE TABLE <name> PERMISSIONS FOR <op> WHERE <expr> [, ...]
1361    fn parse_define_table_permissions(&mut self) -> Result<Statement, ParseError> {
1362        let table = self.parse_object_name()?;
1363        self.expect(
1364            &TokenKind::Permissions,
1365            "Expected PERMISSIONS after table name",
1366        )?;
1367
1368        let mut permissions = Vec::new();
1369        loop {
1370            if !self.match_token(&TokenKind::For) {
1371                break;
1372            }
1373
1374            let operation = self.parse_permission_op()?;
1375            self.expect(&TokenKind::Where, "Expected WHERE after FOR <operation>")?;
1376            let condition = self.parse_expr()?;
1377
1378            permissions.push(TablePermission {
1379                operation,
1380                condition,
1381            });
1382        }
1383
1384        Ok(Statement::DefineTablePermissions(
1385            DefineTablePermissionsStmt { table, permissions },
1386        ))
1387    }
1388
1389    /// Parse permission operation: select | create | insert | update | delete
1390    fn parse_permission_op(&mut self) -> Result<PermissionOp, ParseError> {
1391        match &self.peek().kind {
1392            TokenKind::Select => {
1393                self.advance();
1394                Ok(PermissionOp::Select)
1395            }
1396            TokenKind::Insert => {
1397                self.advance();
1398                Ok(PermissionOp::Create)
1399            }
1400            TokenKind::Update => {
1401                self.advance();
1402                Ok(PermissionOp::Update)
1403            }
1404            TokenKind::Delete => {
1405                self.advance();
1406                Ok(PermissionOp::Delete)
1407            }
1408            TokenKind::Create => {
1409                self.advance();
1410                Ok(PermissionOp::Create)
1411            }
1412            TokenKind::Identifier(s) if s.eq_ignore_ascii_case("CREATE") => {
1413                self.advance();
1414                Ok(PermissionOp::Create)
1415            }
1416            _ => Err(ParseError::new(
1417                "Expected SELECT, CREATE, INSERT, UPDATE, or DELETE after FOR",
1418                self.current_span(),
1419            )),
1420        }
1421    }
1422
1423    /// Parse REMOVE SCOPE <name>
1424    fn parse_remove(&mut self) -> Result<Statement, ParseError> {
1425        self.expect(&TokenKind::Remove, "Expected REMOVE")?;
1426        self.expect(&TokenKind::Scope, "Expected SCOPE after REMOVE")?;
1427        let name = self.expect_identifier("Expected scope name after REMOVE SCOPE")?;
1428        Ok(Statement::RemoveScope(name))
1429    }
1430
1431    /// Parse DEFINE EVENT <name> ON TABLE <table> WHEN <condition> THEN (<action>)
1432    fn parse_define_event(&mut self) -> Result<Statement, ParseError> {
1433        let start_span = self.current_span();
1434        let name = self.expect_identifier("Expected event name after DEFINE EVENT")?;
1435
1436        // ON [TABLE] <table>
1437        self.expect(&TokenKind::On, "Expected ON after event name")?;
1438        self.match_token(&TokenKind::Table); // optional TABLE keyword
1439        let table = self.parse_object_name()?;
1440
1441        // WHEN <condition>
1442        self.expect(&TokenKind::When, "Expected WHEN")?;
1443        let condition = self.parse_expr()?;
1444
1445        // THEN (<action>)
1446        self.expect(&TokenKind::Then, "Expected THEN")?;
1447        let action = self.parse_expr()?;
1448
1449        Ok(Statement::DefineEvent(DefineEventStmt {
1450            span: start_span.merge(self.current_span()),
1451            name,
1452            table,
1453            condition,
1454            action,
1455        }))
1456    }
1457
1458    // ========== Transaction Parsing ==========
1459
1460    fn parse_begin(&mut self) -> Result<BeginStmt, ParseError> {
1461        self.expect(&TokenKind::Begin, "Expected BEGIN")?;
1462        self.match_token(&TokenKind::Transaction);
1463
1464        // TODO: Parse isolation level
1465        Ok(BeginStmt {
1466            read_only: false,
1467            isolation_level: None,
1468        })
1469    }
1470
1471    fn parse_rollback(&mut self) -> Result<Statement, ParseError> {
1472        self.expect(&TokenKind::Rollback, "Expected ROLLBACK")?;
1473        self.match_token(&TokenKind::Transaction);
1474
1475        // Check for ROLLBACK TO SAVEPOINT
1476        // TODO
1477
1478        Ok(Statement::Rollback(None))
1479    }
1480
1481    fn parse_savepoint(&mut self) -> Result<Statement, ParseError> {
1482        self.expect(&TokenKind::Savepoint, "Expected SAVEPOINT")?;
1483        let name = self.expect_identifier("Expected savepoint name")?;
1484        Ok(Statement::Savepoint(name))
1485    }
1486
1487    fn parse_release(&mut self) -> Result<Statement, ParseError> {
1488        self.expect(&TokenKind::Release, "Expected RELEASE")?;
1489        self.match_token(&TokenKind::Savepoint);
1490        let name = self.expect_identifier("Expected savepoint name")?;
1491        Ok(Statement::Release(name))
1492    }
1493
1494    // ========== Expression Parsing ==========
1495
1496    /// Enter one level of expression recursion, erroring if too deep.
1497    /// Paired with `exit_recursion` so the depth counter stays balanced across
1498    /// sibling expressions on the success path.
1499    #[inline]
1500    fn enter_recursion(&mut self) -> Result<(), ParseError> {
1501        self.depth += 1;
1502        if self.depth > MAX_EXPR_DEPTH {
1503            self.depth -= 1;
1504            return Err(ParseError::new(
1505                "expression nesting too deep",
1506                self.current_span(),
1507            ));
1508        }
1509        Ok(())
1510    }
1511
1512    #[inline]
1513    fn exit_recursion(&mut self) {
1514        self.depth = self.depth.saturating_sub(1);
1515    }
1516
1517    fn parse_expr(&mut self) -> Result<Expr, ParseError> {
1518        self.enter_recursion()?;
1519        let r = self.parse_or_expr();
1520        self.exit_recursion();
1521        r
1522    }
1523
1524    fn parse_or_expr(&mut self) -> Result<Expr, ParseError> {
1525        let mut left = self.parse_and_expr()?;
1526
1527        while self.match_token(&TokenKind::Or) {
1528            let right = self.parse_and_expr()?;
1529            left = Expr::BinaryOp {
1530                left: Box::new(left),
1531                op: BinaryOperator::Or,
1532                right: Box::new(right),
1533            };
1534        }
1535
1536        Ok(left)
1537    }
1538
1539    fn parse_and_expr(&mut self) -> Result<Expr, ParseError> {
1540        let mut left = self.parse_not_expr()?;
1541
1542        while self.match_token(&TokenKind::And) {
1543            let right = self.parse_not_expr()?;
1544            left = Expr::BinaryOp {
1545                left: Box::new(left),
1546                op: BinaryOperator::And,
1547                right: Box::new(right),
1548            };
1549        }
1550
1551        Ok(left)
1552    }
1553
1554    fn parse_not_expr(&mut self) -> Result<Expr, ParseError> {
1555        self.enter_recursion()?;
1556        let r = if self.match_token(&TokenKind::Not) {
1557            self.parse_not_expr().map(|expr| Expr::UnaryOp {
1558                op: UnaryOperator::Not,
1559                expr: Box::new(expr),
1560            })
1561        } else {
1562            self.parse_comparison_expr()
1563        };
1564        self.exit_recursion();
1565        r
1566    }
1567
1568    fn parse_comparison_expr(&mut self) -> Result<Expr, ParseError> {
1569        let mut left = self.parse_graph_expr()?;
1570
1571        // IS NULL / IS NOT NULL
1572        if self.match_token(&TokenKind::Is) {
1573            let negated = self.match_token(&TokenKind::Not);
1574            self.expect(&TokenKind::Null, "Expected NULL after IS")?;
1575            return Ok(Expr::IsNull {
1576                expr: Box::new(left),
1577                negated,
1578            });
1579        }
1580
1581        // IN / NOT IN
1582        let negated = self.match_token(&TokenKind::Not);
1583        if self.match_token(&TokenKind::In) {
1584            self.expect(&TokenKind::LParen, "Expected '(' after IN")?;
1585
1586            if self.check_keyword(&TokenKind::Select) {
1587                let subquery = self.parse_select()?;
1588                self.expect(&TokenKind::RParen, "Expected ')'")?;
1589                return Ok(Expr::InSubquery {
1590                    expr: Box::new(left),
1591                    subquery: Box::new(subquery),
1592                    negated,
1593                });
1594            } else {
1595                let list = self.parse_expr_list()?;
1596                self.expect(&TokenKind::RParen, "Expected ')'")?;
1597                return Ok(Expr::InList {
1598                    expr: Box::new(left),
1599                    list,
1600                    negated,
1601                });
1602            }
1603        }
1604
1605        // BETWEEN
1606        if self.match_token(&TokenKind::Between) {
1607            let low = self.parse_graph_expr()?;
1608            self.expect(&TokenKind::And, "Expected AND in BETWEEN")?;
1609            let high = self.parse_graph_expr()?;
1610            return Ok(Expr::Between {
1611                expr: Box::new(left),
1612                low: Box::new(low),
1613                high: Box::new(high),
1614                negated,
1615            });
1616        }
1617
1618        // LIKE
1619        if self.match_token(&TokenKind::Like) {
1620            let pattern = self.parse_graph_expr()?;
1621            let escape = if self.match_token(&TokenKind::Escape) {
1622                Some(Box::new(self.parse_graph_expr()?))
1623            } else {
1624                None
1625            };
1626            return Ok(Expr::Like {
1627                expr: Box::new(left),
1628                pattern: Box::new(pattern),
1629                escape,
1630                negated,
1631            });
1632        }
1633
1634        // If we consumed NOT but didn't find IN/BETWEEN/LIKE, error
1635        if negated {
1636            return Err(ParseError::new(
1637                "Expected IN, BETWEEN, or LIKE after NOT",
1638                self.current_span(),
1639            ));
1640        }
1641
1642        // Comparison operators
1643        let op = match &self.peek().kind {
1644            TokenKind::Eq => Some(BinaryOperator::Eq),
1645            TokenKind::Ne => Some(BinaryOperator::Ne),
1646            TokenKind::Lt => Some(BinaryOperator::Lt),
1647            TokenKind::Le => Some(BinaryOperator::Le),
1648            TokenKind::Gt => Some(BinaryOperator::Gt),
1649            TokenKind::Ge => Some(BinaryOperator::Ge),
1650            _ => None,
1651        };
1652
1653        if let Some(op) = op {
1654            self.advance();
1655            let right = self.parse_graph_expr()?;
1656            left = Expr::BinaryOp {
1657                left: Box::new(left),
1658                op,
1659                right: Box::new(right),
1660            };
1661        }
1662
1663        Ok(left)
1664    }
1665
1666    /// Parse graph traversal expressions.
1667    ///
1668    /// Graph operators (`->`, `<-`, `<->`) sit between comparison and additive
1669    /// in the precedence chain and left-recurse:
1670    /// ```text
1671    /// person:1 -> knows -> person:2       // outgoing traversal
1672    /// person:1 <- knows <- person:2       // incoming traversal
1673    /// person:1 <-> knows <-> person:2     // bidirectional
1674    /// ```
1675    fn parse_graph_expr(&mut self) -> Result<Expr, ParseError> {
1676        let mut left = self.parse_additive_expr()?;
1677
1678        loop {
1679            let op = match &self.peek().kind {
1680                TokenKind::Arrow => BinaryOperator::GraphRight,
1681                TokenKind::LeftArrow => BinaryOperator::GraphLeft,
1682                TokenKind::BiArrow => BinaryOperator::GraphBi,
1683                _ => break,
1684            };
1685            self.advance();
1686
1687            let right = self.parse_additive_expr()?;
1688            left = Expr::BinaryOp {
1689                left: Box::new(left),
1690                op,
1691                right: Box::new(right),
1692            };
1693        }
1694
1695        Ok(left)
1696    }
1697
1698    fn parse_additive_expr(&mut self) -> Result<Expr, ParseError> {
1699        let mut left = self.parse_multiplicative_expr()?;
1700
1701        loop {
1702            let op = match &self.peek().kind {
1703                TokenKind::Plus => BinaryOperator::Plus,
1704                TokenKind::Minus => BinaryOperator::Minus,
1705                TokenKind::Concat => BinaryOperator::Concat,
1706                _ => break,
1707            };
1708            self.advance();
1709
1710            let right = self.parse_multiplicative_expr()?;
1711            left = Expr::BinaryOp {
1712                left: Box::new(left),
1713                op,
1714                right: Box::new(right),
1715            };
1716        }
1717
1718        Ok(left)
1719    }
1720
1721    fn parse_multiplicative_expr(&mut self) -> Result<Expr, ParseError> {
1722        let mut left = self.parse_unary_expr()?;
1723
1724        loop {
1725            let op = match &self.peek().kind {
1726                TokenKind::Star => BinaryOperator::Multiply,
1727                TokenKind::Slash => BinaryOperator::Divide,
1728                TokenKind::Percent => BinaryOperator::Modulo,
1729                _ => break,
1730            };
1731            self.advance();
1732
1733            let right = self.parse_unary_expr()?;
1734            left = Expr::BinaryOp {
1735                left: Box::new(left),
1736                op,
1737                right: Box::new(right),
1738            };
1739        }
1740
1741        Ok(left)
1742    }
1743
1744    fn parse_unary_expr(&mut self) -> Result<Expr, ParseError> {
1745        // Guard the `- - - …` / `+ +` / `~ ~` prefix chains, which self-recurse
1746        // without passing through parse_expr.
1747        let op = match &self.peek().kind {
1748            TokenKind::Minus => Some(UnaryOperator::Minus),
1749            TokenKind::Plus => Some(UnaryOperator::Plus),
1750            TokenKind::BitNot => Some(UnaryOperator::BitNot),
1751            _ => None,
1752        };
1753        match op {
1754            Some(op) => {
1755                self.advance();
1756                self.enter_recursion()?;
1757                let inner = self.parse_unary_expr();
1758                self.exit_recursion();
1759                inner.map(|expr| Expr::UnaryOp {
1760                    op,
1761                    expr: Box::new(expr),
1762                })
1763            }
1764            None => self.parse_primary_expr(),
1765        }
1766    }
1767
1768    fn parse_primary_expr(&mut self) -> Result<Expr, ParseError> {
1769        let expr = match self.peek().kind.clone() {
1770            // Literals
1771            TokenKind::Integer(n) => {
1772                self.advance();
1773                Expr::Literal(Literal::Integer(n))
1774            }
1775            TokenKind::Float(n) => {
1776                self.advance();
1777                Expr::Literal(Literal::Float(n))
1778            }
1779            TokenKind::String(s) => {
1780                self.advance();
1781                Expr::Literal(Literal::String(s.into_owned()))
1782            }
1783            TokenKind::Blob(b) => {
1784                self.advance();
1785                Expr::Literal(Literal::Blob(b))
1786            }
1787            TokenKind::True => {
1788                self.advance();
1789                Expr::Literal(Literal::Boolean(true))
1790            }
1791            TokenKind::False => {
1792                self.advance();
1793                Expr::Literal(Literal::Boolean(false))
1794            }
1795            TokenKind::Null => {
1796                self.advance();
1797                Expr::Literal(Literal::Null)
1798            }
1799
1800            // Placeholder
1801            TokenKind::Placeholder(n) => {
1802                self.advance();
1803                Expr::Placeholder(n)
1804            }
1805
1806            // Parenthesized expression or subquery
1807            TokenKind::LParen => {
1808                self.advance();
1809                if self.check_keyword(&TokenKind::Select) {
1810                    let query = self.parse_select()?;
1811                    self.expect(&TokenKind::RParen, "Expected ')'")?;
1812                    Expr::Subquery(Box::new(query))
1813                } else {
1814                    let expr = self.parse_expr()?;
1815
1816                    // Check for tuple
1817                    if self.match_token(&TokenKind::Comma) {
1818                        let mut exprs = vec![expr];
1819                        exprs.push(self.parse_expr()?);
1820                        while self.match_token(&TokenKind::Comma) {
1821                            exprs.push(self.parse_expr()?);
1822                        }
1823                        self.expect(&TokenKind::RParen, "Expected ')'")?;
1824                        Expr::Tuple(exprs)
1825                    } else {
1826                        self.expect(&TokenKind::RParen, "Expected ')'")?;
1827                        expr
1828                    }
1829                }
1830            }
1831
1832            // CASE expression
1833            TokenKind::Case => {
1834                self.advance();
1835                self.parse_case_expr()?
1836            }
1837
1838            // EXISTS
1839            TokenKind::Exists => {
1840                self.advance();
1841                self.expect(&TokenKind::LParen, "Expected '(' after EXISTS")?;
1842                let query = self.parse_select()?;
1843                self.expect(&TokenKind::RParen, "Expected ')'")?;
1844                Expr::Exists(Box::new(query))
1845            }
1846
1847            // CAST
1848            TokenKind::Cast => {
1849                self.advance();
1850                self.expect(&TokenKind::LParen, "Expected '(' after CAST")?;
1851                let expr = self.parse_expr()?;
1852                self.expect(&TokenKind::As, "Expected AS in CAST")?;
1853                let data_type = self.parse_data_type()?;
1854                self.expect(&TokenKind::RParen, "Expected ')'")?;
1855                Expr::Cast {
1856                    expr: Box::new(expr),
1857                    data_type,
1858                }
1859            }
1860
1861            // SochDB Extensions
1862            TokenKind::VectorSearch => {
1863                self.advance();
1864                self.parse_vector_search()?
1865            }
1866            TokenKind::ContextWindow => {
1867                self.advance();
1868                self.parse_context_window()?
1869            }
1870
1871            // Aggregate functions
1872            TokenKind::Count
1873            | TokenKind::Sum
1874            | TokenKind::Avg
1875            | TokenKind::Min
1876            | TokenKind::Max => self.parse_aggregate_function()?,
1877
1878            // Function call or column reference
1879            TokenKind::Identifier(_) | TokenKind::QuotedIdentifier(_) => {
1880                self.parse_identifier_or_function()?
1881            }
1882
1883            // Type keywords used as column names
1884            TokenKind::Vector | TokenKind::Embedding | TokenKind::Text | TokenKind::BlobKw => {
1885                // Convert keyword to identifier
1886                let name = match &self.peek().kind {
1887                    TokenKind::Vector => "vector".to_string(),
1888                    TokenKind::Embedding => "embedding".to_string(),
1889                    TokenKind::Text => "text".to_string(),
1890                    TokenKind::BlobKw => "blob".to_string(),
1891                    _ => unreachable!(),
1892                };
1893                self.advance();
1894                Expr::Column(ColumnRef::new(name))
1895            }
1896
1897            _ => {
1898                return Err(ParseError::new(
1899                    format!("Unexpected token in expression: {:?}", self.peek().kind),
1900                    self.current_span(),
1901                ));
1902            }
1903        };
1904
1905        // Handle postfix operators
1906        self.parse_postfix_expr(expr)
1907    }
1908
1909    fn parse_postfix_expr(&mut self, mut expr: Expr) -> Result<Expr, ParseError> {
1910        loop {
1911            if self.match_token(&TokenKind::LBracket) {
1912                // Array subscript
1913                let index = self.parse_expr()?;
1914                self.expect(&TokenKind::RBracket, "Expected ']'")?;
1915                expr = Expr::Subscript {
1916                    expr: Box::new(expr),
1917                    index: Box::new(index),
1918                };
1919            } else if self.match_token(&TokenKind::DoubleArrow) {
1920                // JSON access returning text: ->>
1921                let path = self.parse_primary_expr()?;
1922                expr = Expr::JsonAccess {
1923                    expr: Box::new(expr),
1924                    path: Box::new(path),
1925                    return_text: true,
1926                };
1927            } else if self.match_token(&TokenKind::DoubleColon) {
1928                // Type cast: ::type
1929                let data_type = self.parse_data_type()?;
1930                expr = Expr::Cast {
1931                    expr: Box::new(expr),
1932                    data_type,
1933                };
1934            } else if self.match_token(&TokenKind::Colon) {
1935                // RecordId: table:id (e.g., person:1, post:abc)
1936                if let Expr::Column(ref col) = expr {
1937                    if col.table.is_none() {
1938                        let table = col.column.clone();
1939                        let id = self.parse_primary_expr()?;
1940                        expr = Expr::RecordId {
1941                            table,
1942                            id: Box::new(id),
1943                        };
1944                        continue;
1945                    }
1946                }
1947                return Err(ParseError::new(
1948                    "Unexpected ':' — record ID requires unqualified identifier on left",
1949                    self.current_span(),
1950                ));
1951            } else {
1952                break;
1953            }
1954        }
1955
1956        Ok(expr)
1957    }
1958
1959    fn parse_case_expr(&mut self) -> Result<Expr, ParseError> {
1960        // Simple CASE: CASE expr WHEN val THEN result ...
1961        // Searched CASE: CASE WHEN cond THEN result ...
1962
1963        let operand = if !self.check_keyword(&TokenKind::When) {
1964            Some(Box::new(self.parse_expr()?))
1965        } else {
1966            None
1967        };
1968
1969        let mut conditions = Vec::new();
1970
1971        while self.match_token(&TokenKind::When) {
1972            let when_expr = self.parse_expr()?;
1973            self.expect(&TokenKind::Then, "Expected THEN")?;
1974            let then_expr = self.parse_expr()?;
1975            conditions.push((when_expr, then_expr));
1976        }
1977
1978        let else_result = if self.match_token(&TokenKind::Else) {
1979            Some(Box::new(self.parse_expr()?))
1980        } else {
1981            None
1982        };
1983
1984        self.expect(&TokenKind::End, "Expected END")?;
1985
1986        Ok(Expr::Case {
1987            operand,
1988            conditions,
1989            else_result,
1990        })
1991    }
1992
1993    fn parse_identifier_or_function(&mut self) -> Result<Expr, ParseError> {
1994        let name = self.parse_object_name()?;
1995
1996        // Check for function call
1997        if self.match_token(&TokenKind::LParen) {
1998            let args = if self.check(&TokenKind::RParen) {
1999                Vec::new()
2000            } else {
2001                self.parse_expr_list()?
2002            };
2003            self.expect(&TokenKind::RParen, "Expected ')'")?;
2004
2005            Ok(Expr::Function(FunctionCall {
2006                name,
2007                args,
2008                distinct: false,
2009                filter: None,
2010                over: None,
2011            }))
2012        } else {
2013            // Column reference
2014            let parts = name.parts;
2015            if parts.len() == 1 {
2016                Ok(Expr::Column(ColumnRef::new(
2017                    parts.into_iter().next().unwrap(),
2018                )))
2019            } else if parts.len() == 2 {
2020                let mut iter = parts.into_iter();
2021                let table = iter.next().unwrap();
2022                let column = iter.next().unwrap();
2023                Ok(Expr::Column(ColumnRef::qualified(table, column)))
2024            } else {
2025                Err(ParseError::new(
2026                    "Invalid column reference",
2027                    self.current_span(),
2028                ))
2029            }
2030        }
2031    }
2032
2033    fn parse_aggregate_function(&mut self) -> Result<Expr, ParseError> {
2034        let name = match &self.peek().kind {
2035            TokenKind::Count => "COUNT",
2036            TokenKind::Sum => "SUM",
2037            TokenKind::Avg => "AVG",
2038            TokenKind::Min => "MIN",
2039            TokenKind::Max => "MAX",
2040            _ => {
2041                return Err(ParseError::new(
2042                    "Expected aggregate function",
2043                    self.current_span(),
2044                ));
2045            }
2046        };
2047        self.advance();
2048
2049        self.expect(&TokenKind::LParen, "Expected '(' after aggregate function")?;
2050
2051        let distinct = self.match_token(&TokenKind::Distinct);
2052
2053        let args = if self.match_token(&TokenKind::Star) {
2054            vec![Expr::Column(ColumnRef::new("*"))]
2055        } else {
2056            self.parse_expr_list()?
2057        };
2058
2059        self.expect(&TokenKind::RParen, "Expected ')'")?;
2060
2061        Ok(Expr::Function(FunctionCall {
2062            name: ObjectName::new(name),
2063            args,
2064            distinct,
2065            filter: None,
2066            over: None,
2067        }))
2068    }
2069
2070    fn parse_vector_search(&mut self) -> Result<Expr, ParseError> {
2071        self.expect(&TokenKind::LParen, "Expected '(' after VECTOR_SEARCH")?;
2072
2073        let column = self.parse_expr()?;
2074        self.expect(&TokenKind::Comma, "Expected ','")?;
2075
2076        let query = self.parse_expr()?;
2077        self.expect(&TokenKind::Comma, "Expected ','")?;
2078
2079        let k = match &self.peek().kind {
2080            TokenKind::Integer(n) => *n as u32,
2081            _ => return Err(ParseError::new("Expected integer k", self.current_span())),
2082        };
2083        self.advance();
2084
2085        let metric = if self.match_token(&TokenKind::Comma) {
2086            match &self.peek().kind {
2087                TokenKind::Cosine => {
2088                    self.advance();
2089                    VectorMetric::Cosine
2090                }
2091                TokenKind::Euclidean => {
2092                    self.advance();
2093                    VectorMetric::Euclidean
2094                }
2095                TokenKind::DotProduct => {
2096                    self.advance();
2097                    VectorMetric::DotProduct
2098                }
2099                _ => VectorMetric::Cosine,
2100            }
2101        } else {
2102            VectorMetric::Cosine
2103        };
2104
2105        self.expect(&TokenKind::RParen, "Expected ')'")?;
2106
2107        Ok(Expr::VectorSearch {
2108            column: Box::new(column),
2109            query: Box::new(query),
2110            k,
2111            metric,
2112        })
2113    }
2114
2115    fn parse_context_window(&mut self) -> Result<Expr, ParseError> {
2116        self.expect(&TokenKind::LParen, "Expected '(' after CONTEXT_WINDOW")?;
2117
2118        let source = self.parse_expr()?;
2119        self.expect(&TokenKind::Comma, "Expected ','")?;
2120
2121        let max_tokens = match &self.peek().kind {
2122            TokenKind::Integer(n) => *n as u32,
2123            _ => {
2124                return Err(ParseError::new(
2125                    "Expected integer max_tokens",
2126                    self.current_span(),
2127                ));
2128            }
2129        };
2130        self.advance();
2131
2132        let priority = if self.match_token(&TokenKind::Comma) {
2133            Some(Box::new(self.parse_expr()?))
2134        } else {
2135            None
2136        };
2137
2138        self.expect(&TokenKind::RParen, "Expected ')'")?;
2139
2140        Ok(Expr::ContextWindow {
2141            source: Box::new(source),
2142            max_tokens,
2143            priority,
2144        })
2145    }
2146
2147    // ========== Helper Parsers ==========
2148
2149    fn parse_object_name(&mut self) -> Result<ObjectName, ParseError> {
2150        let mut parts = Vec::new();
2151        parts.push(self.expect_identifier("Expected identifier")?);
2152
2153        while self.match_token(&TokenKind::Dot) {
2154            // Check for wildcard after dot (table.*)
2155            if self.check(&TokenKind::Star) {
2156                // Don't consume star, let caller handle it
2157                break;
2158            }
2159            parts.push(self.expect_identifier("Expected identifier after '.'")?);
2160        }
2161
2162        Ok(ObjectName { parts })
2163    }
2164
2165    fn parse_identifier_list(&mut self) -> Result<Vec<String>, ParseError> {
2166        let mut list = vec![self.expect_identifier("Expected identifier")?];
2167
2168        while self.match_token(&TokenKind::Comma) {
2169            list.push(self.expect_identifier("Expected identifier")?);
2170        }
2171
2172        Ok(list)
2173    }
2174
2175    fn parse_expr_list(&mut self) -> Result<Vec<Expr>, ParseError> {
2176        let mut list = vec![self.parse_expr()?];
2177
2178        while self.match_token(&TokenKind::Comma) {
2179            list.push(self.parse_expr()?);
2180        }
2181
2182        Ok(list)
2183    }
2184
2185    fn parse_order_by_list(&mut self) -> Result<Vec<OrderByItem>, ParseError> {
2186        let mut list = Vec::new();
2187
2188        loop {
2189            let expr = self.parse_expr()?;
2190
2191            let asc = if self.match_token(&TokenKind::Desc) {
2192                false
2193            } else {
2194                self.match_token(&TokenKind::Asc);
2195                true
2196            };
2197
2198            let nulls_first = if self.match_token(&TokenKind::Nulls) {
2199                if self.match_token(&TokenKind::First) {
2200                    Some(true)
2201                } else if self.match_token(&TokenKind::Last) {
2202                    Some(false)
2203                } else {
2204                    return Err(ParseError::new(
2205                        "Expected FIRST or LAST after NULLS",
2206                        self.current_span(),
2207                    ));
2208                }
2209            } else {
2210                None
2211            };
2212
2213            list.push(OrderByItem {
2214                expr,
2215                asc,
2216                nulls_first,
2217            });
2218
2219            if !self.match_token(&TokenKind::Comma) {
2220                break;
2221            }
2222        }
2223
2224        Ok(list)
2225    }
2226}
2227
2228#[cfg(test)]
2229mod tests {
2230    use super::*;
2231
2232    #[test]
2233    fn test_simple_select() {
2234        let stmt = Parser::parse("SELECT * FROM users").unwrap();
2235        assert!(matches!(stmt, Statement::Select(_)));
2236    }
2237
2238    #[test]
2239    fn test_deeply_nested_expr_errors_not_panics() {
2240        // Regression: unbounded recursive-descent recursion used to overflow
2241        // the stack (SIGABRT) on attacker-controlled SQL. Now it must return a
2242        // parse error well within stack limits. Three vectors: parentheses,
2243        // NOT chains, unary-minus chains.
2244        let depth = MAX_EXPR_DEPTH + 50;
2245        for (open, close) in [("(", ")"), ("NOT ", ""), ("-", "")] {
2246            let expr = format!(
2247                "SELECT {}1{} FROM t",
2248                open.repeat(depth),
2249                close.repeat(depth)
2250            );
2251            let r = Parser::parse(&expr);
2252            assert!(
2253                r.is_err(),
2254                "depth {} of {:?} should error, not parse/panic",
2255                depth,
2256                open
2257            );
2258        }
2259        // A reasonably-nested expression still parses fine (no false positive).
2260        let ok = format!("SELECT {}1{} FROM t", "(".repeat(20), ")".repeat(20));
2261        assert!(Parser::parse(&ok).is_ok(), "20-deep nesting must still parse");
2262    }
2263
2264    #[test]
2265    fn test_select_with_where() {
2266        let stmt = Parser::parse("SELECT id, name FROM users WHERE id = 1").unwrap();
2267        if let Statement::Select(select) = stmt {
2268            assert_eq!(select.columns.len(), 2);
2269            assert!(select.where_clause.is_some());
2270        } else {
2271            panic!("Expected SELECT statement");
2272        }
2273    }
2274
2275    #[test]
2276    fn test_insert() {
2277        let stmt = Parser::parse("INSERT INTO users (id, name) VALUES (1, 'Alice')").unwrap();
2278        assert!(matches!(stmt, Statement::Insert(_)));
2279    }
2280
2281    #[test]
2282    fn test_create_table() {
2283        let stmt = Parser::parse(
2284            "CREATE TABLE users (id INTEGER PRIMARY KEY, name VARCHAR(100) NOT NULL)",
2285        )
2286        .unwrap();
2287        if let Statement::CreateTable(create) = stmt {
2288            assert_eq!(create.columns.len(), 2);
2289        } else {
2290            panic!("Expected CREATE TABLE statement");
2291        }
2292    }
2293
2294    #[test]
2295    fn test_vector_search() {
2296        let stmt = Parser::parse(
2297            "SELECT * FROM docs WHERE VECTOR_SEARCH(embedding, $1, 10, COSINE) > 0.8",
2298        )
2299        .unwrap();
2300        assert!(matches!(stmt, Statement::Select(_)));
2301    }
2302
2303    #[test]
2304    fn test_join() {
2305        let stmt = Parser::parse(
2306            "SELECT u.name, o.total FROM users u INNER JOIN orders o ON u.id = o.user_id",
2307        )
2308        .unwrap();
2309        assert!(matches!(stmt, Statement::Select(_)));
2310    }
2311
2312    #[test]
2313    fn test_subquery() {
2314        let stmt =
2315            Parser::parse("SELECT * FROM users WHERE id IN (SELECT user_id FROM orders)").unwrap();
2316        assert!(matches!(stmt, Statement::Select(_)));
2317    }
2318
2319    #[test]
2320    fn test_update() {
2321        let stmt = Parser::parse("UPDATE users SET name = 'Bob', age = 30 WHERE id = 1").unwrap();
2322        assert!(matches!(stmt, Statement::Update(_)));
2323    }
2324
2325    #[test]
2326    fn test_delete() {
2327        let stmt = Parser::parse("DELETE FROM users WHERE id = 1").unwrap();
2328        assert!(matches!(stmt, Statement::Delete(_)));
2329    }
2330
2331    #[test]
2332    fn test_group_by() {
2333        let stmt = Parser::parse(
2334            "SELECT category, COUNT(*) FROM products GROUP BY category HAVING COUNT(*) > 5",
2335        )
2336        .unwrap();
2337        if let Statement::Select(select) = stmt {
2338            assert!(!select.group_by.is_empty());
2339            assert!(select.having.is_some());
2340        } else {
2341            panic!("Expected SELECT statement");
2342        }
2343    }
2344
2345    #[test]
2346    fn test_order_by() {
2347        let stmt =
2348            Parser::parse("SELECT * FROM users ORDER BY name ASC, age DESC NULLS LAST").unwrap();
2349        if let Statement::Select(select) = stmt {
2350            assert_eq!(select.order_by.len(), 2);
2351        } else {
2352            panic!("Expected SELECT statement");
2353        }
2354    }
2355
2356    #[test]
2357    fn test_between() {
2358        let stmt = Parser::parse("SELECT * FROM products WHERE price BETWEEN 10 AND 100").unwrap();
2359        assert!(matches!(stmt, Statement::Select(_)));
2360    }
2361
2362    #[test]
2363    fn test_like() {
2364        let stmt = Parser::parse("SELECT * FROM users WHERE name LIKE '%Alice%'").unwrap();
2365        assert!(matches!(stmt, Statement::Select(_)));
2366    }
2367
2368    #[test]
2369    fn test_case() {
2370        let stmt =
2371            Parser::parse("SELECT CASE WHEN x > 0 THEN 'positive' ELSE 'non-positive' END FROM t")
2372                .unwrap();
2373        assert!(matches!(stmt, Statement::Select(_)));
2374    }
2375
2376    #[test]
2377    fn test_transactions() {
2378        let stmts = Parser::parse_statements("BEGIN; COMMIT; ROLLBACK").unwrap();
2379        assert_eq!(stmts.len(), 3);
2380        assert!(matches!(stmts[0], Statement::Begin(_)));
2381        assert!(matches!(stmts[1], Statement::Commit));
2382        assert!(matches!(stmts[2], Statement::Rollback(_)));
2383    }
2384
2385    // ===== Dialect-Specific Insert Tests =====
2386
2387    #[test]
2388    fn test_insert_on_conflict_do_nothing() {
2389        let stmt = Parser::parse(
2390            "INSERT INTO users (id, name) VALUES (1, 'Alice') ON CONFLICT DO NOTHING",
2391        )
2392        .unwrap();
2393        if let Statement::Insert(insert) = stmt {
2394            assert!(insert.on_conflict.is_some());
2395            let on_conflict = insert.on_conflict.unwrap();
2396            assert!(matches!(on_conflict.action, ConflictAction::DoNothing));
2397        } else {
2398            panic!("Expected INSERT statement");
2399        }
2400    }
2401
2402    #[test]
2403    fn test_insert_on_conflict_do_update() {
2404        let stmt = Parser::parse(
2405            "INSERT INTO users (id, name) VALUES (1, 'Alice') ON CONFLICT (id) DO UPDATE SET name = 'Bob'",
2406        )
2407        .unwrap();
2408        if let Statement::Insert(insert) = stmt {
2409            assert!(insert.on_conflict.is_some());
2410            let on_conflict = insert.on_conflict.unwrap();
2411            assert!(matches!(
2412                on_conflict.target,
2413                Some(ConflictTarget::Columns(_))
2414            ));
2415            assert!(matches!(on_conflict.action, ConflictAction::DoUpdate(_)));
2416        } else {
2417            panic!("Expected INSERT statement");
2418        }
2419    }
2420
2421    #[test]
2422    fn test_insert_ignore_mysql() {
2423        let stmt =
2424            Parser::parse("INSERT IGNORE INTO users (id, name) VALUES (1, 'Alice')").unwrap();
2425        if let Statement::Insert(insert) = stmt {
2426            assert!(insert.on_conflict.is_some());
2427            let on_conflict = insert.on_conflict.unwrap();
2428            assert!(matches!(on_conflict.action, ConflictAction::DoNothing));
2429        } else {
2430            panic!("Expected INSERT statement");
2431        }
2432    }
2433
2434    #[test]
2435    fn test_insert_or_ignore_sqlite() {
2436        let stmt =
2437            Parser::parse("INSERT OR IGNORE INTO users (id, name) VALUES (1, 'Alice')").unwrap();
2438        if let Statement::Insert(insert) = stmt {
2439            assert!(insert.on_conflict.is_some());
2440            let on_conflict = insert.on_conflict.unwrap();
2441            assert!(matches!(on_conflict.action, ConflictAction::DoNothing));
2442        } else {
2443            panic!("Expected INSERT statement");
2444        }
2445    }
2446
2447    #[test]
2448    fn test_insert_or_replace_sqlite() {
2449        let stmt =
2450            Parser::parse("INSERT OR REPLACE INTO users (id, name) VALUES (1, 'Alice')").unwrap();
2451        if let Statement::Insert(insert) = stmt {
2452            assert!(insert.on_conflict.is_some());
2453            let on_conflict = insert.on_conflict.unwrap();
2454            assert!(matches!(on_conflict.action, ConflictAction::DoReplace));
2455        } else {
2456            panic!("Expected INSERT statement");
2457        }
2458    }
2459
2460    #[test]
2461    fn test_on_duplicate_key_update_mysql() {
2462        let stmt = Parser::parse(
2463            "INSERT INTO users (id, name) VALUES (1, 'Alice') ON DUPLICATE KEY UPDATE name = 'Bob'",
2464        )
2465        .unwrap();
2466        if let Statement::Insert(insert) = stmt {
2467            assert!(insert.on_conflict.is_some());
2468            let on_conflict = insert.on_conflict.unwrap();
2469            assert!(matches!(on_conflict.action, ConflictAction::DoUpdate(_)));
2470        } else {
2471            panic!("Expected INSERT statement");
2472        }
2473    }
2474
2475    // ===== Idempotent DDL Tests =====
2476
2477    #[test]
2478    fn test_create_table_if_not_exists() {
2479        let stmt = Parser::parse("CREATE TABLE IF NOT EXISTS users (id INT PRIMARY KEY)").unwrap();
2480        if let Statement::CreateTable(create) = stmt {
2481            assert!(create.if_not_exists);
2482        } else {
2483            panic!("Expected CREATE TABLE statement");
2484        }
2485    }
2486
2487    #[test]
2488    fn test_drop_table_if_exists() {
2489        let stmt = Parser::parse("DROP TABLE IF EXISTS users").unwrap();
2490        if let Statement::DropTable(drop) = stmt {
2491            assert!(drop.if_exists);
2492        } else {
2493            panic!("Expected DROP TABLE statement");
2494        }
2495    }
2496
2497    #[test]
2498    fn test_create_index() {
2499        let stmt = Parser::parse("CREATE INDEX idx_users_name ON users (name)").unwrap();
2500        if let Statement::CreateIndex(create) = stmt {
2501            assert_eq!(create.name, "idx_users_name");
2502            assert_eq!(create.table.name(), "users");
2503            assert!(!create.unique);
2504            assert!(!create.if_not_exists);
2505        } else {
2506            panic!("Expected CREATE INDEX statement");
2507        }
2508    }
2509
2510    #[test]
2511    fn test_create_unique_index() {
2512        let stmt = Parser::parse("CREATE UNIQUE INDEX idx_users_email ON users (email)").unwrap();
2513        if let Statement::CreateIndex(create) = stmt {
2514            assert!(create.unique);
2515        } else {
2516            panic!("Expected CREATE INDEX statement");
2517        }
2518    }
2519
2520    #[test]
2521    fn test_create_index_if_not_exists() {
2522        let stmt =
2523            Parser::parse("CREATE INDEX IF NOT EXISTS idx_users_name ON users (name)").unwrap();
2524        if let Statement::CreateIndex(create) = stmt {
2525            assert!(create.if_not_exists);
2526        } else {
2527            panic!("Expected CREATE INDEX statement");
2528        }
2529    }
2530
2531    #[test]
2532    fn test_drop_index() {
2533        let stmt = Parser::parse("DROP INDEX idx_users_name").unwrap();
2534        if let Statement::DropIndex(drop) = stmt {
2535            assert_eq!(drop.name, "idx_users_name");
2536            assert!(!drop.if_exists);
2537        } else {
2538            panic!("Expected DROP INDEX statement");
2539        }
2540    }
2541
2542    #[test]
2543    fn test_drop_index_if_exists() {
2544        let stmt = Parser::parse("DROP INDEX IF EXISTS idx_users_name").unwrap();
2545        if let Statement::DropIndex(drop) = stmt {
2546            assert!(drop.if_exists);
2547        } else {
2548            panic!("Expected DROP INDEX statement");
2549        }
2550    }
2551
2552    // ===== RETURNING clause tests =====
2553
2554    #[test]
2555    fn test_insert_returning() {
2556        let stmt =
2557            Parser::parse("INSERT INTO users (id, name) VALUES (1, 'Alice') RETURNING id, name")
2558                .unwrap();
2559        if let Statement::Insert(insert) = stmt {
2560            assert!(insert.returning.is_some());
2561            let returning = insert.returning.unwrap();
2562            assert_eq!(returning.len(), 2);
2563        } else {
2564            panic!("Expected INSERT statement");
2565        }
2566    }
2567
2568    #[test]
2569    fn test_define_scope() {
2570        let stmt =
2571            Parser::parse("DEFINE SCOPE user_scope SESSION 86400 SIGNIN (1) SIGNUP (2)").unwrap();
2572        if let Statement::DefineScope(scope) = stmt {
2573            assert_eq!(scope.name, "user_scope");
2574            assert_eq!(scope.session_duration_secs, Some(86400));
2575            assert!(scope.signin.is_some());
2576            assert!(scope.signup.is_some());
2577        } else {
2578            panic!("Expected DEFINE SCOPE statement, got {:?}", stmt);
2579        }
2580    }
2581
2582    #[test]
2583    fn test_define_table_permissions() {
2584        let stmt =
2585            Parser::parse("DEFINE TABLE post PERMISSIONS FOR select WHERE 1 FOR delete WHERE 0")
2586                .unwrap();
2587        if let Statement::DefineTablePermissions(def) = stmt {
2588            assert_eq!(def.table.to_string(), "post");
2589            assert_eq!(def.permissions.len(), 2);
2590            assert_eq!(def.permissions[0].operation, PermissionOp::Select);
2591            assert_eq!(def.permissions[1].operation, PermissionOp::Delete);
2592        } else {
2593            panic!(
2594                "Expected DEFINE TABLE PERMISSIONS statement, got {:?}",
2595                stmt
2596            );
2597        }
2598    }
2599
2600    #[test]
2601    fn test_remove_scope() {
2602        let stmt = Parser::parse("REMOVE SCOPE user_scope").unwrap();
2603        if let Statement::RemoveScope(name) = stmt {
2604            assert_eq!(name, "user_scope");
2605        } else {
2606            panic!("Expected REMOVE SCOPE statement");
2607        }
2608    }
2609
2610    // ===== Graph & Real-Time tests =====
2611
2612    #[test]
2613    fn test_graph_arrow_operator() {
2614        // person -> knows should parse as BinaryOp { GraphRight }
2615        let stmt = Parser::parse("SELECT person -> knows FROM graph").unwrap();
2616        if let Statement::Select(select) = stmt {
2617            if let SelectItem::Expr { expr, .. } = &select.columns[0] {
2618                if let Expr::BinaryOp { op, .. } = expr {
2619                    assert_eq!(*op, BinaryOperator::GraphRight);
2620                } else {
2621                    panic!("Expected BinaryOp with GraphRight, got {:?}", expr);
2622                }
2623            } else {
2624                panic!("Expected Expr select item");
2625            }
2626        } else {
2627            panic!("Expected SELECT statement");
2628        }
2629    }
2630
2631    #[test]
2632    fn test_graph_left_arrow_operator() {
2633        let stmt = Parser::parse("SELECT x <- y FROM graph").unwrap();
2634        if let Statement::Select(select) = stmt {
2635            if let SelectItem::Expr { expr, .. } = &select.columns[0] {
2636                if let Expr::BinaryOp { op, .. } = expr {
2637                    assert_eq!(*op, BinaryOperator::GraphLeft);
2638                } else {
2639                    panic!("Expected BinaryOp with GraphLeft, got {:?}", expr);
2640                }
2641            } else {
2642                panic!("Expected Expr select item");
2643            }
2644        } else {
2645            panic!("Expected SELECT statement");
2646        }
2647    }
2648
2649    #[test]
2650    fn test_graph_biarrow_operator() {
2651        let stmt = Parser::parse("SELECT x <-> y FROM graph").unwrap();
2652        if let Statement::Select(select) = stmt {
2653            if let SelectItem::Expr { expr, .. } = &select.columns[0] {
2654                if let Expr::BinaryOp { op, .. } = expr {
2655                    assert_eq!(*op, BinaryOperator::GraphBi);
2656                } else {
2657                    panic!("Expected BinaryOp with GraphBi, got {:?}", expr);
2658                }
2659            } else {
2660                panic!("Expected Expr select item");
2661            }
2662        } else {
2663            panic!("Expected SELECT statement");
2664        }
2665    }
2666
2667    #[test]
2668    fn test_graph_traversal_chain() {
2669        // person:1 -> knows -> person should left-associate
2670        let stmt = Parser::parse("SELECT a -> b -> c FROM graph").unwrap();
2671        if let Statement::Select(select) = stmt {
2672            if let SelectItem::Expr { expr, .. } = &select.columns[0] {
2673                // (a -> b) -> c
2674                if let Expr::BinaryOp { left, op, .. } = expr {
2675                    assert_eq!(*op, BinaryOperator::GraphRight);
2676                    if let Expr::BinaryOp { op: inner_op, .. } = left.as_ref() {
2677                        assert_eq!(*inner_op, BinaryOperator::GraphRight);
2678                    } else {
2679                        panic!("Expected chained -> operator");
2680                    }
2681                } else {
2682                    panic!("Expected BinaryOp");
2683                }
2684            }
2685        }
2686    }
2687
2688    #[test]
2689    fn test_record_id_literal() {
2690        let stmt = Parser::parse("SELECT person:1 FROM people").unwrap();
2691        if let Statement::Select(select) = stmt {
2692            if let SelectItem::Expr { expr, .. } = &select.columns[0] {
2693                if let Expr::RecordId { table, id } = expr {
2694                    assert_eq!(table, "person");
2695                    assert!(matches!(id.as_ref(), Expr::Literal(Literal::Integer(1))));
2696                } else {
2697                    panic!("Expected RecordId, got {:?}", expr);
2698                }
2699            }
2700        }
2701    }
2702
2703    #[test]
2704    fn test_record_id_with_string() {
2705        let stmt = Parser::parse("SELECT user:'abc' FROM users").unwrap();
2706        if let Statement::Select(select) = stmt {
2707            if let SelectItem::Expr { expr, .. } = &select.columns[0] {
2708                if let Expr::RecordId { table, id } = expr {
2709                    assert_eq!(table, "user");
2710                    if let Expr::Literal(Literal::String(s)) = id.as_ref() {
2711                        assert_eq!(s, "abc");
2712                    } else {
2713                        panic!("Expected string id");
2714                    }
2715                } else {
2716                    panic!("Expected RecordId, got {:?}", expr);
2717                }
2718            }
2719        }
2720    }
2721
2722    #[test]
2723    fn test_relate_statement() {
2724        let stmt =
2725            Parser::parse("RELATE person:1 -> knows -> person:2 SET since = '2024-01-01'").unwrap();
2726        if let Statement::Relate(relate) = stmt {
2727            assert_eq!(relate.edge.to_string(), "knows");
2728            if let Expr::RecordId { table, .. } = &relate.from {
2729                assert_eq!(table, "person");
2730            } else {
2731                panic!("Expected RecordId for from, got {:?}", relate.from);
2732            }
2733            if let Expr::RecordId { table, .. } = &relate.to {
2734                assert_eq!(table, "person");
2735            } else {
2736                panic!("Expected RecordId for to, got {:?}", relate.to);
2737            }
2738            assert_eq!(relate.set.len(), 1);
2739            assert_eq!(relate.set[0].column, "since");
2740        } else {
2741            panic!("Expected RELATE statement, got {:?}", stmt);
2742        }
2743    }
2744
2745    #[test]
2746    fn test_relate_with_content() {
2747        let stmt = Parser::parse("RELATE user:1 -> follows -> user:2 CONTENT 'data'").unwrap();
2748        if let Statement::Relate(relate) = stmt {
2749            assert_eq!(relate.edge.to_string(), "follows");
2750            assert!(relate.content.is_some());
2751            assert!(relate.set.is_empty());
2752        } else {
2753            panic!("Expected RELATE statement");
2754        }
2755    }
2756
2757    #[test]
2758    fn test_live_select() {
2759        let stmt = Parser::parse("LIVE SELECT * FROM person WHERE age > 18").unwrap();
2760        if let Statement::LiveSelect(live) = stmt {
2761            assert!(!live.diff);
2762            assert_eq!(live.select.columns.len(), 1);
2763            assert!(matches!(live.select.columns[0], SelectItem::Wildcard));
2764            assert!(live.select.where_clause.is_some());
2765        } else {
2766            panic!("Expected LIVE SELECT statement, got {:?}", stmt);
2767        }
2768    }
2769
2770    #[test]
2771    fn test_live_select_diff() {
2772        let stmt = Parser::parse("LIVE DIFF SELECT * FROM person").unwrap();
2773        if let Statement::LiveSelect(live) = stmt {
2774            assert!(live.diff);
2775        } else {
2776            panic!("Expected LIVE SELECT DIFF statement");
2777        }
2778    }
2779
2780    #[test]
2781    fn test_define_event() {
2782        let stmt = Parser::parse("DEFINE EVENT notify ON TABLE user WHEN 1 THEN 2").unwrap();
2783        if let Statement::DefineEvent(event) = stmt {
2784            assert_eq!(event.name, "notify");
2785            assert_eq!(event.table.to_string(), "user");
2786        } else {
2787            panic!("Expected DEFINE EVENT statement, got {:?}", stmt);
2788        }
2789    }
2790
2791    #[test]
2792    fn test_graph_precedence_vs_comparison() {
2793        // a -> b = c  should parse as  (a -> b) = c
2794        let stmt = Parser::parse("SELECT a -> b = c FROM t").unwrap();
2795        if let Statement::Select(select) = stmt {
2796            if let SelectItem::Expr { expr, .. } = &select.columns[0] {
2797                if let Expr::BinaryOp { op, left, .. } = expr {
2798                    assert_eq!(*op, BinaryOperator::Eq);
2799                    // Left side should be (a -> b)
2800                    if let Expr::BinaryOp { op: inner_op, .. } = left.as_ref() {
2801                        assert_eq!(*inner_op, BinaryOperator::GraphRight);
2802                    } else {
2803                        panic!("Expected -> in left operand of =");
2804                    }
2805                } else {
2806                    panic!("Expected comparison at top level");
2807                }
2808            }
2809        }
2810    }
2811}
2812
2813// ============================================================================
2814// Helper Functions
2815// ============================================================================
2816
2817/// Parse a duration string like "24h", "7d", "30m", "3600" into seconds.
2818fn parse_duration_string(s: &str) -> u64 {
2819    let s = s.trim();
2820    if s.is_empty() {
2821        return 0;
2822    }
2823
2824    // Try pure numeric
2825    if let Ok(n) = s.parse::<u64>() {
2826        return n;
2827    }
2828
2829    // Try suffix: s (seconds), m (minutes), h (hours), d (days)
2830    let (num_part, suffix) = s.split_at(s.len() - 1);
2831    let n: u64 = num_part.parse().unwrap_or(0);
2832    match suffix {
2833        "s" => n,
2834        "m" => n * 60,
2835        "h" => n * 3600,
2836        "d" => n * 86400,
2837        "w" => n * 604800,
2838        _ => 0,
2839    }
2840}