@@ -2491,37 +2491,30 @@ pub enum Statement {
2491
2491
values : Vec < Option < String > > ,
2492
2492
} ,
2493
2493
/// ```sql
2494
- /// COPY INTO <table>
2494
+ /// COPY INTO <table> | <location>
2495
2495
/// ```
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
+ ///
2497
2500
/// Copy Into syntax available for Snowflake is different than the one implemented in
2498
2501
/// Postgres. Although they share common prefix, it is reasonable to implement them
2499
2502
/// in different enums. This can be refactored later once custom dialects
2500
2503
/// are allowed to have custom Statements.
2501
- CopyIntoSnowflakeTable {
2504
+ CopyIntoSnowflake {
2505
+ kind : CopyIntoSnowflakeKind ,
2502
2506
into : ObjectName ,
2503
- from_stage : ObjectName ,
2504
- from_stage_alias : Option < Ident > ,
2507
+ from_obj : Option < ObjectName > ,
2508
+ from_obj_alias : Option < Ident > ,
2505
2509
stage_params : StageParamsObject ,
2506
2510
from_transformations : Option < Vec < StageLoadSelectItem > > ,
2511
+ from_query : Option < Box < Query > > ,
2507
2512
files : Option < Vec < String > > ,
2508
2513
pattern : Option < String > ,
2509
2514
file_format : DataLoadingOptions ,
2510
2515
copy_options : DataLoadingOptions ,
2511
2516
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 > > ,
2525
2518
} ,
2526
2519
/// ```sql
2527
2520
/// CLOSE
@@ -4994,88 +4987,70 @@ impl fmt::Display for Statement {
4994
4987
}
4995
4988
Ok ( ( ) )
4996
4989
}
4997
- Statement :: CopyIntoSnowflakeTable {
4990
+ Statement :: CopyIntoSnowflake {
4991
+ kind,
4998
4992
into,
4999
- from_stage ,
5000
- from_stage_alias ,
4993
+ from_obj ,
4994
+ from_obj_alias ,
5001
4995
stage_params,
5002
4996
from_transformations,
4997
+ from_query,
5003
4998
files,
5004
4999
pattern,
5005
5000
file_format,
5006
5001
copy_options,
5007
5002
validation_mode,
5003
+ partition,
5008
5004
} => {
5009
5005
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 {
5017
5007
// 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) ?;
5027
5019
}
5028
5020
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})" ) ?;
5029
5030
}
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, "', '" ) ) ?;
5052
5034
}
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) ?;
5069
5037
}
5070
- write ! ( f, "{stage_params}" ) ?;
5071
5038
if let Some ( partition) = partition {
5072
5039
write ! ( f, " PARTITION BY {partition}" ) ?;
5073
5040
}
5074
5041
if !file_format. options . is_empty ( ) {
5075
5042
write ! ( f, " FILE_FORMAT=({})" , file_format) ?;
5076
5043
}
5077
5044
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) ?;
5079
5054
}
5080
5055
Ok ( ( ) )
5081
5056
}
@@ -8489,6 +8464,19 @@ impl Display for StorageSerializationPolicy {
8489
8464
}
8490
8465
}
8491
8466
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
+
8492
8480
#[ cfg( test) ]
8493
8481
mod tests {
8494
8482
use super :: * ;
0 commit comments