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