diff --git a/src/ast/mod.rs b/src/ast/mod.rs index bc5c5dafc..a867abcf9 100644 --- a/src/ast/mod.rs +++ b/src/ast/mod.rs @@ -535,6 +535,8 @@ pub enum Statement { Commit { chain: bool }, /// `ROLLBACK [ TRANSACTION | WORK ] [ AND [ NO ] CHAIN ]` Rollback { chain: bool }, + /// CREATE SCHEMA + CreateSchema { schema_name: ObjectName }, } impl fmt::Display for Statement { @@ -754,6 +756,7 @@ impl fmt::Display for Statement { Statement::Rollback { chain } => { write!(f, "ROLLBACK{}", if *chain { " AND CHAIN" } else { "" },) } + Statement::CreateSchema { schema_name } => write!(f, "CREATE SCHEMA {}", schema_name), } } } @@ -852,6 +855,7 @@ pub enum ObjectType { Table, View, Index, + Schema, } impl fmt::Display for ObjectType { @@ -860,6 +864,7 @@ impl fmt::Display for ObjectType { ObjectType::Table => "TABLE", ObjectType::View => "VIEW", ObjectType::Index => "INDEX", + ObjectType::Schema => "SCHEMA", }) } } diff --git a/src/dialect/keywords.rs b/src/dialect/keywords.rs index 4f39904b6..b8f8817f5 100644 --- a/src/dialect/keywords.rs +++ b/src/dialect/keywords.rs @@ -330,6 +330,7 @@ define_keywords!( ROW_NUMBER, ROWS, SAVEPOINT, + SCHEMA, SCOPE, SCROLL, SEARCH, diff --git a/src/parser.rs b/src/parser.rs index 5741167de..d235eb169 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -864,11 +864,21 @@ impl Parser { self.parse_create_view() } else if self.parse_keyword("EXTERNAL") { self.parse_create_external_table() + } else if self.parse_keyword("SCHEMA") { + self.parse_create_schema() } else { - self.expected("TABLE, VIEW or INDEX after CREATE", self.peek_token()) + self.expected( + "TABLE, VIEW, INDEX or SCHEMA after CREATE", + self.peek_token(), + ) } } + pub fn parse_create_schema(&mut self) -> Result { + let schema_name = self.parse_object_name()?; + Ok(Statement::CreateSchema { schema_name }) + } + pub fn parse_create_external_table(&mut self) -> Result { self.expect_keyword("TABLE")?; let table_name = self.parse_object_name()?; @@ -918,8 +928,10 @@ impl Parser { ObjectType::View } else if self.parse_keyword("INDEX") { ObjectType::Index + } else if self.parse_keyword("SCHEMA") { + ObjectType::Schema } else { - return self.expected("TABLE, VIEW or INDEX after DROP", self.peek_token()); + return self.expected("TABLE, VIEW, INDEX or SCHEMA after DROP", self.peek_token()); }; // Many dialects support the non standard `IF EXISTS` clause and allow // specifying multiple objects to delete in a single statement diff --git a/tests/sqlparser_common.rs b/tests/sqlparser_common.rs index 47d7db053..7272e35ac 100644 --- a/tests/sqlparser_common.rs +++ b/tests/sqlparser_common.rs @@ -1027,6 +1027,28 @@ fn parse_create_table_with_multiple_on_delete_fails() { .expect_err("should have failed"); } +#[test] +fn parse_create_schema() { + let sql = "CREATE SCHEMA X"; + + match verified_stmt(sql) { + Statement::CreateSchema { schema_name } => { + assert_eq!(schema_name.to_string(), "X".to_owned()) + } + _ => unreachable!(), + } +} + +#[test] +fn parse_drop_schema() { + let sql = "DROP SCHEMA X"; + + match verified_stmt(sql) { + Statement::Drop { object_type, .. } => assert_eq!(object_type, ObjectType::Schema), + _ => unreachable!(), + } +} + #[test] fn parse_create_table_with_on_delete_on_update_2in_any_order() -> Result<(), ParserError> { let sql = |options: &str| -> String {