@@ -2505,24 +2505,30 @@ pub enum Statement {
25052505 values : Vec < Option < String > > ,
25062506 } ,
25072507 /// ```sql
2508- /// COPY INTO
2508+ /// COPY INTO <table> | <location>
25092509 /// ```
2510- /// See <https://docs.snowflake.com/en/sql-reference/sql/copy-into-table>
2510+ /// See:
2511+ /// <https://docs.snowflake.com/en/sql-reference/sql/copy-into-table>
2512+ /// <https://docs.snowflake.com/en/sql-reference/sql/copy-into-location>
2513+ ///
25112514 /// Copy Into syntax available for Snowflake is different than the one implemented in
25122515 /// Postgres. Although they share common prefix, it is reasonable to implement them
25132516 /// in different enums. This can be refactored later once custom dialects
25142517 /// are allowed to have custom Statements.
25152518 CopyIntoSnowflake {
2519+ kind : CopyIntoSnowflakeKind ,
25162520 into : ObjectName ,
2517- from_stage : ObjectName ,
2518- from_stage_alias : Option < Ident > ,
2521+ from_obj : Option < ObjectName > ,
2522+ from_obj_alias : Option < Ident > ,
25192523 stage_params : StageParamsObject ,
25202524 from_transformations : Option < Vec < StageLoadSelectItem > > ,
2525+ from_query : Option < Box < Query > > ,
25212526 files : Option < Vec < String > > ,
25222527 pattern : Option < String > ,
25232528 file_format : DataLoadingOptions ,
25242529 copy_options : DataLoadingOptions ,
25252530 validation_mode : Option < String > ,
2531+ partition : Option < Box < Expr > > ,
25262532 } ,
25272533 /// ```sql
25282534 /// CLOSE
@@ -3011,6 +3017,12 @@ pub enum Statement {
30113017 show_options : ShowStatementOptions ,
30123018 } ,
30133019 /// ```sql
3020+ /// SHOW OBJECTS LIKE 'line%' IN mydb.public
3021+ /// ```
3022+ /// Snowflake-specific statement
3023+ /// <https://docs.snowflake.com/en/sql-reference/sql/show-objects>
3024+ ShowObjects ( ShowObjects ) ,
3025+ /// ```sql
30143026 /// SHOW TABLES
30153027 /// ```
30163028 ShowTables {
@@ -4704,6 +4716,17 @@ impl fmt::Display for Statement {
47044716 ) ?;
47054717 Ok ( ( ) )
47064718 }
4719+ Statement :: ShowObjects ( ShowObjects {
4720+ terse,
4721+ show_options,
4722+ } ) => {
4723+ write ! (
4724+ f,
4725+ "SHOW {terse}OBJECTS{show_options}" ,
4726+ terse = if * terse { "TERSE " } else { "" } ,
4727+ ) ?;
4728+ Ok ( ( ) )
4729+ }
47074730 Statement :: ShowTables {
47084731 terse,
47094732 history,
@@ -5055,60 +5078,69 @@ impl fmt::Display for Statement {
50555078 Ok ( ( ) )
50565079 }
50575080 Statement :: CopyIntoSnowflake {
5081+ kind,
50585082 into,
5059- from_stage ,
5060- from_stage_alias ,
5083+ from_obj ,
5084+ from_obj_alias ,
50615085 stage_params,
50625086 from_transformations,
5087+ from_query,
50635088 files,
50645089 pattern,
50655090 file_format,
50665091 copy_options,
50675092 validation_mode,
5093+ partition,
50685094 } => {
50695095 write ! ( f, "COPY INTO {}" , into) ?;
5070- if from_transformations. is_none ( ) {
5071- // Standard data load
5072- write ! ( f, " FROM {}{}" , from_stage, stage_params) ?;
5073- if from_stage_alias. as_ref ( ) . is_some ( ) {
5074- write ! ( f, " AS {}" , from_stage_alias. as_ref( ) . unwrap( ) ) ?;
5075- }
5076- } else {
5096+ if let Some ( from_transformations) = from_transformations {
50775097 // Data load with transformation
5078- write ! (
5079- f,
5080- " FROM (SELECT {} FROM {}{}" ,
5081- display_separated( from_transformations. as_ref( ) . unwrap( ) , ", " ) ,
5082- from_stage,
5083- stage_params,
5084- ) ?;
5085- if from_stage_alias. as_ref ( ) . is_some ( ) {
5086- write ! ( f, " AS {}" , from_stage_alias. as_ref( ) . unwrap( ) ) ?;
5098+ if let Some ( from_stage) = from_obj {
5099+ write ! (
5100+ f,
5101+ " FROM (SELECT {} FROM {}{}" ,
5102+ display_separated( from_transformations, ", " ) ,
5103+ from_stage,
5104+ stage_params
5105+ ) ?;
5106+ }
5107+ if let Some ( from_obj_alias) = from_obj_alias {
5108+ write ! ( f, " AS {}" , from_obj_alias) ?;
50875109 }
50885110 write ! ( f, ")" ) ?;
5111+ } else if let Some ( from_obj) = from_obj {
5112+ // Standard data load
5113+ write ! ( f, " FROM {}{}" , from_obj, stage_params) ?;
5114+ if let Some ( from_obj_alias) = from_obj_alias {
5115+ write ! ( f, " AS {from_obj_alias}" ) ?;
5116+ }
5117+ } else if let Some ( from_query) = from_query {
5118+ // Data unload from query
5119+ write ! ( f, " FROM ({from_query})" ) ?;
50895120 }
5090- if files. is_some ( ) {
5091- write ! (
5092- f,
5093- " FILES = ('{}')" ,
5094- display_separated( files. as_ref( ) . unwrap( ) , "', '" )
5095- ) ?;
5121+
5122+ if let Some ( files) = files {
5123+ write ! ( f, " FILES = ('{}')" , display_separated( files, "', '" ) ) ?;
50965124 }
5097- if pattern. is_some ( ) {
5098- write ! ( f, " PATTERN = '{}'" , pattern. as_ref( ) . unwrap( ) ) ?;
5125+ if let Some ( pattern) = pattern {
5126+ write ! ( f, " PATTERN = '{}'" , pattern) ?;
5127+ }
5128+ if let Some ( partition) = partition {
5129+ write ! ( f, " PARTITION BY {partition}" ) ?;
50995130 }
51005131 if !file_format. options . is_empty ( ) {
51015132 write ! ( f, " FILE_FORMAT=({})" , file_format) ?;
51025133 }
51035134 if !copy_options. options . is_empty ( ) {
5104- write ! ( f, " COPY_OPTIONS=({})" , copy_options) ?;
5135+ match kind {
5136+ CopyIntoSnowflakeKind :: Table => {
5137+ write ! ( f, " COPY_OPTIONS=({})" , copy_options) ?
5138+ }
5139+ CopyIntoSnowflakeKind :: Location => write ! ( f, " {copy_options}" ) ?,
5140+ }
51055141 }
5106- if validation_mode. is_some ( ) {
5107- write ! (
5108- f,
5109- " VALIDATION_MODE = {}" ,
5110- validation_mode. as_ref( ) . unwrap( )
5111- ) ?;
5142+ if let Some ( validation_mode) = validation_mode {
5143+ write ! ( f, " VALIDATION_MODE = {}" , validation_mode) ?;
51125144 }
51135145 Ok ( ( ) )
51145146 }
@@ -8335,6 +8367,14 @@ impl fmt::Display for ShowStatementIn {
83358367 }
83368368}
83378369
8370+ #[ derive( Debug , Clone , PartialEq , PartialOrd , Eq , Ord , Hash ) ]
8371+ #[ cfg_attr( feature = "serde" , derive( Serialize , Deserialize ) ) ]
8372+ #[ cfg_attr( feature = "visitor" , derive( Visit , VisitMut ) ) ]
8373+ pub struct ShowObjects {
8374+ pub terse : bool ,
8375+ pub show_options : ShowStatementOptions ,
8376+ }
8377+
83388378/// MSSQL's json null clause
83398379///
83408380/// ```plaintext
@@ -8550,6 +8590,19 @@ impl Display for StorageSerializationPolicy {
85508590 }
85518591}
85528592
8593+ /// Variants of the Snowflake `COPY INTO` statement
8594+ #[ derive( Debug , Copy , Clone , PartialEq , PartialOrd , Eq , Ord , Hash ) ]
8595+ #[ cfg_attr( feature = "serde" , derive( Serialize , Deserialize ) ) ]
8596+ #[ cfg_attr( feature = "visitor" , derive( Visit , VisitMut ) ) ]
8597+ pub enum CopyIntoSnowflakeKind {
8598+ /// Loads data from files to a table
8599+ /// See: <https://docs.snowflake.com/en/sql-reference/sql/copy-into-table>
8600+ Table ,
8601+ /// Unloads data from a table or query to external files
8602+ /// See: <https://docs.snowflake.com/en/sql-reference/sql/copy-into-location>
8603+ Location ,
8604+ }
8605+
85538606#[ cfg( test) ]
85548607mod tests {
85558608 use super :: * ;
0 commit comments