Skip to content

Commit d5e66f5

Browse files
hovaescosabir-akhadov-localstack
authored andcommitted
Accept CREATE OR REPLACE SCHEMA
Add an `or_replace: bool` field to `Statement::CreateSchema` and route the SCHEMA keyword ahead of the `or_replace` whitelist bail-out in `Parser::parse_create` so that `CREATE OR REPLACE SCHEMA [IF NOT EXISTS] foo` parses successfully. Display round-trips OR REPLACE.
1 parent be95cf6 commit d5e66f5

3 files changed

Lines changed: 43 additions & 5 deletions

File tree

src/ast/mod.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4356,6 +4356,8 @@ pub enum Statement {
43564356
CreateSchema {
43574357
/// `<schema name> | AUTHORIZATION <schema authorization identifier> | <schema name> AUTHORIZATION <schema authorization identifier>`
43584358
schema_name: SchemaName,
4359+
/// `true` when `OR REPLACE` was present.
4360+
or_replace: bool,
43594361
/// `true` when `IF NOT EXISTS` was present.
43604362
if_not_exists: bool,
43614363
/// Schema properties.
@@ -6018,6 +6020,7 @@ impl fmt::Display for Statement {
60186020
}
60196021
Statement::CreateSchema {
60206022
schema_name,
6023+
or_replace,
60216024
if_not_exists,
60226025
with,
60236026
options,
@@ -6026,7 +6029,8 @@ impl fmt::Display for Statement {
60266029
} => {
60276030
write!(
60286031
f,
6029-
"CREATE SCHEMA {if_not_exists}{name}",
6032+
"CREATE {or_replace}SCHEMA {if_not_exists}{name}",
6033+
or_replace = if *or_replace { "OR REPLACE " } else { "" },
60306034
if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
60316035
name = schema_name
60326036
)?;

src/parser/mod.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5283,9 +5283,11 @@ impl<'a> Parser<'a> {
52835283
self.parse_create_secret(or_replace, temporary, persistent)
52845284
} else if self.parse_keyword(Keyword::USER) {
52855285
self.parse_create_user(or_replace).map(Into::into)
5286+
} else if self.parse_keyword(Keyword::SCHEMA) {
5287+
self.parse_create_schema(or_replace)
52865288
} else if or_replace {
52875289
self.expected_ref(
5288-
"[EXTERNAL] TABLE or [MATERIALIZED] VIEW or FUNCTION after CREATE OR REPLACE",
5290+
"[EXTERNAL] TABLE or [MATERIALIZED] VIEW or FUNCTION or SCHEMA after CREATE OR REPLACE",
52895291
self.peek_token_ref(),
52905292
)
52915293
} else if self.parse_keyword(Keyword::EXTENSION) {
@@ -5296,8 +5298,6 @@ impl<'a> Parser<'a> {
52965298
self.parse_create_index(true).map(Into::into)
52975299
} else if self.parse_keyword(Keyword::VIRTUAL) {
52985300
self.parse_create_virtual_table()
5299-
} else if self.parse_keyword(Keyword::SCHEMA) {
5300-
self.parse_create_schema()
53015301
} else if self.parse_keyword(Keyword::DATABASE) {
53025302
self.parse_create_database()
53035303
} else if self.parse_keyword(Keyword::ROLE) {
@@ -5611,7 +5611,7 @@ impl<'a> Parser<'a> {
56115611
}
56125612

56135613
/// Parse a `CREATE SCHEMA` statement.
5614-
pub fn parse_create_schema(&mut self) -> Result<Statement, ParserError> {
5614+
pub fn parse_create_schema(&mut self, or_replace: bool) -> Result<Statement, ParserError> {
56155615
let if_not_exists = self.parse_keywords(&[Keyword::IF, Keyword::NOT, Keyword::EXISTS]);
56165616

56175617
let schema_name = self.parse_schema_name()?;
@@ -5642,6 +5642,7 @@ impl<'a> Parser<'a> {
56425642

56435643
Ok(Statement::CreateSchema {
56445644
schema_name,
5645+
or_replace,
56455646
if_not_exists,
56465647
with,
56475648
options,

tests/sqlparser_common.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4545,6 +4545,39 @@ fn parse_create_schema() {
45454545
verified_stmt(r#"CREATE SCHEMA a CLONE b"#);
45464546
}
45474547

4548+
#[test]
4549+
fn parse_create_or_replace_schema() {
4550+
let sql = "CREATE OR REPLACE SCHEMA X";
4551+
match verified_stmt(sql) {
4552+
Statement::CreateSchema {
4553+
schema_name,
4554+
or_replace,
4555+
if_not_exists,
4556+
..
4557+
} => {
4558+
assert_eq!(schema_name.to_string(), "X".to_owned());
4559+
assert!(or_replace);
4560+
assert!(!if_not_exists);
4561+
}
4562+
_ => unreachable!(),
4563+
}
4564+
4565+
let sql = "CREATE OR REPLACE SCHEMA IF NOT EXISTS X";
4566+
match verified_stmt(sql) {
4567+
Statement::CreateSchema {
4568+
schema_name,
4569+
or_replace,
4570+
if_not_exists,
4571+
..
4572+
} => {
4573+
assert_eq!(schema_name.to_string(), "X".to_owned());
4574+
assert!(or_replace);
4575+
assert!(if_not_exists);
4576+
}
4577+
_ => unreachable!(),
4578+
}
4579+
}
4580+
45484581
#[test]
45494582
fn parse_create_schema_with_authorization() {
45504583
let sql = "CREATE SCHEMA AUTHORIZATION Y";

0 commit comments

Comments
 (0)