Merge pull request #173 from alex-dukhno/create-schema

Support `CREATE SCHEMA schema_name` and `DROP SCHEMA schema_name`.

Both ANSI SQL and Posgres define a number of options for the CREATE SCHEMA statement.
They also support including other CREATE statements as part of the schema definition,
rather than separate statements. This PR supports neither.
This commit is contained in:
Nickolay Ponomarev 2020-05-28 21:05:34 +03:00 committed by GitHub
commit c918ff042d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 42 additions and 2 deletions

View file

@ -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",
})
}
}

View file

@ -330,6 +330,7 @@ define_keywords!(
ROW_NUMBER,
ROWS,
SAVEPOINT,
SCHEMA,
SCOPE,
SCROLL,
SEARCH,

View file

@ -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<Statement, ParserError> {
let schema_name = self.parse_object_name()?;
Ok(Statement::CreateSchema { schema_name })
}
pub fn parse_create_external_table(&mut self) -> Result<Statement, ParserError> {
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

View file

@ -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 {