Skip to content

Commit 130f3fe

Browse files
yoavcloudayman-sigma
authored andcommitted
Snowflake: Support CLONE option in CREATE DATABASE/SCHEMA statements (apache#1958)
1 parent 0dd47a1 commit 130f3fe

File tree

3 files changed

+63
-0
lines changed

3 files changed

+63
-0
lines changed

src/ast/mod.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3875,6 +3875,14 @@ pub enum Statement {
38753875
///
38763876
/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_schema_statement)
38773877
default_collate_spec: Option<Expr>,
3878+
/// Clones a schema
3879+
///
3880+
/// ```sql
3881+
/// CREATE SCHEMA myschema CLONE otherschema
3882+
/// ```
3883+
///
3884+
/// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-clone#databases-schemas)
3885+
clone: Option<ObjectName>,
38783886
},
38793887
/// ```sql
38803888
/// CREATE DATABASE
@@ -3884,6 +3892,14 @@ pub enum Statement {
38843892
if_not_exists: bool,
38853893
location: Option<String>,
38863894
managed_location: Option<String>,
3895+
/// Clones a database
3896+
///
3897+
/// ```sql
3898+
/// CREATE DATABASE mydb CLONE otherdb
3899+
/// ```
3900+
///
3901+
/// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-clone#databases-schemas)
3902+
clone: Option<ObjectName>,
38873903
},
38883904
/// ```sql
38893905
/// CREATE FUNCTION
@@ -4826,6 +4842,7 @@ impl fmt::Display for Statement {
48264842
if_not_exists,
48274843
location,
48284844
managed_location,
4845+
clone,
48294846
} => {
48304847
write!(f, "CREATE DATABASE")?;
48314848
if *if_not_exists {
@@ -4838,6 +4855,9 @@ impl fmt::Display for Statement {
48384855
if let Some(ml) = managed_location {
48394856
write!(f, " MANAGEDLOCATION '{ml}'")?;
48404857
}
4858+
if let Some(clone) = clone {
4859+
write!(f, " CLONE {clone}")?;
4860+
}
48414861
Ok(())
48424862
}
48434863
Statement::CreateFunction(create_function) => create_function.fmt(f),
@@ -5759,6 +5779,7 @@ impl fmt::Display for Statement {
57595779
with,
57605780
options,
57615781
default_collate_spec,
5782+
clone,
57625783
} => {
57635784
write!(
57645785
f,
@@ -5779,6 +5800,9 @@ impl fmt::Display for Statement {
57795800
write!(f, " OPTIONS({})", display_comma_separated(options))?;
57805801
}
57815802

5803+
if let Some(clone) = clone {
5804+
write!(f, " CLONE {clone}")?;
5805+
}
57825806
Ok(())
57835807
}
57845808
Statement::Assert { condition, message } => {

src/parser/mod.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4948,12 +4948,19 @@ impl<'a> Parser<'a> {
49484948
None
49494949
};
49504950

4951+
let clone = if self.parse_keyword(Keyword::CLONE) {
4952+
Some(self.parse_object_name(false)?)
4953+
} else {
4954+
None
4955+
};
4956+
49514957
Ok(Statement::CreateSchema {
49524958
schema_name,
49534959
if_not_exists,
49544960
with,
49554961
options,
49564962
default_collate_spec,
4963+
clone,
49574964
})
49584965
}
49594966

@@ -4988,11 +4995,18 @@ impl<'a> Parser<'a> {
49884995
_ => break,
49894996
}
49904997
}
4998+
let clone = if self.parse_keyword(Keyword::CLONE) {
4999+
Some(self.parse_object_name(false)?)
5000+
} else {
5001+
None
5002+
};
5003+
49915004
Ok(Statement::CreateDatabase {
49925005
db_name,
49935006
if_not_exists: ine,
49945007
location,
49955008
managed_location,
5009+
clone,
49965010
})
49975011
}
49985012

tests/sqlparser_common.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4297,6 +4297,7 @@ fn parse_create_schema() {
42974297
verified_stmt(r#"CREATE SCHEMA a.b.c WITH (key1 = 'value1', key2 = 'value2')"#);
42984298
verified_stmt(r#"CREATE SCHEMA IF NOT EXISTS a WITH (key1 = 'value1')"#);
42994299
verified_stmt(r#"CREATE SCHEMA IF NOT EXISTS a WITH ()"#);
4300+
verified_stmt(r#"CREATE SCHEMA a CLONE b"#);
43004301
}
43014302

43024303
#[test]
@@ -7901,11 +7902,33 @@ fn parse_create_database() {
79017902
if_not_exists,
79027903
location,
79037904
managed_location,
7905+
clone,
79047906
} => {
79057907
assert_eq!("mydb", db_name.to_string());
79067908
assert!(!if_not_exists);
79077909
assert_eq!(None, location);
79087910
assert_eq!(None, managed_location);
7911+
assert_eq!(None, clone);
7912+
}
7913+
_ => unreachable!(),
7914+
}
7915+
let sql = "CREATE DATABASE mydb CLONE otherdb";
7916+
match verified_stmt(sql) {
7917+
Statement::CreateDatabase {
7918+
db_name,
7919+
if_not_exists,
7920+
location,
7921+
managed_location,
7922+
clone,
7923+
} => {
7924+
assert_eq!("mydb", db_name.to_string());
7925+
assert!(!if_not_exists);
7926+
assert_eq!(None, location);
7927+
assert_eq!(None, managed_location);
7928+
assert_eq!(
7929+
Some(ObjectName::from(vec![Ident::new("otherdb".to_string())])),
7930+
clone
7931+
);
79097932
}
79107933
_ => unreachable!(),
79117934
}
@@ -7920,11 +7943,13 @@ fn parse_create_database_ine() {
79207943
if_not_exists,
79217944
location,
79227945
managed_location,
7946+
clone,
79237947
} => {
79247948
assert_eq!("mydb", db_name.to_string());
79257949
assert!(if_not_exists);
79267950
assert_eq!(None, location);
79277951
assert_eq!(None, managed_location);
7952+
assert_eq!(None, clone);
79287953
}
79297954
_ => unreachable!(),
79307955
}

0 commit comments

Comments
 (0)