vibesql/parser/
stmt.rs

1//! DML and DDL statement parsing.
2
3use super::Parser;
4use crate::ast::*;
5use crate::error::{Error, Result, Span};
6use crate::lexer::{Keyword, TokenKind};
7
8impl<'a> Parser<'a> {
9    // ========================================================================
10    // DML Statements
11    // ========================================================================
12
13    /// Parse INSERT statement.
14    pub fn parse_insert(&mut self) -> Result<StatementKind> {
15        self.expect_keyword(Keyword::Insert)?;
16
17        // Optional OR action
18        let or_action = if self.consume_keyword(Keyword::Or)?.is_some() {
19            if self.consume_keyword(Keyword::Ignore)?.is_some() {
20                Some(InsertOrAction::Ignore)
21            } else if self.consume_keyword(Keyword::Replace)?.is_some() {
22                Some(InsertOrAction::Replace)
23            } else if self.consume_keyword(Keyword::Update)?.is_some() {
24                Some(InsertOrAction::Update)
25            } else {
26                let token = self.peek()?;
27                return Err(Error::unexpected_token(
28                    "IGNORE, REPLACE, or UPDATE",
29                    format!("{}", token.kind),
30                    token.span,
31                ));
32            }
33        } else {
34            None
35        };
36
37        self.expect_keyword(Keyword::Into)?;
38        let table = self.parse_object_name()?;
39
40        // Optional column list
41        let columns = if self.consume(&TokenKind::LeftParen)?.is_some() {
42            let cols = self.parse_comma_separated(|p| p.parse_identifier())?;
43            self.expect(&TokenKind::RightParen)?;
44            cols
45        } else {
46            Vec::new()
47        };
48
49        // Parse source
50        let source = if self.consume_keyword(Keyword::Default)?.is_some() {
51            self.expect_keyword(Keyword::Values)?;
52            InsertSource::DefaultValues
53        } else if self.consume_keyword(Keyword::Values)?.is_some() {
54            let rows = self.parse_comma_separated(|p| {
55                p.expect(&TokenKind::LeftParen)?;
56                let values = p.parse_comma_separated(|p2| p2.parse_expression())?;
57                p.expect(&TokenKind::RightParen)?;
58                Ok(values)
59            })?;
60            InsertSource::Values(rows)
61        } else {
62            let query = self.parse_query()?;
63            InsertSource::Query(Box::new(query))
64        };
65
66        // Optional RETURNING clause
67        let returning = self.parse_returning_clause()?;
68
69        Ok(StatementKind::Insert(InsertStatement {
70            or_action,
71            table,
72            columns,
73            source,
74            returning,
75        }))
76    }
77
78    /// Parse UPDATE statement.
79    pub fn parse_update(&mut self) -> Result<StatementKind> {
80        self.expect_keyword(Keyword::Update)?;
81        let table = self.parse_table_ref()?;
82
83        self.expect_keyword(Keyword::Set)?;
84        let assignments = self.parse_comma_separated(|p| p.parse_assignment())?;
85
86        // Optional FROM clause
87        let from = if self.consume_keyword(Keyword::From)?.is_some() {
88            let tables = self.parse_comma_separated(|p| p.parse_table_ref())?;
89            Some(FromClause { tables })
90        } else {
91            None
92        };
93
94        // Optional WHERE clause
95        let where_clause = if self.consume_keyword(Keyword::Where)?.is_some() {
96            Some(self.parse_expression()?)
97        } else {
98            None
99        };
100
101        // Optional RETURNING clause
102        let returning = self.parse_returning_clause()?;
103
104        Ok(StatementKind::Update(UpdateStatement {
105            table,
106            assignments,
107            from,
108            where_clause,
109            returning,
110        }))
111    }
112
113    /// Parse an assignment (column = expr).
114    fn parse_assignment(&mut self) -> Result<Assignment> {
115        let first = self.parse_identifier()?;
116
117        // Check for path (col.field.field = value)
118        let target = if self.consume(&TokenKind::Dot)?.is_some() {
119            let mut parts = vec![first];
120            parts.push(self.parse_identifier()?);
121            while self.consume(&TokenKind::Dot)?.is_some() {
122                parts.push(self.parse_identifier()?);
123            }
124            AssignmentTarget::Path(parts)
125        } else {
126            AssignmentTarget::Column(first)
127        };
128
129        self.expect(&TokenKind::Eq)?;
130        let value = self.parse_expression()?;
131
132        Ok(Assignment { target, value })
133    }
134
135    /// Parse DELETE statement.
136    pub fn parse_delete(&mut self) -> Result<StatementKind> {
137        self.expect_keyword(Keyword::Delete)?;
138        self.expect_keyword(Keyword::From)?;
139
140        let table = self.parse_object_name()?;
141        let alias = self.parse_optional_table_alias()?;
142
143        // Optional WHERE clause
144        let where_clause = if self.consume_keyword(Keyword::Where)?.is_some() {
145            Some(self.parse_expression()?)
146        } else {
147            None
148        };
149
150        // Optional RETURNING clause
151        let returning = self.parse_returning_clause()?;
152
153        Ok(StatementKind::Delete(DeleteStatement {
154            table,
155            alias,
156            where_clause,
157            returning,
158        }))
159    }
160
161    /// Parse MERGE statement.
162    pub fn parse_merge(&mut self) -> Result<StatementKind> {
163        self.expect_keyword(Keyword::Merge)?;
164        self.expect_keyword(Keyword::Into)?;
165
166        let target = self.parse_table_ref()?;
167
168        self.expect_keyword(Keyword::Using)?;
169        let source = self.parse_table_ref()?;
170
171        self.expect_keyword(Keyword::On)?;
172        let on = self.parse_expression()?;
173
174        let mut clauses = Vec::new();
175        while self.consume_keyword(Keyword::When)?.is_some() {
176            let clause = self.parse_merge_clause()?;
177            clauses.push(clause);
178        }
179
180        Ok(StatementKind::Merge(MergeStatement {
181            target,
182            source,
183            on,
184            clauses,
185        }))
186    }
187
188    /// Parse a MERGE clause (WHEN MATCHED/NOT MATCHED).
189    fn parse_merge_clause(&mut self) -> Result<MergeClause> {
190        let is_not = self.consume_keyword(Keyword::Not)?.is_some();
191
192        self.expect_keyword(Keyword::Matched)?;
193
194        let by_source = if is_not {
195            self.consume_keyword(Keyword::By)?.is_some() && {
196                self.expect_keyword(Keyword::Source)?;
197                true
198            }
199        } else {
200            false
201        };
202
203        // Optional AND condition
204        let condition = if self.consume_keyword(Keyword::And)?.is_some() {
205            Some(self.parse_expression()?)
206        } else {
207            None
208        };
209
210        self.expect_keyword(Keyword::Then)?;
211
212        if is_not && !by_source {
213            // WHEN NOT MATCHED [BY TARGET] THEN INSERT
214            self.expect_keyword(Keyword::Insert)?;
215
216            let columns = if self.consume(&TokenKind::LeftParen)?.is_some() {
217                let cols = self.parse_comma_separated(|p| p.parse_identifier())?;
218                self.expect(&TokenKind::RightParen)?;
219                cols
220            } else {
221                Vec::new()
222            };
223
224            self.expect_keyword(Keyword::Values)?;
225            self.expect(&TokenKind::LeftParen)?;
226            let values = self.parse_comma_separated(|p| p.parse_expression())?;
227            self.expect(&TokenKind::RightParen)?;
228
229            Ok(MergeClause::NotMatched {
230                condition,
231                action: MergeNotMatchedAction { columns, values },
232            })
233        } else if is_not && by_source {
234            // WHEN NOT MATCHED BY SOURCE THEN UPDATE/DELETE
235            let action = self.parse_merge_matched_action()?;
236            Ok(MergeClause::NotMatchedBySource { condition, action })
237        } else {
238            // WHEN MATCHED THEN UPDATE/DELETE
239            let action = self.parse_merge_matched_action()?;
240            Ok(MergeClause::Matched { condition, action })
241        }
242    }
243
244    /// Parse MERGE matched action (UPDATE or DELETE).
245    fn parse_merge_matched_action(&mut self) -> Result<MergeMatchedAction> {
246        if self.consume_keyword(Keyword::Update)?.is_some() {
247            self.expect_keyword(Keyword::Set)?;
248            let assignments = self.parse_comma_separated(|p| p.parse_assignment())?;
249            Ok(MergeMatchedAction::Update { assignments })
250        } else if self.consume_keyword(Keyword::Delete)?.is_some() {
251            Ok(MergeMatchedAction::Delete)
252        } else {
253            let token = self.peek()?;
254            Err(Error::unexpected_token(
255                "UPDATE or DELETE",
256                format!("{}", token.kind),
257                token.span,
258            ))
259        }
260    }
261
262    /// Parse RETURNING clause.
263    fn parse_returning_clause(&mut self) -> Result<Option<ReturningClause>> {
264        if self.consume_keyword(Keyword::Returning)?.is_some() {
265            let items = self.parse_comma_separated(|p| p.parse_select_item())?;
266            let with_action = false; // WITH ACTION not yet supported
267            Ok(Some(ReturningClause { items, with_action }))
268        } else {
269            Ok(None)
270        }
271    }
272
273    // ========================================================================
274    // DDL Statements
275    // ========================================================================
276
277    /// Parse CREATE statement.
278    pub fn parse_create(&mut self) -> Result<StatementKind> {
279        self.expect_keyword(Keyword::Create)?;
280
281        // Check for OR REPLACE
282        let or_replace = if self.consume_keyword(Keyword::Or)?.is_some() {
283            self.expect_keyword(Keyword::Replace)?;
284            true
285        } else {
286            false
287        };
288
289        // Check for TEMPORARY
290        let temporary = self.consume_keyword(Keyword::Temporary)?.is_some()
291            || self.consume_keyword(Keyword::Temp)?.is_some();
292
293        if self.consume_keyword(Keyword::Table)?.is_some() {
294            self.parse_create_table(or_replace, temporary)
295        } else if self.consume_keyword(Keyword::View)?.is_some() {
296            self.parse_create_view(or_replace, false)
297        } else if self.consume_keyword(Keyword::Materialized)?.is_some() {
298            self.expect_keyword(Keyword::View)?;
299            self.parse_create_view(or_replace, true)
300        } else if self.consume_keyword(Keyword::Index)?.is_some() {
301            self.parse_create_index(false)
302        } else if self.consume_keyword(Keyword::Unique)?.is_some() {
303            self.expect_keyword(Keyword::Index)?;
304            self.parse_create_index(true)
305        } else if self.consume_keyword(Keyword::Function)?.is_some() {
306            self.parse_create_function(or_replace, temporary)
307        } else if self.consume_keyword(Keyword::Procedure)?.is_some() {
308            self.parse_create_procedure(or_replace)
309        } else if self.consume_keyword(Keyword::Database)?.is_some()
310            || self.consume_keyword(Keyword::Schema)?.is_some()
311        {
312            self.parse_create_database()
313        } else {
314            let token = self.peek()?;
315            Err(Error::unexpected_token(
316                "TABLE, VIEW, INDEX, FUNCTION, PROCEDURE, or DATABASE",
317                format!("{}", token.kind),
318                token.span,
319            ))
320        }
321    }
322
323    /// Parse CREATE TABLE statement.
324    fn parse_create_table(&mut self, or_replace: bool, temporary: bool) -> Result<StatementKind> {
325        let if_not_exists = if self.consume_keyword(Keyword::If)?.is_some() {
326            self.expect_keyword(Keyword::Not)?;
327            self.expect_keyword(Keyword::Exists)?;
328            true
329        } else {
330            false
331        };
332
333        let name = self.parse_object_name()?;
334
335        // Check for LIKE or CLONE
336        let like = if self.consume_keyword(Keyword::Like)?.is_some() {
337            Some(self.parse_object_name()?)
338        } else {
339            None
340        };
341
342        let clone = if self.consume_keyword(Keyword::Clone)?.is_some() {
343            Some(self.parse_object_name()?)
344        } else {
345            None
346        };
347
348        // Check for AS SELECT
349        let as_query = if self.consume_keyword(Keyword::As)?.is_some() {
350            Some(Box::new(self.parse_query()?))
351        } else {
352            None
353        };
354
355        // Parse column definitions and constraints
356        let (columns, constraints) = if self.consume(&TokenKind::LeftParen)?.is_some() {
357            let mut columns = Vec::new();
358            let mut constraints = Vec::new();
359
360            loop {
361                // Check for table constraint
362                if self.check_keyword(Keyword::Primary)?
363                    || self.check_keyword(Keyword::Unique)?
364                    || self.check_keyword(Keyword::Foreign)?
365                    || self.check_keyword(Keyword::Check)?
366                    || self.check_keyword(Keyword::Constraint)?
367                {
368                    constraints.push(self.parse_table_constraint()?);
369                } else {
370                    columns.push(self.parse_column_def()?);
371                }
372
373                if self.consume(&TokenKind::Comma)?.is_none() {
374                    break;
375                }
376            }
377
378            self.expect(&TokenKind::RightParen)?;
379            (columns, constraints)
380        } else {
381            (Vec::new(), Vec::new())
382        };
383
384        // Parse PARTITION BY
385        let partition_by = if self.consume_keyword(Keyword::Partition)?.is_some() {
386            self.expect_keyword(Keyword::By)?;
387            self.parse_comma_separated(|p| p.parse_expression())?
388        } else {
389            Vec::new()
390        };
391
392        // Parse CLUSTER BY
393        let cluster_by = if self.consume_keyword(Keyword::Cluster)?.is_some() {
394            self.expect_keyword(Keyword::By)?;
395            self.parse_comma_separated(|p| p.parse_expression())?
396        } else {
397            Vec::new()
398        };
399
400        // Parse OPTIONS
401        let options = self.parse_options_clause()?;
402
403        Ok(StatementKind::CreateTable(CreateTableStatement {
404            or_replace,
405            temporary,
406            if_not_exists,
407            name,
408            columns,
409            constraints,
410            partition_by,
411            cluster_by,
412            options,
413            as_query,
414            like,
415            clone,
416        }))
417    }
418
419    /// Parse column definition.
420    fn parse_column_def(&mut self) -> Result<ColumnDef> {
421        let start = self.current_position();
422        let name = self.parse_identifier()?;
423
424        // Optional data type
425        let data_type = if !self.check(&TokenKind::Comma)?
426            && !self.check(&TokenKind::RightParen)?
427            && !self.check_keyword(Keyword::Primary)?
428            && !self.check_keyword(Keyword::Not)?
429            && !self.check(&TokenKind::Null)?  // NULL is a special token
430            && !self.check_keyword(Keyword::Default)?
431            && !self.check_keyword(Keyword::Unique)?
432            && !self.check_keyword(Keyword::Check)?
433            && !self.check_keyword(Keyword::References)?
434            && !self.check_keyword(Keyword::Generated)?
435            && !self.check_keyword(Keyword::Hidden)?
436            && !self.check_keyword(Keyword::Options)?
437        {
438            Some(self.parse_data_type()?)
439        } else {
440            None
441        };
442
443        // Parse column constraints
444        let mut constraints = Vec::new();
445        loop {
446            if self.consume_keyword(Keyword::Not)?.is_some() {
447                self.expect(&TokenKind::Null)?; // NULL is a special token
448                constraints.push(ColumnConstraint::NotNull);
449            } else if self.consume(&TokenKind::Null)?.is_some() {
450                // NULL is a special token
451                constraints.push(ColumnConstraint::Null);
452            } else if self.consume_keyword(Keyword::Primary)?.is_some() {
453                self.expect_keyword(Keyword::Key)?;
454                constraints.push(ColumnConstraint::PrimaryKey);
455            } else if self.consume_keyword(Keyword::Unique)?.is_some() {
456                constraints.push(ColumnConstraint::Unique);
457            } else if self.consume_keyword(Keyword::Default)?.is_some() {
458                let expr = self.parse_expression()?;
459                constraints.push(ColumnConstraint::Default(expr));
460            } else if self.consume_keyword(Keyword::Check)?.is_some() {
461                self.expect(&TokenKind::LeftParen)?;
462                let expr = self.parse_expression()?;
463                self.expect(&TokenKind::RightParen)?;
464                constraints.push(ColumnConstraint::Check(expr));
465            } else if self.consume_keyword(Keyword::References)?.is_some() {
466                let table = self.parse_object_name()?;
467                let columns = if self.consume(&TokenKind::LeftParen)?.is_some() {
468                    let cols = self.parse_comma_separated(|p| p.parse_identifier())?;
469                    self.expect(&TokenKind::RightParen)?;
470                    cols
471                } else {
472                    Vec::new()
473                };
474                let on_delete = self.parse_referential_action(Keyword::Delete)?;
475                let on_update = self.parse_referential_action(Keyword::Update)?;
476                constraints.push(ColumnConstraint::References {
477                    table,
478                    columns,
479                    on_delete,
480                    on_update,
481                });
482            } else if self.consume_keyword(Keyword::Generated)?.is_some() {
483                let always = if self.consume_keyword(Keyword::Always)?.is_some() {
484                    true
485                } else {
486                    self.expect_keyword(Keyword::By)?;
487                    self.expect_keyword(Keyword::Default)?;
488                    false
489                };
490                self.expect_keyword(Keyword::As)?;
491                self.expect(&TokenKind::LeftParen)?;
492                let expr = self.parse_expression()?;
493                self.expect(&TokenKind::RightParen)?;
494                constraints.push(ColumnConstraint::Generated { expr, always });
495            } else if self.consume_keyword(Keyword::Hidden)?.is_some() {
496                constraints.push(ColumnConstraint::Hidden);
497            } else {
498                break;
499            }
500        }
501
502        // Parse OPTIONS
503        let options = self.parse_options_clause()?;
504
505        let end = self.current_position();
506        Ok(ColumnDef {
507            name,
508            data_type,
509            constraints,
510            options,
511            span: Span::new(start, end),
512        })
513    }
514
515    /// Parse referential action (ON DELETE/UPDATE).
516    fn parse_referential_action(&mut self, keyword: Keyword) -> Result<Option<ReferentialAction>> {
517        if self.consume_keyword(Keyword::On)?.is_some() {
518            self.expect_keyword(keyword)?;
519            let action = if self.consume_keyword(Keyword::No)?.is_some() {
520                self.expect_keyword(Keyword::Action)?;
521                ReferentialAction::NoAction
522            } else if self.consume_keyword(Keyword::Restrict)?.is_some() {
523                ReferentialAction::Restrict
524            } else if self.consume_keyword(Keyword::Cascade)?.is_some() {
525                ReferentialAction::Cascade
526            } else if self.consume_keyword(Keyword::Set)?.is_some() {
527                if self.consume(&TokenKind::Null)?.is_some() {
528                    // NULL is a special token
529                    ReferentialAction::SetNull
530                } else {
531                    self.expect_keyword(Keyword::Default)?;
532                    ReferentialAction::SetDefault
533                }
534            } else {
535                let token = self.peek()?;
536                return Err(Error::unexpected_token(
537                    "NO ACTION, RESTRICT, CASCADE, SET NULL, or SET DEFAULT",
538                    format!("{}", token.kind),
539                    token.span,
540                ));
541            };
542            Ok(Some(action))
543        } else {
544            Ok(None)
545        }
546    }
547
548    /// Parse table constraint.
549    fn parse_table_constraint(&mut self) -> Result<TableConstraint> {
550        // Optional constraint name
551        let name = if self.consume_keyword(Keyword::Constraint)?.is_some() {
552            Some(self.parse_identifier()?)
553        } else {
554            None
555        };
556
557        if self.consume_keyword(Keyword::Primary)?.is_some() {
558            self.expect_keyword(Keyword::Key)?;
559            self.expect(&TokenKind::LeftParen)?;
560            let columns = self.parse_comma_separated(|p| p.parse_sort_key())?;
561            self.expect(&TokenKind::RightParen)?;
562            let options = self.parse_options_clause()?;
563            Ok(TableConstraint::PrimaryKey {
564                name,
565                columns,
566                options,
567            })
568        } else if self.consume_keyword(Keyword::Unique)?.is_some() {
569            self.expect(&TokenKind::LeftParen)?;
570            let columns = self.parse_comma_separated(|p| p.parse_identifier())?;
571            self.expect(&TokenKind::RightParen)?;
572            Ok(TableConstraint::Unique { name, columns })
573        } else if self.consume_keyword(Keyword::Foreign)?.is_some() {
574            self.expect_keyword(Keyword::Key)?;
575            self.expect(&TokenKind::LeftParen)?;
576            let columns = self.parse_comma_separated(|p| p.parse_identifier())?;
577            self.expect(&TokenKind::RightParen)?;
578            self.expect_keyword(Keyword::References)?;
579            let references_table = self.parse_object_name()?;
580            self.expect(&TokenKind::LeftParen)?;
581            let references_columns = self.parse_comma_separated(|p| p.parse_identifier())?;
582            self.expect(&TokenKind::RightParen)?;
583            let on_delete = self.parse_referential_action(Keyword::Delete)?;
584            let on_update = self.parse_referential_action(Keyword::Update)?;
585            Ok(TableConstraint::ForeignKey {
586                name,
587                columns,
588                references_table,
589                references_columns,
590                on_delete,
591                on_update,
592            })
593        } else if self.consume_keyword(Keyword::Check)?.is_some() {
594            self.expect(&TokenKind::LeftParen)?;
595            let expr = self.parse_expression()?;
596            self.expect(&TokenKind::RightParen)?;
597            let enforced = if self.consume_keyword(Keyword::Enforced)?.is_some() {
598                Some(true)
599            } else if self.consume_keyword(Keyword::Not)?.is_some() {
600                self.expect_keyword(Keyword::Enforced)?;
601                Some(false)
602            } else {
603                None
604            };
605            Ok(TableConstraint::Check {
606                name,
607                expr,
608                enforced,
609            })
610        } else {
611            let token = self.peek()?;
612            Err(Error::unexpected_token(
613                "PRIMARY, UNIQUE, FOREIGN, or CHECK",
614                format!("{}", token.kind),
615                token.span,
616            ))
617        }
618    }
619
620    /// Parse sort key for PRIMARY KEY.
621    fn parse_sort_key(&mut self) -> Result<SortKey> {
622        let column = self.parse_identifier()?;
623        let order = if self.consume_keyword(Keyword::Asc)?.is_some() {
624            Some(SortOrder::Asc)
625        } else if self.consume_keyword(Keyword::Desc)?.is_some() {
626            Some(SortOrder::Desc)
627        } else {
628            None
629        };
630        let nulls = None; // Not typically used in PRIMARY KEY
631        Ok(SortKey {
632            column,
633            order,
634            nulls,
635        })
636    }
637
638    /// Parse OPTIONS clause.
639    fn parse_options_clause(&mut self) -> Result<Vec<SqlOption>> {
640        if self.consume_keyword(Keyword::Options)?.is_some() {
641            self.expect(&TokenKind::LeftParen)?;
642            let options = self.parse_comma_separated(|p| {
643                let name = p.parse_identifier()?;
644                p.expect(&TokenKind::Eq)?;
645                let value = p.parse_expression()?;
646                Ok(SqlOption { name, value })
647            })?;
648            self.expect(&TokenKind::RightParen)?;
649            Ok(options)
650        } else {
651            Ok(Vec::new())
652        }
653    }
654
655    /// Parse CREATE VIEW statement.
656    fn parse_create_view(&mut self, or_replace: bool, materialized: bool) -> Result<StatementKind> {
657        let if_not_exists = if self.consume_keyword(Keyword::If)?.is_some() {
658            self.expect_keyword(Keyword::Not)?;
659            self.expect_keyword(Keyword::Exists)?;
660            true
661        } else {
662            false
663        };
664
665        let name = self.parse_object_name()?;
666
667        // Optional column list
668        let columns = if self.consume(&TokenKind::LeftParen)?.is_some() {
669            let cols = self.parse_comma_separated(|p| p.parse_identifier())?;
670            self.expect(&TokenKind::RightParen)?;
671            cols
672        } else {
673            Vec::new()
674        };
675
676        let options = self.parse_options_clause()?;
677
678        self.expect_keyword(Keyword::As)?;
679        let query = Box::new(self.parse_query()?);
680
681        Ok(StatementKind::CreateView(CreateViewStatement {
682            or_replace,
683            materialized,
684            if_not_exists,
685            name,
686            columns,
687            query,
688            options,
689        }))
690    }
691
692    /// Parse CREATE INDEX statement.
693    fn parse_create_index(&mut self, unique: bool) -> Result<StatementKind> {
694        let if_not_exists = if self.consume_keyword(Keyword::If)?.is_some() {
695            self.expect_keyword(Keyword::Not)?;
696            self.expect_keyword(Keyword::Exists)?;
697            true
698        } else {
699            false
700        };
701
702        // Optional index name
703        let name = if !self.check_keyword(Keyword::On)? {
704            Some(self.parse_identifier()?)
705        } else {
706            None
707        };
708
709        self.expect_keyword(Keyword::On)?;
710        let table = self.parse_object_name()?;
711
712        self.expect(&TokenKind::LeftParen)?;
713        let columns = self.parse_comma_separated(|p| p.parse_sort_key())?;
714        self.expect(&TokenKind::RightParen)?;
715
716        let options = self.parse_options_clause()?;
717
718        Ok(StatementKind::CreateIndex(CreateIndexStatement {
719            unique,
720            if_not_exists,
721            name,
722            table,
723            columns,
724            options,
725        }))
726    }
727
728    /// Parse CREATE FUNCTION statement.
729    fn parse_create_function(
730        &mut self,
731        or_replace: bool,
732        temporary: bool,
733    ) -> Result<StatementKind> {
734        let if_not_exists = if self.consume_keyword(Keyword::If)?.is_some() {
735            self.expect_keyword(Keyword::Not)?;
736            self.expect_keyword(Keyword::Exists)?;
737            true
738        } else {
739            false
740        };
741
742        let name = self.parse_object_name()?;
743
744        // Parse parameters
745        self.expect(&TokenKind::LeftParen)?;
746        let params = if self.check(&TokenKind::RightParen)? {
747            Vec::new()
748        } else {
749            self.parse_comma_separated(|p| p.parse_function_param())?
750        };
751        self.expect(&TokenKind::RightParen)?;
752
753        // Optional RETURNS clause
754        let returns = if self.consume_keyword(Keyword::Returns)?.is_some() {
755            Some(self.parse_data_type()?)
756        } else {
757            None
758        };
759
760        // Optional LANGUAGE clause
761        let language = if self.consume_keyword(Keyword::Language)?.is_some() {
762            let token = self.advance()?;
763            match token.kind {
764                TokenKind::Identifier(name) => Some(name),
765                TokenKind::Keyword(_) => Some(token.text.to_string()),
766                _ => {
767                    return Err(Error::expected_identifier(token.span));
768                }
769            }
770        } else {
771            None
772        };
773
774        let options = self.parse_options_clause()?;
775
776        // Parse body
777        let body = if self.consume_keyword(Keyword::As)?.is_some() {
778            if self.consume(&TokenKind::LeftParen)?.is_some() {
779                let expr = self.parse_expression()?;
780                self.expect(&TokenKind::RightParen)?;
781                FunctionBody::Expr(expr)
782            } else {
783                let token = self.advance()?;
784                match token.kind {
785                    TokenKind::String(s) => FunctionBody::External(s),
786                    _ => {
787                        return Err(Error::unexpected_token(
788                            "expression or string literal",
789                            format!("{}", token.kind),
790                            token.span,
791                        ));
792                    }
793                }
794            }
795        } else {
796            // No body - external function
797            FunctionBody::External(String::new())
798        };
799
800        Ok(StatementKind::CreateFunction(CreateFunctionStatement {
801            or_replace,
802            temporary,
803            if_not_exists,
804            name,
805            params,
806            returns,
807            language,
808            body,
809            options,
810        }))
811    }
812
813    /// Parse function parameter.
814    fn parse_function_param(&mut self) -> Result<FunctionParam> {
815        // Optional parameter name
816        let token = self.peek()?;
817        let name = if matches!(
818            &token.kind,
819            TokenKind::Identifier(_) | TokenKind::QuotedIdentifier(_)
820        ) {
821            let next = self.peek_nth(1)?;
822            if !matches!(next.kind, TokenKind::Comma | TokenKind::RightParen) {
823                Some(self.parse_identifier()?)
824            } else {
825                None
826            }
827        } else {
828            None
829        };
830
831        let data_type = self.parse_data_type()?;
832
833        // Optional default value
834        let default = if self.consume_keyword(Keyword::Default)?.is_some() {
835            Some(self.parse_expression()?)
836        } else {
837            None
838        };
839
840        Ok(FunctionParam {
841            name,
842            data_type,
843            default,
844        })
845    }
846
847    /// Parse CREATE PROCEDURE statement.
848    fn parse_create_procedure(&mut self, or_replace: bool) -> Result<StatementKind> {
849        let if_not_exists = if self.consume_keyword(Keyword::If)?.is_some() {
850            self.expect_keyword(Keyword::Not)?;
851            self.expect_keyword(Keyword::Exists)?;
852            true
853        } else {
854            false
855        };
856
857        let name = self.parse_object_name()?;
858
859        // Parse parameters
860        self.expect(&TokenKind::LeftParen)?;
861        let params = if self.check(&TokenKind::RightParen)? {
862            Vec::new()
863        } else {
864            self.parse_comma_separated(|p| p.parse_procedure_param())?
865        };
866        self.expect(&TokenKind::RightParen)?;
867
868        let options = self.parse_options_clause()?;
869
870        // Parse body (BEGIN ... END)
871        self.expect_keyword(Keyword::Begin)?;
872        let body = self.parse_statement_list()?;
873        self.expect_keyword(Keyword::End)?;
874
875        Ok(StatementKind::CreateProcedure(CreateProcedureStatement {
876            or_replace,
877            if_not_exists,
878            name,
879            params,
880            body,
881            options,
882        }))
883    }
884
885    /// Parse procedure parameter.
886    fn parse_procedure_param(&mut self) -> Result<ProcedureParam> {
887        let mode = if self.consume_keyword(Keyword::In)?.is_some() {
888            if self.consume_keyword(Keyword::Out)?.is_some() {
889                ParamMode::InOut
890            } else {
891                ParamMode::In
892            }
893        } else if self.consume_keyword(Keyword::Out)?.is_some() {
894            ParamMode::Out
895        } else if self.consume_keyword(Keyword::Inout)?.is_some() {
896            ParamMode::InOut
897        } else {
898            ParamMode::In
899        };
900
901        // Optional parameter name
902        let name = {
903            let next = self.peek_nth(1)?;
904            if !matches!(next.kind, TokenKind::Comma | TokenKind::RightParen) {
905                Some(self.parse_identifier()?)
906            } else {
907                None
908            }
909        };
910
911        let data_type = self.parse_data_type()?;
912
913        Ok(ProcedureParam {
914            mode,
915            name,
916            data_type,
917        })
918    }
919
920    /// Parse CREATE DATABASE statement.
921    fn parse_create_database(&mut self) -> Result<StatementKind> {
922        let if_not_exists = if self.consume_keyword(Keyword::If)?.is_some() {
923            self.expect_keyword(Keyword::Not)?;
924            self.expect_keyword(Keyword::Exists)?;
925            true
926        } else {
927            false
928        };
929
930        let name = self.parse_identifier()?;
931        let options = self.parse_options_clause()?;
932
933        Ok(StatementKind::CreateDatabase(CreateDatabaseStatement {
934            name,
935            if_not_exists,
936            options,
937        }))
938    }
939
940    /// Parse ALTER statement.
941    pub fn parse_alter(&mut self) -> Result<StatementKind> {
942        self.expect_keyword(Keyword::Alter)?;
943
944        if self.consume_keyword(Keyword::Table)?.is_some() {
945            self.parse_alter_table()
946        } else if self.consume_keyword(Keyword::View)?.is_some() {
947            self.parse_alter_view()
948        } else {
949            let token = self.peek()?;
950            Err(Error::unexpected_token(
951                "TABLE or VIEW",
952                format!("{}", token.kind),
953                token.span,
954            ))
955        }
956    }
957
958    /// Parse ALTER TABLE statement.
959    fn parse_alter_table(&mut self) -> Result<StatementKind> {
960        let if_exists = if self.consume_keyword(Keyword::If)?.is_some() {
961            self.expect_keyword(Keyword::Exists)?;
962            true
963        } else {
964            false
965        };
966
967        let name = self.parse_object_name()?;
968        let action = self.parse_alter_table_action()?;
969
970        Ok(StatementKind::AlterTable(AlterTableStatement {
971            if_exists,
972            name,
973            action,
974        }))
975    }
976
977    /// Parse ALTER TABLE action.
978    fn parse_alter_table_action(&mut self) -> Result<AlterTableAction> {
979        if self.consume_keyword(Keyword::Add)?.is_some() {
980            if self.consume_keyword(Keyword::Column)?.is_some() {
981                let if_not_exists = if self.consume_keyword(Keyword::If)?.is_some() {
982                    self.expect_keyword(Keyword::Not)?;
983                    self.expect_keyword(Keyword::Exists)?;
984                    true
985                } else {
986                    false
987                };
988                let column = self.parse_column_def()?;
989                Ok(AlterTableAction::AddColumn {
990                    if_not_exists,
991                    column,
992                })
993            } else if self.check_keyword(Keyword::Constraint)?
994                || self.check_keyword(Keyword::Primary)?
995                || self.check_keyword(Keyword::Unique)?
996                || self.check_keyword(Keyword::Foreign)?
997                || self.check_keyword(Keyword::Check)?
998            {
999                let constraint = self.parse_table_constraint()?;
1000                Ok(AlterTableAction::AddConstraint(constraint))
1001            } else {
1002                let column = self.parse_column_def()?;
1003                Ok(AlterTableAction::AddColumn {
1004                    if_not_exists: false,
1005                    column,
1006                })
1007            }
1008        } else if self.consume_keyword(Keyword::Drop)?.is_some() {
1009            if self.consume_keyword(Keyword::Column)?.is_some() {
1010                let if_exists = if self.consume_keyword(Keyword::If)?.is_some() {
1011                    self.expect_keyword(Keyword::Exists)?;
1012                    true
1013                } else {
1014                    false
1015                };
1016                let column = self.parse_identifier()?;
1017                Ok(AlterTableAction::DropColumn { if_exists, column })
1018            } else if self.consume_keyword(Keyword::Constraint)?.is_some() {
1019                let if_exists = if self.consume_keyword(Keyword::If)?.is_some() {
1020                    self.expect_keyword(Keyword::Exists)?;
1021                    true
1022                } else {
1023                    false
1024                };
1025                let name = self.parse_identifier()?;
1026                Ok(AlterTableAction::DropConstraint { if_exists, name })
1027            } else {
1028                let token = self.peek()?;
1029                Err(Error::unexpected_token(
1030                    "COLUMN or CONSTRAINT",
1031                    format!("{}", token.kind),
1032                    token.span,
1033                ))
1034            }
1035        } else if self.consume_keyword(Keyword::Alter)?.is_some() {
1036            self.consume_keyword(Keyword::Column)?;
1037            let column = self.parse_identifier()?;
1038            let action = self.parse_alter_column_action()?;
1039            Ok(AlterTableAction::AlterColumn { column, action })
1040        } else if self.consume_keyword(Keyword::Rename)?.is_some() {
1041            if self.consume_keyword(Keyword::Column)?.is_some() {
1042                let from = self.parse_identifier()?;
1043                self.expect_keyword(Keyword::To)?;
1044                let to = self.parse_identifier()?;
1045                Ok(AlterTableAction::RenameColumn { from, to })
1046            } else if self.consume_keyword(Keyword::To)?.is_some() {
1047                let new_name = self.parse_object_name()?;
1048                Ok(AlterTableAction::RenameTable(new_name))
1049            } else {
1050                let token = self.peek()?;
1051                Err(Error::unexpected_token(
1052                    "COLUMN or TO",
1053                    format!("{}", token.kind),
1054                    token.span,
1055                ))
1056            }
1057        } else if self.consume_keyword(Keyword::Set)?.is_some() {
1058            self.expect_keyword(Keyword::Options)?;
1059            self.expect(&TokenKind::LeftParen)?;
1060            let options = self.parse_comma_separated(|p| {
1061                let name = p.parse_identifier()?;
1062                p.expect(&TokenKind::Eq)?;
1063                let value = p.parse_expression()?;
1064                Ok(SqlOption { name, value })
1065            })?;
1066            self.expect(&TokenKind::RightParen)?;
1067            Ok(AlterTableAction::SetOptions(options))
1068        } else {
1069            let token = self.peek()?;
1070            Err(Error::unexpected_token(
1071                "ADD, DROP, ALTER, RENAME, or SET",
1072                format!("{}", token.kind),
1073                token.span,
1074            ))
1075        }
1076    }
1077
1078    /// Parse ALTER COLUMN action.
1079    fn parse_alter_column_action(&mut self) -> Result<AlterColumnAction> {
1080        if self.consume_keyword(Keyword::Set)?.is_some() {
1081            if self.consume_keyword(Keyword::Data)?.is_some() {
1082                self.expect_keyword(Keyword::Type)?;
1083                let data_type = self.parse_data_type()?;
1084                Ok(AlterColumnAction::SetDataType(data_type))
1085            } else if self.consume_keyword(Keyword::Default)?.is_some() {
1086                let expr = self.parse_expression()?;
1087                Ok(AlterColumnAction::SetDefault(expr))
1088            } else if self.consume_keyword(Keyword::Not)?.is_some() {
1089                self.expect(&TokenKind::Null)?; // NULL is a special token
1090                Ok(AlterColumnAction::SetNotNull)
1091            } else if self.consume_keyword(Keyword::Options)?.is_some() {
1092                self.expect(&TokenKind::LeftParen)?;
1093                let options = self.parse_comma_separated(|p| {
1094                    let name = p.parse_identifier()?;
1095                    p.expect(&TokenKind::Eq)?;
1096                    let value = p.parse_expression()?;
1097                    Ok(SqlOption { name, value })
1098                })?;
1099                self.expect(&TokenKind::RightParen)?;
1100                Ok(AlterColumnAction::SetOptions(options))
1101            } else {
1102                let token = self.peek()?;
1103                Err(Error::unexpected_token(
1104                    "DATA TYPE, DEFAULT, NOT NULL, or OPTIONS",
1105                    format!("{}", token.kind),
1106                    token.span,
1107                ))
1108            }
1109        } else if self.consume_keyword(Keyword::Drop)?.is_some() {
1110            if self.consume_keyword(Keyword::Default)?.is_some() {
1111                Ok(AlterColumnAction::DropDefault)
1112            } else if self.consume_keyword(Keyword::Not)?.is_some() {
1113                self.expect(&TokenKind::Null)?; // NULL is a special token
1114                Ok(AlterColumnAction::DropNotNull)
1115            } else {
1116                let token = self.peek()?;
1117                Err(Error::unexpected_token(
1118                    "DEFAULT or NOT NULL",
1119                    format!("{}", token.kind),
1120                    token.span,
1121                ))
1122            }
1123        } else if self.consume_keyword(Keyword::Type)?.is_some() {
1124            let data_type = self.parse_data_type()?;
1125            Ok(AlterColumnAction::SetDataType(data_type))
1126        } else {
1127            let token = self.peek()?;
1128            Err(Error::unexpected_token(
1129                "SET, DROP, or TYPE",
1130                format!("{}", token.kind),
1131                token.span,
1132            ))
1133        }
1134    }
1135
1136    /// Parse ALTER VIEW statement.
1137    fn parse_alter_view(&mut self) -> Result<StatementKind> {
1138        let if_exists = if self.consume_keyword(Keyword::If)?.is_some() {
1139            self.expect_keyword(Keyword::Exists)?;
1140            true
1141        } else {
1142            false
1143        };
1144
1145        let name = self.parse_object_name()?;
1146
1147        let action = if self.consume_keyword(Keyword::Set)?.is_some() {
1148            self.expect_keyword(Keyword::Options)?;
1149            self.expect(&TokenKind::LeftParen)?;
1150            let options = self.parse_comma_separated(|p| {
1151                let name = p.parse_identifier()?;
1152                p.expect(&TokenKind::Eq)?;
1153                let value = p.parse_expression()?;
1154                Ok(SqlOption { name, value })
1155            })?;
1156            self.expect(&TokenKind::RightParen)?;
1157            AlterViewAction::SetOptions(options)
1158        } else if self.consume_keyword(Keyword::As)?.is_some() {
1159            let query = Box::new(self.parse_query()?);
1160            AlterViewAction::SetQuery(query)
1161        } else {
1162            let token = self.peek()?;
1163            return Err(Error::unexpected_token(
1164                "SET or AS",
1165                format!("{}", token.kind),
1166                token.span,
1167            ));
1168        };
1169
1170        Ok(StatementKind::AlterView(AlterViewStatement {
1171            if_exists,
1172            name,
1173            action,
1174        }))
1175    }
1176
1177    /// Parse DROP statement.
1178    pub fn parse_drop(&mut self) -> Result<StatementKind> {
1179        self.expect_keyword(Keyword::Drop)?;
1180
1181        let object_type = if self.consume_keyword(Keyword::Table)?.is_some() {
1182            ObjectType::Table
1183        } else if self.consume_keyword(Keyword::View)?.is_some() {
1184            ObjectType::View
1185        } else if self.consume_keyword(Keyword::Materialized)?.is_some() {
1186            self.expect_keyword(Keyword::View)?;
1187            ObjectType::MaterializedView
1188        } else if self.consume_keyword(Keyword::Index)?.is_some() {
1189            ObjectType::Index
1190        } else if self.consume_keyword(Keyword::Function)?.is_some() {
1191            ObjectType::Function
1192        } else if self.consume_keyword(Keyword::Procedure)?.is_some() {
1193            ObjectType::Procedure
1194        } else if self.consume_keyword(Keyword::Database)?.is_some() {
1195            ObjectType::Database
1196        } else if self.consume_keyword(Keyword::Schema)?.is_some() {
1197            ObjectType::Schema
1198        } else {
1199            let token = self.peek()?;
1200            return Err(Error::unexpected_token(
1201                "TABLE, VIEW, INDEX, FUNCTION, PROCEDURE, DATABASE, or SCHEMA",
1202                format!("{}", token.kind),
1203                token.span,
1204            ));
1205        };
1206
1207        let if_exists = if self.consume_keyword(Keyword::If)?.is_some() {
1208            self.expect_keyword(Keyword::Exists)?;
1209            true
1210        } else {
1211            false
1212        };
1213
1214        let names = self.parse_comma_separated(|p| p.parse_object_name())?;
1215
1216        let cascade = self.consume_keyword(Keyword::Cascade)?.is_some();
1217        if !cascade {
1218            self.consume_keyword(Keyword::Restrict)?;
1219        }
1220
1221        Ok(StatementKind::Drop(DropStatement {
1222            object_type,
1223            if_exists,
1224            names,
1225            cascade,
1226        }))
1227    }
1228
1229    /// Parse TRUNCATE statement.
1230    pub fn parse_truncate(&mut self) -> Result<StatementKind> {
1231        self.expect_keyword(Keyword::Truncate)?;
1232        self.consume_keyword(Keyword::Table)?;
1233        let table = self.parse_object_name()?;
1234        Ok(StatementKind::Truncate(TruncateStatement { table }))
1235    }
1236
1237    // ========================================================================
1238    // Transaction Control
1239    // ========================================================================
1240
1241    /// Parse BEGIN statement.
1242    pub fn parse_begin(&mut self) -> Result<StatementKind> {
1243        self.expect_keyword(Keyword::Begin)?;
1244
1245        // Check if this is BEGIN TRANSACTION or BEGIN ... END block
1246        if self.consume_keyword(Keyword::Transaction)?.is_some()
1247            || self.consume_keyword(Keyword::Work)?.is_some()
1248            || self.check_keyword(Keyword::Read)?
1249            || self.check(&TokenKind::Semicolon)?
1250            || self.check_eof()?
1251        {
1252            // Transaction
1253            let mode = if self.consume_keyword(Keyword::Read)?.is_some() {
1254                if self.consume_keyword(Keyword::Only)?.is_some() {
1255                    Some(TransactionMode::ReadOnly)
1256                } else {
1257                    self.expect_keyword(Keyword::Write)?;
1258                    Some(TransactionMode::ReadWrite)
1259                }
1260            } else {
1261                None
1262            };
1263            Ok(StatementKind::Begin(BeginStatement { mode }))
1264        } else {
1265            // BEGIN ... END block (for procedures)
1266            let _statements = self.parse_statement_list()?;
1267            self.expect_keyword(Keyword::End)?;
1268            // Return as simple begin for now
1269            Ok(StatementKind::Begin(BeginStatement { mode: None }))
1270        }
1271    }
1272
1273    /// Parse ROLLBACK statement.
1274    pub fn parse_rollback(&mut self) -> Result<StatementKind> {
1275        self.expect_keyword(Keyword::Rollback)?;
1276        self.consume_keyword(Keyword::Transaction)?;
1277        self.consume_keyword(Keyword::Work)?;
1278
1279        let savepoint = if self.consume_keyword(Keyword::To)?.is_some() {
1280            self.consume_keyword(Keyword::Savepoint)?;
1281            Some(self.parse_identifier()?)
1282        } else {
1283            None
1284        };
1285
1286        Ok(StatementKind::Rollback(RollbackStatement { savepoint }))
1287    }
1288
1289    // ========================================================================
1290    // Utility Statements
1291    // ========================================================================
1292
1293    /// Parse EXPLAIN statement.
1294    pub fn parse_explain(&mut self) -> Result<StatementKind> {
1295        self.expect_keyword(Keyword::Explain)?;
1296
1297        let analyze = self.consume_keyword(Keyword::Analyze)?.is_some();
1298
1299        let format = if self.consume_keyword(Keyword::Format)?.is_some() {
1300            if self.consume_keyword(Keyword::Text)?.is_some() {
1301                Some(ExplainFormat::Text)
1302            } else if self.consume_keyword(Keyword::Json)?.is_some() {
1303                Some(ExplainFormat::Json)
1304            } else {
1305                let token = self.peek()?;
1306                return Err(Error::unexpected_token(
1307                    "TEXT or JSON",
1308                    format!("{}", token.kind),
1309                    token.span,
1310                ));
1311            }
1312        } else {
1313            None
1314        };
1315
1316        let statement = Box::new(self.parse_statement()?);
1317
1318        Ok(StatementKind::Explain(ExplainStatement {
1319            analyze,
1320            format,
1321            statement,
1322        }))
1323    }
1324
1325    /// Parse DESCRIBE statement.
1326    pub fn parse_describe(&mut self) -> Result<StatementKind> {
1327        self.expect_keyword(Keyword::Describe)?;
1328        let object = self.parse_object_name()?;
1329        Ok(StatementKind::Describe(DescribeStatement { object }))
1330    }
1331
1332    /// Parse SHOW statement.
1333    pub fn parse_show(&mut self) -> Result<StatementKind> {
1334        self.expect_keyword(Keyword::Show)?;
1335
1336        let object_type = if self.consume_keyword(Keyword::Tables)?.is_some() {
1337            let from = if self.consume_keyword(Keyword::From)?.is_some()
1338                || self.consume_keyword(Keyword::In)?.is_some()
1339            {
1340                Some(self.parse_identifier()?)
1341            } else {
1342                None
1343            };
1344            ShowObjectType::Tables { from }
1345        } else if self.consume_keyword(Keyword::Databases)?.is_some() {
1346            ShowObjectType::Databases
1347        } else if self.consume_keyword(Keyword::Schemas)?.is_some() {
1348            let from = if self.consume_keyword(Keyword::From)?.is_some()
1349                || self.consume_keyword(Keyword::In)?.is_some()
1350            {
1351                Some(self.parse_identifier()?)
1352            } else {
1353                None
1354            };
1355            ShowObjectType::Schemas { from }
1356        } else if self.consume_keyword(Keyword::Columns)?.is_some() {
1357            self.expect_keyword(Keyword::From)?;
1358            let from = self.parse_object_name()?;
1359            ShowObjectType::Columns { from }
1360        } else if self.consume_keyword(Keyword::Functions)?.is_some() {
1361            let from = if self.consume_keyword(Keyword::From)?.is_some()
1362                || self.consume_keyword(Keyword::In)?.is_some()
1363            {
1364                Some(self.parse_identifier()?)
1365            } else {
1366                None
1367            };
1368            ShowObjectType::Functions { from }
1369        } else if self.consume_keyword(Keyword::Variables)?.is_some() {
1370            ShowObjectType::Variables
1371        } else {
1372            let token = self.peek()?;
1373            return Err(Error::unexpected_token(
1374                "TABLES, DATABASES, SCHEMAS, COLUMNS, FUNCTIONS, or VARIABLES",
1375                format!("{}", token.kind),
1376                token.span,
1377            ));
1378        };
1379
1380        let filter = if self.consume_keyword(Keyword::Like)?.is_some() {
1381            let token = self.advance()?;
1382            match token.kind {
1383                TokenKind::String(s) => Some(ShowFilter::Like(s)),
1384                _ => {
1385                    return Err(Error::unexpected_token(
1386                        "string literal",
1387                        format!("{}", token.kind),
1388                        token.span,
1389                    ));
1390                }
1391            }
1392        } else if self.consume_keyword(Keyword::Where)?.is_some() {
1393            Some(ShowFilter::Where(self.parse_expression()?))
1394        } else {
1395            None
1396        };
1397
1398        Ok(StatementKind::Show(ShowStatement {
1399            object_type,
1400            filter,
1401        }))
1402    }
1403
1404    /// Parse SET statement.
1405    pub fn parse_set(&mut self) -> Result<StatementKind> {
1406        self.expect_keyword(Keyword::Set)?;
1407
1408        let variable = self.parse_identifier()?;
1409
1410        self.expect(&TokenKind::Eq)?;
1411
1412        let value = if self.consume_keyword(Keyword::Default)?.is_some() {
1413            SetValue::Default
1414        } else {
1415            SetValue::Expr(self.parse_expression()?)
1416        };
1417
1418        Ok(StatementKind::Set(SetStatement { variable, value }))
1419    }
1420
1421    /// Parse a list of statements (for procedure bodies).
1422    fn parse_statement_list(&mut self) -> Result<Vec<Statement>> {
1423        let mut statements = Vec::new();
1424
1425        while !self.check_keyword(Keyword::End)?
1426            && !self.check_keyword(Keyword::Exception)?
1427            && !self.check_eof()?
1428        {
1429            if self.consume(&TokenKind::Semicolon)?.is_some() {
1430                continue;
1431            }
1432            let stmt = self.parse_statement()?;
1433            statements.push(stmt);
1434            self.consume(&TokenKind::Semicolon)?;
1435        }
1436
1437        Ok(statements)
1438    }
1439}
1440
1441#[cfg(test)]
1442mod tests {
1443    use super::*;
1444    use crate::parser::Parser;
1445
1446    fn parse_stmt(sql: &str) -> Statement {
1447        let mut parser = Parser::new(sql);
1448        parser.parse_statement().expect("Failed to parse")
1449    }
1450
1451    #[test]
1452    fn test_insert_values() {
1453        let stmt = parse_stmt("INSERT INTO users (id, name) VALUES (1, 'Alice')");
1454        assert!(matches!(stmt.kind, StatementKind::Insert(_)));
1455    }
1456
1457    #[test]
1458    fn test_insert_select() {
1459        let stmt = parse_stmt("INSERT INTO archive SELECT * FROM users WHERE active = false");
1460        assert!(matches!(stmt.kind, StatementKind::Insert(_)));
1461    }
1462
1463    #[test]
1464    fn test_update() {
1465        let stmt = parse_stmt("UPDATE users SET name = 'Bob' WHERE id = 1");
1466        assert!(matches!(stmt.kind, StatementKind::Update(_)));
1467    }
1468
1469    #[test]
1470    fn test_delete() {
1471        let stmt = parse_stmt("DELETE FROM users WHERE id = 1");
1472        assert!(matches!(stmt.kind, StatementKind::Delete(_)));
1473    }
1474
1475    #[test]
1476    fn test_create_table() {
1477        let stmt = parse_stmt(
1478            "CREATE TABLE users (
1479                id INT64 NOT NULL PRIMARY KEY,
1480                name STRING,
1481                email STRING UNIQUE
1482            )",
1483        );
1484        assert!(matches!(stmt.kind, StatementKind::CreateTable(_)));
1485    }
1486
1487    #[test]
1488    fn test_create_view() {
1489        let stmt =
1490            parse_stmt("CREATE VIEW active_users AS SELECT * FROM users WHERE active = true");
1491        assert!(matches!(stmt.kind, StatementKind::CreateView(_)));
1492    }
1493
1494    #[test]
1495    fn test_drop_table() {
1496        let stmt = parse_stmt("DROP TABLE IF EXISTS users CASCADE");
1497        assert!(matches!(stmt.kind, StatementKind::Drop(_)));
1498    }
1499
1500    #[test]
1501    fn test_alter_table() {
1502        let stmt = parse_stmt("ALTER TABLE users ADD COLUMN age INT64");
1503        assert!(matches!(stmt.kind, StatementKind::AlterTable(_)));
1504    }
1505
1506    #[test]
1507    fn test_begin_commit() {
1508        let stmt = parse_stmt("BEGIN TRANSACTION");
1509        assert!(matches!(stmt.kind, StatementKind::Begin(_)));
1510    }
1511
1512    #[test]
1513    fn test_rollback() {
1514        let stmt = parse_stmt("ROLLBACK");
1515        assert!(matches!(stmt.kind, StatementKind::Rollback(_)));
1516    }
1517
1518    #[test]
1519    fn test_explain() {
1520        let stmt = parse_stmt("EXPLAIN SELECT * FROM users");
1521        assert!(matches!(stmt.kind, StatementKind::Explain(_)));
1522    }
1523
1524    #[test]
1525    fn test_update_nested_field() {
1526        use crate::AssignmentTarget;
1527
1528        // Test UPDATE with nested field assignment (e.g., struct.field = value)
1529        let stmt = parse_stmt("UPDATE users SET address.city = 'NYC' WHERE id = 1");
1530        if let StatementKind::Update(update) = &stmt.kind {
1531            assert_eq!(update.assignments.len(), 1);
1532            let assignment = &update.assignments[0];
1533            // Check that the target is a Path (compound identifier)
1534            if let AssignmentTarget::Path(parts) = &assignment.target {
1535                assert_eq!(parts.len(), 2);
1536                assert_eq!(parts[0].value, "address");
1537                assert_eq!(parts[1].value, "city");
1538            } else {
1539                panic!("Expected Path target for nested field");
1540            }
1541        } else {
1542            panic!("Expected UPDATE statement");
1543        }
1544    }
1545
1546    #[test]
1547    fn test_update_deeply_nested_field() {
1548        use crate::AssignmentTarget;
1549
1550        // Test UPDATE with deeply nested field assignment
1551        let stmt = parse_stmt("UPDATE users SET profile.contact.email = 'test@example.com'");
1552        if let StatementKind::Update(update) = &stmt.kind {
1553            assert_eq!(update.assignments.len(), 1);
1554            let assignment = &update.assignments[0];
1555            if let AssignmentTarget::Path(parts) = &assignment.target {
1556                assert_eq!(parts.len(), 3);
1557                assert_eq!(parts[0].value, "profile");
1558                assert_eq!(parts[1].value, "contact");
1559                assert_eq!(parts[2].value, "email");
1560            } else {
1561                panic!("Expected Path target for nested field");
1562            }
1563        } else {
1564            panic!("Expected UPDATE statement");
1565        }
1566    }
1567
1568    #[test]
1569    fn test_update_simple_column() {
1570        use crate::AssignmentTarget;
1571
1572        let stmt = parse_stmt("UPDATE users SET name = 'Bob'");
1573        if let StatementKind::Update(update) = &stmt.kind {
1574            assert_eq!(update.assignments.len(), 1);
1575            let assignment = &update.assignments[0];
1576            // Simple column assignment could be Column or Path with length 1
1577            match &assignment.target {
1578                AssignmentTarget::Column(ident) => {
1579                    assert_eq!(ident.value, "name");
1580                }
1581                AssignmentTarget::Path(parts) => {
1582                    assert_eq!(parts.len(), 1);
1583                    assert_eq!(parts[0].value, "name");
1584                }
1585            }
1586        } else {
1587            panic!("Expected UPDATE statement");
1588        }
1589    }
1590
1591    #[test]
1592    fn test_update_multiple_assignments() {
1593        let stmt = parse_stmt("UPDATE users SET name = 'Bob', age = 30, active = true");
1594        if let StatementKind::Update(update) = &stmt.kind {
1595            assert_eq!(update.assignments.len(), 3);
1596        } else {
1597            panic!("Expected UPDATE statement");
1598        }
1599    }
1600}