@@ -4294,15 +4294,24 @@ pub enum Statement {
42944294 /// ```
42954295 /// Note: this is a MySQL-specific statement. See <https://dev.mysql.com/doc/refman/8.0/en/lock-tables.html>
42964296 UnlockTables ,
4297+ /// Unloads the result of a query to file
4298+ ///
4299+ /// [Athena](https://docs.aws.amazon.com/athena/latest/ug/unload.html):
42974300 /// ```sql
42984301 /// UNLOAD(statement) TO <destination> [ WITH options ]
42994302 /// ```
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+ /// ```
43024308 Unload {
4303- query : Box < Query > ,
4309+ query : Option < Box < Query > > ,
4310+ query_text : Option < String > ,
43044311 to : Ident ,
4312+ auth : Option < IamRoleKind > ,
43054313 with : Vec < SqlOption > ,
4314+ options : Vec < CopyLegacyOption > ,
43064315 } ,
43074316 /// ```sql
43084317 /// 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 {
62826291 Statement :: UnlockTables => {
62836292 write ! ( f, "UNLOCK TABLES" )
62846293 }
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+ }
62886313 if !with. is_empty ( ) {
62896314 write ! ( f, " WITH ({})" , display_comma_separated( with) ) ?;
62906315 }
6291-
6316+ if !options. is_empty ( ) {
6317+ write ! ( f, " {}" , display_separated( options, " " ) ) ?;
6318+ }
62926319 Ok ( ( ) )
62936320 }
62946321 Statement :: OptimizeTable {
@@ -8797,10 +8824,18 @@ pub enum CopyLegacyOption {
87978824 AcceptAnyDate ,
87988825 /// ACCEPTINVCHARS
87998826 AcceptInvChars ( Option < String > ) ,
8827+ /// ADDQUOTES
8828+ AddQuotes ,
8829+ /// ALLOWOVERWRITE
8830+ AllowOverwrite ,
88008831 /// BINARY
88018832 Binary ,
88028833 /// BLANKSASNULL
88038834 BlankAsNull ,
8835+ /// BZIP2
8836+ Bzip2 ,
8837+ /// CLEANPATH
8838+ CleanPath ,
88048839 /// CSV ...
88058840 Csv ( Vec < CopyLegacyCsvOption > ) ,
88068841 /// DATEFORMAT \[ AS \] {'dateformat_string' | 'auto' }
@@ -8809,16 +8844,46 @@ pub enum CopyLegacyOption {
88098844 Delimiter ( char ) ,
88108845 /// EMPTYASNULL
88118846 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 ,
88128859 /// IAM_ROLE { DEFAULT | 'arn:aws:iam::123456789:role/role1' }
88138860 IamRole ( IamRoleKind ) ,
88148861 /// IGNOREHEADER \[ AS \] number_rows
88158862 IgnoreHeader ( u64 ) ,
8863+ /// JSON
8864+ Json ,
8865+ /// MANIFEST \[ VERBOSE \]
8866+ Manifest { verbose : bool } ,
8867+ /// MAXFILESIZE \[ AS \] max-size \[ MB | GB \]
8868+ MaxFileSize ( FileSize ) ,
88168869 /// NULL \[ AS \] 'null_string'
88178870 Null ( String ) ,
8871+ /// PARALLEL [ { ON | TRUE } | { OFF | FALSE } ]
8872+ Parallel ( Option < bool > ) ,
8873+ /// PARQUET
8874+ Parquet ,
8875+ /// PARTITION BY ( column_name [, ... ] ) \[ INCLUDE \]
8876+ PartitionBy ( UnloadPartitionBy ) ,
8877+ /// REGION \[ AS \] 'aws-region' }
8878+ Region ( String ) ,
8879+ /// ROWGROUPSIZE \[ AS \] size \[ MB | GB \]
8880+ RowGroupSize ( FileSize ) ,
88188881 /// TIMEFORMAT \[ AS \] {'timeformat_string' | 'auto' | 'epochsecs' | 'epochmillisecs' }
88198882 TimeFormat ( Option < String > ) ,
88208883 /// TRUNCATECOLUMNS
88218884 TruncateColumns ,
8885+ /// ZSTD
8886+ Zstd ,
88228887}
88238888
88248889impl fmt:: Display for CopyLegacyOption {
@@ -8833,8 +8898,12 @@ impl fmt::Display for CopyLegacyOption {
88338898 }
88348899 Ok ( ( ) )
88358900 }
8901+ AddQuotes => write ! ( f, "ADDQUOTES" ) ,
8902+ AllowOverwrite => write ! ( f, "ALLOWOVERWRITE" ) ,
88368903 Binary => write ! ( f, "BINARY" ) ,
88378904 BlankAsNull => write ! ( f, "BLANKSASNULL" ) ,
8905+ Bzip2 => write ! ( f, "BZIP2" ) ,
8906+ CleanPath => write ! ( f, "CLEANPATH" ) ,
88388907 Csv ( opts) => {
88398908 write ! ( f, "CSV" ) ?;
88408909 if !opts. is_empty ( ) {
@@ -8851,9 +8920,37 @@ impl fmt::Display for CopyLegacyOption {
88518920 }
88528921 Delimiter ( char) => write ! ( f, "DELIMITER '{char}'" ) ,
88538922 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" ) ,
88548933 IamRole ( role) => write ! ( f, "IAM_ROLE {role}" ) ,
88558934 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}" ) ,
88568938 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}" ) ,
88578954 TimeFormat ( fmt) => {
88588955 write ! ( f, "TIMEFORMAT" ) ?;
88598956 if let Some ( fmt) = fmt {
@@ -8862,10 +8959,73 @@ impl fmt::Display for CopyLegacyOption {
88628959 Ok ( ( ) )
88638960 }
88648961 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" ) ,
88659001 }
88669002 }
88679003}
88689004
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 UnloadPartitionBy {
9014+ pub columns : Vec < Ident > ,
9015+ pub include : bool ,
9016+ }
9017+
9018+ impl fmt:: Display for UnloadPartitionBy {
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+
88699029/// An `IAM_ROLE` option in the AWS ecosystem
88709030///
88719031/// [Redshift COPY](https://docs.aws.amazon.com/redshift/latest/dg/copy-parameters-authorization.html#copy-iam-role)
0 commit comments