Skip to content

Commit 0df2042

Browse files
committed
Refactor to use the existing struct for Snowflake COPY INTO
1 parent a7a1b54 commit 0df2042

File tree

4 files changed

+247
-257
lines changed

4 files changed

+247
-257
lines changed

src/ast/mod.rs

Lines changed: 65 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -2461,37 +2461,30 @@ pub enum Statement {
24612461
values: Vec<Option<String>>,
24622462
},
24632463
/// ```sql
2464-
/// COPY INTO <table>
2464+
/// COPY INTO <table> | <location>
24652465
/// ```
2466-
/// See <https://docs.snowflake.com/en/sql-reference/sql/copy-into-table>
2466+
/// See:
2467+
/// <https://docs.snowflake.com/en/sql-reference/sql/copy-into-table>
2468+
/// <https://docs.snowflake.com/en/sql-reference/sql/copy-into-location>
2469+
///
24672470
/// Copy Into syntax available for Snowflake is different than the one implemented in
24682471
/// Postgres. Although they share common prefix, it is reasonable to implement them
24692472
/// in different enums. This can be refactored later once custom dialects
24702473
/// are allowed to have custom Statements.
2471-
CopyIntoSnowflakeTable {
2474+
CopyIntoSnowflake {
2475+
kind: CopyIntoSnowflakeKind,
24722476
into: ObjectName,
2473-
from_stage: ObjectName,
2474-
from_stage_alias: Option<Ident>,
2477+
from_obj: Option<ObjectName>,
2478+
from_obj_alias: Option<Ident>,
24752479
stage_params: StageParamsObject,
24762480
from_transformations: Option<Vec<StageLoadSelectItem>>,
2481+
from_query: Option<Box<Query>>,
24772482
files: Option<Vec<String>>,
24782483
pattern: Option<String>,
24792484
file_format: DataLoadingOptions,
24802485
copy_options: DataLoadingOptions,
24812486
validation_mode: Option<String>,
2482-
},
2483-
/// ```sql
2484-
/// COPY INTO <location>
2485-
/// ```
2486-
/// See <https://docs.snowflake.com/en/sql-reference/sql/copy-into-location>
2487-
CopyIntoSnowflakeLocation {
2488-
into: ObjectName,
2489-
from_table: Option<ObjectName>,
2490-
from_query: Option<Box<Query>>,
2491-
stage_params: StageParamsObject,
2492-
partition: Option<Expr>,
2493-
file_format: DataLoadingOptions,
2494-
copy_options: DataLoadingOptions,
2487+
partition: Option<Box<Expr>>,
24952488
},
24962489
/// ```sql
24972490
/// CLOSE
@@ -4964,88 +4957,70 @@ impl fmt::Display for Statement {
49644957
}
49654958
Ok(())
49664959
}
4967-
Statement::CopyIntoSnowflakeTable {
4960+
Statement::CopyIntoSnowflake {
4961+
kind,
49684962
into,
4969-
from_stage,
4970-
from_stage_alias,
4963+
from_obj,
4964+
from_obj_alias,
49714965
stage_params,
49724966
from_transformations,
4967+
from_query,
49734968
files,
49744969
pattern,
49754970
file_format,
49764971
copy_options,
49774972
validation_mode,
4973+
partition,
49784974
} => {
49794975
write!(f, "COPY INTO {}", into)?;
4980-
if from_transformations.is_none() {
4981-
// Standard data load
4982-
write!(f, " FROM {}{}", from_stage, stage_params)?;
4983-
if from_stage_alias.as_ref().is_some() {
4984-
write!(f, " AS {}", from_stage_alias.as_ref().unwrap())?;
4985-
}
4986-
} else {
4976+
if let Some(from_transformations) = from_transformations {
49874977
// Data load with transformation
4988-
write!(
4989-
f,
4990-
" FROM (SELECT {} FROM {}{}",
4991-
display_separated(from_transformations.as_ref().unwrap(), ", "),
4992-
from_stage,
4993-
stage_params,
4994-
)?;
4995-
if from_stage_alias.as_ref().is_some() {
4996-
write!(f, " AS {}", from_stage_alias.as_ref().unwrap())?;
4978+
if let Some(from_stage) = from_obj {
4979+
write!(
4980+
f,
4981+
" FROM (SELECT {} FROM {}{}",
4982+
display_separated(from_transformations, ", "),
4983+
from_stage,
4984+
stage_params
4985+
)?;
4986+
}
4987+
if let Some(from_obj_alias) = from_obj_alias {
4988+
write!(f, " AS {}", from_obj_alias)?;
49974989
}
49984990
write!(f, ")")?;
4991+
} else if let Some(from_obj) = from_obj {
4992+
// Standard data load
4993+
write!(f, " FROM {}{}", from_obj, stage_params)?;
4994+
if let Some(from_obj_alias) = from_obj_alias {
4995+
write!(f, " AS {from_obj_alias}")?;
4996+
}
4997+
} else if let Some(from_query) = from_query {
4998+
// Data unload from query
4999+
write!(f, " FROM ({from_query})")?;
49995000
}
5000-
if files.is_some() {
5001-
write!(
5002-
f,
5003-
" FILES = ('{}')",
5004-
display_separated(files.as_ref().unwrap(), "', '")
5005-
)?;
5006-
}
5007-
if pattern.is_some() {
5008-
write!(f, " PATTERN = '{}'", pattern.as_ref().unwrap())?;
5009-
}
5010-
if !file_format.options.is_empty() {
5011-
write!(f, " FILE_FORMAT=({})", file_format)?;
5012-
}
5013-
if !copy_options.options.is_empty() {
5014-
write!(f, " COPY_OPTIONS=({})", copy_options)?;
5015-
}
5016-
if validation_mode.is_some() {
5017-
write!(
5018-
f,
5019-
" VALIDATION_MODE = {}",
5020-
validation_mode.as_ref().unwrap()
5021-
)?;
5001+
5002+
if let Some(files) = files {
5003+
write!(f, " FILES = ('{}')", display_separated(files, "', '"))?;
50225004
}
5023-
Ok(())
5024-
}
5025-
Statement::CopyIntoSnowflakeLocation {
5026-
into,
5027-
from_table,
5028-
from_query,
5029-
stage_params,
5030-
partition,
5031-
file_format,
5032-
copy_options,
5033-
} => {
5034-
write!(f, "COPY INTO {into} FROM")?;
5035-
if let Some(from_table) = from_table {
5036-
write!(f, " {from_table}")?;
5037-
} else if let Some(from_query) = from_query {
5038-
write!(f, " ({from_query})")?;
5005+
if let Some(pattern) = pattern {
5006+
write!(f, " PATTERN = '{}'", pattern)?;
50395007
}
5040-
write!(f, "{stage_params}")?;
50415008
if let Some(partition) = partition {
50425009
write!(f, " PARTITION BY {partition}")?;
50435010
}
50445011
if !file_format.options.is_empty() {
50455012
write!(f, " FILE_FORMAT=({})", file_format)?;
50465013
}
50475014
if !copy_options.options.is_empty() {
5048-
write!(f, " {}", copy_options)?;
5015+
match kind {
5016+
CopyIntoSnowflakeKind::Table => {
5017+
write!(f, " COPY_OPTIONS=({})", copy_options)?
5018+
}
5019+
CopyIntoSnowflakeKind::Location => write!(f, " {copy_options}")?,
5020+
}
5021+
}
5022+
if let Some(validation_mode) = validation_mode {
5023+
write!(f, " VALIDATION_MODE = {}", validation_mode)?;
50495024
}
50505025
Ok(())
50515026
}
@@ -8459,6 +8434,19 @@ impl Display for StorageSerializationPolicy {
84598434
}
84608435
}
84618436

8437+
/// Variants of the Snowflake `COPY INTO` statement
8438+
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8439+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8440+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8441+
pub enum CopyIntoSnowflakeKind {
8442+
/// Loads data from files to a table
8443+
/// See: <https://docs.snowflake.com/en/sql-reference/sql/copy-into-table>
8444+
Table,
8445+
/// Unloads data from a table or query to external files
8446+
/// See: <https://docs.snowflake.com/en/sql-reference/sql/copy-into-location>
8447+
Location,
8448+
}
8449+
84628450
#[cfg(test)]
84638451
mod tests {
84648452
use super::*;

src/ast/spans.rs

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -211,8 +211,7 @@ impl Spanned for Values {
211211
/// # partial span
212212
///
213213
/// Missing spans:
214-
/// - [Statement::CopyIntoSnowflakeTable]
215-
/// - [Statement::CopyIntoSnowflakeLocation]
214+
/// - [Statement::CopyIntoSnowflake]
216215
/// - [Statement::CreateSecret]
217216
/// - [Statement::CreateRole]
218217
/// - [Statement::AlterRole]
@@ -331,26 +330,20 @@ impl Spanned for Statement {
331330
legacy_options: _,
332331
values: _,
333332
} => source.span(),
334-
Statement::CopyIntoSnowflakeTable {
333+
Statement::CopyIntoSnowflake {
335334
into: _,
336-
from_stage: _,
337-
from_stage_alias: _,
335+
from_obj: _,
336+
from_obj_alias: _,
338337
stage_params: _,
339338
from_transformations: _,
340339
files: _,
341340
pattern: _,
342341
file_format: _,
343342
copy_options: _,
344343
validation_mode: _,
345-
} => Span::empty(),
346-
Statement::CopyIntoSnowflakeLocation {
347-
into: _,
348-
from_table: _,
344+
kind: _,
349345
from_query: _,
350-
stage_params: _,
351346
partition: _,
352-
file_format: _,
353-
copy_options: _,
354347
} => Span::empty(),
355348
Statement::Close { cursor } => match cursor {
356349
CloseCursor::All => Span::empty(),

0 commit comments

Comments
 (0)