1use alloc::vec::Vec;
2
3use crate::{
15 data_type::parse_data_type,
16 expression::parse_expression,
17 keywords::Keyword,
18 lexer::Token,
19 parser::{ParseError, Parser},
20 qualified_name::parse_qualified_name,
21 DataType, Expression, Identifier, QualifiedName, SString, Span, Spanned, Statement,
22};
23
24#[derive(Clone, Debug)]
26pub enum IndexOption<'a> {
27 IndexTypeBTree(Span),
29 IndexTypeHash(Span),
31 IndexTypeRTree(Span),
33 Comment(SString<'a>),
35}
36
37impl<'a> Spanned for IndexOption<'a> {
38 fn span(&self) -> Span {
39 match &self {
40 IndexOption::IndexTypeBTree(v) => v.span(),
41 IndexOption::IndexTypeHash(v) => v.span(),
42 IndexOption::IndexTypeRTree(v) => v.span(),
43 IndexOption::Comment(v) => v.span(),
44 }
45 }
46}
47
48#[derive(Clone, Debug)]
50pub enum IndexType {
51 Index(Span),
52 Primary(Span),
53 Unique(Span),
54 FullText(Span),
55 Spatial(Span),
56}
57
58impl Spanned for IndexType {
59 fn span(&self) -> Span {
60 match &self {
61 IndexType::Index(v) => v.span(),
62 IndexType::Primary(v) => v.span(),
63 IndexType::Unique(v) => v.span(),
64 IndexType::FullText(v) => v.span(),
65 IndexType::Spatial(v) => v.span(),
66 }
67 }
68}
69
70#[derive(Clone, Debug)]
72pub enum ForeignKeyOnType {
73 Update(Span),
74 Delete(Span),
75}
76
77impl Spanned for ForeignKeyOnType {
78 fn span(&self) -> Span {
79 match &self {
80 ForeignKeyOnType::Update(v) => v.span(),
81 ForeignKeyOnType::Delete(v) => v.span(),
82 }
83 }
84}
85
86#[derive(Clone, Debug)]
88pub enum ForeignKeyOnAction {
89 Restrict(Span),
90 Cascade(Span),
91 SetNull(Span),
92 NoAction(Span),
93 SetDefault(Span),
94}
95
96impl Spanned for ForeignKeyOnAction {
97 fn span(&self) -> Span {
98 match &self {
99 ForeignKeyOnAction::Restrict(v) => v.span(),
100 ForeignKeyOnAction::Cascade(v) => v.span(),
101 ForeignKeyOnAction::SetNull(v) => v.span(),
102 ForeignKeyOnAction::NoAction(v) => v.span(),
103 ForeignKeyOnAction::SetDefault(v) => v.span(),
104 }
105 }
106}
107
108#[derive(Clone, Debug)]
110pub struct ForeignKeyOn {
111 pub type_: ForeignKeyOnType,
112 pub action: ForeignKeyOnAction,
113}
114
115impl Spanned for ForeignKeyOn {
116 fn span(&self) -> Span {
117 self.type_.join_span(&self.action)
118 }
119}
120
121#[derive(Clone, Debug)]
123pub struct IndexCol<'a> {
124 pub name: Identifier<'a>,
126 pub size: Option<(u32, Span)>,
128}
129
130impl<'a> Spanned for IndexCol<'a> {
131 fn span(&self) -> Span {
132 self.name.join_span(&self.size)
133 }
134}
135
136#[derive(Clone, Debug)]
138pub enum AlterColumnAction<'a> {
139 SetDefault {
140 set_default_span: Span,
141 value: Expression<'a>,
142 },
143 DropDefault {
144 drop_default_span: Span,
145 },
146 Type {
147 type_span: Span,
148 type_: DataType<'a>,
149 },
150 SetNotNull {
151 set_not_null_span: Span,
152 },
153 DropNotNull {
154 drop_not_null_span: Span,
155 },
156}
157
158impl<'a> Spanned for AlterColumnAction<'a> {
159 fn span(&self) -> Span {
160 match self {
161 AlterColumnAction::SetDefault {
162 set_default_span,
163 value,
164 } => set_default_span.join_span(value),
165 AlterColumnAction::DropDefault { drop_default_span } => drop_default_span.clone(),
166 AlterColumnAction::Type { type_span, type_ } => type_span.join_span(type_),
167 AlterColumnAction::SetNotNull { set_not_null_span } => set_not_null_span.clone(),
168 AlterColumnAction::DropNotNull { drop_not_null_span } => drop_not_null_span.clone(),
169 }
170 }
171}
172
173#[derive(Clone, Debug)]
175pub enum AlterSpecification<'a> {
176 AddColumn {
177 add_span: Span,
178 if_not_exists_span: Option<Span>,
179 identifier: Identifier<'a>,
180 data_type: DataType<'a>,
181 },
182 AddIndex {
184 add_span: Span,
186 index_type: IndexType,
188 if_not_exists: Option<Span>,
190 name: Option<Identifier<'a>>,
192 constraint: Option<(Span, Option<Identifier<'a>>)>,
194 cols: Vec<IndexCol<'a>>,
196 index_options: Vec<IndexOption<'a>>,
198 },
199 AddForeignKey {
201 add_span: Span,
203 constraint: Option<(Span, Option<Identifier<'a>>)>,
205 foreign_key_span: Span,
207 if_not_exists: Option<Span>,
209 name: Option<Identifier<'a>>,
211 cols: Vec<IndexCol<'a>>,
213 references_span: Span,
215 references_table: Identifier<'a>,
217 references_cols: Vec<Identifier<'a>>,
219 ons: Vec<ForeignKeyOn>,
221 },
222 Modify {
224 modify_span: Span,
226 if_exists: Option<Span>,
228 col: Identifier<'a>,
230 definition: DataType<'a>,
232 },
233 DropColumn {
234 drop_column_span: Span,
236 column: Identifier<'a>,
238 cascade: Option<Span>,
240 },
241 AlterColumn {
242 alter_column_span: Span,
244 column: Identifier<'a>,
246 alter_column_action: AlterColumnAction<'a>,
247 },
248 OwnerTo {
250 span: Span,
252 owner: Identifier<'a>,
254 },
255}
256
257impl<'a> Spanned for AlterSpecification<'a> {
258 fn span(&self) -> Span {
259 match &self {
260 AlterSpecification::AddColumn {
261 add_span,
262 if_not_exists_span,
263 identifier,
264 data_type,
265 } => add_span
266 .join_span(if_not_exists_span)
267 .join_span(identifier)
268 .join_span(data_type),
269 AlterSpecification::AddIndex {
270 add_span,
271 index_type,
272 if_not_exists,
273 name,
274 constraint,
275 cols,
276 index_options,
277 } => add_span
278 .join_span(index_type)
279 .join_span(if_not_exists)
280 .join_span(name)
281 .join_span(constraint)
282 .join_span(cols)
283 .join_span(index_options),
284 AlterSpecification::AddForeignKey {
285 add_span,
286 constraint,
287 foreign_key_span: foregin_key_span,
288 if_not_exists,
289 name,
290 cols,
291 references_span,
292 references_table,
293 references_cols,
294 ons,
295 } => add_span
296 .join_span(constraint)
297 .join_span(foregin_key_span)
298 .join_span(if_not_exists)
299 .join_span(name)
300 .join_span(cols)
301 .join_span(references_span)
302 .join_span(references_table)
303 .join_span(references_cols)
304 .join_span(ons),
305 AlterSpecification::Modify {
306 modify_span,
307 if_exists,
308 col,
309 definition,
310 } => modify_span
311 .join_span(if_exists)
312 .join_span(col)
313 .join_span(definition),
314 AlterSpecification::OwnerTo { span, owner } => span.join_span(owner),
315 AlterSpecification::DropColumn {
316 drop_column_span,
317 column: col,
318 cascade,
319 } => drop_column_span.join_span(col).join_span(cascade),
320 AlterSpecification::AlterColumn {
321 alter_column_span,
322 column: col,
323 alter_column_action,
324 } => alter_column_span
325 .join_span(col)
326 .join_span(alter_column_action),
327 }
328 }
329}
330
331fn parse_index_type<'a>(
332 parser: &mut Parser<'a, '_>,
333 out: &mut Vec<IndexOption<'a>>,
334) -> Result<(), ParseError> {
335 parser.consume_keyword(Keyword::USING)?;
336 out.push(match &parser.token {
337 Token::Ident(_, Keyword::BTREE) => {
338 IndexOption::IndexTypeBTree(parser.consume_keyword(Keyword::BTREE)?)
339 }
340 Token::Ident(_, Keyword::HASH) => {
341 IndexOption::IndexTypeHash(parser.consume_keyword(Keyword::HASH)?)
342 }
343 Token::Ident(_, Keyword::RTREE) => {
344 IndexOption::IndexTypeRTree(parser.consume_keyword(Keyword::RTREE)?)
345 }
346 _ => parser.expected_failure("'BTREE', 'RTREE' or 'HASH'")?,
347 });
348 Ok(())
349}
350
351fn parse_index_options<'a>(
352 parser: &mut Parser<'a, '_>,
353 out: &mut Vec<IndexOption<'a>>,
354) -> Result<(), ParseError> {
355 loop {
356 match &parser.token {
357 Token::Ident(_, Keyword::USING) => parse_index_type(parser, out)?,
358 Token::Ident(_, Keyword::COMMENT) => {
359 parser.consume_keyword(Keyword::COMMENT)?;
360 out.push(IndexOption::Comment(parser.consume_string()?))
361 }
362 _ => break,
363 }
364 }
365 Ok(())
366}
367
368fn parse_index_cols<'a>(parser: &mut Parser<'a, '_>) -> Result<Vec<IndexCol<'a>>, ParseError> {
369 parser.consume_token(Token::LParen)?;
370 let mut ans = Vec::new();
371 parser.recovered("')'", &|t| t == &Token::RParen, |parser| {
372 loop {
373 let name = parser.consume_plain_identifier()?;
374 let size = if parser.skip_token(Token::LParen).is_some() {
375 let size = parser.recovered("')'", &|t| t == &Token::RParen, |parser| {
376 parser.consume_int()
377 })?;
378 parser.consume_token(Token::RParen)?;
379 Some(size)
380 } else {
381 None
382 };
383
384 ans.push(IndexCol { name, size });
387 if parser.skip_token(Token::Comma).is_none() {
388 break;
389 }
390 }
391 Ok(())
392 })?;
393 parser.consume_token(Token::RParen)?;
394 Ok(ans)
395}
396
397fn parse_cols<'a>(parser: &mut Parser<'a, '_>) -> Result<Vec<Identifier<'a>>, ParseError> {
398 parser.consume_token(Token::LParen)?;
399 let mut ans = Vec::new();
400 parser.recovered("')'", &|t| t == &Token::RParen, |parser| {
401 loop {
402 ans.push(parser.consume_plain_identifier()?);
403 if parser.skip_token(Token::Comma).is_none() {
404 break;
405 }
406 }
407 Ok(())
408 })?;
409 parser.consume_token(Token::RParen)?;
410 Ok(ans)
411}
412
413fn parse_add_alter_specification<'a>(
414 parser: &mut Parser<'a, '_>,
415) -> Result<AlterSpecification<'a>, ParseError> {
416 let add_span = parser.consume_keyword(Keyword::ADD)?;
417 let constraint = if let Some(span) = parser.skip_keyword(Keyword::CONSTRAINT) {
418 let v = match &parser.token {
419 Token::Ident(_, kw) if !kw.reserved() => Some(parser.consume_plain_identifier()?),
420 _ => None,
421 };
422 Some((span, v))
423 } else {
424 None
425 };
426 match &parser.token {
427 Token::Ident(_, Keyword::FOREIGN) => {
428 let foregin_key_span = parser.consume_keywords(&[Keyword::FOREIGN, Keyword::KEY])?;
429 let if_not_exists = if let Some(s) = parser.skip_keyword(Keyword::IF) {
430 Some(
431 parser
432 .consume_keywords(&[Keyword::NOT, Keyword::EXISTS])?
433 .join_span(&s),
434 )
435 } else {
436 None
437 };
438 let name = match &parser.token {
439 Token::Ident(_, kw) if !kw.reserved() => Some(parser.consume_plain_identifier()?),
440 _ => None,
441 };
442
443 let cols = parse_index_cols(parser)?;
444 let references_span = parser.consume_keyword(Keyword::REFERENCES)?;
445 let references_table = parser.consume_plain_identifier()?;
446 let references_cols = parse_cols(parser)?;
447 let mut ons = Vec::new();
448 while let Some(on) = parser.skip_keyword(Keyword::ON) {
449 let type_ = match parser.token {
450 Token::Ident(_, Keyword::UPDATE) => ForeignKeyOnType::Update(
451 parser.consume_keyword(Keyword::UPDATE)?.join_span(&on),
452 ),
453 Token::Ident(_, Keyword::DELETE) => ForeignKeyOnType::Delete(
454 parser.consume_keyword(Keyword::DELETE)?.join_span(&on),
455 ),
456 _ => parser.expected_failure("'UPDATE' or 'DELETE'")?,
457 };
458
459 let action = match parser.token {
460 Token::Ident(_, Keyword::RESTRICT) => {
461 ForeignKeyOnAction::Restrict(parser.consume_keyword(Keyword::RESTRICT)?)
462 }
463 Token::Ident(_, Keyword::CASCADE) => {
464 ForeignKeyOnAction::Cascade(parser.consume_keyword(Keyword::CASCADE)?)
465 }
466 Token::Ident(_, Keyword::SET) => {
467 let set = parser.consume_keyword(Keyword::SET)?;
468 match parser.token {
469 Token::Ident(_, Keyword::NULL) => ForeignKeyOnAction::SetNull(
470 parser.consume_keyword(Keyword::NULL)?.join_span(&set),
471 ),
472 Token::Ident(_, Keyword::DELETE) => ForeignKeyOnAction::SetDefault(
473 parser.consume_keyword(Keyword::DEFAULT)?.join_span(&set),
474 ),
475 _ => parser.expected_failure("'NULL' or 'DEFAULT'")?,
476 }
477 }
478 Token::Ident(_, Keyword::NO) => ForeignKeyOnAction::SetNull(
479 parser.consume_keywords(&[Keyword::NO, Keyword::ACTION])?,
480 ),
481 _ => parser.expected_failure("'RESTRICT' or 'CASCADE', 'SET' or 'NO")?,
482 };
483 ons.push(ForeignKeyOn { type_, action })
484 }
485 Ok(AlterSpecification::AddForeignKey {
486 add_span,
487 constraint,
488 foreign_key_span: foregin_key_span,
489 if_not_exists,
490 name,
491 cols,
492 references_span,
493 references_table,
494 references_cols,
495 ons,
496 })
497 }
498 Token::Ident(
499 _,
500 Keyword::PRIMARY
501 | Keyword::INDEX
502 | Keyword::KEY
503 | Keyword::FULLTEXT
504 | Keyword::UNIQUE
505 | Keyword::SPATIAL,
506 ) => {
507 let index_type = match &parser.token {
508 Token::Ident(_, Keyword::PRIMARY) => {
509 IndexType::Primary(parser.consume_keywords(&[Keyword::PRIMARY, Keyword::KEY])?)
510 }
511 Token::Ident(_, Keyword::INDEX | Keyword::KEY) => {
512 IndexType::Index(parser.consume())
513 }
514 Token::Ident(_, Keyword::FULLTEXT) => {
515 let s = parser.consume_keyword(Keyword::FULLTEXT)?;
516 match &parser.token {
517 Token::Ident(_, kw @ Keyword::INDEX | kw @ Keyword::KEY) => {
518 let kw = *kw;
519 IndexType::FullText(parser.consume_keyword(kw)?.join_span(&s))
520 }
521 _ => parser.expected_failure("'KEY' or 'INDEX'")?,
522 }
523 }
524 Token::Ident(_, Keyword::SPATIAL) => {
525 let s = parser.consume_keyword(Keyword::SPATIAL)?;
526 match &parser.token {
527 Token::Ident(_, kw @ Keyword::INDEX | kw @ Keyword::KEY) => {
528 let kw = *kw;
529 IndexType::FullText(parser.consume_keyword(kw)?.join_span(&s))
530 }
531 _ => parser.expected_failure("'KEY' or 'INDEX'")?,
532 }
533 }
534 Token::Ident(_, Keyword::UNIQUE) => {
535 let s = parser.consume_keyword(Keyword::UNIQUE)?;
536 match &parser.token {
537 Token::Ident(_, kw @ Keyword::INDEX | kw @ Keyword::KEY) => {
538 let kw = *kw;
539 IndexType::FullText(parser.consume_keyword(kw)?.join_span(&s))
540 }
541 _ => parser.expected_failure("'KEY' or 'INDEX'")?,
542 }
543 }
544 _ => parser.ice(file!(), line!())?,
545 };
546
547 let if_not_exists = if let Some(s) = parser.skip_keyword(Keyword::IF) {
548 Some(
549 parser
550 .consume_keywords(&[Keyword::NOT, Keyword::EXISTS])?
551 .join_span(&s),
552 )
553 } else {
554 None
555 };
556
557 let name = match &parser.token {
558 Token::Ident(_, kw) if !kw.reserved() => Some(parser.consume_plain_identifier()?),
559 _ => None,
560 };
561
562 let mut index_options = Vec::new();
563 if matches!(parser.token, Token::Ident(_, Keyword::USING)) {
564 parse_index_type(parser, &mut index_options)?;
565 }
566 let cols = parse_index_cols(parser)?;
567 parse_index_options(parser, &mut index_options)?;
568
569 Ok(AlterSpecification::AddIndex {
570 add_span,
571 constraint,
572 index_type,
573 if_not_exists,
574 name,
575 cols,
576 index_options,
577 })
578 }
579 Token::Ident(_, Keyword::COLUMN) => {
580 parser.consume_keyword(Keyword::COLUMN)?;
581 let mut if_not_exists_span = None;
582 if matches!(parser.token, Token::Ident(_, Keyword::IF)) {
583 if_not_exists_span =
584 Some(parser.consume_keywords(&[Keyword::IF, Keyword::NOT, Keyword::EXISTS])?);
585 }
586
587 if let Some(s) = &if_not_exists_span {
588 if parser.options.dialect.is_maria() {
589 parser.err("IF NOT EXIST is not supported", s);
590 }
591 }
592
593 let identifier = parser.consume_plain_identifier()?;
594 let data_type = parse_data_type(parser, false)?;
595 Ok(AlterSpecification::AddColumn {
596 add_span,
597 if_not_exists_span,
598 identifier,
599 data_type,
600 })
601 }
602 _ => parser.expected_failure("addable"),
603 }
604}
605
606#[derive(Clone, Debug)]
645pub struct AlterTable<'a> {
646 pub alter_span: Span,
648 pub online: Option<Span>,
650 pub ignore: Option<Span>,
652 pub table_span: Span,
654 pub if_exists: Option<Span>,
656 pub table: QualifiedName<'a>,
658 pub alter_specifications: Vec<AlterSpecification<'a>>,
660}
661
662impl<'a> Spanned for AlterTable<'a> {
663 fn span(&self) -> Span {
664 self.alter_span
665 .join_span(&self.online)
666 .join_span(&self.ignore)
667 .join_span(&self.table_span)
668 .join_span(&self.if_exists)
669 .join_span(&self.table)
670 .join_span(&self.alter_specifications)
671 }
672}
673
674fn parse_alter_table<'a>(
675 parser: &mut Parser<'a, '_>,
676 alter_span: Span,
677 online: Option<Span>,
678 ignore: Option<Span>,
679) -> Result<AlterTable<'a>, ParseError> {
680 let table_span = parser.consume_keyword(Keyword::TABLE)?;
681 let if_exists = if let Some(span) = parser.skip_keyword(Keyword::IF) {
682 Some(parser.consume_keyword(Keyword::EXISTS)?.join_span(&span))
683 } else {
684 None
685 };
686 let table = parse_qualified_name(parser)?;
687 let d = parser.delimiter.clone();
688 let mut alter_specifications = Vec::new();
689 parser.recovered(d.name(), &|t| (t == &d || t == &Token::Eof), |parser| {
690 loop {
691 alter_specifications.push(match parser.token {
692 Token::Ident(_, Keyword::ADD) => parse_add_alter_specification(parser)?,
693 Token::Ident(_, Keyword::MODIFY) => {
694 let mut modify_span = parser.consume_keyword(Keyword::MODIFY)?;
695 if let Some(v) = parser.skip_keyword(Keyword::COLUMN) {
696 modify_span = modify_span.join_span(&v);
697 }
698 let if_exists = if let Some(span) = parser.skip_keyword(Keyword::IF) {
699 Some(parser.consume_keyword(Keyword::EXISTS)?.join_span(&span))
700 } else {
701 None
702 };
703 let col = parser.consume_plain_identifier()?;
704 let definition = parse_data_type(parser, false)?;
705 AlterSpecification::Modify {
707 modify_span,
708 if_exists,
709 col,
710 definition,
711 }
712 }
713 Token::Ident(_, Keyword::OWNER) => {
714 let span = parser.consume_keywords(&[Keyword::OWNER, Keyword::TO])?;
715 let owner = parser.consume_plain_identifier()?;
716 AlterSpecification::OwnerTo { span, owner }
717 }
718 Token::Ident(_, Keyword::DROP) => {
719 let drop_column_span =
720 parser.consume_keywords(&[Keyword::DROP, Keyword::COLUMN])?;
721 let column = parser.consume_plain_identifier()?;
722 let cascade = parser.skip_keyword(Keyword::CASCADE);
723 AlterSpecification::DropColumn {
724 drop_column_span,
725 column,
726 cascade,
727 }
728 }
729 Token::Ident(_, Keyword::ALTER) => {
730 let span = parser.consume_keywords(&[Keyword::ALTER, Keyword::COLUMN])?;
731 let column = parser.consume_plain_identifier()?;
732
733 let alter_column_action = match parser.token {
734 Token::Ident(_, Keyword::SET) => {
735 let set_span = parser.consume();
736 match parser.token {
737 Token::Ident(_, Keyword::DEFAULT) => {
738 let set_default_span = parser.consume().join_span(&set_span);
739 let value = parse_expression(parser, false)?;
740 AlterColumnAction::SetDefault {
741 set_default_span,
742 value,
743 }
744 }
745 Token::Ident(_, Keyword::NOT) => {
746 let set_not_null_span = set_span.join_span(
747 &parser.consume_keywords(&[Keyword::NOT, Keyword::NULL])?,
748 );
749 AlterColumnAction::SetNotNull { set_not_null_span }
750 }
751 _ => parser.expected_failure("'DEFAULT' or 'NOT NULL'")?,
752 }
753 }
754 Token::Ident(_, Keyword::DROP) => {
755 let set_span = parser.consume();
756 match parser.token {
757 Token::Ident(_, Keyword::DEFAULT) => {
758 let drop_default_span = parser.consume().join_span(&set_span);
759 AlterColumnAction::DropDefault {
760 drop_default_span: drop_default_span,
761 }
762 }
763 Token::Ident(_, Keyword::NOT) => {
764 let drop_not_null_span = set_span.join_span(
765 &parser.consume_keywords(&[Keyword::NOT, Keyword::NULL])?,
766 );
767 AlterColumnAction::DropNotNull { drop_not_null_span }
768 }
769 _ => parser.expected_failure("'DEFAULT' or 'NOT NULL'")?,
770 }
771 }
772 Token::Ident(_, Keyword::TYPE) => {
773 let type_span = parser.consume();
774 let type_ = parse_data_type(parser, false)?;
775 AlterColumnAction::Type { type_span, type_ }
776 }
777 _ => parser.expected_failure("alter column action")?,
778 };
779 AlterSpecification::AlterColumn {
780 alter_column_span: span,
781 column,
782 alter_column_action,
783 }
784 }
785 _ => parser.expected_failure("alter specification")?,
786 });
787 if parser.skip_token(Token::Comma).is_none() {
788 break;
789 }
790 }
791 Ok(())
792 })?;
793 Ok(AlterTable {
794 alter_span,
795 online,
796 ignore,
797 table_span,
798 if_exists,
799 table,
800 alter_specifications,
801 })
802}
803
804pub(crate) fn parse_alter<'a>(parser: &mut Parser<'a, '_>) -> Result<Statement<'a>, ParseError> {
805 let alter_span = parser.consume_keyword(Keyword::ALTER)?;
806
807 let online = parser.skip_keyword(Keyword::ONLINE);
808 let ignore = parser.skip_keyword(Keyword::IGNORE);
809
810 match &parser.token {
811 Token::Ident(_, Keyword::TABLE) => Ok(Statement::AlterTable(parse_alter_table(
812 parser, alter_span, online, ignore,
813 )?)),
814 _ => parser.expected_failure("alterable"),
815 }
816}