Skip to content

Commit 784e94c

Browse files
committed
Refactor to use the existing struct for Snowflake COPY INTO
1 parent 28f706b commit 784e94c

File tree

4 files changed

+245
-261
lines changed

4 files changed

+245
-261
lines changed

src/ast/mod.rs

Lines changed: 65 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -2491,37 +2491,30 @@ pub enum Statement {
24912491
values: Vec<Option<String>>,
24922492
},
24932493
/// ```sql
2494-
/// COPY INTO <table>
2494+
/// COPY INTO <table> | <location>
24952495
/// ```
2496-
/// See <https://docs.snowflake.com/en/sql-reference/sql/copy-into-table>
2496+
/// See:
2497+
/// <https://docs.snowflake.com/en/sql-reference/sql/copy-into-table>
2498+
/// <https://docs.snowflake.com/en/sql-reference/sql/copy-into-location>
2499+
///
24972500
/// Copy Into syntax available for Snowflake is different than the one implemented in
24982501
/// Postgres. Although they share common prefix, it is reasonable to implement them
24992502
/// in different enums. This can be refactored later once custom dialects
25002503
/// are allowed to have custom Statements.
2501-
CopyIntoSnowflakeTable {
2504+
CopyIntoSnowflake {
2505+
kind: CopyIntoSnowflakeKind,
25022506
into: ObjectName,
2503-
from_stage: ObjectName,
2504-
from_stage_alias: Option<Ident>,
2507+
from_obj: Option<ObjectName>,
2508+
from_obj_alias: Option<Ident>,
25052509
stage_params: StageParamsObject,
25062510
from_transformations: Option<Vec<StageLoadSelectItem>>,
2511+
from_query: Option<Box<Query>>,
25072512
files: Option<Vec<String>>,
25082513
pattern: Option<String>,
25092514
file_format: DataLoadingOptions,
25102515
copy_options: DataLoadingOptions,
25112516
validation_mode: Option<String>,
2512-
},
2513-
/// ```sql
2514-
/// COPY INTO <location>
2515-
/// ```
2516-
/// See <https://docs.snowflake.com/en/sql-reference/sql/copy-into-location>
2517-
CopyIntoSnowflakeLocation {
2518-
into: ObjectName,
2519-
from_table: Option<ObjectName>,
2520-
from_query: Option<Box<Query>>,
2521-
stage_params: StageParamsObject,
2522-
partition: Option<Expr>,
2523-
file_format: DataLoadingOptions,
2524-
copy_options: DataLoadingOptions,
2517+
partition: Option<Box<Expr>>,
25252518
},
25262519
/// ```sql
25272520
/// CLOSE
@@ -4994,88 +4987,70 @@ impl fmt::Display for Statement {
49944987
}
49954988
Ok(())
49964989
}
4997-
Statement::CopyIntoSnowflakeTable {
4990+
Statement::CopyIntoSnowflake {
4991+
kind,
49984992
into,
4999-
from_stage,
5000-
from_stage_alias,
4993+
from_obj,
4994+
from_obj_alias,
50014995
stage_params,
50024996
from_transformations,
4997+
from_query,
50034998
files,
50044999
pattern,
50055000
file_format,
50065001
copy_options,
50075002
validation_mode,
5003+
partition,
50085004
} => {
50095005
write!(f, "COPY INTO {}", into)?;
5010-
if from_transformations.is_none() {
5011-
// Standard data load
5012-
write!(f, " FROM {}{}", from_stage, stage_params)?;
5013-
if from_stage_alias.as_ref().is_some() {
5014-
write!(f, " AS {}", from_stage_alias.as_ref().unwrap())?;
5015-
}
5016-
} else {
5006+
if let Some(from_transformations) = from_transformations {
50175007
// Data load with transformation
5018-
write!(
5019-
f,
5020-
" FROM (SELECT {} FROM {}{}",
5021-
display_separated(from_transformations.as_ref().unwrap(), ", "),
5022-
from_stage,
5023-
stage_params,
5024-
)?;
5025-
if from_stage_alias.as_ref().is_some() {
5026-
write!(f, " AS {}", from_stage_alias.as_ref().unwrap())?;
5008+
if let Some(from_stage) = from_obj {
5009+
write!(
5010+
f,
5011+
" FROM (SELECT {} FROM {}{}",
5012+
display_separated(from_transformations, ", "),
5013+
from_stage,
5014+
stage_params
5015+
)?;
5016+
}
5017+
if let Some(from_obj_alias) = from_obj_alias {
5018+
write!(f, " AS {}", from_obj_alias)?;
50275019
}
50285020
write!(f, ")")?;
5021+
} else if let Some(from_obj) = from_obj {
5022+
// Standard data load
5023+
write!(f, " FROM {}{}", from_obj, stage_params)?;
5024+
if let Some(from_obj_alias) = from_obj_alias {
5025+
write!(f, " AS {from_obj_alias}")?;
5026+
}
5027+
} else if let Some(from_query) = from_query {
5028+
// Data unload from query
5029+
write!(f, " FROM ({from_query})")?;
50295030
}
5030-
if files.is_some() {
5031-
write!(
5032-
f,
5033-
" FILES = ('{}')",
5034-
display_separated(files.as_ref().unwrap(), "', '")
5035-
)?;
5036-
}
5037-
if pattern.is_some() {
5038-
write!(f, " PATTERN = '{}'", pattern.as_ref().unwrap())?;
5039-
}
5040-
if !file_format.options.is_empty() {
5041-
write!(f, " FILE_FORMAT=({})", file_format)?;
5042-
}
5043-
if !copy_options.options.is_empty() {
5044-
write!(f, " COPY_OPTIONS=({})", copy_options)?;
5045-
}
5046-
if validation_mode.is_some() {
5047-
write!(
5048-
f,
5049-
" VALIDATION_MODE = {}",
5050-
validation_mode.as_ref().unwrap()
5051-
)?;
5031+
5032+
if let Some(files) = files {
5033+
write!(f, " FILES = ('{}')", display_separated(files, "', '"))?;
50525034
}
5053-
Ok(())
5054-
}
5055-
Statement::CopyIntoSnowflakeLocation {
5056-
into,
5057-
from_table,
5058-
from_query,
5059-
stage_params,
5060-
partition,
5061-
file_format,
5062-
copy_options,
5063-
} => {
5064-
write!(f, "COPY INTO {into} FROM")?;
5065-
if let Some(from_table) = from_table {
5066-
write!(f, " {from_table}")?;
5067-
} else if let Some(from_query) = from_query {
5068-
write!(f, " ({from_query})")?;
5035+
if let Some(pattern) = pattern {
5036+
write!(f, " PATTERN = '{}'", pattern)?;
50695037
}
5070-
write!(f, "{stage_params}")?;
50715038
if let Some(partition) = partition {
50725039
write!(f, " PARTITION BY {partition}")?;
50735040
}
50745041
if !file_format.options.is_empty() {
50755042
write!(f, " FILE_FORMAT=({})", file_format)?;
50765043
}
50775044
if !copy_options.options.is_empty() {
5078-
write!(f, " {}", copy_options)?;
5045+
match kind {
5046+
CopyIntoSnowflakeKind::Table => {
5047+
write!(f, " COPY_OPTIONS=({})", copy_options)?
5048+
}
5049+
CopyIntoSnowflakeKind::Location => write!(f, " {copy_options}")?,
5050+
}
5051+
}
5052+
if let Some(validation_mode) = validation_mode {
5053+
write!(f, " VALIDATION_MODE = {}", validation_mode)?;
50795054
}
50805055
Ok(())
50815056
}
@@ -8489,6 +8464,19 @@ impl Display for StorageSerializationPolicy {
84898464
}
84908465
}
84918466

8467+
/// Variants of the Snowflake `COPY INTO` statement
8468+
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8469+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8470+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8471+
pub enum CopyIntoSnowflakeKind {
8472+
/// Loads data from files to a table
8473+
/// See: <https://docs.snowflake.com/en/sql-reference/sql/copy-into-table>
8474+
Table,
8475+
/// Unloads data from a table or query to external files
8476+
/// See: <https://docs.snowflake.com/en/sql-reference/sql/copy-into-location>
8477+
Location,
8478+
}
8479+
84928480
#[cfg(test)]
84938481
mod tests {
84948482
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)