1use core::fmt;
2use std::fmt::{write, Display, Formatter};
3
4use nom::branch::alt;
5use nom::bytes::complete::{tag, tag_no_case, take_until};
6use nom::character::complete::{multispace0, multispace1};
7use nom::combinator::{map, opt};
8use nom::multi::many1;
9use nom::sequence::{delimited, preceded, terminated, tuple};
10use nom::IResult;
11
12use base::column::{Column, ColumnSpecification};
13use base::error::ParseSQLError;
14use base::fulltext_or_spatial_type::FulltextOrSpatialType;
15use base::index_option::IndexOption;
16use base::index_or_key_type::IndexOrKeyType;
17use base::index_type::IndexType;
18use base::table::Table;
19use base::table_option::TableOption;
20use base::{CheckConstraintDefinition, CommonParser, KeyPart, ReferenceDefinition};
21use dms::SelectStatement;
22
23#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
48pub struct CreateTableStatement {
49 pub temporary: bool,
51 pub if_not_exists: bool,
53 pub table: Table,
55 pub create_type: CreateTableType,
57}
58
59impl Display for CreateTableStatement {
60 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
61 write!(f, "CREATE");
62 if self.temporary {
63 write!(f, " TEMPORARY");
64 }
65 write!(f, " TABLE {}", &self.table);
66 write!(f, " {}", &self.create_type);
67 Ok(())
68 }
69}
70
71impl CreateTableStatement {
72 pub fn parse(i: &str) -> IResult<&str, CreateTableStatement, ParseSQLError<&str>> {
73 alt((
74 CreateTableType::create_simple,
75 CreateTableType::create_as_query,
76 CreateTableType::create_like_old_table,
77 ))(i)
78 }
79}
80
81#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
82pub enum IgnoreOrReplaceType {
83 Ignore,
84 Replace,
85}
86
87impl Display for IgnoreOrReplaceType {
88 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
89 match *self {
90 IgnoreOrReplaceType::Ignore => write!(f, "IGNORE"),
91 IgnoreOrReplaceType::Replace => write!(f, "REPLACE"),
92 }
93 }
94}
95
96impl IgnoreOrReplaceType {
97 fn parse(i: &str) -> IResult<&str, IgnoreOrReplaceType, ParseSQLError<&str>> {
98 alt((
99 map(tag_no_case("IGNORE"), |_| IgnoreOrReplaceType::Ignore),
100 map(tag_no_case("REPLACE"), |_| IgnoreOrReplaceType::Replace),
101 ))(i)
102 }
103}
104
105#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
106pub enum CreateTableType {
107 Simple {
115 create_definition: Vec<CreateDefinition>, table_options: Option<Vec<TableOption>>, partition_options: Option<CreatePartitionOption>, },
119
120 AsQuery {
130 create_definition: Option<Vec<CreateDefinition>>, table_options: Option<Vec<TableOption>>, partition_options: Option<CreatePartitionOption>, opt_ignore_or_replace: Option<IgnoreOrReplaceType>, query_expression: SelectStatement, },
136
137 LikeOldTable { table: Table },
143}
144
145impl Display for CreateTableType {
146 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
147 match *self {
148 CreateTableType::Simple {
149 ref create_definition,
150 ref table_options,
151 ref partition_options,
152 } => {
153 write!(f, " {}", CreateDefinition::format_list(create_definition));
154 if let Some(table_options) = table_options {
155 write!(f, " {}", TableOption::format_list(table_options));
156 };
157 if let Some(partition_options) = partition_options {
158 write!(f, " {}", partition_options);
159 };
160 Ok(())
161 }
162 CreateTableType::AsQuery {
163 ref create_definition,
164 ref table_options,
165 ref partition_options,
166 ref opt_ignore_or_replace,
167 ref query_expression,
168 } => {
169 if let Some(create_definition) = create_definition {
170 write!(f, " {}", CreateDefinition::format_list(create_definition));
171 }
172 if let Some(table_options) = table_options {
173 write!(f, " {}", TableOption::format_list(table_options));
174 };
175 if let Some(partition_options) = partition_options {
176 write!(f, " {}", partition_options);
177 };
178 if let Some(opt_ignore_or_replace) = opt_ignore_or_replace {
179 write!(f, " {}", opt_ignore_or_replace);
180 };
181 write!(f, " {}", query_expression);
182 Ok(())
183 }
184 CreateTableType::LikeOldTable { ref table } => write!(f, "LIKE {}", table),
185 }
186 }
187}
188
189impl CreateTableType {
190 fn create_simple(i: &str) -> IResult<&str, CreateTableStatement, ParseSQLError<&str>> {
192 map(
193 tuple((
194 Self::create_table_with_name,
195 multispace0,
196 CreateDefinition::create_definition_list,
198 multispace0,
199 opt(Self::create_table_options),
201 multispace0,
202 opt(CreatePartitionOption::parse),
204 CommonParser::statement_terminator,
205 )),
206 |(x)| {
207 let temporary = x.0 .0;
208 let if_not_exists = x.0 .1;
209 let table = x.0 .2;
210 let create_type = CreateTableType::Simple {
211 create_definition: x.2,
212 table_options: x.4,
213 partition_options: x.6,
214 };
215 CreateTableStatement {
216 table,
217 temporary,
218 if_not_exists,
219 create_type,
220 }
221 },
222 )(i)
223 }
224
225 fn create_as_query(i: &str) -> IResult<&str, CreateTableStatement, ParseSQLError<&str>> {
227 map(
228 tuple((
229 Self::create_table_with_name,
230 multispace0,
231 opt(CreateDefinition::create_definition_list),
233 multispace0,
234 opt(Self::create_table_options),
236 multispace0,
237 opt(CreatePartitionOption::parse),
239 multispace0,
240 opt(IgnoreOrReplaceType::parse),
241 multispace0,
242 opt(tag_no_case("AS")),
243 multispace0,
244 SelectStatement::parse,
245 )),
246 |(x)| {
247 let table = x.0 .2;
248 let if_not_exists = x.0 .1;
249 let temporary = x.0 .0;
250 let create_type = CreateTableType::AsQuery {
251 create_definition: x.2,
252 table_options: x.4,
253 partition_options: x.6,
254 opt_ignore_or_replace: x.8,
255 query_expression: x.12,
256 };
257 CreateTableStatement {
258 table,
259 temporary,
260 if_not_exists,
261 create_type,
262 }
263 },
264 )(i)
265 }
266
267 fn create_like_old_table(i: &str) -> IResult<&str, CreateTableStatement, ParseSQLError<&str>> {
269 map(
270 tuple((
271 Self::create_table_with_name,
272 multispace0,
273 map(
275 alt((
276 map(
277 tuple((
278 tag_no_case("LIKE"),
279 multispace1,
280 Table::schema_table_reference,
281 )),
282 |x| x.2,
283 ),
284 map(
285 delimited(tag("("), Table::schema_table_reference, tag(")")),
286 |x| x,
287 ),
288 )),
289 |x| CreateTableType::LikeOldTable { table: x },
290 ),
291 CommonParser::statement_terminator,
292 )),
293 |(x, _, create_type, _)| {
294 let table = x.2;
295 let if_not_exists = x.1;
296 let temporary = x.0;
297 CreateTableStatement {
298 table,
299 temporary,
300 if_not_exists,
301 create_type,
302 }
303 },
304 )(i)
305 }
306
307 fn create_table_options(i: &str) -> IResult<&str, Vec<TableOption>, ParseSQLError<&str>> {
309 map(
310 many1(map(
311 tuple((
312 TableOption::parse,
313 multispace0,
314 opt(CommonParser::ws_sep_comma),
315 )),
316 |x| x.0,
317 )),
318 |x| x,
319 )(i)
320 }
321
322 fn create_table_with_name(i: &str) -> IResult<&str, (bool, bool, Table), ParseSQLError<&str>> {
324 map(
325 tuple((
326 tuple((tag_no_case("CREATE"), multispace1)),
327 opt(tag_no_case("TEMPORARY")),
328 multispace0,
329 tuple((tag_no_case("TABLE"), multispace1)),
330 Self::if_not_exists,
332 multispace0,
333 Table::schema_table_reference,
335 )),
336 |x| (x.1.is_some(), x.4, x.6),
337 )(i)
338 }
339
340 fn if_not_exists(i: &str) -> IResult<&str, bool, ParseSQLError<&str>> {
342 map(
343 opt(tuple((
344 tag_no_case("IF"),
345 multispace1,
346 tag_no_case("NOT"),
347 multispace1,
348 tag_no_case("EXISTS"),
349 ))),
350 |x| x.is_some(),
351 )(i)
352 }
353}
354
355#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
356pub enum CreateDefinition {
357 ColumnDefinition {
359 column_definition: ColumnSpecification,
360 },
361
362 IndexOrKey {
364 index_or_key: IndexOrKeyType, opt_index_name: Option<String>, opt_index_type: Option<IndexType>, key_part: Vec<KeyPart>, opt_index_option: Option<Vec<IndexOption>>, },
370
371 FulltextOrSpatial {
373 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>>, },
379
380 PrimaryKey {
382 opt_symbol: Option<String>, opt_index_type: Option<IndexType>, key_part: Vec<KeyPart>, opt_index_option: Option<Vec<IndexOption>>, },
387
388 Unique {
390 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>>, },
397
398 ForeignKey {
400 opt_symbol: Option<String>, opt_index_name: Option<String>, columns: Vec<String>, reference_definition: ReferenceDefinition, },
405
406 Check {
408 check_constraint_definition: CheckConstraintDefinition,
409 },
410}
411
412impl Display for CreateDefinition {
413 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
414 match *self {
415 CreateDefinition::ColumnDefinition {
416 ref column_definition,
417 } => write!(f, " {}", column_definition),
418 CreateDefinition::IndexOrKey {
419 ref index_or_key,
420 ref opt_index_name,
421 ref opt_index_type,
422 ref key_part,
423 ref opt_index_option,
424 } => {
425 write!(f, " {}", index_or_key);
426 if let Some(opt_index_name) = opt_index_name {
427 write!(f, " {}", opt_index_name);
428 }
429 if let Some(opt_index_type) = opt_index_type {
430 write!(f, " {}", opt_index_type);
431 }
432 write!(f, " {}", KeyPart::format_list(key_part));
433 if let Some(opt_index_option) = opt_index_option {
434 write!(f, " {}", IndexOption::format_list(opt_index_option));
435 }
436 Ok(())
437 }
438 CreateDefinition::FulltextOrSpatial {
439 ref fulltext_or_spatial,
440 ref opt_index_or_key,
441 ref opt_index_name,
442 ref key_part,
443 ref opt_index_option,
444 } => {
445 write!(f, " {}", fulltext_or_spatial);
446 if let Some(opt_index_or_key) = opt_index_or_key {
447 write!(f, " {}", opt_index_or_key);
448 }
449 if let Some(opt_index_name) = opt_index_name {
450 write!(f, " {}", opt_index_name);
451 }
452 write!(f, " {}", KeyPart::format_list(key_part));
453 if let Some(opt_index_option) = opt_index_option {
454 write!(f, " {}", IndexOption::format_list(opt_index_option));
455 }
456 Ok(())
457 }
458 CreateDefinition::PrimaryKey {
459 ref opt_symbol,
460 ref opt_index_type,
461 ref key_part,
462 ref opt_index_option,
463 } => {
464 if let Some(opt_symbol) = opt_symbol {
465 write!(f, " CONSTRAINT {}", opt_symbol);
466 }
467 write!(f, " PRIMARY KEY");
468 if let Some(opt_index_type) = opt_index_type {
469 write!(f, " {}", opt_index_type);
470 }
471 write!(f, " {}", KeyPart::format_list(key_part));
472 if let Some(opt_index_option) = opt_index_option {
473 write!(f, " {}", IndexOption::format_list(opt_index_option));
474 }
475 Ok(())
476 }
477 CreateDefinition::Unique {
478 ref opt_symbol,
479 ref opt_index_or_key,
480 ref opt_index_name,
481 ref opt_index_type,
482 ref key_part,
483 ref opt_index_option,
484 } => {
485 if let Some(opt_symbol) = opt_symbol {
486 write!(f, " CONSTRAINT {}", opt_symbol);
487 }
488 write!(f, " UNIQUE");
489 if let Some(opt_index_or_key) = opt_index_or_key {
490 write!(f, " {}", opt_index_or_key);
491 }
492 if let Some(opt_index_name) = opt_index_name {
493 write!(f, " {}", opt_index_name);
494 }
495 if let Some(opt_index_type) = opt_index_type {
496 write!(f, " {}", opt_index_type);
497 }
498 write!(f, " {}", KeyPart::format_list(key_part));
499 if let Some(opt_index_option) = opt_index_option {
500 write!(f, " {}", IndexOption::format_list(opt_index_option));
501 }
502 Ok(())
503 }
504 CreateDefinition::ForeignKey {
505 ref opt_symbol,
506 ref opt_index_name,
507 ref columns,
508 ref reference_definition,
509 } => {
510 if let Some(opt_symbol) = opt_symbol {
511 write!(f, " CONSTRAINT {}", opt_symbol);
512 }
513 write!(f, " FOREIGN KEY");
514 if let Some(opt_index_name) = opt_index_name {
515 write!(f, " {}", opt_index_name);
516 }
517 write!(f, " ({})", columns.join(", "));
518 write!(f, " {}", reference_definition);
519 Ok(())
520 }
521 CreateDefinition::Check {
522 ref check_constraint_definition,
523 } => write!(f, " {}", check_constraint_definition),
524 }
525 }
526}
527
528impl CreateDefinition {
529 pub fn parse(i: &str) -> IResult<&str, CreateDefinition, ParseSQLError<&str>> {
547 alt((
548 map(ColumnSpecification::parse, |x| {
549 CreateDefinition::ColumnDefinition {
550 column_definition: x,
551 }
552 }),
553 CreateDefinition::index_or_key,
554 CreateDefinition::fulltext_or_spatial,
555 CreateDefinition::primary_key,
556 CreateDefinition::unique,
557 CreateDefinition::foreign_key,
558 CreateDefinition::check_constraint_definition,
559 ))(i)
560 }
561
562 pub fn format_list(list: &[CreateDefinition]) -> String {
563 list.iter()
564 .map(|x| x.to_string())
565 .collect::<Vec<String>>()
566 .join(", ")
567 }
568
569 fn create_definition_list(
570 i: &str,
571 ) -> IResult<&str, Vec<CreateDefinition>, ParseSQLError<&str>> {
572 delimited(
573 tag("("),
574 many1(map(
575 tuple((
576 multispace0,
577 CreateDefinition::parse,
578 multispace0,
579 opt(CommonParser::ws_sep_comma),
580 multispace0,
581 )),
582 |x| x.1,
583 )),
584 tag(")"),
585 )(i)
586 }
587
588 fn index_or_key(i: &str) -> IResult<&str, CreateDefinition, ParseSQLError<&str>> {
590 map(
591 tuple((
592 IndexOrKeyType::parse,
594 CommonParser::opt_index_name,
596 IndexType::opt_index_type,
598 KeyPart::parse,
600 IndexOption::opt_index_option,
602 )),
603 |(index_or_key, opt_index_name, opt_index_type, key_part, opt_index_option)| {
604 CreateDefinition::IndexOrKey {
605 index_or_key,
606 opt_index_name,
607 opt_index_type,
608 key_part,
609 opt_index_option,
610 }
611 },
612 )(i)
613 }
614
615 fn fulltext_or_spatial(i: &str) -> IResult<&str, CreateDefinition, ParseSQLError<&str>> {
617 map(
618 tuple((
619 FulltextOrSpatialType::parse,
621 preceded(multispace1, opt(IndexOrKeyType::parse)),
623 CommonParser::opt_index_name,
625 KeyPart::parse,
627 IndexOption::opt_index_option,
629 )),
630 |(fulltext_or_spatial, index_or_key, index_name, key_part, opt_index_option)| {
631 CreateDefinition::FulltextOrSpatial {
632 fulltext_or_spatial,
633 opt_index_or_key: index_or_key,
634 opt_index_name: index_name,
635 key_part,
636 opt_index_option,
637 }
638 },
639 )(i)
640 }
641
642 fn primary_key(i: &str) -> IResult<&str, CreateDefinition, ParseSQLError<&str>> {
644 map(
645 tuple((
646 Self::opt_constraint_with_opt_symbol, tuple((
648 multispace0,
649 tag_no_case("PRIMARY"),
650 multispace1,
651 tag_no_case("KEY"),
652 )), IndexType::opt_index_type, KeyPart::parse, IndexOption::opt_index_option, )),
657 |(opt_symbol, _, opt_index_type, key_part, opt_index_option)| {
658 CreateDefinition::PrimaryKey {
659 opt_symbol,
660 opt_index_type,
661 key_part,
662 opt_index_option,
663 }
664 },
665 )(i)
666 }
667
668 fn unique(i: &str) -> IResult<&str, CreateDefinition, ParseSQLError<&str>> {
671 map(
672 tuple((
673 Self::opt_constraint_with_opt_symbol, map(
675 tuple((
676 multispace0,
677 tag_no_case("UNIQUE"),
678 multispace1,
679 opt(IndexOrKeyType::parse),
680 )),
681 |(_, _, _, value)| value,
682 ), CommonParser::opt_index_name, IndexType::opt_index_type, KeyPart::parse, IndexOption::opt_index_option, )),
688 |(
689 opt_symbol,
690 opt_index_or_key,
691 opt_index_name,
692 opt_index_type,
693 key_part,
694 opt_index_option,
695 )| {
696 CreateDefinition::Unique {
697 opt_symbol,
698 opt_index_or_key,
699 opt_index_name,
700 opt_index_type,
701 key_part,
702 opt_index_option,
703 }
704 },
705 )(i)
706 }
707
708 fn foreign_key(i: &str) -> IResult<&str, CreateDefinition, ParseSQLError<&str>> {
710 map(
711 tuple((
712 Self::opt_constraint_with_opt_symbol,
714 tuple((
716 multispace0,
717 tag_no_case("FOREIGN"),
718 multispace1,
719 tag_no_case("KEY"),
720 )),
721 CommonParser::opt_index_name,
723 map(
725 tuple((
726 multispace0,
727 delimited(
728 tag("("),
729 delimited(multispace0, Column::index_col_list, multispace0),
730 tag(")"),
731 ),
732 multispace0,
733 )),
734 |(_, value, _)| value.iter().map(|x| x.name.clone()).collect(),
735 ),
736 ReferenceDefinition::parse,
738 )),
739 |(opt_symbol, _, opt_index_name, columns, reference_definition)| {
740 CreateDefinition::ForeignKey {
741 opt_symbol,
742 opt_index_name,
743 columns,
744 reference_definition,
745 }
746 },
747 )(i)
748 }
749
750 fn check_constraint_definition(
753 i: &str,
754 ) -> IResult<&str, CreateDefinition, ParseSQLError<&str>> {
755 map(
756 tuple((
757 Self::opt_constraint_with_opt_symbol,
759 tuple((multispace1, tag_no_case("CHECK"), multispace0)),
761 delimited(tag("("), take_until(")"), tag(")")),
763 opt(tuple((
765 multispace0,
766 opt(tag_no_case("NOT")),
767 multispace1,
768 tag_no_case("ENFORCED"),
769 multispace0,
770 ))),
771 )),
772 |(symbol, _, expr, opt_whether_enforced)| {
773 let expr = String::from(expr);
774 let enforced =
775 opt_whether_enforced.map_or(true, |(_, opt_not, _, _, _)| opt_not.is_none());
776 CreateDefinition::Check {
777 check_constraint_definition: CheckConstraintDefinition {
778 symbol,
779 expr,
780 enforced,
781 },
782 }
783 },
784 )(i)
785 }
786
787 fn opt_constraint_with_opt_symbol(
789 i: &str,
790 ) -> IResult<&str, Option<String>, ParseSQLError<&str>> {
791 map(
792 opt(preceded(
793 tag_no_case("CONSTRAINT"),
794 opt(preceded(multispace1, CommonParser::sql_identifier)),
795 )),
796 |(x)| x.and_then(|inner| inner.map(String::from)),
797 )(i)
798 }
799}
800
801#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
803pub enum CreatePartitionOption {
804 None,
805}
806
807impl Display for CreatePartitionOption {
808 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
809 write!(f, "")
810 }
811}
812
813impl CreatePartitionOption {
814 fn parse(i: &str) -> IResult<&str, CreatePartitionOption, ParseSQLError<&str>> {
815 map(tag_no_case(""), |_| CreatePartitionOption::None)(i)
816 }
817}
818#[cfg(test)]
821mod tests {
822 use base::column::{ColumnConstraint, ColumnSpecification};
823 use base::table_option::TableOption;
824 use base::{
825 Column, DataType, FieldDefinitionExpression, KeyPart, KeyPartType, Literal,
826 ReferenceDefinition,
827 };
828 use dds::create_table::{
829 CreateDefinition, CreatePartitionOption, CreateTableStatement, CreateTableType,
830 };
831 use dms::SelectStatement;
832
833 #[test]
834 fn parse_create_simple() {
835 let sqls = ["create table admin_role \
836 (`role_id` int(10) unsigned NOT NULL Auto_Increment COMMENT 'Role ID',\
837 `role_type` varchar(1) NOT NULL DEFAULT '0' COMMENT 'Role Type',\
838 PRIMARY KEY (`role_id`))\
839 ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Admin Role Table';"];
840 let exp = [
841 CreateTableStatement {
842 temporary: false,
843 if_not_exists: false,
844 table: "admin_role".into(),
845 create_type: CreateTableType::Simple {
846 create_definition: vec![
847 CreateDefinition::ColumnDefinition {
848 column_definition: ColumnSpecification {
849 column: "role_id".into(),
850 data_type: DataType::UnsignedInt(10),
851 constraints: vec![
852 ColumnConstraint::NotNull,
853 ColumnConstraint::AutoIncrement,
854 ],
855 comment: Some("Role ID".to_string()),
856 position: None,
857 },
858 },
859 CreateDefinition::ColumnDefinition {
860 column_definition: ColumnSpecification {
861 column: "role_type".into(),
862 data_type: DataType::Varchar(1),
863 constraints: vec![
864 ColumnConstraint::NotNull,
865 ColumnConstraint::DefaultValue(Literal::String(
866 "0".to_string(),
867 )),
868 ],
869 comment: Some("Role Type".to_string()),
870 position: None,
871 },
872 },
873 CreateDefinition::PrimaryKey {
874 opt_symbol: None,
875 opt_index_type: None,
876 key_part: vec![KeyPart {
877 r#type: KeyPartType::ColumnNameWithLength {
878 col_name: "role_id".to_string(),
879 length: None,
880 },
881 order: None,
882 }],
883 opt_index_option: None,
884 },
885 ],
886 table_options: Some(vec![
887 TableOption::Engine("InnoDB".to_string()),
888 TableOption::DefaultCharset("utf8".to_string()),
889 TableOption::Comment("Admin Role Table".to_string()),
890 ]),
891 partition_options: Some(CreatePartitionOption::None),
892 },
893 },
894 CreateTableStatement {
895 temporary: false,
896 if_not_exists: false,
897 table: "tbl_name".into(),
898 create_type: CreateTableType::LikeOldTable {
899 table: "old_tbl_name".into(),
900 },
901 },
902 ];
903
904 for i in 0..sqls.len() {
905 let res = CreateTableType::create_simple(sqls[i]);
906 assert!(res.is_ok());
907 assert_eq!(res.unwrap().1, exp[i]);
908 }
909 }
910
911 #[test]
912 fn parse_create_as_query() {
913 let sqls = ["CREATE TABLE tbl_name AS SELECT * from other_tbl_name"];
914 let exp = [CreateTableStatement {
915 temporary: false,
916 if_not_exists: false,
917 table: "tbl_name".into(),
918 create_type: CreateTableType::AsQuery {
919 create_definition: None,
920 table_options: None,
921 partition_options: Some(CreatePartitionOption::None),
922 opt_ignore_or_replace: None,
923 query_expression: SelectStatement {
924 tables: vec!["other_tbl_name".into()],
925 distinct: false,
926 fields: vec![FieldDefinitionExpression::All],
927 join: vec![],
928 where_clause: None,
929 group_by: None,
930 order: None,
931 limit: None,
932 },
933 },
934 }];
935 for i in 0..sqls.len() {
936 let res = CreateTableType::create_as_query(sqls[i]);
937 assert!(res.is_ok());
938 assert_eq!(res.unwrap().1, exp[i]);
939 }
940 }
941
942 #[test]
943 fn parse_create_like_old() {
944 let sqls = ["CREATE TABLE tbl_name LIKE old_tbl_name"];
945 let exp = [CreateTableStatement {
946 temporary: false,
947 if_not_exists: false,
948 table: "tbl_name".into(),
949 create_type: CreateTableType::LikeOldTable {
950 table: "old_tbl_name".into(),
951 },
952 }];
953 for i in 0..sqls.len() {
954 let res = CreateTableType::create_like_old_table(sqls[i]);
955 assert!(res.is_ok());
956 assert_eq!(res.unwrap().1, exp[i]);
957 }
958 }
959
960 #[test]
961 fn parse_create_definition_list() {
962 let part = "(order_id INT not null, product_id INT DEFAULT 10,\
963 PRIMARY KEY(order_id, product_id), FOREIGN KEY (product_id) REFERENCES product(id))";
964 let exp = vec![
965 CreateDefinition::ColumnDefinition {
966 column_definition: ColumnSpecification {
967 column: "order_id".into(),
968 data_type: DataType::Int(32),
969 constraints: vec![ColumnConstraint::NotNull],
970 comment: None,
971 position: None,
972 },
973 },
974 CreateDefinition::ColumnDefinition {
975 column_definition: ColumnSpecification {
976 column: "product_id".into(),
977 data_type: DataType::Int(32),
978 constraints: vec![ColumnConstraint::DefaultValue(Literal::Integer(10))],
979 comment: None,
980 position: None,
981 },
982 },
983 CreateDefinition::PrimaryKey {
984 opt_symbol: None,
985 opt_index_type: None,
986 key_part: vec![
987 KeyPart {
988 r#type: KeyPartType::ColumnNameWithLength {
989 col_name: "order_id".to_string(),
990 length: None,
991 },
992 order: None,
993 },
994 KeyPart {
995 r#type: KeyPartType::ColumnNameWithLength {
996 col_name: "product_id".to_string(),
997 length: None,
998 },
999 order: None,
1000 },
1001 ],
1002 opt_index_option: None,
1003 },
1004 CreateDefinition::ForeignKey {
1005 opt_symbol: None,
1006 opt_index_name: None,
1007 columns: vec!["product_id".to_string()],
1008 reference_definition: ReferenceDefinition {
1009 tbl_name: "product".to_string(),
1010 key_part: vec![KeyPart {
1011 r#type: KeyPartType::ColumnNameWithLength {
1012 col_name: "id".to_string(),
1013 length: None,
1014 },
1015 order: None,
1016 }],
1017 match_type: None,
1018 on_delete: None,
1019 on_update: None,
1020 },
1021 },
1022 ];
1023 let res = CreateDefinition::create_definition_list(part);
1024 assert!(res.is_ok());
1025 assert_eq!(res.unwrap().1, exp);
1026 }
1027}