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