@@ -4323,15 +4323,24 @@ pub enum Statement {
43234323 /// ```
43244324 /// Note: this is a MySQL-specific statement. See <https://dev.mysql.com/doc/refman/8.0/en/lock-tables.html>
43254325 UnlockTables ,
4326+ /// Unloads the result of a query to file
4327+ ///
4328+ /// [Athena](https://docs.aws.amazon.com/athena/latest/ug/unload.html):
43264329 /// ```sql
43274330 /// UNLOAD(statement) TO <destination> [ WITH options ]
43284331 /// ```
4329- /// See Redshift <https://docs.aws.amazon.com/redshift/latest/dg/r_UNLOAD.html> and
4330- // Athena <https://docs.aws.amazon.com/athena/latest/ug/unload.html>
4332+ ///
4333+ /// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_UNLOAD.html):
4334+ /// ```sql
4335+ /// UNLOAD('statement') TO <destination> [ OPTIONS ]
4336+ /// ```
43314337 Unload {
4332- query : Box < Query > ,
4338+ query : Option < Box < Query > > ,
4339+ query_text : Option < String > ,
43334340 to : Ident ,
4341+ auth : Option < IamRoleKind > ,
43344342 with : Vec < SqlOption > ,
4343+ options : Vec < CopyLegacyOption > ,
43354344 } ,
43364345 /// ```sql
43374346 /// OPTIMIZE TABLE [db.]name [ON CLUSTER cluster] [PARTITION partition | PARTITION ID 'partition_id'] [FINAL] [DEDUPLICATE [BY expression]]
@@ -6311,13 +6320,31 @@ impl fmt::Display for Statement {
63116320 Statement :: UnlockTables => {
63126321 write ! ( f, "UNLOCK TABLES" )
63136322 }
6314- Statement :: Unload { query, to, with } => {
6315- write ! ( f, "UNLOAD({query}) TO {to}" ) ?;
6316-
6323+ Statement :: Unload {
6324+ query,
6325+ query_text,
6326+ to,
6327+ auth,
6328+ with,
6329+ options,
6330+ } => {
6331+ write ! ( f, "UNLOAD(" ) ?;
6332+ if let Some ( query) = query {
6333+ write ! ( f, "{query}" ) ?;
6334+ }
6335+ if let Some ( query_text) = query_text {
6336+ write ! ( f, "'{query_text}'" ) ?;
6337+ }
6338+ write ! ( f, ") TO {to}" ) ?;
6339+ if let Some ( auth) = auth {
6340+ write ! ( f, " IAM_ROLE {auth}" ) ?;
6341+ }
63176342 if !with. is_empty ( ) {
63186343 write ! ( f, " WITH ({})" , display_comma_separated( with) ) ?;
63196344 }
6320-
6345+ if !options. is_empty ( ) {
6346+ write ! ( f, " {}" , display_separated( options, " " ) ) ?;
6347+ }
63216348 Ok ( ( ) )
63226349 }
63236350 Statement :: OptimizeTable {
@@ -8826,10 +8853,18 @@ pub enum CopyLegacyOption {
88268853 AcceptAnyDate ,
88278854 /// ACCEPTINVCHARS
88288855 AcceptInvChars ( Option < String > ) ,
8856+ /// ADDQUOTES
8857+ AddQuotes ,
8858+ /// ALLOWOVERWRITE
8859+ AllowOverwrite ,
88298860 /// BINARY
88308861 Binary ,
88318862 /// BLANKSASNULL
88328863 BlankAsNull ,
8864+ /// BZIP2
8865+ Bzip2 ,
8866+ /// CLEANPATH
8867+ CleanPath ,
88338868 /// CSV ...
88348869 Csv ( Vec < CopyLegacyCsvOption > ) ,
88358870 /// DATEFORMAT \[ AS \] {'dateformat_string' | 'auto' }
@@ -8838,16 +8873,46 @@ pub enum CopyLegacyOption {
88388873 Delimiter ( char ) ,
88398874 /// EMPTYASNULL
88408875 EmptyAsNull ,
8876+ /// ENCRYPTED \[ AUTO \]
8877+ Encrypted { auto : bool } ,
8878+ /// ESCAPE
8879+ Escape ,
8880+ /// EXTENSION 'extension-name'
8881+ Extension ( String ) ,
8882+ /// FIXEDWIDTH \[ AS \] 'fixedwidth-spec'
8883+ FixedWidth ( String ) ,
8884+ /// GZIP
8885+ Gzip ,
8886+ /// HEADER
8887+ Header ,
88418888 /// IAM_ROLE { DEFAULT | 'arn:aws:iam::123456789:role/role1' }
88428889 IamRole ( IamRoleKind ) ,
88438890 /// IGNOREHEADER \[ AS \] number_rows
88448891 IgnoreHeader ( u64 ) ,
8892+ /// JSON
8893+ Json ,
8894+ /// MANIFEST \[ VERBOSE \]
8895+ Manifest { verbose : bool } ,
8896+ /// MAXFILESIZE \[ AS \] max-size \[ MB | GB \]
8897+ MaxFileSize ( FileSize ) ,
88458898 /// NULL \[ AS \] 'null_string'
88468899 Null ( String ) ,
8900+ /// PARALLEL [ { ON | TRUE } | { OFF | FALSE } ]
8901+ Parallel ( Option < bool > ) ,
8902+ /// PARQUET
8903+ Parquet ,
8904+ /// PARTITION BY ( column_name [, ... ] ) \[ INCLUDE \]
8905+ PartitionBy ( UnloadPartitionBy ) ,
8906+ /// REGION \[ AS \] 'aws-region' }
8907+ Region ( String ) ,
8908+ /// ROWGROUPSIZE \[ AS \] size \[ MB | GB \]
8909+ RowGroupSize ( FileSize ) ,
88478910 /// TIMEFORMAT \[ AS \] {'timeformat_string' | 'auto' | 'epochsecs' | 'epochmillisecs' }
88488911 TimeFormat ( Option < String > ) ,
88498912 /// TRUNCATECOLUMNS
88508913 TruncateColumns ,
8914+ /// ZSTD
8915+ Zstd ,
88518916}
88528917
88538918impl fmt:: Display for CopyLegacyOption {
@@ -8862,8 +8927,12 @@ impl fmt::Display for CopyLegacyOption {
88628927 }
88638928 Ok ( ( ) )
88648929 }
8930+ AddQuotes => write ! ( f, "ADDQUOTES" ) ,
8931+ AllowOverwrite => write ! ( f, "ALLOWOVERWRITE" ) ,
88658932 Binary => write ! ( f, "BINARY" ) ,
88668933 BlankAsNull => write ! ( f, "BLANKSASNULL" ) ,
8934+ Bzip2 => write ! ( f, "BZIP2" ) ,
8935+ CleanPath => write ! ( f, "CLEANPATH" ) ,
88678936 Csv ( opts) => {
88688937 write ! ( f, "CSV" ) ?;
88698938 if !opts. is_empty ( ) {
@@ -8880,9 +8949,37 @@ impl fmt::Display for CopyLegacyOption {
88808949 }
88818950 Delimiter ( char) => write ! ( f, "DELIMITER '{char}'" ) ,
88828951 EmptyAsNull => write ! ( f, "EMPTYASNULL" ) ,
8952+ Encrypted { auto } => write ! ( f, "ENCRYPTED{}" , if * auto { " AUTO" } else { "" } ) ,
8953+ Escape => write ! ( f, "ESCAPE" ) ,
8954+ Extension ( ext) => write ! ( f, "EXTENSION '{}'" , value:: escape_single_quote_string( ext) ) ,
8955+ FixedWidth ( spec) => write ! (
8956+ f,
8957+ "FIXEDWIDTH '{}'" ,
8958+ value:: escape_single_quote_string( spec)
8959+ ) ,
8960+ Gzip => write ! ( f, "GZIP" ) ,
8961+ Header => write ! ( f, "HEADER" ) ,
88838962 IamRole ( role) => write ! ( f, "IAM_ROLE {role}" ) ,
88848963 IgnoreHeader ( num_rows) => write ! ( f, "IGNOREHEADER {num_rows}" ) ,
8964+ Json => write ! ( f, "JSON" ) ,
8965+ Manifest { verbose } => write ! ( f, "MANIFEST{}" , if * verbose { " VERBOSE" } else { "" } ) ,
8966+ MaxFileSize ( file_size) => write ! ( f, "MAXFILESIZE {file_size}" ) ,
88858967 Null ( string) => write ! ( f, "NULL '{}'" , value:: escape_single_quote_string( string) ) ,
8968+ Parallel ( enabled) => {
8969+ write ! (
8970+ f,
8971+ "PARALLEL{}" ,
8972+ match enabled {
8973+ Some ( true ) => " TRUE" ,
8974+ Some ( false ) => " FALSE" ,
8975+ _ => "" ,
8976+ }
8977+ )
8978+ }
8979+ Parquet => write ! ( f, "PARQUET" ) ,
8980+ PartitionBy ( p) => write ! ( f, "{p}" ) ,
8981+ Region ( region) => write ! ( f, "REGION '{}'" , value:: escape_single_quote_string( region) ) ,
8982+ RowGroupSize ( file_size) => write ! ( f, "ROWGROUPSIZE {file_size}" ) ,
88868983 TimeFormat ( fmt) => {
88878984 write ! ( f, "TIMEFORMAT" ) ?;
88888985 if let Some ( fmt) = fmt {
@@ -8891,10 +8988,73 @@ impl fmt::Display for CopyLegacyOption {
88918988 Ok ( ( ) )
88928989 }
88938990 TruncateColumns => write ! ( f, "TRUNCATECOLUMNS" ) ,
8991+ Zstd => write ! ( f, "ZSTD" ) ,
8992+ }
8993+ }
8994+ }
8995+
8996+ /// ```sql
8997+ /// SIZE \[ MB | GB \]
8998+ /// ```
8999+ #[ derive( Debug , Clone , PartialEq , PartialOrd , Eq , Ord , Hash ) ]
9000+ #[ cfg_attr( feature = "serde" , derive( Serialize , Deserialize ) ) ]
9001+ #[ cfg_attr( feature = "visitor" , derive( Visit , VisitMut ) ) ]
9002+ pub struct FileSize {
9003+ pub size : Value ,
9004+ pub unit : Option < FileSizeUnit > ,
9005+ }
9006+
9007+ impl fmt:: Display for FileSize {
9008+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
9009+ write ! ( f, "{}" , self . size) ?;
9010+ if let Some ( unit) = & self . unit {
9011+ write ! ( f, " {unit}" ) ?;
9012+ }
9013+ Ok ( ( ) )
9014+ }
9015+ }
9016+
9017+ #[ derive( Debug , Clone , PartialEq , PartialOrd , Eq , Ord , Hash ) ]
9018+ #[ cfg_attr( feature = "serde" , derive( Serialize , Deserialize ) ) ]
9019+ #[ cfg_attr( feature = "visitor" , derive( Visit , VisitMut ) ) ]
9020+ pub enum FileSizeUnit {
9021+ MB ,
9022+ GB ,
9023+ }
9024+
9025+ impl fmt:: Display for FileSizeUnit {
9026+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
9027+ match self {
9028+ FileSizeUnit :: MB => write ! ( f, "MB" ) ,
9029+ FileSizeUnit :: GB => write ! ( f, "GB" ) ,
88949030 }
88959031 }
88969032}
88979033
9034+ /// Specifies the partition keys for the unload operation
9035+ ///
9036+ /// ```sql
9037+ /// PARTITION BY ( column_name [, ... ] ) [ INCLUDE ]
9038+ /// ```
9039+ #[ derive( Debug , Clone , PartialEq , PartialOrd , Eq , Ord , Hash ) ]
9040+ #[ cfg_attr( feature = "serde" , derive( Serialize , Deserialize ) ) ]
9041+ #[ cfg_attr( feature = "visitor" , derive( Visit , VisitMut ) ) ]
9042+ pub struct UnloadPartitionBy {
9043+ pub columns : Vec < Ident > ,
9044+ pub include : bool ,
9045+ }
9046+
9047+ impl fmt:: Display for UnloadPartitionBy {
9048+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
9049+ write ! (
9050+ f,
9051+ "PARTITION BY ({}){}" ,
9052+ display_comma_separated( & self . columns) ,
9053+ if self . include { " INCLUDE" } else { "" }
9054+ )
9055+ }
9056+ }
9057+
88989058/// An `IAM_ROLE` option in the AWS ecosystem
88999059///
89009060/// [Redshift COPY](https://docs.aws.amazon.com/redshift/latest/dg/copy-parameters-authorization.html#copy-iam-role)
0 commit comments