1use bumpalo::collections::Vec as BumpVec;
10use vibesql_ast::arena::{
11 AddColumnStmt, AddConstraintStmt, AlterColumnStmt, AlterTableStmt, AnalyzeStmt, BeginStmt,
12 ChangeColumnStmt, ColumnConstraint, ColumnConstraintKind, ColumnDef, CommitStmt,
13 CreateIndexStmt, CreateViewStmt, DropColumnStmt, DropConstraintStmt, DropIndexStmt,
14 DropTableStmt, DropViewStmt, DurabilityHint, Expression, IndexColumn, IndexType,
15 ModifyColumnStmt, OrderDirection, ReferentialAction, ReleaseSavepointStmt, RenameTableStmt,
16 RollbackStmt, RollbackToSavepointStmt, SavepointStmt, Symbol, TableConstraint,
17 TableConstraintKind, TruncateCascadeOption, TruncateTableStmt,
18};
19
20use super::ArenaParser;
21use crate::keywords::Keyword;
22use crate::token::Token;
23use crate::ParseError;
24
25impl<'arena> ArenaParser<'arena> {
26 pub(crate) fn parse_begin_statement(&mut self) -> Result<BeginStmt, ParseError> {
32 if self.peek_keyword(Keyword::Begin) {
33 self.consume_keyword(Keyword::Begin)?;
34 } else if self.peek_keyword(Keyword::Start) {
35 self.consume_keyword(Keyword::Start)?;
36 } else {
37 return Err(ParseError { message: "Expected BEGIN or START".to_string() });
38 }
39
40 self.try_consume_keyword(Keyword::Transaction);
42
43 let durability = if self.peek_keyword(Keyword::With) {
45 self.consume_keyword(Keyword::With)?;
46 self.consume_keyword(Keyword::Durability)?;
47
48 self.try_consume(&Token::Symbol('='));
50
51 self.parse_durability_hint()?
53 } else {
54 DurabilityHint::Default
55 };
56
57 Ok(BeginStmt { durability })
58 }
59
60 fn parse_durability_hint(&mut self) -> Result<DurabilityHint, ParseError> {
62 if self.try_consume_keyword(Keyword::Default) {
63 Ok(DurabilityHint::Default)
64 } else if self.try_consume_keyword(Keyword::Durable) {
65 Ok(DurabilityHint::Durable)
66 } else if self.try_consume_keyword(Keyword::Lazy) {
67 Ok(DurabilityHint::Lazy)
68 } else if self.try_consume_keyword(Keyword::Volatile) {
69 Ok(DurabilityHint::Volatile)
70 } else {
71 Err(ParseError {
72 message: "Expected durability mode: DEFAULT, DURABLE, LAZY, or VOLATILE".to_string(),
73 })
74 }
75 }
76
77 pub(crate) fn parse_commit_statement(&mut self) -> Result<CommitStmt, ParseError> {
79 self.consume_keyword(Keyword::Commit)?;
80 Ok(CommitStmt)
81 }
82
83 pub(crate) fn parse_rollback_statement(&mut self) -> Result<RollbackStmt, ParseError> {
85 self.consume_keyword(Keyword::Rollback)?;
86 Ok(RollbackStmt)
87 }
88
89 pub(crate) fn parse_rollback_to_savepoint_statement(
91 &mut self,
92 ) -> Result<RollbackToSavepointStmt, ParseError> {
93 self.consume_keyword(Keyword::Rollback)?;
94 self.consume_keyword(Keyword::To)?;
95 self.consume_keyword(Keyword::Savepoint)?;
96 let name = self.parse_arena_identifier()?;
97 Ok(RollbackToSavepointStmt { name })
98 }
99
100 pub(crate) fn parse_savepoint_statement(&mut self) -> Result<SavepointStmt, ParseError> {
102 self.consume_keyword(Keyword::Savepoint)?;
103 let name = self.parse_arena_identifier()?;
104 Ok(SavepointStmt { name })
105 }
106
107 pub(crate) fn parse_release_savepoint_statement(
109 &mut self,
110 ) -> Result<ReleaseSavepointStmt, ParseError> {
111 self.consume_keyword(Keyword::Release)?;
112 self.consume_keyword(Keyword::Savepoint)?;
113 let name = self.parse_arena_identifier()?;
114 Ok(ReleaseSavepointStmt { name })
115 }
116
117 pub(crate) fn parse_create_index_statement(
123 &mut self,
124 ) -> Result<CreateIndexStmt<'arena>, ParseError> {
125 self.consume_keyword(Keyword::Create)?;
126
127 let index_type = if self.try_consume_keyword(Keyword::Unique) {
129 IndexType::BTree { unique: true }
130 } else if self.try_consume_keyword(Keyword::Fulltext) {
131 IndexType::Fulltext
132 } else if self.try_consume_keyword(Keyword::Spatial) {
133 IndexType::Spatial
134 } else {
135 IndexType::BTree { unique: false }
136 };
137
138 self.consume_keyword(Keyword::Index)?;
139
140 let if_not_exists = if self.try_consume_keyword(Keyword::If) {
142 self.expect_keyword(Keyword::Not)?;
143 self.expect_keyword(Keyword::Exists)?;
144 true
145 } else {
146 false
147 };
148
149 let index_name = self.parse_arena_identifier()?;
150
151 self.consume_keyword(Keyword::On)?;
152 let table_name = self.parse_arena_identifier()?;
153
154 self.expect_token(Token::LParen)?;
155 let columns = self.parse_index_columns()?;
156 self.expect_token(Token::RParen)?;
157
158 Ok(CreateIndexStmt { if_not_exists, index_name, table_name, index_type, columns })
159 }
160
161 pub(crate) fn parse_create_view_statement(
163 &mut self,
164 ) -> Result<CreateViewStmt<'arena>, ParseError> {
165 self.consume_keyword(Keyword::Create)?;
166
167 let or_replace = if self.try_consume_keyword(Keyword::Or) {
169 self.expect_keyword(Keyword::Replace)?;
170 true
171 } else {
172 false
173 };
174
175 let temporary =
177 self.try_consume_keyword(Keyword::Temp) || self.try_consume_keyword(Keyword::Temporary);
178
179 self.consume_keyword(Keyword::View)?;
180
181 let view_name = self.parse_arena_identifier()?;
182
183 let columns = if self.try_consume(&Token::LParen) {
185 let cols = self.parse_identifier_list()?;
186 self.expect_token(Token::RParen)?;
187 Some(cols)
188 } else {
189 None
190 };
191
192 self.consume_keyword(Keyword::As)?;
193
194 let query = self.parse_select_statement()?;
195
196 let with_check_option = if self.try_consume_keyword(Keyword::With) {
198 self.expect_keyword(Keyword::Check)?;
199 self.expect_keyword(Keyword::Option)?;
200 true
201 } else {
202 false
203 };
204
205 Ok(CreateViewStmt { view_name, columns, query, with_check_option, or_replace, temporary })
206 }
207
208 pub(crate) fn parse_drop_table_statement(&mut self) -> Result<DropTableStmt, ParseError> {
214 self.consume_keyword(Keyword::Drop)?;
215 self.consume_keyword(Keyword::Table)?;
216
217 let if_exists = if self.try_consume_keyword(Keyword::If) {
218 self.expect_keyword(Keyword::Exists)?;
219 true
220 } else {
221 false
222 };
223
224 let table_name = self.parse_arena_identifier()?;
225
226 Ok(DropTableStmt { table_name, if_exists })
227 }
228
229 pub(crate) fn parse_drop_index_statement(&mut self) -> Result<DropIndexStmt, ParseError> {
231 self.consume_keyword(Keyword::Drop)?;
232 self.consume_keyword(Keyword::Index)?;
233
234 let if_exists = if self.try_consume_keyword(Keyword::If) {
235 self.expect_keyword(Keyword::Exists)?;
236 true
237 } else {
238 false
239 };
240
241 let index_name = self.parse_arena_identifier()?;
242
243 Ok(DropIndexStmt { if_exists, index_name })
244 }
245
246 pub(crate) fn parse_drop_view_statement(&mut self) -> Result<DropViewStmt, ParseError> {
248 self.consume_keyword(Keyword::Drop)?;
249 self.consume_keyword(Keyword::View)?;
250
251 let if_exists = if self.try_consume_keyword(Keyword::If) {
252 self.expect_keyword(Keyword::Exists)?;
253 true
254 } else {
255 false
256 };
257
258 let view_name = self.parse_arena_identifier()?;
259
260 let (cascade, restrict) = if self.try_consume_keyword(Keyword::Cascade) {
261 (true, false)
262 } else if self.try_consume_keyword(Keyword::Restrict) {
263 (false, true)
264 } else {
265 (false, false)
266 };
267
268 Ok(DropViewStmt { view_name, if_exists, cascade, restrict })
269 }
270
271 pub(crate) fn parse_truncate_table_statement(
273 &mut self,
274 ) -> Result<TruncateTableStmt<'arena>, ParseError> {
275 self.consume_keyword(Keyword::Truncate)?;
276 self.try_consume_keyword(Keyword::Table);
277
278 let if_exists = if self.try_consume_keyword(Keyword::If) {
279 self.expect_keyword(Keyword::Exists)?;
280 true
281 } else {
282 false
283 };
284
285 let mut table_names = BumpVec::new_in(self.arena);
287 loop {
288 table_names.push(self.parse_arena_identifier()?);
289 if !self.try_consume(&Token::Comma) {
290 break;
291 }
292 }
293
294 let cascade = if self.try_consume_keyword(Keyword::Cascade) {
295 Some(TruncateCascadeOption::Cascade)
296 } else if self.try_consume_keyword(Keyword::Restrict) {
297 Some(TruncateCascadeOption::Restrict)
298 } else {
299 None
300 };
301
302 Ok(TruncateTableStmt { table_names, if_exists, cascade })
303 }
304
305 pub fn parse_alter_table_statement(
311 &mut self,
312 ) -> Result<&'arena AlterTableStmt<'arena>, ParseError> {
313 self.expect_keyword(Keyword::Alter)?;
315 self.expect_keyword(Keyword::Table)?;
316
317 let table_name = self.parse_table_name()?;
318
319 let stmt = match self.peek() {
321 Token::Keyword(Keyword::Add) => {
322 self.advance();
323 match self.peek() {
324 Token::Keyword(Keyword::Column) => {
325 self.advance();
326 self.parse_add_column(table_name)?
327 }
328 Token::Keyword(
330 Keyword::Constraint
331 | Keyword::Check
332 | Keyword::Unique
333 | Keyword::Primary
334 | Keyword::Foreign,
335 ) => self.parse_add_constraint(table_name)?,
336 Token::Identifier(_) => self.parse_add_column(table_name)?,
338 _ => {
339 return Err(ParseError {
340 message:
341 "Expected COLUMN, constraint keyword, or column name after ADD"
342 .to_string(),
343 })
344 }
345 }
346 }
347 Token::Keyword(Keyword::Drop) => {
348 self.advance();
349 match self.peek() {
350 Token::Keyword(Keyword::Column) => {
351 self.advance();
352 self.parse_drop_column(table_name)?
353 }
354 Token::Keyword(Keyword::Constraint) => {
355 self.advance();
356 self.parse_drop_constraint(table_name)?
357 }
358 _ => {
359 return Err(ParseError {
360 message: "Expected COLUMN or CONSTRAINT after DROP".to_string(),
361 })
362 }
363 }
364 }
365 Token::Keyword(Keyword::Alter) => {
366 self.advance();
367 self.expect_keyword(Keyword::Column)?;
368 self.parse_alter_column(table_name)?
369 }
370 Token::Keyword(Keyword::Rename) => {
371 self.advance();
372 self.parse_rename_table(table_name)?
373 }
374 Token::Keyword(Keyword::Modify) => {
375 self.advance();
376 self.parse_modify_column(table_name)?
377 }
378 Token::Keyword(Keyword::Change) => {
379 self.advance();
380 self.parse_change_column(table_name)?
381 }
382 _ => {
383 return Err(ParseError {
384 message:
385 "Expected ADD, DROP, ALTER, RENAME, MODIFY, or CHANGE after table name"
386 .to_string(),
387 })
388 }
389 };
390
391 Ok(self.arena.alloc(stmt))
392 }
393
394 fn parse_table_name(&mut self) -> Result<Symbol, ParseError> {
396 match self.peek() {
397 Token::Identifier(name) => {
398 let name = name.clone();
399 self.advance();
400 Ok(self.intern(&name))
401 }
402 _ => {
403 Err(ParseError { message: format!("Expected table name, found {:?}", self.peek()) })
404 }
405 }
406 }
407
408 fn parse_column_name(&mut self) -> Result<Symbol, ParseError> {
410 match self.peek() {
411 Token::Identifier(name) => {
412 let name = name.clone();
413 self.advance();
414 Ok(self.intern(&name))
415 }
416 _ => Err(ParseError {
417 message: format!("Expected column name, found {:?}", self.peek()),
418 }),
419 }
420 }
421
422 fn parse_add_column(
424 &mut self,
425 table_name: Symbol,
426 ) -> Result<AlterTableStmt<'arena>, ParseError> {
427 let column_name = self.parse_column_name()?;
428 let data_type = self.parse_data_type()?;
429
430 let default_value: Option<&'arena Expression<'arena>> =
432 if self.peek_keyword(Keyword::Default) {
433 self.advance();
434 let expr = self.parse_expression()?;
435 Some(self.arena.alloc(expr))
436 } else {
437 None
438 };
439
440 let mut nullable = true;
442 let mut constraints = BumpVec::new_in(self.arena);
443
444 loop {
445 match self.peek() {
446 Token::Keyword(Keyword::Not) => {
447 self.advance();
448 self.expect_keyword(Keyword::Null)?;
449 nullable = false;
450 }
451 Token::Keyword(Keyword::Primary) => {
452 self.advance();
453 self.expect_keyword(Keyword::Key)?;
454 constraints.push(ColumnConstraint {
455 name: None,
456 kind: ColumnConstraintKind::PrimaryKey,
457 });
458 }
459 Token::Keyword(Keyword::Unique) => {
460 self.advance();
461 constraints
462 .push(ColumnConstraint { name: None, kind: ColumnConstraintKind::Unique });
463 }
464 Token::Keyword(Keyword::References) => {
465 self.advance();
466 let ref_table = self.parse_table_name()?;
467 self.expect_token(Token::LParen)?;
468 let ref_column = self.parse_column_name()?;
469 self.expect_token(Token::RParen)?;
470 constraints.push(ColumnConstraint {
471 name: None,
472 kind: ColumnConstraintKind::References {
473 table: ref_table,
474 column: ref_column,
475 on_delete: None,
476 on_update: None,
477 },
478 });
479 }
480 _ => break,
481 }
482 }
483
484 let column_def = ColumnDef {
485 name: column_name,
486 data_type,
487 nullable,
488 constraints,
489 default_value,
490 comment: None,
491 };
492
493 Ok(AlterTableStmt::AddColumn(AddColumnStmt { table_name, column_def }))
494 }
495
496 fn parse_drop_column(
498 &mut self,
499 table_name: Symbol,
500 ) -> Result<AlterTableStmt<'arena>, ParseError> {
501 let if_exists =
502 self.try_consume_keyword(Keyword::If) && self.try_consume_keyword(Keyword::Exists);
503
504 let column_name = self.parse_column_name()?;
505
506 Ok(AlterTableStmt::DropColumn(DropColumnStmt { table_name, column_name, if_exists }))
507 }
508
509 fn parse_alter_column(
511 &mut self,
512 table_name: Symbol,
513 ) -> Result<AlterTableStmt<'arena>, ParseError> {
514 let column_name = self.parse_column_name()?;
515
516 match self.peek() {
517 Token::Keyword(Keyword::Set) => {
518 self.advance();
519 match self.peek() {
520 Token::Keyword(Keyword::Default) => {
521 self.advance();
522 let default = self.parse_expression()?;
523 Ok(AlterTableStmt::AlterColumn(AlterColumnStmt::SetDefault {
524 table_name,
525 column_name,
526 default,
527 }))
528 }
529 Token::Keyword(Keyword::Not) => {
530 self.advance();
531 self.expect_keyword(Keyword::Null)?;
532 Ok(AlterTableStmt::AlterColumn(AlterColumnStmt::SetNotNull {
533 table_name,
534 column_name,
535 }))
536 }
537 _ => Err(ParseError {
538 message: "Expected DEFAULT or NOT NULL after SET".to_string(),
539 }),
540 }
541 }
542 Token::Keyword(Keyword::Drop) => {
543 self.advance();
544 match self.peek() {
545 Token::Keyword(Keyword::Default) => {
546 self.advance();
547 Ok(AlterTableStmt::AlterColumn(AlterColumnStmt::DropDefault {
548 table_name,
549 column_name,
550 }))
551 }
552 Token::Keyword(Keyword::Not) => {
553 self.advance();
554 self.expect_keyword(Keyword::Null)?;
555 Ok(AlterTableStmt::AlterColumn(AlterColumnStmt::DropNotNull {
556 table_name,
557 column_name,
558 }))
559 }
560 _ => Err(ParseError {
561 message: "Expected DEFAULT or NOT NULL after DROP".to_string(),
562 }),
563 }
564 }
565 _ => Err(ParseError { message: "Expected SET or DROP after column name".to_string() }),
566 }
567 }
568
569 fn parse_add_constraint(
571 &mut self,
572 table_name: Symbol,
573 ) -> Result<AlterTableStmt<'arena>, ParseError> {
574 let constraint = self.parse_table_constraint()?;
575 Ok(AlterTableStmt::AddConstraint(AddConstraintStmt { table_name, constraint }))
576 }
577
578 fn parse_drop_constraint(
580 &mut self,
581 table_name: Symbol,
582 ) -> Result<AlterTableStmt<'arena>, ParseError> {
583 let constraint_name = self.parse_column_name()?;
584 Ok(AlterTableStmt::DropConstraint(DropConstraintStmt { table_name, constraint_name }))
585 }
586
587 fn parse_rename_table(
589 &mut self,
590 table_name: Symbol,
591 ) -> Result<AlterTableStmt<'arena>, ParseError> {
592 self.expect_keyword(Keyword::To)?;
593 let new_table_name = self.parse_table_name()?;
594 Ok(AlterTableStmt::RenameTable(RenameTableStmt { table_name, new_table_name }))
595 }
596
597 fn parse_modify_column(
599 &mut self,
600 table_name: Symbol,
601 ) -> Result<AlterTableStmt<'arena>, ParseError> {
602 if self.peek_keyword(Keyword::Column) {
604 self.advance();
605 }
606
607 let column_name = self.parse_column_name()?;
608 let data_type = self.parse_data_type()?;
609
610 let default_value: Option<&'arena Expression<'arena>> =
612 if self.peek_keyword(Keyword::Default) {
613 self.advance();
614 let expr = self.parse_expression()?;
615 Some(self.arena.alloc(expr))
616 } else {
617 None
618 };
619
620 let (nullable, constraints) = self.parse_column_constraints()?;
622
623 let new_column_def = ColumnDef {
624 name: column_name,
625 data_type,
626 nullable,
627 constraints,
628 default_value,
629 comment: None,
630 };
631
632 Ok(AlterTableStmt::ModifyColumn(ModifyColumnStmt {
633 table_name,
634 column_name,
635 new_column_def,
636 }))
637 }
638
639 fn parse_change_column(
641 &mut self,
642 table_name: Symbol,
643 ) -> Result<AlterTableStmt<'arena>, ParseError> {
644 if self.peek_keyword(Keyword::Column) {
646 self.advance();
647 }
648
649 let old_column_name = self.parse_column_name()?;
650 let new_column_name = self.parse_column_name()?;
651 let data_type = self.parse_data_type()?;
652
653 let default_value: Option<&'arena Expression<'arena>> =
655 if self.peek_keyword(Keyword::Default) {
656 self.advance();
657 let expr = self.parse_expression()?;
658 Some(self.arena.alloc(expr))
659 } else {
660 None
661 };
662
663 let (nullable, constraints) = self.parse_column_constraints()?;
665
666 let new_column_def = ColumnDef {
667 name: new_column_name,
668 data_type,
669 nullable,
670 constraints,
671 default_value,
672 comment: None,
673 };
674
675 Ok(AlterTableStmt::ChangeColumn(ChangeColumnStmt {
676 table_name,
677 old_column_name,
678 new_column_def,
679 }))
680 }
681
682 fn parse_column_constraints(
684 &mut self,
685 ) -> Result<(bool, BumpVec<'arena, ColumnConstraint<'arena>>), ParseError> {
686 let mut nullable = true;
687 let mut constraints = BumpVec::new_in(self.arena);
688
689 loop {
690 match self.peek() {
691 Token::Keyword(Keyword::Not) => {
692 self.advance();
693 self.expect_keyword(Keyword::Null)?;
694 nullable = false;
695 }
696 Token::Keyword(Keyword::Primary) => {
697 self.advance();
698 self.expect_keyword(Keyword::Key)?;
699 constraints.push(ColumnConstraint {
700 name: None,
701 kind: ColumnConstraintKind::PrimaryKey,
702 });
703 }
704 Token::Keyword(Keyword::Unique) => {
705 self.advance();
706 constraints
707 .push(ColumnConstraint { name: None, kind: ColumnConstraintKind::Unique });
708 }
709 Token::Keyword(Keyword::References) => {
710 self.advance();
711 let ref_table = self.parse_table_name()?;
712 self.expect_token(Token::LParen)?;
713 let ref_column = self.parse_column_name()?;
714 self.expect_token(Token::RParen)?;
715 constraints.push(ColumnConstraint {
716 name: None,
717 kind: ColumnConstraintKind::References {
718 table: ref_table,
719 column: ref_column,
720 on_delete: None,
721 on_update: None,
722 },
723 });
724 }
725 _ => break,
726 }
727 }
728
729 Ok((nullable, constraints))
730 }
731
732 fn parse_table_constraint(&mut self) -> Result<TableConstraint<'arena>, ParseError> {
734 let name = if self.try_consume_keyword(Keyword::Constraint) {
736 Some(self.parse_column_name()?)
737 } else {
738 None
739 };
740
741 let kind = match self.peek() {
742 Token::Keyword(Keyword::Primary) => {
743 self.advance();
744 self.expect_keyword(Keyword::Key)?;
745 self.expect_token(Token::LParen)?;
746 let columns = self.parse_index_column_list()?;
747 self.expect_token(Token::RParen)?;
748 TableConstraintKind::PrimaryKey { columns }
749 }
750 Token::Keyword(Keyword::Unique) => {
751 self.advance();
752 self.expect_token(Token::LParen)?;
753 let columns = self.parse_index_column_list()?;
754 self.expect_token(Token::RParen)?;
755 TableConstraintKind::Unique { columns }
756 }
757 Token::Keyword(Keyword::Foreign) => {
758 self.advance();
759 self.expect_keyword(Keyword::Key)?;
760 self.expect_token(Token::LParen)?;
761 let columns = self.parse_column_name_list()?;
762 self.expect_token(Token::RParen)?;
763 self.expect_keyword(Keyword::References)?;
764 let references_table = self.parse_table_name()?;
765 self.expect_token(Token::LParen)?;
766 let references_columns = self.parse_column_name_list()?;
767 self.expect_token(Token::RParen)?;
768
769 let (on_delete, on_update) = self.parse_referential_actions()?;
770
771 TableConstraintKind::ForeignKey {
772 columns,
773 references_table,
774 references_columns,
775 on_delete,
776 on_update,
777 }
778 }
779 Token::Keyword(Keyword::Check) => {
780 self.advance();
781 self.expect_token(Token::LParen)?;
782 let expr = self.parse_expression()?;
783 self.expect_token(Token::RParen)?;
784 TableConstraintKind::Check { expr: self.arena.alloc(expr) }
785 }
786 _ => {
787 return Err(ParseError {
788 message: format!("Expected constraint type, found {:?}", self.peek()),
789 })
790 }
791 };
792
793 Ok(TableConstraint { name, kind })
794 }
795
796 fn parse_index_column_list(&mut self) -> Result<BumpVec<'arena, IndexColumn>, ParseError> {
798 let mut columns = BumpVec::new_in(self.arena);
799
800 loop {
801 let column_name = self.parse_column_name()?;
802
803 let prefix_length = if self.try_consume(&Token::LParen) {
805 let len = match self.peek() {
806 Token::Number(n) => {
807 let len = n.parse::<u64>().ok();
808 self.advance();
809 len
810 }
811 _ => None,
812 };
813 self.expect_token(Token::RParen)?;
814 len
815 } else {
816 None
817 };
818
819 let direction = if self.try_consume_keyword(Keyword::Asc) {
821 OrderDirection::Asc
822 } else if self.try_consume_keyword(Keyword::Desc) {
823 OrderDirection::Desc
824 } else {
825 OrderDirection::Asc
826 };
827
828 columns.push(IndexColumn { column_name, direction, prefix_length });
829
830 if !self.try_consume(&Token::Comma) {
831 break;
832 }
833 }
834
835 Ok(columns)
836 }
837
838 fn parse_column_name_list(&mut self) -> Result<BumpVec<'arena, Symbol>, ParseError> {
840 let mut columns = BumpVec::new_in(self.arena);
841
842 loop {
843 let col = self.parse_column_name()?;
844 columns.push(col);
845
846 if !self.try_consume(&Token::Comma) {
847 break;
848 }
849 }
850
851 Ok(columns)
852 }
853
854 fn parse_referential_actions(
856 &mut self,
857 ) -> Result<(Option<ReferentialAction>, Option<ReferentialAction>), ParseError> {
858 let mut on_delete = None;
859 let mut on_update = None;
860
861 for _ in 0..2 {
862 if self.try_consume_keyword(Keyword::On) {
863 if self.try_consume_keyword(Keyword::Delete) {
864 on_delete = Some(self.parse_referential_action()?);
865 } else if self.try_consume_keyword(Keyword::Update) {
866 on_update = Some(self.parse_referential_action()?);
867 }
868 }
869 }
870
871 Ok((on_delete, on_update))
872 }
873
874 fn parse_referential_action(&mut self) -> Result<ReferentialAction, ParseError> {
876 if self.try_consume_keyword(Keyword::Cascade) {
877 Ok(ReferentialAction::Cascade)
878 } else if self.try_consume_keyword(Keyword::Restrict) {
879 Ok(ReferentialAction::Restrict)
880 } else if self.try_consume_keyword(Keyword::Set) {
881 if self.try_consume_keyword(Keyword::Null) {
882 Ok(ReferentialAction::SetNull)
883 } else if self.try_consume_keyword(Keyword::Default) {
884 Ok(ReferentialAction::SetDefault)
885 } else {
886 Err(ParseError { message: "Expected NULL or DEFAULT after SET".to_string() })
887 }
888 } else if self.try_consume_keyword(Keyword::No) {
889 self.expect_keyword(Keyword::Action)?;
890 Ok(ReferentialAction::NoAction)
891 } else {
892 Err(ParseError {
893 message: "Expected CASCADE, RESTRICT, SET NULL, SET DEFAULT, or NO ACTION"
894 .to_string(),
895 })
896 }
897 }
898
899 pub(crate) fn parse_analyze_statement(&mut self) -> Result<AnalyzeStmt<'arena>, ParseError> {
905 self.consume_keyword(Keyword::Analyze)?;
906
907 let table_name = if let Token::Identifier(_) = self.peek() {
909 Some(self.parse_arena_identifier()?)
910 } else {
911 None
912 };
913
914 let columns = if table_name.is_some() && self.try_consume(&Token::LParen) {
916 let cols = self.parse_identifier_list()?;
917 self.expect_token(Token::RParen)?;
918 Some(cols)
919 } else {
920 None
921 };
922
923 Ok(AnalyzeStmt { table_name, columns })
924 }
925
926 fn parse_index_columns(&mut self) -> Result<BumpVec<'arena, IndexColumn>, ParseError> {
932 let mut columns = BumpVec::new_in(self.arena);
933 loop {
934 let column_name = self.parse_arena_identifier()?;
935
936 let prefix_length = if self.try_consume(&Token::LParen) {
938 let len = match self.peek() {
939 Token::Number(n) => n
940 .parse::<u64>()
941 .map_err(|_| ParseError { message: "Invalid prefix length".to_string() })?,
942 _ => {
943 return Err(ParseError {
944 message: "Expected number for prefix length".to_string(),
945 })
946 }
947 };
948 self.advance();
949 self.expect_token(Token::RParen)?;
950 Some(len)
951 } else {
952 None
953 };
954
955 let direction = if self.try_consume_keyword(Keyword::Desc) {
957 OrderDirection::Desc
958 } else {
959 self.try_consume_keyword(Keyword::Asc);
960 OrderDirection::Asc
961 };
962
963 columns.push(IndexColumn { column_name, direction, prefix_length });
964
965 if !self.try_consume(&Token::Comma) {
966 break;
967 }
968 }
969 Ok(columns)
970 }
971}