Skip to content

Commit 1ac2083

Browse files
authored
Support IF NOT EXISTS for CREATE SCHEMA (apache#276)
This is a Postgres-specific clause: https://www.postgresql.org/docs/12/sql-createschema.html Also add a test for `DROP SCHEMA IF EXISTS schema_name`, which is already supported in the parser.
1 parent 926b03a commit 1ac2083

File tree

4 files changed

+46
-4
lines changed

4 files changed

+46
-4
lines changed

src/ast/mod.rs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -558,7 +558,10 @@ pub enum Statement {
558558
/// `ROLLBACK [ TRANSACTION | WORK ] [ AND [ NO ] CHAIN ]`
559559
Rollback { chain: bool },
560560
/// CREATE SCHEMA
561-
CreateSchema { schema_name: ObjectName },
561+
CreateSchema {
562+
schema_name: ObjectName,
563+
if_not_exists: bool,
564+
},
562565
/// `ASSERT <condition> [AS <message>]`
563566
Assert {
564567
condition: Expr,
@@ -829,7 +832,15 @@ impl fmt::Display for Statement {
829832
Statement::Rollback { chain } => {
830833
write!(f, "ROLLBACK{}", if *chain { " AND CHAIN" } else { "" },)
831834
}
832-
Statement::CreateSchema { schema_name } => write!(f, "CREATE SCHEMA {}", schema_name),
835+
Statement::CreateSchema {
836+
schema_name,
837+
if_not_exists,
838+
} => write!(
839+
f,
840+
"CREATE SCHEMA {if_not_exists}{name}",
841+
if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
842+
name = schema_name
843+
),
833844
Statement::Assert { condition, message } => {
834845
write!(f, "ASSERT {}", condition)?;
835846
if let Some(m) = message {

src/parser.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1078,8 +1078,12 @@ impl<'a> Parser<'a> {
10781078
}
10791079

10801080
pub fn parse_create_schema(&mut self) -> Result<Statement, ParserError> {
1081+
let if_not_exists = self.parse_keywords(&[Keyword::IF, Keyword::NOT, Keyword::EXISTS]);
10811082
let schema_name = self.parse_object_name()?;
1082-
Ok(Statement::CreateSchema { schema_name })
1083+
Ok(Statement::CreateSchema {
1084+
schema_name,
1085+
if_not_exists,
1086+
})
10831087
}
10841088

10851089
pub fn parse_create_external_table(

tests/sqlparser_common.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1204,7 +1204,7 @@ fn parse_create_schema() {
12041204
let sql = "CREATE SCHEMA X";
12051205

12061206
match verified_stmt(sql) {
1207-
Statement::CreateSchema { schema_name } => {
1207+
Statement::CreateSchema { schema_name, .. } => {
12081208
assert_eq!(schema_name.to_string(), "X".to_owned())
12091209
}
12101210
_ => unreachable!(),

tests/sqlparser_postgres.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,33 @@ fn parse_bad_if_not_exists() {
300300
);
301301
}
302302

303+
#[test]
304+
fn parse_create_schema_if_not_exists() {
305+
let sql = "CREATE SCHEMA IF NOT EXISTS schema_name";
306+
let ast = pg_and_generic().verified_stmt(sql);
307+
match ast {
308+
Statement::CreateSchema {
309+
if_not_exists: true,
310+
schema_name,
311+
} => assert_eq!("schema_name", schema_name.to_string()),
312+
_ => unreachable!(),
313+
}
314+
}
315+
316+
#[test]
317+
fn parse_drop_schema_if_exists() {
318+
let sql = "DROP SCHEMA IF EXISTS schema_name";
319+
let ast = pg().verified_stmt(sql);
320+
match ast {
321+
Statement::Drop {
322+
object_type,
323+
if_exists: true,
324+
..
325+
} => assert_eq!(object_type, ObjectType::Schema),
326+
_ => unreachable!(),
327+
}
328+
}
329+
303330
#[test]
304331
fn parse_copy_example() {
305332
let sql = r#"COPY public.actor (actor_id, first_name, last_name, last_update, value) FROM stdin;

0 commit comments

Comments
 (0)