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