Skip to content

Commit 799c1f7

Browse files
authored
Snowflake: Support CLONE option in CREATE DATABASE/SCHEMA statements (#1958)
1 parent a73577c commit 799c1f7

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
@@ -3846,6 +3846,14 @@ pub enum Statement {
38463846
///
38473847
/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_schema_statement)
38483848
default_collate_spec: Option<Expr>,
3849+
/// Clones a schema
3850+
///
3851+
/// ```sql
3852+
/// CREATE SCHEMA myschema CLONE otherschema
3853+
/// ```
3854+
///
3855+
/// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-clone#databases-schemas)
3856+
clone: Option<ObjectName>,
38493857
},
38503858
/// ```sql
38513859
/// CREATE DATABASE
@@ -3855,6 +3863,14 @@ pub enum Statement {
38553863
if_not_exists: bool,
38563864
location: Option<String>,
38573865
managed_location: Option<String>,
3866+
/// Clones a database
3867+
///
3868+
/// ```sql
3869+
/// CREATE DATABASE mydb CLONE otherdb
3870+
/// ```
3871+
///
3872+
/// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-clone#databases-schemas)
3873+
clone: Option<ObjectName>,
38583874
},
38593875
/// ```sql
38603876
/// CREATE FUNCTION
@@ -4797,6 +4813,7 @@ impl fmt::Display for Statement {
47974813
if_not_exists,
47984814
location,
47994815
managed_location,
4816+
clone,
48004817
} => {
48014818
write!(f, "CREATE DATABASE")?;
48024819
if *if_not_exists {
@@ -4809,6 +4826,9 @@ impl fmt::Display for Statement {
48094826
if let Some(ml) = managed_location {
48104827
write!(f, " MANAGEDLOCATION '{ml}'")?;
48114828
}
4829+
if let Some(clone) = clone {
4830+
write!(f, " CLONE {clone}")?;
4831+
}
48124832
Ok(())
48134833
}
48144834
Statement::CreateFunction(create_function) => create_function.fmt(f),
@@ -5730,6 +5750,7 @@ impl fmt::Display for Statement {
57305750
with,
57315751
options,
57325752
default_collate_spec,
5753+
clone,
57335754
} => {
57345755
write!(
57355756
f,
@@ -5750,6 +5771,9 @@ impl fmt::Display for Statement {
57505771
write!(f, " OPTIONS({})", display_comma_separated(options))?;
57515772
}
57525773

5774+
if let Some(clone) = clone {
5775+
write!(f, " CLONE {clone}")?;
5776+
}
57535777
Ok(())
57545778
}
57555779
Statement::Assert { condition, message } => {

src/parser/mod.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4917,12 +4917,19 @@ impl<'a> Parser<'a> {
49174917
None
49184918
};
49194919

4920+
let clone = if self.parse_keyword(Keyword::CLONE) {
4921+
Some(self.parse_object_name(false)?)
4922+
} else {
4923+
None
4924+
};
4925+
49204926
Ok(Statement::CreateSchema {
49214927
schema_name,
49224928
if_not_exists,
49234929
with,
49244930
options,
49254931
default_collate_spec,
4932+
clone,
49264933
})
49274934
}
49284935

@@ -4957,11 +4964,18 @@ impl<'a> Parser<'a> {
49574964
_ => break,
49584965
}
49594966
}
4967+
let clone = if self.parse_keyword(Keyword::CLONE) {
4968+
Some(self.parse_object_name(false)?)
4969+
} else {
4970+
None
4971+
};
4972+
49604973
Ok(Statement::CreateDatabase {
49614974
db_name,
49624975
if_not_exists: ine,
49634976
location,
49644977
managed_location,
4978+
clone,
49654979
})
49664980
}
49674981

tests/sqlparser_common.rs

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

43014302
#[test]
@@ -7900,11 +7901,33 @@ fn parse_create_database() {
79007901
if_not_exists,
79017902
location,
79027903
managed_location,
7904+
clone,
79037905
} => {
79047906
assert_eq!("mydb", db_name.to_string());
79057907
assert!(!if_not_exists);
79067908
assert_eq!(None, location);
79077909
assert_eq!(None, managed_location);
7910+
assert_eq!(None, clone);
7911+
}
7912+
_ => unreachable!(),
7913+
}
7914+
let sql = "CREATE DATABASE mydb CLONE otherdb";
7915+
match verified_stmt(sql) {
7916+
Statement::CreateDatabase {
7917+
db_name,
7918+
if_not_exists,
7919+
location,
7920+
managed_location,
7921+
clone,
7922+
} => {
7923+
assert_eq!("mydb", db_name.to_string());
7924+
assert!(!if_not_exists);
7925+
assert_eq!(None, location);
7926+
assert_eq!(None, managed_location);
7927+
assert_eq!(
7928+
Some(ObjectName::from(vec![Ident::new("otherdb".to_string())])),
7929+
clone
7930+
);
79087931
}
79097932
_ => unreachable!(),
79107933
}
@@ -7919,11 +7942,13 @@ fn parse_create_database_ine() {
79197942
if_not_exists,
79207943
location,
79217944
managed_location,
7945+
clone,
79227946
} => {
79237947
assert_eq!("mydb", db_name.to_string());
79247948
assert!(if_not_exists);
79257949
assert_eq!(None, location);
79267950
assert_eq!(None, managed_location);
7951+
assert_eq!(None, clone);
79277952
}
79287953
_ => unreachable!(),
79297954
}

0 commit comments

Comments
 (0)