feat: Add support for MSSQL table options (#1414)

This commit is contained in:
Simon Sawert 2024-09-11 19:09:41 +02:00 committed by GitHub
parent cb0c511b05
commit b9e7754886
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 523 additions and 65 deletions

View file

@ -653,6 +653,261 @@ fn parse_use() {
}
}
#[test]
fn parse_create_table_with_valid_options() {
let options = [
(
"CREATE TABLE mytable (column_a INT, column_b INT, column_c INT) WITH (DISTRIBUTION = ROUND_ROBIN, PARTITION (column_a RANGE FOR VALUES (10, 11)))",
vec![
SqlOption::KeyValue {
key: Ident {
value: "DISTRIBUTION".to_string(),
quote_style: None,
},
value: Expr::Identifier(Ident {
value: "ROUND_ROBIN".to_string(),
quote_style: None,
})
},
SqlOption::Partition {
column_name: "column_a".into(),
range_direction: None,
for_values: vec![Expr::Value(test_utils::number("10")), Expr::Value(test_utils::number("11"))] ,
},
],
),
(
"CREATE TABLE mytable (column_a INT, column_b INT, column_c INT) WITH (PARTITION (column_a RANGE LEFT FOR VALUES (10, 11)))",
vec![
SqlOption::Partition {
column_name: "column_a".into(),
range_direction: Some(PartitionRangeDirection::Left),
for_values: vec![
Expr::Value(test_utils::number("10")),
Expr::Value(test_utils::number("11")),
],
}
],
),
(
"CREATE TABLE mytable (column_a INT, column_b INT, column_c INT) WITH (CLUSTERED COLUMNSTORE INDEX)",
vec![SqlOption::Clustered(TableOptionsClustered::ColumnstoreIndex)],
),
(
"CREATE TABLE mytable (column_a INT, column_b INT, column_c INT) WITH (CLUSTERED COLUMNSTORE INDEX ORDER (column_a, column_b))",
vec![
SqlOption::Clustered(TableOptionsClustered::ColumnstoreIndexOrder(vec![
"column_a".into(),
"column_b".into(),
]))
],
),
(
"CREATE TABLE mytable (column_a INT, column_b INT, column_c INT) WITH (CLUSTERED INDEX (column_a ASC, column_b DESC, column_c))",
vec![
SqlOption::Clustered(TableOptionsClustered::Index(vec![
ClusteredIndex {
name: Ident {
value: "column_a".to_string(),
quote_style: None,
},
asc: Some(true),
},
ClusteredIndex {
name: Ident {
value: "column_b".to_string(),
quote_style: None,
},
asc: Some(false),
},
ClusteredIndex {
name: Ident {
value: "column_c".to_string(),
quote_style: None,
},
asc: None,
},
]))
],
),
(
"CREATE TABLE mytable (column_a INT, column_b INT, column_c INT) WITH (DISTRIBUTION = HASH(column_a, column_b), HEAP)",
vec![
SqlOption::KeyValue {
key: Ident {
value: "DISTRIBUTION".to_string(),
quote_style: None,
},
value: Expr::Function(
Function {
name: ObjectName(
vec![
Ident {
value: "HASH".to_string(),
quote_style: None,
},
],
),
parameters: FunctionArguments::None,
args: FunctionArguments::List(
FunctionArgumentList {
duplicate_treatment: None,
args: vec![
FunctionArg::Unnamed(
FunctionArgExpr::Expr(
Expr::Identifier(
Ident {
value: "column_a".to_string(),
quote_style: None,
},
),
),
),
FunctionArg::Unnamed(
FunctionArgExpr::Expr(
Expr::Identifier(
Ident {
value: "column_b".to_string(),
quote_style: None,
},
),
),
),
],
clauses: vec![],
},
),
filter: None,
null_treatment: None,
over: None,
within_group: vec![],
},
),
},
SqlOption::Ident("HEAP".into()),
],
),
];
for (sql, with_options) in options {
assert_eq!(
ms_and_generic().verified_stmt(sql),
Statement::CreateTable(CreateTable {
or_replace: false,
temporary: false,
external: false,
global: None,
if_not_exists: false,
transient: false,
volatile: false,
name: ObjectName(vec![Ident {
value: "mytable".to_string(),
quote_style: None,
},],),
columns: vec![
ColumnDef {
name: Ident {
value: "column_a".to_string(),
quote_style: None,
},
data_type: Int(None,),
collation: None,
options: vec![],
},
ColumnDef {
name: Ident {
value: "column_b".to_string(),
quote_style: None,
},
data_type: Int(None,),
collation: None,
options: vec![],
},
ColumnDef {
name: Ident {
value: "column_c".to_string(),
quote_style: None,
},
data_type: Int(None,),
collation: None,
options: vec![],
},
],
constraints: vec![],
hive_distribution: HiveDistributionStyle::NONE,
hive_formats: Some(HiveFormat {
row_format: None,
serde_properties: None,
storage: None,
location: None,
},),
table_properties: vec![],
with_options,
file_format: None,
location: None,
query: None,
without_rowid: false,
like: None,
clone: None,
engine: None,
comment: None,
auto_increment_offset: None,
default_charset: None,
collation: None,
on_commit: None,
on_cluster: None,
primary_key: None,
order_by: None,
partition_by: None,
cluster_by: None,
clustered_by: None,
options: None,
strict: false,
copy_grants: false,
enable_schema_evolution: None,
change_tracking: None,
data_retention_time_in_days: None,
max_data_extension_time_in_days: None,
default_ddl_collation: None,
with_aggregation_policy: None,
with_row_access_policy: None,
with_tags: None,
})
);
}
}
#[test]
fn parse_create_table_with_invalid_options() {
let invalid_cases = vec![
(
"CREATE TABLE mytable (column_a INT, column_b INT, column_c INT) WITH (CLUSTERED COLUMNSTORE INDEX ORDER ())",
"Expected: identifier, found: )",
),
(
"CREATE TABLE mytable (column_a INT, column_b INT, column_c INT) WITH (CLUSTERED COLUMNSTORE)",
"invalid CLUSTERED sequence",
),
(
"CREATE TABLE mytable (column_a INT, column_b INT, column_c INT) WITH (HEAP INDEX)",
"Expected: ), found: INDEX",
),
(
"CREATE TABLE mytable (column_a INT, column_b INT, column_c INT) WITH (PARTITION (RANGE LEFT FOR VALUES (10, 11)))",
"Expected: RANGE, found: LEFT",
),
];
for (sql, expected_error) in invalid_cases {
let res = ms_and_generic().parse_sql_statements(sql);
assert_eq!(
format!("sql parser error: {expected_error}"),
res.unwrap_err().to_string()
);
}
}
fn ms() -> TestedDialects {
TestedDialects {
dialects: vec![Box::new(MsSqlDialect {})],