1use core::fmt;
2use std::fmt::{write, Display, Formatter};
3use std::str::FromStr;
4
5use nom::branch::alt;
6use nom::bytes::complete::{tag, tag_no_case, take_until};
7use nom::character::complete::{alphanumeric1, anychar, digit1, multispace0, multispace1};
8use nom::combinator::{map, opt, recognize};
9use nom::error::ParseError;
10use nom::multi::{many0, many1};
11use nom::sequence::{delimited, preceded, terminated, tuple};
12use nom::{IResult, Parser};
13
14use base::algorithm_type::AlgorithmType;
15use base::column::{Column, ColumnSpecification};
16use base::fulltext_or_spatial_type::FulltextOrSpatialType;
17use base::index_option::IndexOption;
18use base::index_or_key_type::IndexOrKeyType;
19use base::index_type::IndexType;
20use base::lock_type::LockType;
21use base::table::Table;
22use base::table_option::TableOption;
23use base::visible_type::VisibleType;
24use base::{
25 CheckConstraintDefinition, CommonParser, KeyPart, ParseSQLError, PartitionDefinition,
26 ReferenceDefinition,
27};
28
29#[derive(Clone, Debug, Default, Eq, Hash, PartialEq, Serialize, Deserialize)]
31pub struct AlterTableStatement {
32 pub table: Table,
33 pub alter_options: Option<Vec<AlterTableOption>>,
34 pub partition_options: Option<Vec<AlterPartitionOption>>,
35}
36
37impl Display for AlterTableStatement {
38 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
39 write!(f, "ALTER TABLE {}", &self.table);
40 if let Some(alter_options) = &self.alter_options {
41 write!(f, " {}", AlterTableOption::format_list(alter_options));
42 }
43 if let Some(partition_options) = &self.partition_options {
44 write!(
45 f,
46 " {}",
47 AlterPartitionOption::format_list(partition_options)
48 );
49 }
50 Ok(())
51 }
52}
53
54impl AlterTableStatement {
55 pub fn parse(i: &str) -> IResult<&str, AlterTableStatement, ParseSQLError<&str>> {
56 let mut parser = tuple((
57 tuple((
58 tag_no_case("ALTER "),
59 multispace0,
60 tag_no_case("TABLE "),
61 multispace0,
62 )),
63 Table::without_alias,
65 multispace0,
66 opt(many0(map(
68 tuple((
69 AlterTableOption::parse,
70 opt(CommonParser::ws_sep_comma),
71 multispace0,
72 )),
73 |x| x.0,
74 ))),
75 opt(many0(terminated(
76 AlterPartitionOption::parse,
77 opt(CommonParser::ws_sep_comma),
78 ))),
79 CommonParser::statement_terminator,
80 ));
81 let (remaining_input, (_, table, _, alter_options, partition_options, _)) = parser(i)?;
82 Ok((
83 remaining_input,
84 AlterTableStatement {
85 table,
86 alter_options,
87 partition_options,
88 },
89 ))
90 }
91}
92#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
96pub enum CheckOrConstraintType {
97 Check,
98 Constraint,
99}
100
101impl Display for CheckOrConstraintType {
102 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
103 match *self {
104 CheckOrConstraintType::Check => write!(f, "CHECK"),
105 CheckOrConstraintType::Constraint => write!(f, "CONSTRAINT"),
106 }
107 }
108}
109
110impl CheckOrConstraintType {
111 fn parse(i: &str) -> IResult<&str, CheckOrConstraintType, ParseSQLError<&str>> {
112 alt((
113 map(tag_no_case("CHECK"), |_| CheckOrConstraintType::Check),
114 map(tag_no_case("CONSTRAINT"), |_| {
115 CheckOrConstraintType::Constraint
116 }),
117 ))(i)
118 }
119}
120
121#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
122pub enum AlterTableOption {
123 TableOptions { table_options: Vec<TableOption> },
125
126 AddColumn {
130 opt_column: bool, columns: Vec<ColumnSpecification>,
132 },
133
134 AddIndexOrKey {
136 index_or_key: IndexOrKeyType, opt_index_name: Option<String>, opt_index_type: Option<IndexType>, key_part: Vec<KeyPart>, opt_index_option: Option<Vec<IndexOption>>, },
142
143 AddFulltextOrSpatial {
145 fulltext_or_spatial: FulltextOrSpatialType, opt_index_or_key: Option<IndexOrKeyType>, opt_index_name: Option<String>, key_part: Vec<KeyPart>, opt_index_option: Option<Vec<IndexOption>>, },
151
152 AddPrimaryKey {
154 opt_symbol: Option<String>, opt_index_type: Option<IndexType>, key_part: Vec<KeyPart>, opt_index_option: Option<Vec<IndexOption>>, },
159
160 AddUnique {
163 opt_symbol: Option<String>, opt_index_or_key: Option<IndexOrKeyType>, opt_index_name: Option<String>, opt_index_type: Option<IndexType>, key_part: Vec<KeyPart>, opt_index_option: Option<Vec<IndexOption>>, },
170
171 AddForeignKey {
174 opt_symbol: Option<String>, opt_index_name: Option<String>, columns: Vec<String>, reference_definition: ReferenceDefinition, },
179
180 AddCheck {
182 check_constraint: CheckConstraintDefinition,
183 },
184
185 DropCheckOrConstraint {
187 check_or_constraint: CheckOrConstraintType,
188 symbol: String,
189 },
190
191 AlterCheckOrConstraintEnforced {
193 check_or_constraint: CheckOrConstraintType,
194 symbol: String,
195 enforced: bool,
196 },
197
198 Algorithm { algorithm: AlgorithmType },
200
201 AlterColumn {
204 col_name: String,
205 alter_column_operation: AlertColumnOperation,
206 },
207
208 AlterIndexVisibility {
210 index_name: String,
211 visible: VisibleType,
212 },
213
214 ChangeColumn {
216 old_col_name: String,
217 column_definition: ColumnSpecification,
218 },
219
220 DefaultCharacterSet {
222 charset_name: String,
223 collation_name: Option<String>,
224 },
225
226 ConvertToCharacterSet {
228 charset_name: String,
229 collation_name: Option<String>,
230 },
231
232 DisableKeys,
234
235 EnableKeys,
237
238 DiscardTablespace,
240
241 ImportTablespace,
243
244 DropColumn { col_name: String },
246
247 DropIndexOrKey {
249 index_or_key: IndexOrKeyType,
250 index_name: String,
251 },
252
253 DropPrimaryKey,
255
256 DropForeignKey { fk_symbol: String },
258
259 Force,
261
262 Lock { lock_type: LockType },
264
265 ModifyColumn {
267 column_definition: ColumnSpecification,
268 },
269
270 OrderBy { columns: Vec<String> },
272
273 RenameColumn {
275 old_col_name: String,
276 new_col_name: String,
277 },
278
279 RenameIndexOrKey {
281 index_or_key: IndexOrKeyType,
282 old_index_name: String,
283 new_index_name: String,
284 },
285
286 RenameTable { new_tbl_name: String },
288
289 Validation { with_validation: bool },
291}
292
293impl Display for AlterTableOption {
294 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
295 match *self {
296 AlterTableOption::TableOptions { ref table_options } => {
297 write!(f, " {}", TableOption::format_list(table_options))
298 }
299 AlterTableOption::AddColumn {
300 ref opt_column,
301 ref columns,
302 } => {
303 if *opt_column {
304 write!(f, " ADD COLUMN");
305 }
306 let columns = columns
307 .iter()
308 .map(|x| x.to_string())
309 .collect::<Vec<String>>()
310 .join(", ");
311 write!(f, " ({})", columns);
312 Ok(())
313 }
314 AlterTableOption::AddIndexOrKey {
315 ref index_or_key,
316 ref opt_index_name,
317 ref opt_index_type,
318 ref key_part,
319 ref opt_index_option,
320 } => {
321 write!(f, " ADD {}", index_or_key);
322 if let Some(opt_index_name) = opt_index_name {
323 write!(f, " {}", opt_index_name);
324 }
325 if let Some(opt_index_type) = opt_index_type {
326 write!(f, " {}", opt_index_type);
327 }
328 write!(f, " {}", KeyPart::format_list(key_part));
329 if let Some(opt_index_option) = opt_index_option {
330 write!(f, " {}", IndexOption::format_list(opt_index_option));
331 }
332 Ok(())
333 }
334 AlterTableOption::AddFulltextOrSpatial {
335 ref fulltext_or_spatial,
336 ref opt_index_or_key,
337 ref opt_index_name,
338 ref key_part,
339 ref opt_index_option,
340 } => {
341 write!(f, " ADD {}", fulltext_or_spatial);
342 if let Some(opt_index_or_key) = opt_index_or_key {
343 write!(f, " {}", opt_index_or_key);
344 }
345 if let Some(opt_index_name) = opt_index_name {
346 write!(f, " {}", opt_index_name);
347 }
348 write!(f, " {}", KeyPart::format_list(key_part));
349 if let Some(opt_index_option) = opt_index_option {
350 write!(f, " {}", IndexOption::format_list(opt_index_option));
351 }
352 Ok(())
353 }
354 AlterTableOption::AddPrimaryKey {
355 ref opt_symbol,
356 ref opt_index_type,
357 ref key_part,
358 ref opt_index_option,
359 } => {
360 write!(f, "ADD");
361 if let Some(opt_symbol) = opt_symbol {
362 write!(f, " CONSTRAINT {}", opt_symbol);
363 }
364 write!(f, " PRIMARY KEY");
365 if let Some(opt_index_type) = opt_index_type {
366 write!(f, " {}", opt_index_type);
367 }
368 write!(f, " {}", KeyPart::format_list(key_part));
369 if let Some(opt_index_option) = opt_index_option {
370 write!(f, " {}", IndexOption::format_list(opt_index_option));
371 }
372 Ok(())
373 }
374 AlterTableOption::AddUnique {
375 ref opt_symbol,
376 ref opt_index_or_key,
377 ref opt_index_name,
378 ref opt_index_type,
379 ref key_part,
380 ref opt_index_option,
381 } => {
382 write!(f, "ADD");
383 if let Some(opt_symbol) = opt_symbol {
384 write!(f, " CONSTRAINT {}", opt_symbol);
385 }
386 write!(f, " UNIQUE");
387 if let Some(opt_index_or_key) = opt_index_or_key {
388 write!(f, " {}", opt_index_or_key);
389 }
390 if let Some(opt_index_name) = opt_index_name {
391 write!(f, " {}", opt_index_name);
392 }
393 if let Some(opt_index_type) = opt_index_type {
394 write!(f, " {}", opt_index_type);
395 }
396 write!(f, " {}", KeyPart::format_list(key_part));
397 if let Some(opt_index_option) = opt_index_option {
398 write!(f, " {}", IndexOption::format_list(opt_index_option));
399 }
400 Ok(())
401 }
402 AlterTableOption::AddForeignKey {
403 ref opt_symbol,
404 ref opt_index_name,
405 ref columns,
406 ref reference_definition,
407 } => {
408 write!(f, "ADD");
409 if let Some(opt_symbol) = opt_symbol {
410 write!(f, " CONSTRAINT {}", opt_symbol);
411 }
412 write!(f, " FOREIGN KEY");
413 if let Some(opt_index_name) = opt_index_name {
414 write!(f, " {}", opt_index_name);
415 }
416 write!(f, " ({})", columns.join(", "));
417 write!(f, " {}", reference_definition);
418 Ok(())
419 }
420 AlterTableOption::AddCheck {
421 ref check_constraint,
422 } => {
423 write!(f, " ADD {}", check_constraint)
424 }
425 AlterTableOption::DropCheckOrConstraint {
426 ref check_or_constraint,
427 ref symbol,
428 } => {
429 write!(f, "DROP {} {}", &check_or_constraint, &symbol)
430 }
431 AlterTableOption::AlterCheckOrConstraintEnforced {
432 ref check_or_constraint,
433 ref symbol,
434 ref enforced,
435 } => {
436 write!(f, "DROP {} {}", &check_or_constraint, &symbol);
437 if !*enforced {
438 write!(f, " NOT");
439 }
440 write!(f, " ENFORCED");
441 Ok(())
442 }
443 AlterTableOption::Algorithm { ref algorithm } => {
444 write!(f, " {}", algorithm)
445 }
446 AlterTableOption::AlterColumn {
447 ref col_name,
448 ref alter_column_operation,
449 } => {
450 write!(f, " ALTER {} {}", col_name, alter_column_operation)
451 }
452 AlterTableOption::AlterIndexVisibility {
453 ref index_name,
454 ref visible,
455 } => {
456 write!(f, " ALTER INDEX {} {}", index_name, visible)
457 }
458 AlterTableOption::ChangeColumn {
459 ref old_col_name,
460 ref column_definition,
461 } => {
462 write!(f, " CHANGE {} {}", old_col_name, column_definition)
463 }
464 AlterTableOption::DefaultCharacterSet {
465 ref charset_name,
466 ref collation_name,
467 } => {
468 write!(f, " CHARACTER SET {}", charset_name);
469 if let Some(collation_name) = collation_name {
470 write!(f, " COLLATE {}", collation_name);
471 }
472 Ok(())
473 }
474 AlterTableOption::ConvertToCharacterSet {
475 ref charset_name,
476 ref collation_name,
477 } => {
478 write!(f, " CONVERT TO CHARACTER SET {}", charset_name);
479 if let Some(collation_name) = collation_name {
480 write!(f, " COLLATE {}", collation_name);
481 }
482 Ok(())
483 }
484 AlterTableOption::DisableKeys => {
485 write!(f, " DISABLE KEYS")
486 }
487 AlterTableOption::EnableKeys => {
488 write!(f, " ENABLE KEYS")
489 }
490 AlterTableOption::DiscardTablespace => {
491 write!(f, " DISCARD TABLESPACE")
492 }
493 AlterTableOption::ImportTablespace => {
494 write!(f, " IMPORT TABLESPACE")
495 }
496 AlterTableOption::DropColumn { ref col_name } => {
497 write!(f, " DROP {}", col_name)
498 }
499 AlterTableOption::DropIndexOrKey {
500 ref index_or_key,
501 ref index_name,
502 } => {
503 write!(f, " DROP {} {}", index_or_key, index_name)
504 }
505 AlterTableOption::DropPrimaryKey => {
506 write!(f, " DROP PRIMARY KEY")
507 }
508 AlterTableOption::DropForeignKey { ref fk_symbol } => {
509 write!(f, " DROP FOREIGN KEY {}", fk_symbol)
510 }
511 AlterTableOption::Force => {
512 write!(f, " FORCE")
513 }
514 AlterTableOption::Lock { ref lock_type } => {
515 write!(f, " LOCK {}", lock_type)
516 }
517 AlterTableOption::ModifyColumn {
518 ref column_definition,
519 } => {
520 write!(f, " MODIFY {}", column_definition)
521 }
522 AlterTableOption::OrderBy { ref columns } => {
523 let columns = columns.join(", ");
524 write!(f, " ORDER BY {}", columns)
525 }
526 AlterTableOption::RenameColumn {
527 ref old_col_name,
528 ref new_col_name,
529 } => {
530 write!(f, " RENAME COLUMN {} {}", old_col_name, new_col_name)
531 }
532 AlterTableOption::RenameIndexOrKey {
533 ref index_or_key,
534 ref old_index_name,
535 ref new_index_name,
536 } => {
537 write!(
538 f,
539 " RENAME {} {} TO {}",
540 index_or_key, old_index_name, new_index_name
541 )
542 }
543 AlterTableOption::RenameTable { ref new_tbl_name } => {
544 write!(f, " RENAME TO {}", new_tbl_name)
545 }
546 AlterTableOption::Validation {
547 ref with_validation,
548 } => {
549 if *with_validation {
550 write!(f, " WITH");
551 } else {
552 write!(f, " WITHOUT");
553 }
554 write!(f, " VALIDATION");
555 Ok(())
556 }
557 }
558 }
559}
560
561impl AlterTableOption {
562 fn parse(i: &str) -> IResult<&str, AlterTableOption, ParseSQLError<&str>> {
563 let mut parser = alt((
564 Self::alter_table_options,
565 Self::alter_option_part_1,
566 Self::alter_option_part_2,
567 ));
568 let (remaining_input, res) = parser(i)?;
569 Ok((remaining_input, res))
570 }
571
572 pub fn format_list(list: &[AlterTableOption]) -> String {
573 list.iter()
574 .map(|x| x.to_string())
575 .collect::<Vec<String>>()
576 .join(", ")
577 }
578
579 pub fn alter_table_options(i: &str) -> IResult<&str, AlterTableOption, ParseSQLError<&str>> {
582 map(
583 many1(terminated(
584 TableOption::parse,
585 opt(CommonParser::ws_sep_comma),
586 )),
587 |table_options| AlterTableOption::TableOptions { table_options },
588 )(i)
589 }
590
591 fn alter_option_part_1(i: &str) -> IResult<&str, AlterTableOption, ParseSQLError<&str>> {
592 alt((
593 Self::add_column,
594 Self::add_index_or_key,
595 Self::add_fulltext_or_spatial,
596 Self::add_primary_key,
597 Self::add_unique,
598 Self::add_foreign_key,
599 Self::add_check,
600 Self::drop_check_or_constraint,
601 Self::alter_check_or_constraint_enforced,
602 map(AlgorithmType::parse, |x| AlterTableOption::Algorithm {
603 algorithm: x,
604 }),
605 Self::alter_column,
606 Self::alter_index_visibility,
607 Self::change_column,
608 Self::default_character_set,
609 ))(i)
610 }
611
612 fn alter_option_part_2(i: &str) -> IResult<&str, AlterTableOption, ParseSQLError<&str>> {
613 alt((
614 Self::convert_to_character_set,
615 Self::disable_or_enable_keys,
616 Self::discard_or_import_tablespace,
617 Self::drop_column,
618 Self::drop_index_or_key,
619 Self::drop_primary_key,
620 Self::drop_foreign_key,
621 Self::force,
622 Self::lock,
623 Self::modify_column,
624 Self::order_by,
625 Self::rename_column,
626 Self::rename_index_or_key,
627 Self::rename_table,
628 Self::without_or_with_validation,
629 ))(i)
630 }
631
632 fn opt_constraint_with_opt_symbol_and_operation(
634 i: &str,
635 ) -> IResult<&str, Option<String>, ParseSQLError<&str>> {
636 map(
637 tuple((
638 tag_no_case("ADD"),
639 opt(preceded(
640 tuple((multispace1, tag_no_case("CONSTRAINT"))),
641 opt(preceded(multispace1, CommonParser::sql_identifier)),
642 )),
643 )),
644 |(_, x)| x.and_then(|inner| inner.map(String::from)),
645 )(i)
646 }
647
648 fn add_column(i: &str) -> IResult<&str, AlterTableOption, ParseSQLError<&str>> {
652 map(
653 tuple((
654 tag_no_case("ADD"),
655 alt((
656 map(
657 tuple((
658 multispace1,
659 tag_no_case("COLUMN"),
660 multispace1,
661 ColumnSpecification::parse,
662 multispace0,
663 )),
664 |x| (true, vec![x.3]),
665 ),
666 map(
667 tuple((
668 multispace1,
669 tag_no_case("COLUMN"),
670 multispace0,
671 tag("("),
672 multispace0,
673 many1(ColumnSpecification::parse),
674 multispace0,
675 tag(")"),
676 )),
677 |x| (true, x.5),
678 ),
679 map(tuple((multispace0, ColumnSpecification::parse)), |x| {
680 (false, vec![x.1])
681 }),
682 map(
683 tuple((
684 multispace0,
685 tag("("),
686 multispace0,
687 many1(ColumnSpecification::parse),
688 multispace0,
689 tag(")"),
690 )),
691 |x| (false, x.3),
692 ),
693 )),
694 )),
695 |(_, (opt_column, columns))| AlterTableOption::AddColumn {
696 opt_column,
697 columns,
698 },
699 )(i)
700 }
701
702 fn add_index_or_key(i: &str) -> IResult<&str, AlterTableOption, ParseSQLError<&str>> {
704 map(
705 tuple((
706 tuple((tag_no_case("ADD"), multispace1)),
707 IndexOrKeyType::parse,
709 CommonParser::opt_index_name,
711 IndexType::opt_index_type,
713 KeyPart::parse,
715 IndexOption::opt_index_option,
717 )),
718 |(_, index_or_key, opt_index_name, opt_index_type, key_part, opt_index_option)| {
719 AlterTableOption::AddIndexOrKey {
720 index_or_key,
721 opt_index_name,
722 opt_index_type,
723 key_part,
724 opt_index_option,
725 }
726 },
727 )(i)
728 }
729
730 fn add_fulltext_or_spatial(i: &str) -> IResult<&str, AlterTableOption, ParseSQLError<&str>> {
732 map(
733 tuple((
734 tuple((tag_no_case("ADD"), multispace1)),
735 FulltextOrSpatialType::parse,
737 preceded(multispace1, opt(IndexOrKeyType::parse)),
739 CommonParser::opt_index_name,
741 KeyPart::parse,
743 IndexOption::opt_index_option,
745 )),
746 |(_, fulltext_or_spatial, index_or_key, opt_index_name, key_part, opt_index_option)| {
747 AlterTableOption::AddFulltextOrSpatial {
748 fulltext_or_spatial,
749 opt_index_or_key: index_or_key,
750 opt_index_name,
751 key_part,
752 opt_index_option,
753 }
754 },
755 )(i)
756 }
757
758 fn add_primary_key(i: &str) -> IResult<&str, AlterTableOption, ParseSQLError<&str>> {
760 map(
761 tuple((
762 Self::opt_constraint_with_opt_symbol_and_operation,
764 tuple((
766 multispace0,
767 tag_no_case("PRIMARY"),
768 multispace1,
769 tag_no_case("KEY"),
770 )),
771 IndexType::opt_index_type,
773 KeyPart::parse,
775 IndexOption::opt_index_option,
777 )),
778 |(opt_symbol, _, opt_index_type, key_part, opt_index_option)| {
779 AlterTableOption::AddPrimaryKey {
780 opt_symbol,
781 opt_index_type,
782 key_part,
783 opt_index_option,
784 }
785 },
786 )(i)
787 }
788
789 fn add_unique(i: &str) -> IResult<&str, AlterTableOption, ParseSQLError<&str>> {
792 map(
793 tuple((
794 Self::opt_constraint_with_opt_symbol_and_operation,
796 map(
798 tuple((
799 multispace0,
800 tag_no_case("UNIQUE"),
801 multispace1,
802 opt(alt((
803 map(tag_no_case("INDEX"), |_| IndexOrKeyType::Index),
804 map(tag_no_case("KEY"), |_| IndexOrKeyType::Key),
805 ))),
806 )),
807 |(_, _, _, value)| value,
808 ),
809 CommonParser::opt_index_name,
811 IndexType::opt_index_type,
813 KeyPart::parse,
815 IndexOption::opt_index_option,
817 )),
818 |(
819 opt_symbol,
820 opt_index_or_key,
821 opt_index_name,
822 opt_index_type,
823 key_part,
824 opt_index_option,
825 )| {
826 AlterTableOption::AddUnique {
827 opt_symbol,
828 opt_index_or_key,
829 opt_index_name,
830 opt_index_type,
831 key_part,
832 opt_index_option,
833 }
834 },
835 )(i)
836 }
837
838 fn add_foreign_key(i: &str) -> IResult<&str, AlterTableOption, ParseSQLError<&str>> {
841 map(
842 tuple((
843 Self::opt_constraint_with_opt_symbol_and_operation,
845 tuple((
847 multispace0,
848 tag_no_case("FOREIGN"),
849 multispace1,
850 tag_no_case("KEY"),
851 )),
852 CommonParser::opt_index_name,
854 map(
856 tuple((
857 multispace0,
858 delimited(
859 tag("("),
860 delimited(multispace0, Column::index_col_list, multispace0),
861 tag(")"),
862 ),
863 )),
864 |(_, value)| value.iter().map(|x| x.name.clone()).collect(),
865 ),
866 ReferenceDefinition::parse,
868 )),
869 |(opt_symbol, _, opt_index_name, columns, reference_definition)| {
870 AlterTableOption::AddForeignKey {
871 opt_symbol,
872 opt_index_name,
873 columns,
874 reference_definition,
875 }
876 },
877 )(i)
878 }
879
880 fn add_check(i: &str) -> IResult<&str, AlterTableOption, ParseSQLError<&str>> {
882 map(
883 tuple((
884 Self::opt_constraint_with_opt_symbol_and_operation,
886 tuple((multispace1, tag_no_case("CHECK"), multispace0)),
888 map(delimited(tag("("), take_until(")"), tag(")")), |expr| {
890 String::from(expr)
891 }),
892 map(
894 opt(tuple((
895 multispace0,
896 opt(tag_no_case("NOT")),
897 multispace1,
898 tag_no_case("ENFORCED"),
899 multispace0,
900 ))),
901 |x| x.map_or(true, |(_, opt_not, _, _, _)| opt_not.is_none()),
902 ),
903 )),
904 |(symbol, _, expr, enforced)| AlterTableOption::AddCheck {
905 check_constraint: CheckConstraintDefinition {
906 symbol,
907 expr,
908 enforced,
909 },
910 },
911 )(i)
912 }
913
914 fn drop_check_or_constraint(i: &str) -> IResult<&str, AlterTableOption, ParseSQLError<&str>> {
916 map(
917 tuple((
918 tuple((tag_no_case("DROP"), multispace1)),
919 CheckOrConstraintType::parse,
921 map(
923 tuple((multispace1, CommonParser::sql_identifier, multispace0)),
924 |(_, symbol, _)| String::from(symbol),
925 ),
926 )),
927 |(_, check_or_constraint, symbol)| AlterTableOption::DropCheckOrConstraint {
928 check_or_constraint,
929 symbol,
930 },
931 )(i)
932 }
933
934 fn alter_check_or_constraint_enforced(
936 i: &str,
937 ) -> IResult<&str, AlterTableOption, ParseSQLError<&str>> {
938 map(
939 tuple((
940 tuple((tag_no_case("ALTER"), multispace1)),
941 CheckOrConstraintType::parse,
943 map(
945 tuple((multispace1, CommonParser::sql_identifier, multispace1)),
946 |(_, symbol, _)| String::from(symbol),
947 ),
948 opt(tag_no_case("NOT ")),
949 tuple((multispace0, tag_no_case("ENFORCED"))),
950 )),
951 |(_, check_or_constraint, symbol, opt_not, _)| {
952 AlterTableOption::AlterCheckOrConstraintEnforced {
953 check_or_constraint,
954 symbol,
955 enforced: opt_not.is_none(),
956 }
957 },
958 )(i)
959 }
960
961 fn alter_column(i: &str) -> IResult<&str, AlterTableOption, ParseSQLError<&str>> {
967 map(
968 tuple((
969 tag_no_case("ALTER "),
970 multispace0,
971 opt(tag_no_case("COLUMN ")),
972 map(
974 tuple((multispace0, CommonParser::sql_identifier, multispace1)),
975 |(_, col_name, _)| String::from(col_name),
976 ),
977 AlertColumnOperation::parse,
978 multispace0,
979 )),
980 |(_, _, _, col_name, alter_column_operation, _)| AlterTableOption::AlterColumn {
981 col_name,
982 alter_column_operation,
983 },
984 )(i)
985 }
986
987 fn alter_index_visibility(i: &str) -> IResult<&str, AlterTableOption, ParseSQLError<&str>> {
989 map(
990 tuple((
991 tag_no_case("ALTER "),
992 multispace0,
993 opt(tag_no_case("INDEX ")),
994 map(
996 tuple((multispace0, CommonParser::sql_identifier, multispace1)),
997 |(_, col_name, _)| String::from(col_name),
998 ),
999 VisibleType::parse,
1000 multispace0,
1001 )),
1002 |(_, _, _, index_name, visible, _)| AlterTableOption::AlterIndexVisibility {
1003 index_name,
1004 visible,
1005 },
1006 )(i)
1007 }
1008
1009 fn change_column(i: &str) -> IResult<&str, AlterTableOption, ParseSQLError<&str>> {
1011 map(
1012 tuple((
1013 tag_no_case("CHANGE "),
1014 multispace0,
1015 opt(tag_no_case("COLUMN ")),
1016 multispace0,
1017 map(CommonParser::sql_identifier, String::from),
1019 multispace1,
1020 ColumnSpecification::parse,
1021 multispace0,
1022 )),
1023 |(_, _, _, _, old_col_name, _, column_definition, _)| AlterTableOption::ChangeColumn {
1024 old_col_name,
1025 column_definition,
1026 },
1027 )(i)
1028 }
1029
1030 fn default_character_set(i: &str) -> IResult<&str, AlterTableOption, ParseSQLError<&str>> {
1032 map(
1033 tuple((
1034 opt(tag_no_case("DEFAULT ")),
1035 multispace0,
1036 tuple((
1037 multispace0,
1038 tag_no_case("CHARACTER"),
1039 multispace1,
1040 tag_no_case("SET"),
1041 multispace0,
1042 opt(tag("=")),
1043 multispace0,
1044 )),
1045 map(CommonParser::sql_identifier, String::from),
1046 multispace0,
1047 opt(map(
1048 tuple((
1049 multispace0,
1050 tag_no_case("COLLATE"),
1051 multispace1,
1052 CommonParser::sql_identifier,
1053 )),
1054 |(_, _, _, collation_name)| String::from(collation_name),
1055 )),
1056 )),
1057 |(_, _, _, charset_name, _, collation_name)| AlterTableOption::DefaultCharacterSet {
1058 charset_name,
1059 collation_name,
1060 },
1061 )(i)
1062 }
1063
1064 fn convert_to_character_set(i: &str) -> IResult<&str, AlterTableOption, ParseSQLError<&str>> {
1066 let prefix = tuple((
1067 tag_no_case("CONVERT"),
1068 multispace1,
1069 tag_no_case("TO"),
1070 multispace1,
1071 tag_no_case("CHARACTER"),
1072 multispace1,
1073 tag_no_case("SET"),
1074 multispace1,
1075 ));
1076 map(
1077 tuple((
1078 prefix,
1080 map(CommonParser::sql_identifier, String::from),
1081 multispace0,
1082 opt(map(
1083 tuple((
1084 multispace0,
1085 tag_no_case("COLLATE"),
1086 multispace1,
1087 CommonParser::sql_identifier,
1088 )),
1089 |(_, _, _, collation_name)| String::from(collation_name),
1090 )),
1091 )),
1092 |(_, charset_name, _, collation_name)| AlterTableOption::ConvertToCharacterSet {
1093 charset_name,
1094 collation_name,
1095 },
1096 )(i)
1097 }
1098
1099 fn disable_or_enable_keys(i: &str) -> IResult<&str, AlterTableOption, ParseSQLError<&str>> {
1101 map(
1102 tuple((
1103 alt((
1104 map(tag_no_case("DISABLE"), |_| AlterTableOption::DisableKeys),
1105 map(tag_no_case("ENABLE"), |_| AlterTableOption::EnableKeys),
1106 )),
1107 multispace1,
1108 tag_no_case("KEYS"),
1109 multispace0,
1110 )),
1111 |(operation, _, _, _)| operation,
1112 )(i)
1113 }
1114
1115 fn discard_or_import_tablespace(
1117 i: &str,
1118 ) -> IResult<&str, AlterTableOption, ParseSQLError<&str>> {
1119 map(
1120 tuple((
1121 alt((
1122 map(tag_no_case("DISCARD"), |_| {
1123 AlterTableOption::DiscardTablespace
1124 }),
1125 map(tag_no_case("IMPORT"), |_| {
1126 AlterTableOption::ImportTablespace
1127 }),
1128 )),
1129 multispace1,
1130 tag_no_case("TABLESPACE"),
1131 multispace0,
1132 )),
1133 |(operation, _, _, _)| operation,
1134 )(i)
1135 }
1136
1137 fn drop_column(i: &str) -> IResult<&str, AlterTableOption, ParseSQLError<&str>> {
1139 map(
1140 tuple((
1141 tag_no_case("DROP "),
1142 multispace0,
1143 opt(tag_no_case("COLUMN ")),
1144 map(
1146 tuple((multispace0, CommonParser::sql_identifier, multispace0)),
1147 |(_, col_name, _)| String::from(col_name),
1148 ),
1149 multispace0,
1150 )),
1151 |(_, _, _, col_name, _)| AlterTableOption::DropColumn { col_name },
1152 )(i)
1153 }
1154
1155 fn drop_index_or_key(i: &str) -> IResult<&str, AlterTableOption, ParseSQLError<&str>> {
1157 map(
1158 tuple((
1159 tuple((tag_no_case("DROP"), multispace1)),
1160 IndexOrKeyType::parse,
1162 map(
1164 tuple((multispace1, CommonParser::sql_identifier, multispace0)),
1165 |(_, index_name, _)| String::from(index_name),
1166 ),
1167 multispace0,
1168 )),
1169 |(_, index_or_key, index_name, _)| AlterTableOption::DropIndexOrKey {
1170 index_or_key,
1171 index_name,
1172 },
1173 )(i)
1174 }
1175
1176 fn drop_primary_key(i: &str) -> IResult<&str, AlterTableOption, ParseSQLError<&str>> {
1178 map(
1179 tuple((
1180 tag_no_case("DROP"),
1181 multispace1,
1182 tag_no_case("PRIMARY"),
1183 multispace1,
1184 tag_no_case("KEY"),
1185 multispace0,
1186 )),
1187 |_| AlterTableOption::DropPrimaryKey,
1188 )(i)
1189 }
1190
1191 fn drop_foreign_key(i: &str) -> IResult<&str, AlterTableOption, ParseSQLError<&str>> {
1193 map(
1194 tuple((
1195 tag_no_case("DROP"),
1196 multispace1,
1197 tag_no_case("FOREIGN"),
1198 multispace1,
1199 tag_no_case("KEY"),
1200 multispace1,
1201 map(CommonParser::sql_identifier, String::from),
1202 multispace0,
1203 )),
1204 |x| AlterTableOption::DropForeignKey { fk_symbol: x.6 },
1205 )(i)
1206 }
1207
1208 fn force(i: &str) -> IResult<&str, AlterTableOption, ParseSQLError<&str>> {
1210 map(tuple((tag_no_case("FORCE"), multispace0)), |_| {
1211 AlterTableOption::Force
1212 })(i)
1213 }
1214
1215 fn lock(i: &str) -> IResult<&str, AlterTableOption, ParseSQLError<&str>> {
1217 map(LockType::parse, |(lock_type)| AlterTableOption::Lock {
1218 lock_type,
1219 })(i)
1220 }
1221
1222 fn modify_column(i: &str) -> IResult<&str, AlterTableOption, ParseSQLError<&str>> {
1224 map(
1225 tuple((
1226 tag_no_case("MODIFY "),
1227 multispace0,
1228 opt(tag_no_case("COLUMN ")),
1229 multispace0,
1230 ColumnSpecification::parse,
1231 multispace0,
1232 )),
1233 |(_, _, _, _, column_definition, _)| AlterTableOption::ModifyColumn {
1234 column_definition,
1235 },
1236 )(i)
1237 }
1238
1239 fn order_by(i: &str) -> IResult<&str, AlterTableOption, ParseSQLError<&str>> {
1241 map(
1242 tuple((
1243 tag_no_case("ORDER"),
1244 multispace1,
1245 tag_no_case("BY"),
1246 multispace1,
1247 many0(map(
1248 terminated(Column::without_alias, opt(CommonParser::ws_sep_comma)),
1249 |e| e.name,
1250 )),
1251 multispace0,
1252 )),
1253 |(_, _, _, _, columns, _)| AlterTableOption::OrderBy { columns },
1254 )(i)
1255 }
1256
1257 fn rename_column(i: &str) -> IResult<&str, AlterTableOption, ParseSQLError<&str>> {
1259 map(
1260 tuple((
1261 tag_no_case("RENAME "),
1262 multispace0,
1263 opt(tag_no_case("COLUMN ")),
1264 multispace0,
1265 map(CommonParser::sql_identifier, String::from),
1267 multispace1,
1268 tag_no_case("TO"),
1269 multispace1,
1270 map(CommonParser::sql_identifier, String::from),
1272 multispace0,
1273 )),
1274 |(_, _, _, _, old_col_name, _, _, _, new_col_name, _)| AlterTableOption::RenameColumn {
1275 old_col_name,
1276 new_col_name,
1277 },
1278 )(i)
1279 }
1280
1281 fn rename_index_or_key(i: &str) -> IResult<&str, AlterTableOption, ParseSQLError<&str>> {
1283 map(
1284 tuple((
1285 tuple((tag_no_case("RENAME"), multispace1)),
1286 IndexOrKeyType::parse,
1288 map(
1290 tuple((multispace1, CommonParser::sql_identifier, multispace1)),
1291 |(_, index_name, _)| String::from(index_name),
1292 ),
1293 tuple((multispace1, tag_no_case("TO"))),
1294 map(
1296 tuple((multispace1, CommonParser::sql_identifier, multispace1)),
1297 |(_, index_name, _)| String::from(index_name),
1298 ),
1299 multispace0,
1300 )),
1301 |(_, index_or_key, old_index_name, _, new_index_name, _)| {
1302 AlterTableOption::RenameIndexOrKey {
1303 index_or_key,
1304 old_index_name,
1305 new_index_name,
1306 }
1307 },
1308 )(i)
1309 }
1310
1311 fn rename_table(i: &str) -> IResult<&str, AlterTableOption, ParseSQLError<&str>> {
1313 map(
1314 tuple((
1315 tuple((tag_no_case("RENAME"), multispace1)),
1316 alt((tag_no_case("TO"), tag_no_case("AS"))),
1318 map(
1320 tuple((multispace1, CommonParser::sql_identifier, multispace0)),
1321 |(_, index_name, _)| String::from(index_name),
1322 ),
1323 multispace0,
1324 )),
1325 |x| AlterTableOption::RenameTable { new_tbl_name: x.2 },
1326 )(i)
1327 }
1328
1329 fn without_or_with_validation(i: &str) -> IResult<&str, AlterTableOption, ParseSQLError<&str>> {
1331 map(
1332 tuple((
1333 alt((
1335 map(tag_no_case("WITHOUT"), |_| false),
1336 map(tag_no_case("WITH"), |_| true),
1337 )),
1338 multispace1,
1339 tag_no_case("VALIDATION"),
1340 multispace0,
1341 )),
1342 |x| AlterTableOption::Validation {
1343 with_validation: x.0,
1344 },
1345 )(i)
1346 }
1347}
1348
1349#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
1351pub enum AlertColumnOperation {
1352 SetDefaultLiteral(String),
1353 SetDefaultExpr(String),
1354 SetVisible(VisibleType),
1355 DropDefault,
1356}
1357
1358impl Display for AlertColumnOperation {
1359 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1360 match *self {
1361 AlertColumnOperation::SetDefaultLiteral(ref val) => write!(f, "SET DEFAULT {}", val),
1362 AlertColumnOperation::SetDefaultExpr(ref val) => write!(f, "SET DEFAULT ({})", val),
1363 AlertColumnOperation::SetVisible(ref val) => write!(f, "SET {}", val),
1364 AlertColumnOperation::DropDefault => write!(f, "DROP DEFAULT"),
1365 }
1366 }
1367}
1368
1369impl AlertColumnOperation {
1370 fn parse(i: &str) -> IResult<&str, AlertColumnOperation, ParseSQLError<&str>> {
1371 alt((
1372 map(
1373 tuple((
1374 tag_no_case("SET"),
1375 multispace1,
1376 tag_no_case("DEFAULT"),
1377 multispace1,
1378 alt((
1379 map(
1380 alt((recognize(tuple((opt(tag("-")), digit1))), alphanumeric1)),
1381 |x| AlertColumnOperation::SetDefaultLiteral(String::from(x)),
1382 ),
1383 map(
1384 delimited(tag("("), recognize(many1(anychar)), tag(")")),
1385 |x| AlertColumnOperation::SetDefaultExpr(String::from(x)),
1386 ),
1387 )),
1388 multispace0,
1389 )),
1390 |x| x.4,
1391 ),
1392 map(
1393 tuple((
1394 tag_no_case("SET"),
1395 multispace1,
1396 VisibleType::parse,
1397 multispace0,
1398 )),
1399 |x| AlertColumnOperation::SetVisible(x.2),
1400 ),
1401 map(
1402 tuple((
1403 tag_no_case("DROP"),
1404 multispace1,
1405 tag_no_case("DEFAULT"),
1406 multispace0,
1407 )),
1408 |_| AlertColumnOperation::DropDefault,
1409 ),
1410 ))(i)
1411 }
1412}
1413
1414#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
1416pub enum AlterPartitionOption {
1417 None,
1418 AddPartition(PartitionDefinition),
1419 DropPartition(String),
1420 DiscardPartition,
1421 ImportPartition,
1422 TruncatePartition,
1423 CoalescePartition,
1424 ReorganizePartitionInto,
1425 ExchangePartitionWithTable,
1426 AnalyzePartition,
1427 CheckPartition,
1428 OptimizePartition,
1429 RebuildPartition,
1430 RepairPartition,
1431 RemovePartitioning,
1432}
1433
1434impl AlterPartitionOption {
1435 fn format_list(list: &[AlterPartitionOption]) -> String {
1436 list.iter()
1437 .map(|x| x.to_string())
1438 .collect::<Vec<String>>()
1439 .join("")
1440 }
1441}
1442
1443impl Display for AlterPartitionOption {
1444 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1445 write!(f, "")
1446 }
1447}
1448
1449impl AlterPartitionOption {
1450 pub fn parse(i: &str) -> IResult<&str, AlterPartitionOption, ParseSQLError<&str>> {
1451 map(tag_no_case(""), |_| AlterPartitionOption::None)(i)
1452 }
1453}
1454#[cfg(test)]
1457mod tests {
1458 use base::column::{ColumnConstraint, ColumnPosition, ColumnSpecification};
1459 use base::fulltext_or_spatial_type::FulltextOrSpatialType;
1460 use base::index_option::IndexOption;
1461 use base::index_or_key_type::IndexOrKeyType;
1462 use base::visible_type::VisibleType;
1463 use base::{CheckConstraintDefinition, DataType, KeyPart, KeyPartType, Literal};
1464 use dds::alter_table::AlterTableOption;
1465
1466 #[test]
1467 fn parse_add_column() {
1468 let parts = [
1469 "ADD COLUMN column7 ENUM('small', 'medium', 'large') FIRST",
1470 "ADD COLUMN new_column5 TEXT COMMENT 'This is a comment' AFTER existing_column;",
1471 "ADD column6 TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP;",
1472 ];
1473 let exps = [
1474 AlterTableOption::AddColumn {
1475 opt_column: true,
1476 columns: vec![ColumnSpecification {
1477 column: "column7".into(),
1478 data_type: DataType::Enum(vec![
1479 Literal::String("small".to_string()),
1480 Literal::String("medium".to_string()),
1481 Literal::String("large".to_string()),
1482 ]),
1483 constraints: vec![],
1484 comment: None,
1485 position: Some(ColumnPosition::First),
1486 }],
1487 },
1488 AlterTableOption::AddColumn {
1489 opt_column: true,
1490 columns: vec![ColumnSpecification {
1491 column: "new_column5".into(),
1492 data_type: DataType::Text,
1493 constraints: vec![],
1494 comment: Some("This is a comment".to_string()),
1495 position: Some(ColumnPosition::After("existing_column".into())),
1496 }],
1497 },
1498 AlterTableOption::AddColumn {
1499 opt_column: false,
1500 columns: vec![ColumnSpecification {
1501 column: "column6".into(),
1502 data_type: DataType::Timestamp,
1503 constraints: vec![
1504 ColumnConstraint::DefaultValue(Literal::CurrentTimestamp),
1505 ColumnConstraint::OnUpdate(Literal::CurrentTimestamp),
1506 ],
1507 comment: None,
1508 position: None,
1509 }],
1510 },
1511 ];
1512 for i in 0..parts.len() {
1513 let res = AlterTableOption::add_column(parts[i]);
1514 assert!(res.is_ok());
1515 assert_eq!(res.unwrap().1, exps[i])
1516 }
1517 }
1518
1519 #[test]
1520 fn parse_add_index_or_key() {
1521 let parts = [
1522 "ADD INDEX index_name (column_name);",
1523 "ADD KEY index_name (column_name) INVISIBLE COMMENT 'This is an index comment';",
1524 ];
1525 let exps = [
1526 AlterTableOption::AddIndexOrKey {
1527 index_or_key: IndexOrKeyType::Index,
1528 opt_index_name: Some("index_name".to_string()),
1529 opt_index_type: None,
1530 key_part: vec![KeyPart {
1531 r#type: KeyPartType::ColumnNameWithLength {
1532 col_name: "column_name".to_string(),
1533 length: None,
1534 },
1535 order: None,
1536 }],
1537 opt_index_option: None,
1538 },
1539 AlterTableOption::AddIndexOrKey {
1540 index_or_key: IndexOrKeyType::Key,
1541 opt_index_name: Some("index_name".to_string()),
1542 opt_index_type: None,
1543 key_part: vec![KeyPart {
1544 r#type: KeyPartType::ColumnNameWithLength {
1545 col_name: "column_name".to_string(),
1546 length: None,
1547 },
1548 order: None,
1549 }],
1550 opt_index_option: Some(vec![
1551 IndexOption::VisibleType(VisibleType::Invisible),
1552 IndexOption::Comment("This is an index comment".to_string()),
1553 ]),
1554 },
1555 ];
1556 for i in 0..parts.len() {
1557 let res = AlterTableOption::add_index_or_key(parts[i]);
1558 assert!(res.is_ok());
1559 assert_eq!(res.unwrap().1, exps[i]);
1560 }
1561 }
1562
1563 #[test]
1564 fn parse_add_fulltext_or_spatial() {
1565 let parts = [
1566 "ADD FULLTEXT INDEX ft_index_name (column_name);",
1567 "ADD FULLTEXT INDEX ft_index_name (column_name) \
1568 KEY_BLOCK_SIZE=1024 COMMENT 'Fulltext index on column_name' WITH PARSER ngram VISIBLE;",
1569 ];
1570 let exps = [
1571 AlterTableOption::AddFulltextOrSpatial {
1572 fulltext_or_spatial: FulltextOrSpatialType::Fulltext,
1573 opt_index_or_key: Some(IndexOrKeyType::Index),
1574 opt_index_name: Some("ft_index_name".to_string()),
1575 key_part: vec![KeyPart {
1576 r#type: KeyPartType::ColumnNameWithLength {
1577 col_name: "column_name".to_string(),
1578 length: None,
1579 },
1580 order: None,
1581 }],
1582 opt_index_option: None,
1583 },
1584 AlterTableOption::AddFulltextOrSpatial {
1585 fulltext_or_spatial: FulltextOrSpatialType::Fulltext,
1586 opt_index_or_key: Some(IndexOrKeyType::Index),
1587 opt_index_name: Some("ft_index_name".to_string()),
1588 key_part: vec![KeyPart {
1589 r#type: KeyPartType::ColumnNameWithLength {
1590 col_name: "column_name".to_string(),
1591 length: None,
1592 },
1593 order: None,
1594 }],
1595 opt_index_option: Some(vec![
1596 IndexOption::KeyBlockSize(1024),
1597 IndexOption::Comment("Fulltext index on column_name".to_string()),
1598 IndexOption::WithParser("ngram".to_string()),
1599 IndexOption::VisibleType(VisibleType::Visible),
1600 ]),
1601 },
1602 ];
1603 for i in 0..parts.len() {
1604 let res = AlterTableOption::add_fulltext_or_spatial(parts[i]);
1605 assert!(res.is_ok());
1606 assert_eq!(res.unwrap().1, exps[i]);
1607 }
1608 }
1609
1610 #[test]
1611 fn parse_add_unique() {
1612 let parts = ["ADD CONSTRAINT UNIQUE (col_19)"];
1613 let exps = [AlterTableOption::AddUnique {
1614 opt_symbol: None,
1615 opt_index_or_key: None,
1616 opt_index_name: None,
1617 opt_index_type: None,
1618 key_part: vec![KeyPart {
1619 r#type: KeyPartType::ColumnNameWithLength {
1620 col_name: "col_19".to_string(),
1621 length: None,
1622 },
1623 order: None,
1624 }],
1625 opt_index_option: None,
1626 }];
1627 for i in 0..parts.len() {
1628 let res = AlterTableOption::add_unique(parts[i]);
1629 assert!(res.is_ok());
1630 assert_eq!(res.unwrap().1, exps[i]);
1631 }
1632 }
1633
1634 #[test]
1635 fn parse_convert_to_character_set() {
1636 let parts = ["CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci"];
1637 let exps = [AlterTableOption::ConvertToCharacterSet {
1638 charset_name: "utf8mb4".to_string(),
1639 collation_name: Some("utf8mb4_unicode_ci".to_string()),
1640 }];
1641 for i in 0..parts.len() {
1642 let res = AlterTableOption::convert_to_character_set(parts[i]);
1643 assert!(res.is_ok());
1644 assert_eq!(res.unwrap().1, exps[i]);
1645 }
1646 }
1647
1648 #[test]
1649 fn parse_add_primary_key() {
1650 let parts = ["ADD PRIMARY KEY (new_column)"];
1651 let exps = [AlterTableOption::AddPrimaryKey {
1652 opt_symbol: None,
1653 opt_index_option: None,
1654 key_part: vec![KeyPart {
1655 r#type: KeyPartType::ColumnNameWithLength {
1656 col_name: "new_column".to_string(),
1657 length: None,
1658 },
1659 order: None,
1660 }],
1661 opt_index_type: None,
1662 }];
1663 for i in 0..parts.len() {
1664 let res = AlterTableOption::add_primary_key(parts[i]);
1665 assert!(res.is_ok());
1666 assert_eq!(res.unwrap().1, exps[i]);
1667 }
1668 }
1669
1670 #[test]
1671 fn parse_add_check() {
1672 let parts = ["ADD CONSTRAINT chk_column CHECK (new_column > 0) NOT ENFORCED;"];
1673 let exps = [AlterTableOption::AddCheck {
1674 check_constraint: CheckConstraintDefinition {
1675 symbol: Some("chk_column".to_string()),
1676 expr: "new_column > 0".to_string(),
1677 enforced: false,
1678 },
1679 }];
1680 for i in 0..parts.len() {
1681 let res = AlterTableOption::add_check(parts[i]);
1682 assert!(res.is_ok());
1683 assert_eq!(res.unwrap().1, exps[i]);
1684 }
1685 }
1686
1687 #[test]
1688 fn parse_modify_column() {
1689 let parts = ["MODIFY COLUMN another_column VARCHAR(255) FIRST;"];
1690 let exps = [AlterTableOption::ModifyColumn {
1691 column_definition: ColumnSpecification {
1692 column: "another_column".into(),
1693 data_type: DataType::Varchar(255),
1694 constraints: vec![],
1695 comment: None,
1696 position: Some(ColumnPosition::First),
1697 },
1698 }];
1699 for i in 0..parts.len() {
1700 let res = AlterTableOption::modify_column(parts[i]);
1701 assert!(res.is_ok());
1702 assert_eq!(res.unwrap().1, exps[i]);
1703 }
1704 }
1705}