mirror of
https://github.com/apache/datafusion-sqlparser-rs.git
synced 2025-08-23 07:24:10 +00:00
Add all missing table options to be handled in any order (#1747)
Co-authored-by: Tomer Shani <tomer.shani@satoricyber.com>
This commit is contained in:
parent
a464f8e8d7
commit
728645fb31
17 changed files with 767 additions and 382 deletions
|
@ -848,9 +848,23 @@ fn parse_create_table_comment() {
|
|||
|
||||
for sql in [without_equal, with_equal] {
|
||||
match mysql().verified_stmt(sql) {
|
||||
Statement::CreateTable(CreateTable { name, comment, .. }) => {
|
||||
Statement::CreateTable(CreateTable {
|
||||
name,
|
||||
table_options,
|
||||
..
|
||||
}) => {
|
||||
assert_eq!(name.to_string(), "foo");
|
||||
assert_eq!(comment.expect("Should exist").to_string(), "baz");
|
||||
|
||||
let plain_options = match table_options {
|
||||
CreateTableOptions::Plain(options) => options,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
let comment = match plain_options.first().unwrap() {
|
||||
SqlOption::Comment(CommentDef::WithEq(c))
|
||||
| SqlOption::Comment(CommentDef::WithoutEq(c)) => c,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
assert_eq!(comment, "baz");
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
|
@ -859,29 +873,226 @@ fn parse_create_table_comment() {
|
|||
|
||||
#[test]
|
||||
fn parse_create_table_auto_increment_offset() {
|
||||
let canonical =
|
||||
"CREATE TABLE foo (bar INT NOT NULL AUTO_INCREMENT) ENGINE=InnoDB AUTO_INCREMENT 123";
|
||||
let with_equal =
|
||||
"CREATE TABLE foo (bar INT NOT NULL AUTO_INCREMENT) ENGINE=InnoDB AUTO_INCREMENT=123";
|
||||
let sql =
|
||||
"CREATE TABLE foo (bar INT NOT NULL AUTO_INCREMENT) ENGINE = InnoDB AUTO_INCREMENT = 123";
|
||||
|
||||
for sql in [canonical, with_equal] {
|
||||
match mysql().one_statement_parses_to(sql, canonical) {
|
||||
match mysql().verified_stmt(sql) {
|
||||
Statement::CreateTable(CreateTable {
|
||||
name,
|
||||
table_options,
|
||||
..
|
||||
}) => {
|
||||
assert_eq!(name.to_string(), "foo");
|
||||
|
||||
let plain_options = match table_options {
|
||||
CreateTableOptions::Plain(options) => options,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
assert!(plain_options.contains(&SqlOption::KeyValue {
|
||||
key: Ident::new("AUTO_INCREMENT"),
|
||||
value: Expr::Value(test_utils::number("123").with_empty_span())
|
||||
}));
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_create_table_multiple_options_order_independent() {
|
||||
let sql1 = "CREATE TABLE mytable (id INT) ENGINE=InnoDB ROW_FORMAT=DYNAMIC KEY_BLOCK_SIZE=8 COMMENT='abc'";
|
||||
let sql2 = "CREATE TABLE mytable (id INT) KEY_BLOCK_SIZE=8 COMMENT='abc' ENGINE=InnoDB ROW_FORMAT=DYNAMIC";
|
||||
let sql3 = "CREATE TABLE mytable (id INT) ROW_FORMAT=DYNAMIC KEY_BLOCK_SIZE=8 COMMENT='abc' ENGINE=InnoDB";
|
||||
|
||||
for sql in [sql1, sql2, sql3] {
|
||||
match mysql().parse_sql_statements(sql).unwrap().pop().unwrap() {
|
||||
Statement::CreateTable(CreateTable {
|
||||
name,
|
||||
auto_increment_offset,
|
||||
table_options,
|
||||
..
|
||||
}) => {
|
||||
assert_eq!(name.to_string(), "foo");
|
||||
assert_eq!(
|
||||
auto_increment_offset.expect("Should exist").to_string(),
|
||||
"123"
|
||||
);
|
||||
assert_eq!(name.to_string(), "mytable");
|
||||
|
||||
let plain_options = match table_options {
|
||||
CreateTableOptions::Plain(options) => options,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
assert!(plain_options.contains(&SqlOption::NamedParenthesizedList(
|
||||
NamedParenthesizedList {
|
||||
key: Ident::new("ENGINE"),
|
||||
name: Some(Ident::new("InnoDB")),
|
||||
values: vec![]
|
||||
}
|
||||
)));
|
||||
|
||||
assert!(plain_options.contains(&SqlOption::KeyValue {
|
||||
key: Ident::new("KEY_BLOCK_SIZE"),
|
||||
value: Expr::Value(test_utils::number("8").with_empty_span())
|
||||
}));
|
||||
|
||||
assert!(plain_options
|
||||
.contains(&SqlOption::Comment(CommentDef::WithEq("abc".to_owned()))));
|
||||
|
||||
assert!(plain_options.contains(&SqlOption::KeyValue {
|
||||
key: Ident::new("ROW_FORMAT"),
|
||||
value: Expr::Identifier(Ident::new("DYNAMIC".to_owned()))
|
||||
}));
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_create_table_with_all_table_options() {
|
||||
let sql =
|
||||
"CREATE TABLE foo (bar INT NOT NULL AUTO_INCREMENT) ENGINE = InnoDB AUTO_INCREMENT = 123 DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci INSERT_METHOD = FIRST KEY_BLOCK_SIZE = 8 ROW_FORMAT = DYNAMIC DATA DIRECTORY = '/var/lib/mysql/data' INDEX DIRECTORY = '/var/lib/mysql/index' PACK_KEYS = 1 STATS_AUTO_RECALC = 1 STATS_PERSISTENT = 0 STATS_SAMPLE_PAGES = 128 DELAY_KEY_WRITE = 1 COMPRESSION = 'ZLIB' ENCRYPTION = 'Y' MAX_ROWS = 10000 MIN_ROWS = 10 AUTOEXTEND_SIZE = 64 AVG_ROW_LENGTH = 128 CHECKSUM = 1 CONNECTION = 'mysql://localhost' ENGINE_ATTRIBUTE = 'primary' PASSWORD = 'secure_password' SECONDARY_ENGINE_ATTRIBUTE = 'secondary_attr' START TRANSACTION TABLESPACE my_tablespace STORAGE DISK UNION = (table1, table2, table3)";
|
||||
|
||||
match mysql().verified_stmt(sql) {
|
||||
Statement::CreateTable(CreateTable {
|
||||
name,
|
||||
table_options,
|
||||
..
|
||||
}) => {
|
||||
assert_eq!(name, vec![Ident::new("foo".to_owned())].into());
|
||||
|
||||
let plain_options = match table_options {
|
||||
CreateTableOptions::Plain(options) => options,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
assert!(plain_options.contains(&SqlOption::NamedParenthesizedList(
|
||||
NamedParenthesizedList {
|
||||
key: Ident::new("ENGINE"),
|
||||
name: Some(Ident::new("InnoDB")),
|
||||
values: vec![]
|
||||
}
|
||||
)));
|
||||
|
||||
assert!(plain_options.contains(&SqlOption::KeyValue {
|
||||
key: Ident::new("COLLATE"),
|
||||
value: Expr::Identifier(Ident::new("utf8mb4_0900_ai_ci".to_owned()))
|
||||
}));
|
||||
assert!(plain_options.contains(&SqlOption::KeyValue {
|
||||
key: Ident::new("DEFAULT CHARSET"),
|
||||
value: Expr::Identifier(Ident::new("utf8mb4".to_owned()))
|
||||
}));
|
||||
assert!(plain_options.contains(&SqlOption::KeyValue {
|
||||
key: Ident::new("AUTO_INCREMENT"),
|
||||
value: Expr::value(test_utils::number("123"))
|
||||
}));
|
||||
assert!(plain_options.contains(&SqlOption::KeyValue {
|
||||
key: Ident::new("KEY_BLOCK_SIZE"),
|
||||
value: Expr::value(test_utils::number("8"))
|
||||
}));
|
||||
assert!(plain_options.contains(&SqlOption::KeyValue {
|
||||
key: Ident::new("ROW_FORMAT"),
|
||||
value: Expr::Identifier(Ident::new("DYNAMIC".to_owned()))
|
||||
}));
|
||||
assert!(plain_options.contains(&SqlOption::KeyValue {
|
||||
key: Ident::new("PACK_KEYS"),
|
||||
value: Expr::value(test_utils::number("1"))
|
||||
}));
|
||||
assert!(plain_options.contains(&SqlOption::KeyValue {
|
||||
key: Ident::new("STATS_AUTO_RECALC"),
|
||||
value: Expr::value(test_utils::number("1"))
|
||||
}));
|
||||
assert!(plain_options.contains(&SqlOption::KeyValue {
|
||||
key: Ident::new("STATS_PERSISTENT"),
|
||||
value: Expr::value(test_utils::number("0"))
|
||||
}));
|
||||
assert!(plain_options.contains(&SqlOption::KeyValue {
|
||||
key: Ident::new("STATS_SAMPLE_PAGES"),
|
||||
value: Expr::value(test_utils::number("128"))
|
||||
}));
|
||||
assert!(plain_options.contains(&SqlOption::KeyValue {
|
||||
key: Ident::new("STATS_SAMPLE_PAGES"),
|
||||
value: Expr::value(test_utils::number("128"))
|
||||
}));
|
||||
assert!(plain_options.contains(&SqlOption::KeyValue {
|
||||
key: Ident::new("INSERT_METHOD"),
|
||||
value: Expr::Identifier(Ident::new("FIRST".to_owned()))
|
||||
}));
|
||||
assert!(plain_options.contains(&SqlOption::KeyValue {
|
||||
key: Ident::new("COMPRESSION"),
|
||||
value: Expr::value(Value::SingleQuotedString("ZLIB".to_owned()))
|
||||
}));
|
||||
assert!(plain_options.contains(&SqlOption::KeyValue {
|
||||
key: Ident::new("ENCRYPTION"),
|
||||
value: Expr::value(Value::SingleQuotedString("Y".to_owned()))
|
||||
}));
|
||||
assert!(plain_options.contains(&SqlOption::KeyValue {
|
||||
key: Ident::new("MAX_ROWS"),
|
||||
value: Expr::value(test_utils::number("10000"))
|
||||
}));
|
||||
assert!(plain_options.contains(&SqlOption::KeyValue {
|
||||
key: Ident::new("MIN_ROWS"),
|
||||
value: Expr::value(test_utils::number("10"))
|
||||
}));
|
||||
assert!(plain_options.contains(&SqlOption::KeyValue {
|
||||
key: Ident::new("AUTOEXTEND_SIZE"),
|
||||
value: Expr::value(test_utils::number("64"))
|
||||
}));
|
||||
assert!(plain_options.contains(&SqlOption::KeyValue {
|
||||
key: Ident::new("AVG_ROW_LENGTH"),
|
||||
value: Expr::value(test_utils::number("128"))
|
||||
}));
|
||||
assert!(plain_options.contains(&SqlOption::KeyValue {
|
||||
key: Ident::new("CHECKSUM"),
|
||||
value: Expr::value(test_utils::number("1"))
|
||||
}));
|
||||
assert!(plain_options.contains(&SqlOption::KeyValue {
|
||||
key: Ident::new("CONNECTION"),
|
||||
value: Expr::value(Value::SingleQuotedString("mysql://localhost".to_owned()))
|
||||
}));
|
||||
assert!(plain_options.contains(&SqlOption::KeyValue {
|
||||
key: Ident::new("ENGINE_ATTRIBUTE"),
|
||||
value: Expr::value(Value::SingleQuotedString("primary".to_owned()))
|
||||
}));
|
||||
assert!(plain_options.contains(&SqlOption::KeyValue {
|
||||
key: Ident::new("PASSWORD"),
|
||||
value: Expr::value(Value::SingleQuotedString("secure_password".to_owned()))
|
||||
}));
|
||||
assert!(plain_options.contains(&SqlOption::KeyValue {
|
||||
key: Ident::new("SECONDARY_ENGINE_ATTRIBUTE"),
|
||||
value: Expr::value(Value::SingleQuotedString("secondary_attr".to_owned()))
|
||||
}));
|
||||
assert!(plain_options.contains(&SqlOption::Ident(Ident::new(
|
||||
"START TRANSACTION".to_owned()
|
||||
))));
|
||||
assert!(
|
||||
plain_options.contains(&SqlOption::TableSpace(TablespaceOption {
|
||||
name: "my_tablespace".to_string(),
|
||||
storage: Some(StorageType::Disk),
|
||||
}))
|
||||
);
|
||||
|
||||
assert!(plain_options.contains(&SqlOption::NamedParenthesizedList(
|
||||
NamedParenthesizedList {
|
||||
key: Ident::new("UNION"),
|
||||
name: None,
|
||||
values: vec![
|
||||
Ident::new("table1".to_string()),
|
||||
Ident::new("table2".to_string()),
|
||||
Ident::new("table3".to_string())
|
||||
]
|
||||
}
|
||||
)));
|
||||
|
||||
assert!(plain_options.contains(&SqlOption::KeyValue {
|
||||
key: Ident::new("DATA DIRECTORY"),
|
||||
value: Expr::value(Value::SingleQuotedString("/var/lib/mysql/data".to_owned()))
|
||||
}));
|
||||
assert!(plain_options.contains(&SqlOption::KeyValue {
|
||||
key: Ident::new("INDEX DIRECTORY"),
|
||||
value: Expr::value(Value::SingleQuotedString("/var/lib/mysql/index".to_owned()))
|
||||
}));
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_create_table_set_enum() {
|
||||
let sql = "CREATE TABLE foo (bar SET('a', 'b'), baz ENUM('a', 'b'))";
|
||||
|
@ -916,13 +1127,12 @@ fn parse_create_table_set_enum() {
|
|||
|
||||
#[test]
|
||||
fn parse_create_table_engine_default_charset() {
|
||||
let sql = "CREATE TABLE foo (id INT(11)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3";
|
||||
let sql = "CREATE TABLE foo (id INT(11)) ENGINE = InnoDB DEFAULT CHARSET = utf8mb3";
|
||||
match mysql().verified_stmt(sql) {
|
||||
Statement::CreateTable(CreateTable {
|
||||
name,
|
||||
columns,
|
||||
engine,
|
||||
default_charset,
|
||||
table_options,
|
||||
..
|
||||
}) => {
|
||||
assert_eq!(name.to_string(), "foo");
|
||||
|
@ -934,14 +1144,24 @@ fn parse_create_table_engine_default_charset() {
|
|||
},],
|
||||
columns
|
||||
);
|
||||
assert_eq!(
|
||||
engine,
|
||||
Some(TableEngine {
|
||||
name: "InnoDB".to_string(),
|
||||
parameters: None
|
||||
})
|
||||
);
|
||||
assert_eq!(default_charset, Some("utf8mb3".to_string()));
|
||||
|
||||
let plain_options = match table_options {
|
||||
CreateTableOptions::Plain(options) => options,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
assert!(plain_options.contains(&SqlOption::KeyValue {
|
||||
key: Ident::new("DEFAULT CHARSET"),
|
||||
value: Expr::Identifier(Ident::new("utf8mb3".to_owned()))
|
||||
}));
|
||||
|
||||
assert!(plain_options.contains(&SqlOption::NamedParenthesizedList(
|
||||
NamedParenthesizedList {
|
||||
key: Ident::new("ENGINE"),
|
||||
name: Some(Ident::new("InnoDB")),
|
||||
values: vec![]
|
||||
}
|
||||
)));
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
|
@ -949,12 +1169,12 @@ fn parse_create_table_engine_default_charset() {
|
|||
|
||||
#[test]
|
||||
fn parse_create_table_collate() {
|
||||
let sql = "CREATE TABLE foo (id INT(11)) COLLATE=utf8mb4_0900_ai_ci";
|
||||
let sql = "CREATE TABLE foo (id INT(11)) COLLATE = utf8mb4_0900_ai_ci";
|
||||
match mysql().verified_stmt(sql) {
|
||||
Statement::CreateTable(CreateTable {
|
||||
name,
|
||||
columns,
|
||||
collation,
|
||||
table_options,
|
||||
..
|
||||
}) => {
|
||||
assert_eq!(name.to_string(), "foo");
|
||||
|
@ -966,7 +1186,16 @@ fn parse_create_table_collate() {
|
|||
},],
|
||||
columns
|
||||
);
|
||||
assert_eq!(collation, Some("utf8mb4_0900_ai_ci".to_string()));
|
||||
|
||||
let plain_options = match table_options {
|
||||
CreateTableOptions::Plain(options) => options,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
assert!(plain_options.contains(&SqlOption::KeyValue {
|
||||
key: Ident::new("COLLATE"),
|
||||
value: Expr::Identifier(Ident::new("utf8mb4_0900_ai_ci".to_owned()))
|
||||
}));
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
|
@ -974,16 +1203,26 @@ fn parse_create_table_collate() {
|
|||
|
||||
#[test]
|
||||
fn parse_create_table_both_options_and_as_query() {
|
||||
let sql = "CREATE TABLE foo (id INT(11)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb4_0900_ai_ci AS SELECT 1";
|
||||
let sql = "CREATE TABLE foo (id INT(11)) ENGINE = InnoDB DEFAULT CHARSET = utf8mb3 COLLATE = utf8mb4_0900_ai_ci AS SELECT 1";
|
||||
match mysql_and_generic().verified_stmt(sql) {
|
||||
Statement::CreateTable(CreateTable {
|
||||
name,
|
||||
collation,
|
||||
query,
|
||||
table_options,
|
||||
..
|
||||
}) => {
|
||||
assert_eq!(name.to_string(), "foo");
|
||||
assert_eq!(collation, Some("utf8mb4_0900_ai_ci".to_string()));
|
||||
|
||||
let plain_options = match table_options {
|
||||
CreateTableOptions::Plain(options) => options,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
assert!(plain_options.contains(&SqlOption::KeyValue {
|
||||
key: Ident::new("COLLATE"),
|
||||
value: Expr::Identifier(Ident::new("utf8mb4_0900_ai_ci".to_owned()))
|
||||
}));
|
||||
|
||||
assert_eq!(
|
||||
query.unwrap().body.as_select().unwrap().projection,
|
||||
vec![SelectItem::UnnamedExpr(Expr::Value(
|
||||
|
@ -994,7 +1233,8 @@ fn parse_create_table_both_options_and_as_query() {
|
|||
_ => unreachable!(),
|
||||
}
|
||||
|
||||
let sql = r"CREATE TABLE foo (id INT(11)) ENGINE=InnoDB AS SELECT 1 DEFAULT CHARSET=utf8mb3";
|
||||
let sql =
|
||||
r"CREATE TABLE foo (id INT(11)) ENGINE = InnoDB AS SELECT 1 DEFAULT CHARSET = utf8mb3";
|
||||
assert!(matches!(
|
||||
mysql_and_generic().parse_sql_statements(sql),
|
||||
Err(ParserError::ParserError(_))
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue