Skip to content

Commit c9fc3fe

Browse files
committed
Merge branch 'main' into solontsev/pg-regex-ops-fix
2 parents 60acdc5 + 1a33abd commit c9fc3fe

11 files changed

Lines changed: 188 additions & 19 deletions

File tree

src/ast/ddl.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -140,10 +140,10 @@ pub enum AlterTableOperation {
140140
name: Ident,
141141
drop_behavior: Option<DropBehavior>,
142142
},
143-
/// `DROP [ COLUMN ] [ IF EXISTS ] <column_name> [ CASCADE ]`
143+
/// `DROP [ COLUMN ] [ IF EXISTS ] <column_name> [ , <column_name>, ... ] [ CASCADE ]`
144144
DropColumn {
145145
has_column_keyword: bool,
146-
column_name: Ident,
146+
column_names: Vec<Ident>,
147147
if_exists: bool,
148148
drop_behavior: Option<DropBehavior>,
149149
},
@@ -631,15 +631,15 @@ impl fmt::Display for AlterTableOperation {
631631
AlterTableOperation::DropIndex { name } => write!(f, "DROP INDEX {name}"),
632632
AlterTableOperation::DropColumn {
633633
has_column_keyword,
634-
column_name,
634+
column_names: column_name,
635635
if_exists,
636636
drop_behavior,
637637
} => write!(
638638
f,
639639
"DROP {}{}{}{}",
640640
if *has_column_keyword { "COLUMN " } else { "" },
641641
if *if_exists { "IF EXISTS " } else { "" },
642-
column_name,
642+
display_comma_separated(column_name),
643643
match drop_behavior {
644644
None => "",
645645
Some(DropBehavior::Restrict) => " RESTRICT",

src/ast/mod.rs

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6928,12 +6928,24 @@ pub enum GrantObjects {
69286928
AllSequencesInSchema { schemas: Vec<ObjectName> },
69296929
/// Grant privileges on `ALL TABLES IN SCHEMA <schema_name> [, ...]`
69306930
AllTablesInSchema { schemas: Vec<ObjectName> },
6931+
/// Grant privileges on `ALL VIEWS IN SCHEMA <schema_name> [, ...]`
6932+
AllViewsInSchema { schemas: Vec<ObjectName> },
6933+
/// Grant privileges on `ALL MATERIALIZED VIEWS IN SCHEMA <schema_name> [, ...]`
6934+
AllMaterializedViewsInSchema { schemas: Vec<ObjectName> },
6935+
/// Grant privileges on `ALL EXTERNAL TABLES IN SCHEMA <schema_name> [, ...]`
6936+
AllExternalTablesInSchema { schemas: Vec<ObjectName> },
69316937
/// Grant privileges on `FUTURE SCHEMAS IN DATABASE <database_name> [, ...]`
69326938
FutureSchemasInDatabase { databases: Vec<ObjectName> },
69336939
/// Grant privileges on `FUTURE TABLES IN SCHEMA <schema_name> [, ...]`
69346940
FutureTablesInSchema { schemas: Vec<ObjectName> },
69356941
/// Grant privileges on `FUTURE VIEWS IN SCHEMA <schema_name> [, ...]`
69366942
FutureViewsInSchema { schemas: Vec<ObjectName> },
6943+
/// Grant privileges on `FUTURE EXTERNAL TABLES IN SCHEMA <schema_name> [, ...]`
6944+
FutureExternalTablesInSchema { schemas: Vec<ObjectName> },
6945+
/// Grant privileges on `FUTURE MATERIALIZED VIEWS IN SCHEMA <schema_name> [, ...]`
6946+
FutureMaterializedViewsInSchema { schemas: Vec<ObjectName> },
6947+
/// Grant privileges on `FUTURE SEQUENCES IN SCHEMA <schema_name> [, ...]`
6948+
FutureSequencesInSchema { schemas: Vec<ObjectName> },
69376949
/// Grant privileges on specific databases
69386950
Databases(Vec<ObjectName>),
69396951
/// Grant privileges on specific schemas
@@ -7002,6 +7014,27 @@ impl fmt::Display for GrantObjects {
70027014
display_comma_separated(schemas)
70037015
)
70047016
}
7017+
GrantObjects::AllExternalTablesInSchema { schemas } => {
7018+
write!(
7019+
f,
7020+
"ALL EXTERNAL TABLES IN SCHEMA {}",
7021+
display_comma_separated(schemas)
7022+
)
7023+
}
7024+
GrantObjects::AllViewsInSchema { schemas } => {
7025+
write!(
7026+
f,
7027+
"ALL VIEWS IN SCHEMA {}",
7028+
display_comma_separated(schemas)
7029+
)
7030+
}
7031+
GrantObjects::AllMaterializedViewsInSchema { schemas } => {
7032+
write!(
7033+
f,
7034+
"ALL MATERIALIZED VIEWS IN SCHEMA {}",
7035+
display_comma_separated(schemas)
7036+
)
7037+
}
70057038
GrantObjects::FutureSchemasInDatabase { databases } => {
70067039
write!(
70077040
f,
@@ -7016,13 +7049,34 @@ impl fmt::Display for GrantObjects {
70167049
display_comma_separated(schemas)
70177050
)
70187051
}
7052+
GrantObjects::FutureExternalTablesInSchema { schemas } => {
7053+
write!(
7054+
f,
7055+
"FUTURE EXTERNAL TABLES IN SCHEMA {}",
7056+
display_comma_separated(schemas)
7057+
)
7058+
}
70197059
GrantObjects::FutureViewsInSchema { schemas } => {
70207060
write!(
70217061
f,
70227062
"FUTURE VIEWS IN SCHEMA {}",
70237063
display_comma_separated(schemas)
70247064
)
70257065
}
7066+
GrantObjects::FutureMaterializedViewsInSchema { schemas } => {
7067+
write!(
7068+
f,
7069+
"FUTURE MATERIALIZED VIEWS IN SCHEMA {}",
7070+
display_comma_separated(schemas)
7071+
)
7072+
}
7073+
GrantObjects::FutureSequencesInSchema { schemas } => {
7074+
write!(
7075+
f,
7076+
"FUTURE SEQUENCES IN SCHEMA {}",
7077+
display_comma_separated(schemas)
7078+
)
7079+
}
70267080
GrantObjects::ResourceMonitors(objects) => {
70277081
write!(f, "RESOURCE MONITOR {}", display_comma_separated(objects))
70287082
}

src/ast/spans.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1112,10 +1112,10 @@ impl Spanned for AlterTableOperation {
11121112
} => name.span,
11131113
AlterTableOperation::DropColumn {
11141114
has_column_keyword: _,
1115-
column_name,
1115+
column_names,
11161116
if_exists: _,
11171117
drop_behavior: _,
1118-
} => column_name.span,
1118+
} => union_spans(column_names.iter().map(|i| i.span)),
11191119
AlterTableOperation::AttachPartition { partition } => partition.span(),
11201120
AlterTableOperation::DetachPartition { partition } => partition.span(),
11211121
AlterTableOperation::FreezePartition {

src/dialect/generic.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,10 @@ impl Dialect for GenericDialect {
116116
true
117117
}
118118

119+
fn supports_projection_trailing_commas(&self) -> bool {
120+
true
121+
}
122+
119123
fn supports_asc_desc_in_column_definition(&self) -> bool {
120124
true
121125
}

src/dialect/mod.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1071,6 +1071,11 @@ pub trait Dialect: Debug + Any {
10711071
fn supports_alter_column_type_using(&self) -> bool {
10721072
false
10731073
}
1074+
1075+
/// Returns true if the dialect supports `ALTER TABLE tbl DROP COLUMN c1, ..., cn`
1076+
fn supports_comma_separated_drop_column_list(&self) -> bool {
1077+
false
1078+
}
10741079
}
10751080

10761081
/// This represents the operators for which precedence must be defined

src/dialect/snowflake.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -301,9 +301,8 @@ impl Dialect for SnowflakeDialect {
301301
true
302302
}
303303

304-
fn is_select_item_alias(&self, explicit: bool, kw: &Keyword, parser: &mut Parser) -> bool {
305-
explicit
306-
|| match kw {
304+
fn is_column_alias(&self, kw: &Keyword, parser: &mut Parser) -> bool {
305+
match kw {
307306
// The following keywords can be considered an alias as long as
308307
// they are not followed by other tokens that may change their meaning
309308
// e.g. `SELECT * EXCEPT (col1) FROM tbl`
@@ -364,6 +363,10 @@ impl Dialect for SnowflakeDialect {
364363
fn supports_space_separated_column_options(&self) -> bool {
365364
true
366365
}
366+
367+
fn supports_comma_separated_drop_column_list(&self) -> bool {
368+
true
369+
}
367370
}
368371

369372
fn parse_file_staging_command(kw: Keyword, parser: &mut Parser) -> Result<Statement, ParserError> {

src/parser/mod.rs

Lines changed: 66 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8683,11 +8683,15 @@ impl<'a> Parser<'a> {
86838683
} else {
86848684
let has_column_keyword = self.parse_keyword(Keyword::COLUMN); // [ COLUMN ]
86858685
let if_exists = self.parse_keywords(&[Keyword::IF, Keyword::EXISTS]);
8686-
let column_name = self.parse_identifier()?;
8686+
let column_names = if self.dialect.supports_comma_separated_drop_column_list() {
8687+
self.parse_comma_separated(Parser::parse_identifier)?
8688+
} else {
8689+
vec![self.parse_identifier()?]
8690+
};
86878691
let drop_behavior = self.parse_optional_drop_behavior();
86888692
AlterTableOperation::DropColumn {
86898693
has_column_keyword,
8690-
column_name,
8694+
column_names,
86918695
if_exists,
86928696
drop_behavior,
86938697
}
@@ -13905,6 +13909,35 @@ impl<'a> Parser<'a> {
1390513909
Some(GrantObjects::AllTablesInSchema {
1390613910
schemas: self.parse_comma_separated(|p| p.parse_object_name(false))?,
1390713911
})
13912+
} else if self.parse_keywords(&[
13913+
Keyword::ALL,
13914+
Keyword::EXTERNAL,
13915+
Keyword::TABLES,
13916+
Keyword::IN,
13917+
Keyword::SCHEMA,
13918+
]) {
13919+
Some(GrantObjects::AllExternalTablesInSchema {
13920+
schemas: self.parse_comma_separated(|p| p.parse_object_name(false))?,
13921+
})
13922+
} else if self.parse_keywords(&[
13923+
Keyword::ALL,
13924+
Keyword::VIEWS,
13925+
Keyword::IN,
13926+
Keyword::SCHEMA,
13927+
]) {
13928+
Some(GrantObjects::AllViewsInSchema {
13929+
schemas: self.parse_comma_separated(|p| p.parse_object_name(false))?,
13930+
})
13931+
} else if self.parse_keywords(&[
13932+
Keyword::ALL,
13933+
Keyword::MATERIALIZED,
13934+
Keyword::VIEWS,
13935+
Keyword::IN,
13936+
Keyword::SCHEMA,
13937+
]) {
13938+
Some(GrantObjects::AllMaterializedViewsInSchema {
13939+
schemas: self.parse_comma_separated(|p| p.parse_object_name(false))?,
13940+
})
1390813941
} else if self.parse_keywords(&[
1390913942
Keyword::FUTURE,
1391013943
Keyword::SCHEMAS,
@@ -13923,6 +13956,16 @@ impl<'a> Parser<'a> {
1392313956
Some(GrantObjects::FutureTablesInSchema {
1392413957
schemas: self.parse_comma_separated(|p| p.parse_object_name(false))?,
1392513958
})
13959+
} else if self.parse_keywords(&[
13960+
Keyword::FUTURE,
13961+
Keyword::EXTERNAL,
13962+
Keyword::TABLES,
13963+
Keyword::IN,
13964+
Keyword::SCHEMA,
13965+
]) {
13966+
Some(GrantObjects::FutureExternalTablesInSchema {
13967+
schemas: self.parse_comma_separated(|p| p.parse_object_name(false))?,
13968+
})
1392613969
} else if self.parse_keywords(&[
1392713970
Keyword::FUTURE,
1392813971
Keyword::VIEWS,
@@ -13932,6 +13975,16 @@ impl<'a> Parser<'a> {
1393213975
Some(GrantObjects::FutureViewsInSchema {
1393313976
schemas: self.parse_comma_separated(|p| p.parse_object_name(false))?,
1393413977
})
13978+
} else if self.parse_keywords(&[
13979+
Keyword::FUTURE,
13980+
Keyword::MATERIALIZED,
13981+
Keyword::VIEWS,
13982+
Keyword::IN,
13983+
Keyword::SCHEMA,
13984+
]) {
13985+
Some(GrantObjects::FutureMaterializedViewsInSchema {
13986+
schemas: self.parse_comma_separated(|p| p.parse_object_name(false))?,
13987+
})
1393513988
} else if self.parse_keywords(&[
1393613989
Keyword::ALL,
1393713990
Keyword::SEQUENCES,
@@ -13941,6 +13994,15 @@ impl<'a> Parser<'a> {
1394113994
Some(GrantObjects::AllSequencesInSchema {
1394213995
schemas: self.parse_comma_separated(|p| p.parse_object_name(false))?,
1394313996
})
13997+
} else if self.parse_keywords(&[
13998+
Keyword::FUTURE,
13999+
Keyword::SEQUENCES,
14000+
Keyword::IN,
14001+
Keyword::SCHEMA,
14002+
]) {
14003+
Some(GrantObjects::FutureSequencesInSchema {
14004+
schemas: self.parse_comma_separated(|p| p.parse_object_name(false))?,
14005+
})
1394414006
} else if self.parse_keywords(&[Keyword::RESOURCE, Keyword::MONITOR]) {
1394514007
Some(GrantObjects::ResourceMonitors(self.parse_comma_separated(
1394614008
|p| p.parse_object_name_with_wildcards(false, true),
@@ -16199,9 +16261,9 @@ impl<'a> Parser<'a> {
1619916261

1620016262
fn parse_parenthesized_identifiers(&mut self) -> Result<Vec<Ident>, ParserError> {
1620116263
self.expect_token(&Token::LParen)?;
16202-
let partitions = self.parse_comma_separated(|p| p.parse_identifier())?;
16264+
let idents = self.parse_comma_separated0(|p| p.parse_identifier(), Token::RParen)?;
1620316265
self.expect_token(&Token::RParen)?;
16204-
Ok(partitions)
16266+
Ok(idents)
1620516267
}
1620616268

1620716269
fn parse_column_position(&mut self) -> Result<Option<MySQLColumnPosition>, ParserError> {

tests/sqlparser_clickhouse.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,10 @@ fn parse_create_table() {
224224
clickhouse().verified_stmt(
225225
r#"CREATE TABLE "x" ("a" "int") ENGINE = MergeTree ORDER BY "x" AS SELECT * FROM "t" WHERE true"#,
226226
);
227+
clickhouse().one_statement_parses_to(
228+
"CREATE TABLE x (a int) ENGINE = MergeTree() ORDER BY a",
229+
"CREATE TABLE x (a INT) ENGINE = MergeTree ORDER BY a",
230+
);
227231
}
228232

229233
#[test]

tests/sqlparser_common.rs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4996,15 +4996,18 @@ fn parse_alter_table_drop_column() {
49964996
"ALTER TABLE tab DROP is_active CASCADE",
49974997
);
49984998

4999+
let dialects = all_dialects_where(|d| d.supports_comma_separated_drop_column_list());
5000+
dialects.verified_stmt("ALTER TABLE tbl DROP COLUMN c1, c2, c3");
5001+
49995002
fn check_one(constraint_text: &str) {
50005003
match alter_table_op(verified_stmt(&format!("ALTER TABLE tab {constraint_text}"))) {
50015004
AlterTableOperation::DropColumn {
50025005
has_column_keyword: true,
5003-
column_name,
5006+
column_names,
50045007
if_exists,
50055008
drop_behavior,
50065009
} => {
5007-
assert_eq!("is_active", column_name.to_string());
5010+
assert_eq!("is_active", column_names.first().unwrap().to_string());
50085011
assert!(if_exists);
50095012
match drop_behavior {
50105013
None => assert!(constraint_text.ends_with(" is_active")),
@@ -9431,6 +9434,9 @@ fn parse_grant() {
94319434
verified_stmt("GRANT SELECT ON ALL TABLES IN SCHEMA db1.sc1 TO APPLICATION role1");
94329435
verified_stmt("GRANT SELECT ON ALL TABLES IN SCHEMA db1.sc1 TO APPLICATION ROLE role1");
94339436
verified_stmt("GRANT SELECT ON ALL TABLES IN SCHEMA db1.sc1 TO SHARE share1");
9437+
verified_stmt("GRANT SELECT ON ALL VIEWS IN SCHEMA db1.sc1 TO ROLE role1");
9438+
verified_stmt("GRANT SELECT ON ALL MATERIALIZED VIEWS IN SCHEMA db1.sc1 TO ROLE role1");
9439+
verified_stmt("GRANT SELECT ON ALL EXTERNAL TABLES IN SCHEMA db1.sc1 TO ROLE role1");
94349440
verified_stmt("GRANT USAGE ON SCHEMA sc1 TO a:b");
94359441
verified_stmt("GRANT USAGE ON SCHEMA sc1 TO GROUP group1");
94369442
verified_stmt("GRANT OWNERSHIP ON ALL TABLES IN SCHEMA DEV_STAS_ROGOZHIN TO ROLE ANALYST");
@@ -9444,7 +9450,10 @@ fn parse_grant() {
94449450
.verified_stmt("GRANT SELECT ON [my_table] TO [public]");
94459451
verified_stmt("GRANT SELECT ON FUTURE SCHEMAS IN DATABASE db1 TO ROLE role1");
94469452
verified_stmt("GRANT SELECT ON FUTURE TABLES IN SCHEMA db1.sc1 TO ROLE role1");
9453+
verified_stmt("GRANT SELECT ON FUTURE EXTERNAL TABLES IN SCHEMA db1.sc1 TO ROLE role1");
94479454
verified_stmt("GRANT SELECT ON FUTURE VIEWS IN SCHEMA db1.sc1 TO ROLE role1");
9455+
verified_stmt("GRANT SELECT ON FUTURE MATERIALIZED VIEWS IN SCHEMA db1.sc1 TO ROLE role1");
9456+
verified_stmt("GRANT SELECT ON FUTURE SEQUENCES IN SCHEMA db1.sc1 TO ROLE role1");
94489457
}
94499458

94509459
#[test]
@@ -11181,7 +11190,7 @@ fn parse_trailing_comma() {
1118111190
trailing_commas.verified_stmt(r#"SELECT "from" FROM "from""#);
1118211191

1118311192
// doesn't allow any trailing commas
11184-
let trailing_commas = TestedDialects::new(vec![Box::new(GenericDialect {})]);
11193+
let trailing_commas = TestedDialects::new(vec![Box::new(PostgreSqlDialect {})]);
1118511194

1118611195
assert_eq!(
1118711196
trailing_commas

tests/sqlparser_mysql.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2876,7 +2876,7 @@ fn parse_alter_table_with_algorithm() {
28762876
vec![
28772877
AlterTableOperation::DropColumn {
28782878
has_column_keyword: true,
2879-
column_name: Ident::new("password_digest"),
2879+
column_names: vec![Ident::new("password_digest")],
28802880
if_exists: false,
28812881
drop_behavior: None,
28822882
},
@@ -2924,7 +2924,7 @@ fn parse_alter_table_with_lock() {
29242924
vec![
29252925
AlterTableOperation::DropColumn {
29262926
has_column_keyword: true,
2927-
column_name: Ident::new("password_digest"),
2927+
column_names: vec![Ident::new("password_digest")],
29282928
if_exists: false,
29292929
drop_behavior: None,
29302930
},

0 commit comments

Comments
 (0)