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