Support IF NOT EXISTS for CREATE SCHEMA (#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.
This commit is contained in:
Alex Dukhno 2020-10-02 17:35:20 +03:00 committed by GitHub
parent 926b03a31d
commit 1ac208307c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 46 additions and 4 deletions

View file

@ -558,7 +558,10 @@ pub enum Statement {
/// `ROLLBACK [ TRANSACTION | WORK ] [ AND [ NO ] CHAIN ]` /// `ROLLBACK [ TRANSACTION | WORK ] [ AND [ NO ] CHAIN ]`
Rollback { chain: bool }, Rollback { chain: bool },
/// CREATE SCHEMA /// CREATE SCHEMA
CreateSchema { schema_name: ObjectName }, CreateSchema {
schema_name: ObjectName,
if_not_exists: bool,
},
/// `ASSERT <condition> [AS <message>]` /// `ASSERT <condition> [AS <message>]`
Assert { Assert {
condition: Expr, condition: Expr,
@ -829,7 +832,15 @@ impl fmt::Display for Statement {
Statement::Rollback { chain } => { Statement::Rollback { chain } => {
write!(f, "ROLLBACK{}", if *chain { " AND CHAIN" } else { "" },) write!(f, "ROLLBACK{}", if *chain { " AND CHAIN" } else { "" },)
} }
Statement::CreateSchema { schema_name } => write!(f, "CREATE SCHEMA {}", schema_name), Statement::CreateSchema {
schema_name,
if_not_exists,
} => write!(
f,
"CREATE SCHEMA {if_not_exists}{name}",
if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
name = schema_name
),
Statement::Assert { condition, message } => { Statement::Assert { condition, message } => {
write!(f, "ASSERT {}", condition)?; write!(f, "ASSERT {}", condition)?;
if let Some(m) = message { if let Some(m) = message {

View file

@ -1078,8 +1078,12 @@ impl<'a> Parser<'a> {
} }
pub fn parse_create_schema(&mut self) -> Result<Statement, ParserError> { pub fn parse_create_schema(&mut self) -> Result<Statement, ParserError> {
let if_not_exists = self.parse_keywords(&[Keyword::IF, Keyword::NOT, Keyword::EXISTS]);
let schema_name = self.parse_object_name()?; let schema_name = self.parse_object_name()?;
Ok(Statement::CreateSchema { schema_name }) Ok(Statement::CreateSchema {
schema_name,
if_not_exists,
})
} }
pub fn parse_create_external_table( pub fn parse_create_external_table(

View file

@ -1204,7 +1204,7 @@ fn parse_create_schema() {
let sql = "CREATE SCHEMA X"; let sql = "CREATE SCHEMA X";
match verified_stmt(sql) { match verified_stmt(sql) {
Statement::CreateSchema { schema_name } => { Statement::CreateSchema { schema_name, .. } => {
assert_eq!(schema_name.to_string(), "X".to_owned()) assert_eq!(schema_name.to_string(), "X".to_owned())
} }
_ => unreachable!(), _ => unreachable!(),

View file

@ -300,6 +300,33 @@ fn parse_bad_if_not_exists() {
); );
} }
#[test]
fn parse_create_schema_if_not_exists() {
let sql = "CREATE SCHEMA IF NOT EXISTS schema_name";
let ast = pg_and_generic().verified_stmt(sql);
match ast {
Statement::CreateSchema {
if_not_exists: true,
schema_name,
} => assert_eq!("schema_name", schema_name.to_string()),
_ => unreachable!(),
}
}
#[test]
fn parse_drop_schema_if_exists() {
let sql = "DROP SCHEMA IF EXISTS schema_name";
let ast = pg().verified_stmt(sql);
match ast {
Statement::Drop {
object_type,
if_exists: true,
..
} => assert_eq!(object_type, ObjectType::Schema),
_ => unreachable!(),
}
}
#[test] #[test]
fn parse_copy_example() { fn parse_copy_example() {
let sql = r#"COPY public.actor (actor_id, first_name, last_name, last_update, value) FROM stdin; let sql = r#"COPY public.actor (actor_id, first_name, last_name, last_update, value) FROM stdin;