Skip to content

Commit cd9c2b1

Browse files
yoavcloudVedin
authored andcommitted
Snowflake: Support CLONE option in CREATE DATABASE/SCHEMA statements (apache#1958)
1 parent 40bbcc9 commit cd9c2b1

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
@@ -4900,12 +4900,19 @@ impl<'a> Parser<'a> {
49004900
None
49014901
};
49024902

4903+
let clone = if self.parse_keyword(Keyword::CLONE) {
4904+
Some(self.parse_object_name(false)?)
4905+
} else {
4906+
None
4907+
};
4908+
49034909
Ok(Statement::CreateSchema {
49044910
schema_name,
49054911
if_not_exists,
49064912
with,
49074913
options,
49084914
default_collate_spec,
4915+
clone,
49094916
})
49104917
}
49114918

@@ -4940,11 +4947,18 @@ impl<'a> Parser<'a> {
49404947
_ => break,
49414948
}
49424949
}
4950+
let clone = if self.parse_keyword(Keyword::CLONE) {
4951+
Some(self.parse_object_name(false)?)
4952+
} else {
4953+
None
4954+
};
4955+
49434956
Ok(Statement::CreateDatabase {
49444957
db_name,
49454958
if_not_exists: ine,
49464959
location,
49474960
managed_location,
4961+
clone,
49484962
})
49494963
}
49504964

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]
@@ -7891,11 +7892,33 @@ fn parse_create_database() {
78917892
if_not_exists,
78927893
location,
78937894
managed_location,
7895+
clone,
78947896
} => {
78957897
assert_eq!("mydb", db_name.to_string());
78967898
assert!(!if_not_exists);
78977899
assert_eq!(None, location);
78987900
assert_eq!(None, managed_location);
7901+
assert_eq!(None, clone);
7902+
}
7903+
_ => unreachable!(),
7904+
}
7905+
let sql = "CREATE DATABASE mydb CLONE otherdb";
7906+
match verified_stmt(sql) {
7907+
Statement::CreateDatabase {
7908+
db_name,
7909+
if_not_exists,
7910+
location,
7911+
managed_location,
7912+
clone,
7913+
} => {
7914+
assert_eq!("mydb", db_name.to_string());
7915+
assert!(!if_not_exists);
7916+
assert_eq!(None, location);
7917+
assert_eq!(None, managed_location);
7918+
assert_eq!(
7919+
Some(ObjectName::from(vec![Ident::new("otherdb".to_string())])),
7920+
clone
7921+
);
78997922
}
79007923
_ => unreachable!(),
79017924
}
@@ -7910,11 +7933,13 @@ fn parse_create_database_ine() {
79107933
if_not_exists,
79117934
location,
79127935
managed_location,
7936+
clone,
79137937
} => {
79147938
assert_eq!("mydb", db_name.to_string());
79157939
assert!(if_not_exists);
79167940
assert_eq!(None, location);
79177941
assert_eq!(None, managed_location);
7942+
assert_eq!(None, clone);
79187943
}
79197944
_ => unreachable!(),
79207945
}

0 commit comments

Comments
 (0)