@@ -4294,15 +4294,24 @@ pub enum Statement {
4294
4294
/// ```
4295
4295
/// Note: this is a MySQL-specific statement. See <https://dev.mysql.com/doc/refman/8.0/en/lock-tables.html>
4296
4296
UnlockTables ,
4297
+ /// Unloads the result of a query to file
4298
+ ///
4299
+ /// [Athena](https://docs.aws.amazon.com/athena/latest/ug/unload.html):
4297
4300
/// ```sql
4298
4301
/// UNLOAD(statement) TO <destination> [ WITH options ]
4299
4302
/// ```
4300
- /// See Redshift <https://docs.aws.amazon.com/redshift/latest/dg/r_UNLOAD.html> and
4301
- // Athena <https://docs.aws.amazon.com/athena/latest/ug/unload.html>
4303
+ ///
4304
+ /// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_UNLOAD.html):
4305
+ /// ```sql
4306
+ /// UNLOAD('statement') TO <destination> [ OPTIONS ]
4307
+ /// ```
4302
4308
Unload {
4303
- query : Box < Query > ,
4309
+ query : Option < Box < Query > > ,
4310
+ query_text : Option < String > ,
4304
4311
to : Ident ,
4312
+ auth : Option < IamRoleKind > ,
4305
4313
with : Vec < SqlOption > ,
4314
+ options : Vec < CopyLegacyOption > ,
4306
4315
} ,
4307
4316
/// ```sql
4308
4317
/// OPTIMIZE TABLE [db.]name [ON CLUSTER cluster] [PARTITION partition | PARTITION ID 'partition_id'] [FINAL] [DEDUPLICATE [BY expression]]
@@ -6282,13 +6291,31 @@ impl fmt::Display for Statement {
6282
6291
Statement :: UnlockTables => {
6283
6292
write ! ( f, "UNLOCK TABLES" )
6284
6293
}
6285
- Statement :: Unload { query, to, with } => {
6286
- write ! ( f, "UNLOAD({query}) TO {to}" ) ?;
6287
-
6294
+ Statement :: Unload {
6295
+ query,
6296
+ query_text,
6297
+ to,
6298
+ auth,
6299
+ with,
6300
+ options,
6301
+ } => {
6302
+ write ! ( f, "UNLOAD(" ) ?;
6303
+ if let Some ( query) = query {
6304
+ write ! ( f, "{query}" ) ?;
6305
+ }
6306
+ if let Some ( query_text) = query_text {
6307
+ write ! ( f, "'{query_text}'" ) ?;
6308
+ }
6309
+ write ! ( f, ") TO {to}" ) ?;
6310
+ if let Some ( auth) = auth {
6311
+ write ! ( f, " IAM_ROLE {auth}" ) ?;
6312
+ }
6288
6313
if !with. is_empty ( ) {
6289
6314
write ! ( f, " WITH ({})" , display_comma_separated( with) ) ?;
6290
6315
}
6291
-
6316
+ if !options. is_empty ( ) {
6317
+ write ! ( f, " {}" , display_separated( options, " " ) ) ?;
6318
+ }
6292
6319
Ok ( ( ) )
6293
6320
}
6294
6321
Statement :: OptimizeTable {
@@ -8797,10 +8824,18 @@ pub enum CopyLegacyOption {
8797
8824
AcceptAnyDate ,
8798
8825
/// ACCEPTINVCHARS
8799
8826
AcceptInvChars ( Option < String > ) ,
8827
+ /// ADDQUOTES
8828
+ AddQuotes ,
8829
+ /// ALLOWOVERWRITE
8830
+ AllowOverwrite ,
8800
8831
/// BINARY
8801
8832
Binary ,
8802
8833
/// BLANKSASNULL
8803
8834
BlankAsNull ,
8835
+ /// BZIP2
8836
+ Bzip2 ,
8837
+ /// CLEANPATH
8838
+ CleanPath ,
8804
8839
/// CSV ...
8805
8840
Csv ( Vec < CopyLegacyCsvOption > ) ,
8806
8841
/// DATEFORMAT \[ AS \] {'dateformat_string' | 'auto' }
@@ -8809,16 +8844,46 @@ pub enum CopyLegacyOption {
8809
8844
Delimiter ( char ) ,
8810
8845
/// EMPTYASNULL
8811
8846
EmptyAsNull ,
8847
+ /// ENCRYPTED \[ AUTO \]
8848
+ Encrypted { auto : bool } ,
8849
+ /// ESCAPE
8850
+ Escape ,
8851
+ /// EXTENSION 'extension-name'
8852
+ Extension ( String ) ,
8853
+ /// FIXEDWIDTH \[ AS \] 'fixedwidth-spec'
8854
+ FixedWidth ( String ) ,
8855
+ /// GZIP
8856
+ Gzip ,
8857
+ /// HEADER
8858
+ Header ,
8812
8859
/// IAM_ROLE { DEFAULT | 'arn:aws:iam::123456789:role/role1' }
8813
8860
IamRole ( IamRoleKind ) ,
8814
8861
/// IGNOREHEADER \[ AS \] number_rows
8815
8862
IgnoreHeader ( u64 ) ,
8863
+ /// JSON
8864
+ Json ,
8865
+ /// MANIFEST \[ VERBOSE \]
8866
+ Manifest { verbose : bool } ,
8867
+ /// MAXFILESIZE \[ AS \] max-size \[ MB | GB \]
8868
+ MaxFileSize ( FileSize ) ,
8816
8869
/// NULL \[ AS \] 'null_string'
8817
8870
Null ( String ) ,
8871
+ /// PARALLEL
8872
+ Parallel ( Option < bool > ) ,
8873
+ /// PARQUET
8874
+ Parquet ,
8875
+ /// PARTITION BY ( column_name [, ... ] ) \[ INCLUDE \]
8876
+ PartitionBy ( PartitionBy ) ,
8877
+ /// REGION \[ AS \] 'aws-region' }
8878
+ Region ( String ) ,
8879
+ /// ROWGROUPSIZE \[ AS \] size \[ MB | GB \]
8880
+ RowGroupSize ( FileSize ) ,
8818
8881
/// TIMEFORMAT \[ AS \] {'timeformat_string' | 'auto' | 'epochsecs' | 'epochmillisecs' }
8819
8882
TimeFormat ( Option < String > ) ,
8820
8883
/// TRUNCATECOLUMNS
8821
8884
TruncateColumns ,
8885
+ /// ZSTD
8886
+ Zstd ,
8822
8887
}
8823
8888
8824
8889
impl fmt:: Display for CopyLegacyOption {
@@ -8833,8 +8898,12 @@ impl fmt::Display for CopyLegacyOption {
8833
8898
}
8834
8899
Ok ( ( ) )
8835
8900
}
8901
+ AddQuotes => write ! ( f, "ADDQUOTES" ) ,
8902
+ AllowOverwrite => write ! ( f, "ALLOWOVERWRITE" ) ,
8836
8903
Binary => write ! ( f, "BINARY" ) ,
8837
8904
BlankAsNull => write ! ( f, "BLANKSASNULL" ) ,
8905
+ Bzip2 => write ! ( f, "BZIP2" ) ,
8906
+ CleanPath => write ! ( f, "CLEANPATH" ) ,
8838
8907
Csv ( opts) => {
8839
8908
write ! ( f, "CSV" ) ?;
8840
8909
if !opts. is_empty ( ) {
@@ -8851,9 +8920,37 @@ impl fmt::Display for CopyLegacyOption {
8851
8920
}
8852
8921
Delimiter ( char) => write ! ( f, "DELIMITER '{char}'" ) ,
8853
8922
EmptyAsNull => write ! ( f, "EMPTYASNULL" ) ,
8923
+ Encrypted { auto } => write ! ( f, "ENCRYPTED{}" , if * auto { " AUTO" } else { "" } ) ,
8924
+ Escape => write ! ( f, "ESCAPE" ) ,
8925
+ Extension ( ext) => write ! ( f, "EXTENSION '{}'" , value:: escape_single_quote_string( ext) ) ,
8926
+ FixedWidth ( spec) => write ! (
8927
+ f,
8928
+ "FIXEDWIDTH '{}'" ,
8929
+ value:: escape_single_quote_string( spec)
8930
+ ) ,
8931
+ Gzip => write ! ( f, "GZIP" ) ,
8932
+ Header => write ! ( f, "HEADER" ) ,
8854
8933
IamRole ( role) => write ! ( f, "IAM_ROLE {role}" ) ,
8855
8934
IgnoreHeader ( num_rows) => write ! ( f, "IGNOREHEADER {num_rows}" ) ,
8935
+ Json => write ! ( f, "JSON" ) ,
8936
+ Manifest { verbose } => write ! ( f, "MANIFEST{}" , if * verbose { " VERBOSE" } else { "" } ) ,
8937
+ MaxFileSize ( file_size) => write ! ( f, "MAXFILESIZE {file_size}" ) ,
8856
8938
Null ( string) => write ! ( f, "NULL '{}'" , value:: escape_single_quote_string( string) ) ,
8939
+ Parallel ( enabled) => {
8940
+ write ! (
8941
+ f,
8942
+ "PARALLEL{}" ,
8943
+ match enabled {
8944
+ Some ( true ) => " TRUE" ,
8945
+ Some ( false ) => " FALSE" ,
8946
+ _ => "" ,
8947
+ }
8948
+ )
8949
+ }
8950
+ Parquet => write ! ( f, "PARQUET" ) ,
8951
+ PartitionBy ( p) => write ! ( f, "{p}" ) ,
8952
+ Region ( region) => write ! ( f, "REGION '{}'" , value:: escape_single_quote_string( region) ) ,
8953
+ RowGroupSize ( file_size) => write ! ( f, "ROWGROUPSIZE {file_size}" ) ,
8857
8954
TimeFormat ( fmt) => {
8858
8955
write ! ( f, "TIMEFORMAT" ) ?;
8859
8956
if let Some ( fmt) = fmt {
@@ -8862,10 +8959,73 @@ impl fmt::Display for CopyLegacyOption {
8862
8959
Ok ( ( ) )
8863
8960
}
8864
8961
TruncateColumns => write ! ( f, "TRUNCATECOLUMNS" ) ,
8962
+ Zstd => write ! ( f, "ZSTD" ) ,
8963
+ }
8964
+ }
8965
+ }
8966
+
8967
+ /// ```sql
8968
+ /// SIZE \[ MB | GB \]
8969
+ /// ```
8970
+ #[ derive( Debug , Clone , PartialEq , PartialOrd , Eq , Ord , Hash ) ]
8971
+ #[ cfg_attr( feature = "serde" , derive( Serialize , Deserialize ) ) ]
8972
+ #[ cfg_attr( feature = "visitor" , derive( Visit , VisitMut ) ) ]
8973
+ pub struct FileSize {
8974
+ pub size : Value ,
8975
+ pub unit : Option < FileSizeUnit > ,
8976
+ }
8977
+
8978
+ impl fmt:: Display for FileSize {
8979
+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
8980
+ write ! ( f, "{}" , self . size) ?;
8981
+ if let Some ( unit) = & self . unit {
8982
+ write ! ( f, " {unit}" ) ?;
8983
+ }
8984
+ Ok ( ( ) )
8985
+ }
8986
+ }
8987
+
8988
+ #[ derive( Debug , Clone , PartialEq , PartialOrd , Eq , Ord , Hash ) ]
8989
+ #[ cfg_attr( feature = "serde" , derive( Serialize , Deserialize ) ) ]
8990
+ #[ cfg_attr( feature = "visitor" , derive( Visit , VisitMut ) ) ]
8991
+ pub enum FileSizeUnit {
8992
+ MB ,
8993
+ GB ,
8994
+ }
8995
+
8996
+ impl fmt:: Display for FileSizeUnit {
8997
+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
8998
+ match self {
8999
+ FileSizeUnit :: MB => write ! ( f, "MB" ) ,
9000
+ FileSizeUnit :: GB => write ! ( f, "GB" ) ,
8865
9001
}
8866
9002
}
8867
9003
}
8868
9004
9005
+ /// Specifies the partition keys for the unload operation
9006
+ ///
9007
+ /// ```sql
9008
+ /// PARTITION BY ( column_name [, ... ] ) [ INCLUDE ]
9009
+ /// ```
9010
+ #[ derive( Debug , Clone , PartialEq , PartialOrd , Eq , Ord , Hash ) ]
9011
+ #[ cfg_attr( feature = "serde" , derive( Serialize , Deserialize ) ) ]
9012
+ #[ cfg_attr( feature = "visitor" , derive( Visit , VisitMut ) ) ]
9013
+ pub struct PartitionBy {
9014
+ pub columns : Vec < Ident > ,
9015
+ pub include : bool ,
9016
+ }
9017
+
9018
+ impl fmt:: Display for PartitionBy {
9019
+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
9020
+ write ! (
9021
+ f,
9022
+ "PARTITION BY ({}){}" ,
9023
+ display_comma_separated( & self . columns) ,
9024
+ if self . include { " INCLUDE" } else { "" }
9025
+ )
9026
+ }
9027
+ }
9028
+
8869
9029
/// An `IAM_ROLE` option in the AWS ecosystem
8870
9030
///
8871
9031
/// [Redshift COPY](https://docs.aws.amazon.com/redshift/latest/dg/copy-parameters-authorization.html#copy-iam-role)
0 commit comments