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, PragmaStmt, PragmaValue, ReferentialAction,
16 ReleaseSavepointStmt, RenameTableStmt, RollbackStmt, RollbackToSavepointStmt, SavepointStmt,
17 Symbol, TableConstraint, TableConstraintKind, TruncateCascadeOption, TruncateTableStmt,
18};
19
20use super::ArenaParser;
21use crate::{keywords::Keyword, token::Token, ParseError};
22
23impl<'arena> ArenaParser<'arena> {
24 pub(crate) fn parse_begin_statement(&mut self) -> Result<BeginStmt, ParseError> {
31 if self.peek_keyword(Keyword::Begin) {
32 self.consume_keyword(Keyword::Begin)?;
33 } else if self.peek_keyword(Keyword::Start) {
34 self.consume_keyword(Keyword::Start)?;
35 } else {
36 return Err(ParseError { message: "Expected BEGIN or START".to_string() });
37 }
38
39 self.try_consume_keyword(Keyword::Transaction);
41
42 let durability = if self.peek_keyword(Keyword::With) {
44 self.consume_keyword(Keyword::With)?;
45 self.consume_keyword(Keyword::Durability)?;
46
47 self.try_consume(&Token::Symbol('='));
49
50 self.parse_durability_hint()?
52 } else {
53 DurabilityHint::Default
54 };
55
56 Ok(BeginStmt { durability })
57 }
58
59 fn parse_durability_hint(&mut self) -> Result<DurabilityHint, ParseError> {
61 if self.try_consume_keyword(Keyword::Default) {
62 Ok(DurabilityHint::Default)
63 } else if self.try_consume_keyword(Keyword::Durable) {
64 Ok(DurabilityHint::Durable)
65 } else if self.try_consume_keyword(Keyword::Lazy) {
66 Ok(DurabilityHint::Lazy)
67 } else if self.try_consume_keyword(Keyword::Volatile) {
68 Ok(DurabilityHint::Volatile)
69 } else {
70 Err(ParseError {
71 message: "Expected durability mode: DEFAULT, DURABLE, LAZY, or VOLATILE"
72 .to_string(),
73 })
74 }
75 }
76
77 pub(crate) fn parse_commit_statement(&mut self) -> Result<CommitStmt, ParseError> {
79 if self.peek_keyword(Keyword::Commit) {
81 self.consume_keyword(Keyword::Commit)?;
82 } else if self.peek_keyword(Keyword::End) {
83 self.consume_keyword(Keyword::End)?;
84 } else {
85 return Err(ParseError { message: "Expected COMMIT or END".to_string() });
86 }
87 Ok(CommitStmt)
88 }
89
90 pub(crate) fn parse_rollback_statement(&mut self) -> Result<RollbackStmt, ParseError> {
92 self.consume_keyword(Keyword::Rollback)?;
93 Ok(RollbackStmt)
94 }
95
96 pub(crate) fn parse_rollback_to_savepoint_statement(
98 &mut self,
99 ) -> Result<RollbackToSavepointStmt, ParseError> {
100 self.consume_keyword(Keyword::Rollback)?;
101 self.consume_keyword(Keyword::To)?;
102 self.consume_keyword(Keyword::Savepoint)?;
103 let name = self.parse_arena_identifier()?;
104 Ok(RollbackToSavepointStmt { name })
105 }
106
107 pub(crate) fn parse_savepoint_statement(&mut self) -> Result<SavepointStmt, ParseError> {
109 self.consume_keyword(Keyword::Savepoint)?;
110 let name = self.parse_arena_identifier()?;
111 Ok(SavepointStmt { name })
112 }
113
114 pub(crate) fn parse_release_savepoint_statement(
116 &mut self,
117 ) -> Result<ReleaseSavepointStmt, ParseError> {
118 self.consume_keyword(Keyword::Release)?;
119 self.consume_keyword(Keyword::Savepoint)?;
120 let name = self.parse_arena_identifier()?;
121 Ok(ReleaseSavepointStmt { name })
122 }
123
124 pub(crate) fn parse_create_index_statement(
130 &mut self,
131 ) -> Result<CreateIndexStmt<'arena>, ParseError> {
132 self.consume_keyword(Keyword::Create)?;
133
134 let index_type = if self.try_consume_keyword(Keyword::Unique) {
136 IndexType::BTree { unique: true }
137 } else if self.try_consume_keyword(Keyword::Fulltext) {
138 IndexType::Fulltext
139 } else if self.try_consume_keyword(Keyword::Spatial) {
140 IndexType::Spatial
141 } else {
142 IndexType::BTree { unique: false }
143 };
144
145 self.consume_keyword(Keyword::Index)?;
146
147 let if_not_exists = if self.try_consume_keyword(Keyword::If) {
149 self.expect_keyword(Keyword::Not)?;
150 self.expect_keyword(Keyword::Exists)?;
151 true
152 } else {
153 false
154 };
155
156 let index_name = self.parse_arena_identifier()?;
157
158 self.consume_keyword(Keyword::On)?;
159 let table_name = self.parse_arena_identifier()?;
160
161 self.expect_token(Token::LParen)?;
162 let columns = self.parse_index_columns()?;
163 self.expect_token(Token::RParen)?;
164
165 Ok(CreateIndexStmt { if_not_exists, index_name, table_name, index_type, columns })
166 }
167
168 pub(crate) fn parse_create_view_statement(
170 &mut self,
171 ) -> Result<CreateViewStmt<'arena>, ParseError> {
172 self.consume_keyword(Keyword::Create)?;
173
174 let or_replace = if self.try_consume_keyword(Keyword::Or) {
176 self.expect_keyword(Keyword::Replace)?;
177 true
178 } else {
179 false
180 };
181
182 let temporary =
184 self.try_consume_keyword(Keyword::Temp) || self.try_consume_keyword(Keyword::Temporary);
185
186 self.consume_keyword(Keyword::View)?;
187
188 let if_not_exists = if self.try_consume_keyword(Keyword::If) {
190 self.expect_keyword(Keyword::Not)?;
191 self.expect_keyword(Keyword::Exists)?;
192 true
193 } else {
194 false
195 };
196
197 let view_name = self.parse_arena_identifier()?;
198
199 let columns = if self.try_consume(&Token::LParen) {
201 let cols = self.parse_identifier_list()?;
202 self.expect_token(Token::RParen)?;
203 Some(cols)
204 } else {
205 None
206 };
207
208 self.consume_keyword(Keyword::As)?;
209
210 let query = if self.peek_keyword(Keyword::Values) {
213 self.parse_values_statement()?
214 } else {
215 self.parse_select_statement()?
216 };
217
218 let with_check_option = if self.try_consume_keyword(Keyword::With) {
220 self.expect_keyword(Keyword::Check)?;
221 self.expect_keyword(Keyword::Option)?;
222 true
223 } else {
224 false
225 };
226
227 Ok(CreateViewStmt {
228 view_name,
229 columns,
230 query,
231 with_check_option,
232 or_replace,
233 if_not_exists,
234 temporary,
235 })
236 }
237
238 pub(crate) fn parse_drop_table_statement(&mut self) -> Result<DropTableStmt, ParseError> {
244 self.consume_keyword(Keyword::Drop)?;
245 self.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 table_name = self.parse_arena_identifier()?;
255
256 Ok(DropTableStmt { table_name, if_exists })
257 }
258
259 pub(crate) fn parse_drop_index_statement(&mut self) -> Result<DropIndexStmt, ParseError> {
261 self.consume_keyword(Keyword::Drop)?;
262 self.consume_keyword(Keyword::Index)?;
263
264 let if_exists = if self.try_consume_keyword(Keyword::If) {
265 self.expect_keyword(Keyword::Exists)?;
266 true
267 } else {
268 false
269 };
270
271 let index_name = self.parse_arena_identifier()?;
272
273 Ok(DropIndexStmt { if_exists, index_name })
274 }
275
276 pub(crate) fn parse_drop_view_statement(&mut self) -> Result<DropViewStmt, ParseError> {
278 self.consume_keyword(Keyword::Drop)?;
279 self.consume_keyword(Keyword::View)?;
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 view_name = self.parse_arena_identifier()?;
289
290 let (cascade, restrict) = if self.try_consume_keyword(Keyword::Cascade) {
291 (true, false)
292 } else if self.try_consume_keyword(Keyword::Restrict) {
293 (false, true)
294 } else {
295 (false, false)
296 };
297
298 Ok(DropViewStmt { view_name, if_exists, cascade, restrict })
299 }
300
301 pub(crate) fn parse_truncate_table_statement(
303 &mut self,
304 ) -> Result<TruncateTableStmt<'arena>, ParseError> {
305 self.consume_keyword(Keyword::Truncate)?;
306 self.try_consume_keyword(Keyword::Table);
307
308 let if_exists = if self.try_consume_keyword(Keyword::If) {
309 self.expect_keyword(Keyword::Exists)?;
310 true
311 } else {
312 false
313 };
314
315 let mut table_names = BumpVec::new_in(self.arena);
317 loop {
318 table_names.push(self.parse_arena_identifier()?);
319 if !self.try_consume(&Token::Comma) {
320 break;
321 }
322 }
323
324 let cascade = if self.try_consume_keyword(Keyword::Cascade) {
325 Some(TruncateCascadeOption::Cascade)
326 } else if self.try_consume_keyword(Keyword::Restrict) {
327 Some(TruncateCascadeOption::Restrict)
328 } else {
329 None
330 };
331
332 Ok(TruncateTableStmt { table_names, if_exists, cascade })
333 }
334
335 pub fn parse_alter_table_statement(
341 &mut self,
342 ) -> Result<&'arena AlterTableStmt<'arena>, ParseError> {
343 self.expect_keyword(Keyword::Alter)?;
345 self.expect_keyword(Keyword::Table)?;
346
347 let table_name = self.parse_table_name()?;
348
349 let stmt = match self.peek() {
351 Token::Keyword { keyword: Keyword::Add, .. } => {
352 self.advance();
353 match self.peek() {
354 Token::Keyword { keyword: Keyword::Column, .. } => {
355 self.advance();
356 self.parse_add_column(table_name)?
357 }
358 Token::Keyword {
360 keyword:
361 Keyword::Constraint
362 | Keyword::Check
363 | Keyword::Unique
364 | Keyword::Primary
365 | Keyword::Foreign,
366 ..
367 } => self.parse_add_constraint(table_name)?,
368 Token::Identifier(_) => self.parse_add_column(table_name)?,
370 _ => {
371 return Err(ParseError {
372 message:
373 "Expected COLUMN, constraint keyword, or column name after ADD"
374 .to_string(),
375 })
376 }
377 }
378 }
379 Token::Keyword { keyword: Keyword::Drop, .. } => {
380 self.advance();
381 match self.peek() {
382 Token::Keyword { keyword: Keyword::Column, .. } => {
383 self.advance();
384 self.parse_drop_column(table_name)?
385 }
386 Token::Keyword { keyword: Keyword::Constraint, .. } => {
387 self.advance();
388 self.parse_drop_constraint(table_name)?
389 }
390 _ => {
391 return Err(ParseError {
392 message: "Expected COLUMN or CONSTRAINT after DROP".to_string(),
393 })
394 }
395 }
396 }
397 Token::Keyword { keyword: Keyword::Alter, .. } => {
398 self.advance();
399 self.expect_keyword(Keyword::Column)?;
400 self.parse_alter_column(table_name)?
401 }
402 Token::Keyword { keyword: Keyword::Rename, .. } => {
403 self.advance();
404 self.parse_rename_table(table_name)?
405 }
406 Token::Keyword { keyword: Keyword::Modify, .. } => {
407 self.advance();
408 self.parse_modify_column(table_name)?
409 }
410 Token::Keyword { keyword: Keyword::Change, .. } => {
411 self.advance();
412 self.parse_change_column(table_name)?
413 }
414 _ => {
415 return Err(ParseError {
416 message:
417 "Expected ADD, DROP, ALTER, RENAME, MODIFY, or CHANGE after table name"
418 .to_string(),
419 })
420 }
421 };
422
423 Ok(self.arena.alloc(stmt))
424 }
425
426 fn parse_table_name(&mut self) -> Result<Symbol, ParseError> {
428 match self.peek() {
429 Token::Identifier(name) => {
430 let name = name.clone();
431 self.advance();
432 Ok(self.intern(&name))
433 }
434 _ => Err(ParseError { message: self.peek().syntax_error() }),
435 }
436 }
437
438 fn parse_column_name(&mut self) -> Result<Symbol, ParseError> {
440 match self.peek() {
441 Token::Identifier(name) => {
442 let name = name.clone();
443 self.advance();
444 Ok(self.intern(&name))
445 }
446 _ => Err(ParseError { message: self.peek().syntax_error() }),
447 }
448 }
449
450 fn parse_add_column(
452 &mut self,
453 table_name: Symbol,
454 ) -> Result<AlterTableStmt<'arena>, ParseError> {
455 let column_name = self.parse_column_name()?;
456 let data_type = self.parse_data_type()?;
457
458 let default_value: Option<&'arena Expression<'arena>> =
460 if self.peek_keyword(Keyword::Default) {
461 self.advance();
462 let expr = self.parse_expression()?;
463 Some(self.arena.alloc(expr))
464 } else {
465 None
466 };
467
468 let mut nullable = true;
470 let mut constraints = BumpVec::new_in(self.arena);
471
472 loop {
473 match self.peek() {
474 Token::Keyword { keyword: Keyword::Not, .. } => {
475 self.advance();
476 self.expect_keyword(Keyword::Null)?;
477 nullable = false;
478 }
479 Token::Keyword { keyword: Keyword::Primary, .. } => {
480 self.advance();
481 self.expect_keyword(Keyword::Key)?;
482 constraints.push(ColumnConstraint {
483 name: None,
484 kind: ColumnConstraintKind::PrimaryKey,
485 });
486 }
487 Token::Keyword { keyword: Keyword::Unique, .. } => {
488 self.advance();
489 constraints
490 .push(ColumnConstraint { name: None, kind: ColumnConstraintKind::Unique });
491 }
492 Token::Keyword { keyword: Keyword::References, .. } => {
493 self.advance();
494 let ref_table = self.parse_table_name()?;
495 let ref_column = if self.peek() == &Token::LParen {
497 self.advance(); let col = self.parse_column_name()?;
499 self.expect_token(Token::RParen)?;
500 Some(col)
501 } else {
502 None
503 };
504 constraints.push(ColumnConstraint {
505 name: None,
506 kind: ColumnConstraintKind::References {
507 table: ref_table,
508 column: ref_column,
509 on_delete: None,
510 on_update: None,
511 },
512 });
513 }
514 _ => break,
515 }
516 }
517
518 let column_def = ColumnDef {
519 name: column_name,
520 data_type,
521 nullable,
522 constraints,
523 default_value,
524 comment: None,
525 generated_expr: None,
526 };
527
528 Ok(AlterTableStmt::AddColumn(AddColumnStmt { table_name, column_def }))
529 }
530
531 fn parse_drop_column(
533 &mut self,
534 table_name: Symbol,
535 ) -> Result<AlterTableStmt<'arena>, ParseError> {
536 let if_exists =
537 self.try_consume_keyword(Keyword::If) && self.try_consume_keyword(Keyword::Exists);
538
539 let column_name = self.parse_column_name()?;
540
541 Ok(AlterTableStmt::DropColumn(DropColumnStmt { table_name, column_name, if_exists }))
542 }
543
544 fn parse_alter_column(
546 &mut self,
547 table_name: Symbol,
548 ) -> Result<AlterTableStmt<'arena>, ParseError> {
549 let column_name = self.parse_column_name()?;
550
551 match self.peek() {
552 Token::Keyword { keyword: Keyword::Set, .. } => {
553 self.advance();
554 match self.peek() {
555 Token::Keyword { keyword: Keyword::Default, .. } => {
556 self.advance();
557 let default = self.parse_expression()?;
558 Ok(AlterTableStmt::AlterColumn(AlterColumnStmt::SetDefault {
559 table_name,
560 column_name,
561 default,
562 }))
563 }
564 Token::Keyword { keyword: Keyword::Not, .. } => {
565 self.advance();
566 self.expect_keyword(Keyword::Null)?;
567 Ok(AlterTableStmt::AlterColumn(AlterColumnStmt::SetNotNull {
568 table_name,
569 column_name,
570 }))
571 }
572 _ => Err(ParseError {
573 message: "Expected DEFAULT or NOT NULL after SET".to_string(),
574 }),
575 }
576 }
577 Token::Keyword { keyword: Keyword::Drop, .. } => {
578 self.advance();
579 match self.peek() {
580 Token::Keyword { keyword: Keyword::Default, .. } => {
581 self.advance();
582 Ok(AlterTableStmt::AlterColumn(AlterColumnStmt::DropDefault {
583 table_name,
584 column_name,
585 }))
586 }
587 Token::Keyword { keyword: Keyword::Not, .. } => {
588 self.advance();
589 self.expect_keyword(Keyword::Null)?;
590 Ok(AlterTableStmt::AlterColumn(AlterColumnStmt::DropNotNull {
591 table_name,
592 column_name,
593 }))
594 }
595 _ => Err(ParseError {
596 message: "Expected DEFAULT or NOT NULL after DROP".to_string(),
597 }),
598 }
599 }
600 _ => Err(ParseError { message: "Expected SET or DROP after column name".to_string() }),
601 }
602 }
603
604 fn parse_add_constraint(
606 &mut self,
607 table_name: Symbol,
608 ) -> Result<AlterTableStmt<'arena>, ParseError> {
609 let constraint = self.parse_table_constraint()?;
610 Ok(AlterTableStmt::AddConstraint(AddConstraintStmt { table_name, constraint }))
611 }
612
613 fn parse_drop_constraint(
615 &mut self,
616 table_name: Symbol,
617 ) -> Result<AlterTableStmt<'arena>, ParseError> {
618 let constraint_name = self.parse_column_name()?;
619 Ok(AlterTableStmt::DropConstraint(DropConstraintStmt { table_name, constraint_name }))
620 }
621
622 fn parse_rename_table(
624 &mut self,
625 table_name: Symbol,
626 ) -> Result<AlterTableStmt<'arena>, ParseError> {
627 self.expect_keyword(Keyword::To)?;
628 let new_table_name = self.parse_table_name()?;
629 Ok(AlterTableStmt::RenameTable(RenameTableStmt { table_name, new_table_name }))
630 }
631
632 fn parse_modify_column(
634 &mut self,
635 table_name: Symbol,
636 ) -> Result<AlterTableStmt<'arena>, ParseError> {
637 if self.peek_keyword(Keyword::Column) {
639 self.advance();
640 }
641
642 let column_name = self.parse_column_name()?;
643 let data_type = self.parse_data_type()?;
644
645 let default_value: Option<&'arena Expression<'arena>> =
647 if self.peek_keyword(Keyword::Default) {
648 self.advance();
649 let expr = self.parse_expression()?;
650 Some(self.arena.alloc(expr))
651 } else {
652 None
653 };
654
655 let (nullable, constraints) = self.parse_column_constraints()?;
657
658 let new_column_def = ColumnDef {
659 name: column_name,
660 data_type,
661 nullable,
662 constraints,
663 default_value,
664 comment: None,
665 generated_expr: None,
666 };
667
668 Ok(AlterTableStmt::ModifyColumn(ModifyColumnStmt {
669 table_name,
670 column_name,
671 new_column_def,
672 }))
673 }
674
675 fn parse_change_column(
677 &mut self,
678 table_name: Symbol,
679 ) -> Result<AlterTableStmt<'arena>, ParseError> {
680 if self.peek_keyword(Keyword::Column) {
682 self.advance();
683 }
684
685 let old_column_name = self.parse_column_name()?;
686 let new_column_name = self.parse_column_name()?;
687 let data_type = self.parse_data_type()?;
688
689 let default_value: Option<&'arena Expression<'arena>> =
691 if self.peek_keyword(Keyword::Default) {
692 self.advance();
693 let expr = self.parse_expression()?;
694 Some(self.arena.alloc(expr))
695 } else {
696 None
697 };
698
699 let (nullable, constraints) = self.parse_column_constraints()?;
701
702 let new_column_def = ColumnDef {
703 name: new_column_name,
704 data_type,
705 nullable,
706 constraints,
707 default_value,
708 comment: None,
709 generated_expr: None,
710 };
711
712 Ok(AlterTableStmt::ChangeColumn(ChangeColumnStmt {
713 table_name,
714 old_column_name,
715 new_column_def,
716 }))
717 }
718
719 fn parse_column_constraints(
721 &mut self,
722 ) -> Result<(bool, BumpVec<'arena, ColumnConstraint<'arena>>), ParseError> {
723 let mut nullable = true;
724 let mut constraints = BumpVec::new_in(self.arena);
725
726 loop {
727 match self.peek() {
728 Token::Keyword { keyword: Keyword::Not, .. } => {
729 self.advance();
730 self.expect_keyword(Keyword::Null)?;
731 nullable = false;
732 }
733 Token::Keyword { keyword: Keyword::Primary, .. } => {
734 self.advance();
735 self.expect_keyword(Keyword::Key)?;
736 constraints.push(ColumnConstraint {
737 name: None,
738 kind: ColumnConstraintKind::PrimaryKey,
739 });
740 }
741 Token::Keyword { keyword: Keyword::Unique, .. } => {
742 self.advance();
743 constraints
744 .push(ColumnConstraint { name: None, kind: ColumnConstraintKind::Unique });
745 }
746 Token::Keyword { keyword: Keyword::References, .. } => {
747 self.advance();
748 let ref_table = self.parse_table_name()?;
749 let ref_column = if self.peek() == &Token::LParen {
751 self.advance(); let col = self.parse_column_name()?;
753 self.expect_token(Token::RParen)?;
754 Some(col)
755 } else {
756 None
757 };
758 constraints.push(ColumnConstraint {
759 name: None,
760 kind: ColumnConstraintKind::References {
761 table: ref_table,
762 column: ref_column,
763 on_delete: None,
764 on_update: None,
765 },
766 });
767 }
768 _ => break,
769 }
770 }
771
772 Ok((nullable, constraints))
773 }
774
775 fn parse_table_constraint(&mut self) -> Result<TableConstraint<'arena>, ParseError> {
777 let name = if self.try_consume_keyword(Keyword::Constraint) {
779 Some(self.parse_column_name()?)
780 } else {
781 None
782 };
783
784 let kind = match self.peek() {
785 Token::Keyword { keyword: Keyword::Primary, .. } => {
786 self.advance();
787 self.expect_keyword(Keyword::Key)?;
788 self.expect_token(Token::LParen)?;
789 let columns = self.parse_index_column_list()?;
790 self.expect_token(Token::RParen)?;
791 TableConstraintKind::PrimaryKey { columns }
792 }
793 Token::Keyword { keyword: Keyword::Unique, .. } => {
794 self.advance();
795 self.expect_token(Token::LParen)?;
796 let columns = self.parse_index_column_list()?;
797 self.expect_token(Token::RParen)?;
798 TableConstraintKind::Unique { columns }
799 }
800 Token::Keyword { keyword: Keyword::Foreign, .. } => {
801 self.advance();
802 self.expect_keyword(Keyword::Key)?;
803 self.expect_token(Token::LParen)?;
804 let columns = self.parse_column_name_list()?;
805 self.expect_token(Token::RParen)?;
806 self.expect_keyword(Keyword::References)?;
807 let references_table = self.parse_table_name()?;
808 self.expect_token(Token::LParen)?;
809 let references_columns = self.parse_column_name_list()?;
810 self.expect_token(Token::RParen)?;
811
812 let (on_delete, on_update) = self.parse_referential_actions()?;
813
814 TableConstraintKind::ForeignKey {
815 columns,
816 references_table,
817 references_columns,
818 on_delete,
819 on_update,
820 }
821 }
822 Token::Keyword { keyword: Keyword::Check, .. } => {
823 self.advance();
824 self.expect_token(Token::LParen)?;
825 let expr = self.parse_expression()?;
826 self.expect_token(Token::RParen)?;
827 TableConstraintKind::Check { expr: self.arena.alloc(expr) }
828 }
829 _ => return Err(ParseError { message: self.peek().syntax_error() }),
830 };
831
832 Ok(TableConstraint { name, kind })
833 }
834
835 fn parse_index_column_list(
837 &mut self,
838 ) -> Result<BumpVec<'arena, IndexColumn<'arena>>, ParseError> {
839 let mut columns = BumpVec::new_in(self.arena);
840
841 loop {
842 let column_name = self.parse_column_name()?;
843
844 let prefix_length = if self.try_consume(&Token::LParen) {
846 let len = match self.peek() {
847 Token::Number(n) => {
848 let len = n.parse::<u64>().ok();
849 self.advance();
850 len
851 }
852 _ => None,
853 };
854 self.expect_token(Token::RParen)?;
855 len
856 } else {
857 None
858 };
859
860 let direction = if self.try_consume_keyword(Keyword::Asc) {
862 OrderDirection::Asc
863 } else if self.try_consume_keyword(Keyword::Desc) {
864 OrderDirection::Desc
865 } else {
866 OrderDirection::Asc
867 };
868
869 columns.push(IndexColumn::Column { column_name, direction, prefix_length });
870
871 if !self.try_consume(&Token::Comma) {
872 break;
873 }
874 }
875
876 Ok(columns)
877 }
878
879 fn parse_column_name_list(&mut self) -> Result<BumpVec<'arena, Symbol>, ParseError> {
881 let mut columns = BumpVec::new_in(self.arena);
882
883 loop {
884 let col = self.parse_column_name()?;
885 columns.push(col);
886
887 if !self.try_consume(&Token::Comma) {
888 break;
889 }
890 }
891
892 Ok(columns)
893 }
894
895 fn parse_referential_actions(
897 &mut self,
898 ) -> Result<(Option<ReferentialAction>, Option<ReferentialAction>), ParseError> {
899 let mut on_delete = None;
900 let mut on_update = None;
901
902 for _ in 0..2 {
903 if self.try_consume_keyword(Keyword::On) {
904 if self.try_consume_keyword(Keyword::Delete) {
905 on_delete = Some(self.parse_referential_action()?);
906 } else if self.try_consume_keyword(Keyword::Update) {
907 on_update = Some(self.parse_referential_action()?);
908 }
909 }
910 }
911
912 Ok((on_delete, on_update))
913 }
914
915 fn parse_referential_action(&mut self) -> Result<ReferentialAction, ParseError> {
917 if self.try_consume_keyword(Keyword::Cascade) {
918 Ok(ReferentialAction::Cascade)
919 } else if self.try_consume_keyword(Keyword::Restrict) {
920 Ok(ReferentialAction::Restrict)
921 } else if self.try_consume_keyword(Keyword::Set) {
922 if self.try_consume_keyword(Keyword::Null) {
923 Ok(ReferentialAction::SetNull)
924 } else if self.try_consume_keyword(Keyword::Default) {
925 Ok(ReferentialAction::SetDefault)
926 } else {
927 Err(ParseError { message: "Expected NULL or DEFAULT after SET".to_string() })
928 }
929 } else if self.try_consume_keyword(Keyword::No) {
930 self.expect_keyword(Keyword::Action)?;
931 Ok(ReferentialAction::NoAction)
932 } else {
933 Err(ParseError {
934 message: "Expected CASCADE, RESTRICT, SET NULL, SET DEFAULT, or NO ACTION"
935 .to_string(),
936 })
937 }
938 }
939
940 pub(crate) fn parse_analyze_statement(&mut self) -> Result<AnalyzeStmt<'arena>, ParseError> {
946 self.consume_keyword(Keyword::Analyze)?;
947
948 let table_name = if let Token::Identifier(_) = self.peek() {
950 Some(self.parse_arena_identifier()?)
951 } else {
952 None
953 };
954
955 let columns = if table_name.is_some() && self.try_consume(&Token::LParen) {
957 let cols = self.parse_identifier_list()?;
958 self.expect_token(Token::RParen)?;
959 Some(cols)
960 } else {
961 None
962 };
963
964 Ok(AnalyzeStmt { table_name, columns })
965 }
966
967 fn parse_index_columns(&mut self) -> Result<BumpVec<'arena, IndexColumn<'arena>>, ParseError> {
973 let mut columns = BumpVec::new_in(self.arena);
974 loop {
975 let column_name = self.parse_arena_identifier()?;
976
977 let prefix_length = if self.try_consume(&Token::LParen) {
979 let len = match self.peek() {
980 Token::Number(n) => n
981 .parse::<u64>()
982 .map_err(|_| ParseError { message: "Invalid prefix length".to_string() })?,
983 _ => {
984 return Err(ParseError {
985 message: "Expected number for prefix length".to_string(),
986 })
987 }
988 };
989 self.advance();
990 self.expect_token(Token::RParen)?;
991 Some(len)
992 } else {
993 None
994 };
995
996 let direction = if self.try_consume_keyword(Keyword::Desc) {
998 OrderDirection::Desc
999 } else {
1000 self.try_consume_keyword(Keyword::Asc);
1001 OrderDirection::Asc
1002 };
1003
1004 columns.push(IndexColumn::Column { column_name, direction, prefix_length });
1005
1006 if !self.try_consume(&Token::Comma) {
1007 break;
1008 }
1009 }
1010 Ok(columns)
1011 }
1012
1013 pub(crate) fn parse_pragma_statement(&mut self) -> Result<PragmaStmt, ParseError> {
1025 self.consume_keyword(Keyword::Pragma)?;
1026
1027 let first_ident = self.parse_arena_identifier()?;
1029
1030 let (database, name) = if self.try_consume(&Token::Symbol('.')) {
1032 let pragma_name = self.parse_arena_identifier()?;
1033 (Some(first_ident), pragma_name)
1034 } else {
1035 (None, first_ident)
1036 };
1037
1038 let value = if self.try_consume(&Token::Symbol('=')) {
1040 Some(self.parse_pragma_value()?)
1041 } else if self.try_consume(&Token::LParen) {
1042 let val = self.parse_pragma_value()?;
1043 self.expect_token(Token::RParen)?;
1044 Some(val)
1045 } else {
1046 None
1047 };
1048
1049 Ok(PragmaStmt { database, name, value })
1050 }
1051
1052 fn parse_pragma_value(&mut self) -> Result<PragmaValue, ParseError> {
1054 match self.peek().clone() {
1055 Token::Identifier(ident) => {
1056 self.advance();
1057 let sym = self.interner.intern(&ident);
1058 Ok(PragmaValue::Identifier(sym))
1059 }
1060 Token::Keyword { keyword: kw, .. } => {
1061 self.advance();
1062 let sym = self.interner.intern(&kw.to_string());
1063 Ok(PragmaValue::Identifier(sym))
1064 }
1065 Token::String(s) => {
1066 self.advance();
1067 let sym = self.interner.intern(&s);
1068 Ok(PragmaValue::String(sym))
1069 }
1070 Token::Number(n) => {
1071 self.advance();
1072 let sym = self.interner.intern(&n);
1073 Ok(PragmaValue::Number(sym))
1074 }
1075 Token::Symbol('-') => {
1076 self.advance(); match self.peek().clone() {
1078 Token::Number(n) => {
1079 self.advance();
1080 let sym = self.interner.intern(&format!("-{}", n));
1081 Ok(PragmaValue::SignedNumber(sym))
1082 }
1083 _ => Err(ParseError {
1084 message: "Expected number after minus sign in PRAGMA value".to_string(),
1085 }),
1086 }
1087 }
1088 Token::Symbol('+') => {
1089 self.advance(); match self.peek().clone() {
1091 Token::Number(n) => {
1092 self.advance();
1093 let sym = self.interner.intern(&n);
1094 Ok(PragmaValue::Number(sym))
1095 }
1096 _ => Err(ParseError {
1097 message: "Expected number after plus sign in PRAGMA value".to_string(),
1098 }),
1099 }
1100 }
1101 _ => Err(ParseError { message: self.peek().syntax_error() }),
1102 }
1103 }
1104}