@@ -4291,15 +4291,24 @@ pub enum Statement {
42914291 /// ```
42924292 /// Note: this is a MySQL-specific statement. See <https://dev.mysql.com/doc/refman/8.0/en/lock-tables.html>
42934293 UnlockTables ,
4294+ /// Unloads the result of a query to file
4295+ ///
4296+ /// [Athena](https://docs.aws.amazon.com/athena/latest/ug/unload.html):
42944297 /// ```sql
42954298 /// UNLOAD(statement) TO <destination> [ WITH options ]
42964299 /// ```
4297- /// See Redshift <https://docs.aws.amazon.com/redshift/latest/dg/r_UNLOAD.html> and
4298- // Athena <https://docs.aws.amazon.com/athena/latest/ug/unload.html>
4300+ ///
4301+ /// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_UNLOAD.html):
4302+ /// ```sql
4303+ /// UNLOAD('statement') TO <destination> [ OPTIONS ]
4304+ /// ```
42994305 Unload {
4300- query : Box < Query > ,
4306+ query : Option < Box < Query > > ,
4307+ query_text : Option < String > ,
43014308 to : Ident ,
4309+ auth : Option < IamRoleKind > ,
43024310 with : Vec < SqlOption > ,
4311+ options : Vec < CopyLegacyOption > ,
43034312 } ,
43044313 /// ```sql
43054314 /// OPTIMIZE TABLE [db.]name [ON CLUSTER cluster] [PARTITION partition | PARTITION ID 'partition_id'] [FINAL] [DEDUPLICATE [BY expression]]
@@ -6277,13 +6286,31 @@ impl fmt::Display for Statement {
62776286 Statement :: UnlockTables => {
62786287 write ! ( f, "UNLOCK TABLES" )
62796288 }
6280- Statement :: Unload { query, to, with } => {
6281- write ! ( f, "UNLOAD({query}) TO {to}" ) ?;
6282-
6289+ Statement :: Unload {
6290+ query,
6291+ query_text,
6292+ to,
6293+ auth,
6294+ with,
6295+ options,
6296+ } => {
6297+ write ! ( f, "UNLOAD(" ) ?;
6298+ if let Some ( query) = query {
6299+ write ! ( f, "{query}" ) ?;
6300+ }
6301+ if let Some ( query_text) = query_text {
6302+ write ! ( f, "'{query_text}'" ) ?;
6303+ }
6304+ write ! ( f, ") TO {to}" ) ?;
6305+ if let Some ( auth) = auth {
6306+ write ! ( f, " IAM_ROLE {auth}" ) ?;
6307+ }
62836308 if !with. is_empty ( ) {
62846309 write ! ( f, " WITH ({})" , display_comma_separated( with) ) ?;
62856310 }
6286-
6311+ if !options. is_empty ( ) {
6312+ write ! ( f, " {}" , display_separated( options, " " ) ) ?;
6313+ }
62876314 Ok ( ( ) )
62886315 }
62896316 Statement :: OptimizeTable {
@@ -8784,10 +8811,18 @@ pub enum CopyLegacyOption {
87848811 AcceptAnyDate ,
87858812 /// ACCEPTINVCHARS
87868813 AcceptInvChars ( Option < String > ) ,
8814+ /// ADDQUOTES
8815+ AddQuotes ,
8816+ /// ALLOWOVERWRITE
8817+ AllowOverwrite ,
87878818 /// BINARY
87888819 Binary ,
87898820 /// BLANKSASNULL
87908821 BlankAsNull ,
8822+ /// BZIP2
8823+ Bzip2 ,
8824+ /// CLEANPATH
8825+ CleanPath ,
87918826 /// CSV ...
87928827 Csv ( Vec < CopyLegacyCsvOption > ) ,
87938828 /// DATEFORMAT \[ AS \] {'dateformat_string' | 'auto' }
@@ -8796,16 +8831,46 @@ pub enum CopyLegacyOption {
87968831 Delimiter ( char ) ,
87978832 /// EMPTYASNULL
87988833 EmptyAsNull ,
8834+ /// ENCRYPTED \[ AUTO \]
8835+ Encrypted { auto : bool } ,
8836+ /// ESCAPE
8837+ Escape ,
8838+ /// EXTENSION 'extension-name'
8839+ Extension ( String ) ,
8840+ /// FIXEDWIDTH \[ AS \] 'fixedwidth-spec'
8841+ FixedWidth ( String ) ,
8842+ /// GZIP
8843+ Gzip ,
8844+ /// HEADER
8845+ Header ,
87998846 /// IAM_ROLE { DEFAULT | 'arn:aws:iam::123456789:role/role1' }
88008847 IamRole ( IamRoleKind ) ,
88018848 /// IGNOREHEADER \[ AS \] number_rows
88028849 IgnoreHeader ( u64 ) ,
8850+ /// JSON
8851+ Json ,
8852+ /// MANIFEST \[ VERBOSE \]
8853+ Manifest { verbose : bool } ,
8854+ /// MAXFILESIZE \[ AS \] max-size \[ MB | GB \]
8855+ MaxFileSize ( FileSize ) ,
88038856 /// NULL \[ AS \] 'null_string'
88048857 Null ( String ) ,
8858+ /// PARALLEL
8859+ Parallel ( Option < bool > ) ,
8860+ /// PARQUET
8861+ Parquet ,
8862+ /// PARTITION BY ( column_name [, ... ] ) \[ INCLUDE \]
8863+ PartitionBy ( PartitionBy ) ,
8864+ /// REGION \[ AS \] 'aws-region' }
8865+ Region ( String ) ,
8866+ /// ROWGROUPSIZE \[ AS \] size \[ MB | GB \]
8867+ RowGroupSize ( FileSize ) ,
88058868 /// TIMEFORMAT \[ AS \] {'timeformat_string' | 'auto' | 'epochsecs' | 'epochmillisecs' }
88068869 TimeFormat ( Option < String > ) ,
88078870 /// TRUNCATECOLUMNS
88088871 TruncateColumns ,
8872+ /// ZSTD
8873+ Zstd ,
88098874}
88108875
88118876impl fmt:: Display for CopyLegacyOption {
@@ -8820,8 +8885,12 @@ impl fmt::Display for CopyLegacyOption {
88208885 }
88218886 Ok ( ( ) )
88228887 }
8888+ AddQuotes => write ! ( f, "ADDQUOTES" ) ,
8889+ AllowOverwrite => write ! ( f, "ALLOWOVERWRITE" ) ,
88238890 Binary => write ! ( f, "BINARY" ) ,
88248891 BlankAsNull => write ! ( f, "BLANKSASNULL" ) ,
8892+ Bzip2 => write ! ( f, "BZIP2" ) ,
8893+ CleanPath => write ! ( f, "CLEANPATH" ) ,
88258894 Csv ( opts) => {
88268895 write ! ( f, "CSV" ) ?;
88278896 if !opts. is_empty ( ) {
@@ -8838,9 +8907,37 @@ impl fmt::Display for CopyLegacyOption {
88388907 }
88398908 Delimiter ( char) => write ! ( f, "DELIMITER '{char}'" ) ,
88408909 EmptyAsNull => write ! ( f, "EMPTYASNULL" ) ,
8910+ Encrypted { auto } => write ! ( f, "ENCRYPTED{}" , if * auto { " AUTO" } else { "" } ) ,
8911+ Escape => write ! ( f, "ESCAPE" ) ,
8912+ Extension ( ext) => write ! ( f, "EXTENSION '{}'" , value:: escape_single_quote_string( ext) ) ,
8913+ FixedWidth ( spec) => write ! (
8914+ f,
8915+ "FIXEDWIDTH '{}'" ,
8916+ value:: escape_single_quote_string( spec)
8917+ ) ,
8918+ Gzip => write ! ( f, "GZIP" ) ,
8919+ Header => write ! ( f, "HEADER" ) ,
88418920 IamRole ( role) => write ! ( f, "IAM_ROLE {role}" ) ,
88428921 IgnoreHeader ( num_rows) => write ! ( f, "IGNOREHEADER {num_rows}" ) ,
8922+ Json => write ! ( f, "JSON" ) ,
8923+ Manifest { verbose } => write ! ( f, "MANIFEST{}" , if * verbose { " VERBOSE" } else { "" } ) ,
8924+ MaxFileSize ( file_size) => write ! ( f, "MAXFILESIZE {file_size}" ) ,
88438925 Null ( string) => write ! ( f, "NULL '{}'" , value:: escape_single_quote_string( string) ) ,
8926+ Parallel ( enabled) => {
8927+ write ! (
8928+ f,
8929+ "PARALLEL{}" ,
8930+ match enabled {
8931+ Some ( true ) => " TRUE" ,
8932+ Some ( false ) => " FALSE" ,
8933+ _ => "" ,
8934+ }
8935+ )
8936+ }
8937+ Parquet => write ! ( f, "PARQUET" ) ,
8938+ PartitionBy ( p) => write ! ( f, "{p}" ) ,
8939+ Region ( region) => write ! ( f, "REGION '{}'" , value:: escape_single_quote_string( region) ) ,
8940+ RowGroupSize ( file_size) => write ! ( f, "ROWGROUPSIZE {file_size}" ) ,
88448941 TimeFormat ( fmt) => {
88458942 write ! ( f, "TIMEFORMAT" ) ?;
88468943 if let Some ( fmt) = fmt {
@@ -8849,10 +8946,73 @@ impl fmt::Display for CopyLegacyOption {
88498946 Ok ( ( ) )
88508947 }
88518948 TruncateColumns => write ! ( f, "TRUNCATECOLUMNS" ) ,
8949+ Zstd => write ! ( f, "ZSTD" ) ,
8950+ }
8951+ }
8952+ }
8953+
8954+ /// ```sql
8955+ /// SIZE \[ MB | GB \]
8956+ /// ```
8957+ #[ derive( Debug , Clone , PartialEq , PartialOrd , Eq , Ord , Hash ) ]
8958+ #[ cfg_attr( feature = "serde" , derive( Serialize , Deserialize ) ) ]
8959+ #[ cfg_attr( feature = "visitor" , derive( Visit , VisitMut ) ) ]
8960+ pub struct FileSize {
8961+ pub size : Value ,
8962+ pub unit : Option < FileSizeUnit > ,
8963+ }
8964+
8965+ impl fmt:: Display for FileSize {
8966+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
8967+ write ! ( f, "{}" , self . size) ?;
8968+ if let Some ( unit) = & self . unit {
8969+ write ! ( f, " {unit}" ) ?;
8970+ }
8971+ Ok ( ( ) )
8972+ }
8973+ }
8974+
8975+ #[ derive( Debug , Clone , PartialEq , PartialOrd , Eq , Ord , Hash ) ]
8976+ #[ cfg_attr( feature = "serde" , derive( Serialize , Deserialize ) ) ]
8977+ #[ cfg_attr( feature = "visitor" , derive( Visit , VisitMut ) ) ]
8978+ pub enum FileSizeUnit {
8979+ MB ,
8980+ GB ,
8981+ }
8982+
8983+ impl fmt:: Display for FileSizeUnit {
8984+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
8985+ match self {
8986+ FileSizeUnit :: MB => write ! ( f, "MB" ) ,
8987+ FileSizeUnit :: GB => write ! ( f, "GB" ) ,
88528988 }
88538989 }
88548990}
88558991
8992+ /// Specifies the partition keys for the unload operation
8993+ ///
8994+ /// ```sql
8995+ /// PARTITION BY ( column_name [, ... ] ) [ INCLUDE ]
8996+ /// ```
8997+ #[ derive( Debug , Clone , PartialEq , PartialOrd , Eq , Ord , Hash ) ]
8998+ #[ cfg_attr( feature = "serde" , derive( Serialize , Deserialize ) ) ]
8999+ #[ cfg_attr( feature = "visitor" , derive( Visit , VisitMut ) ) ]
9000+ pub struct PartitionBy {
9001+ pub columns : Vec < Ident > ,
9002+ pub include : bool ,
9003+ }
9004+
9005+ impl fmt:: Display for PartitionBy {
9006+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
9007+ write ! (
9008+ f,
9009+ "PARTITION BY ({}){}" ,
9010+ display_comma_separated( & self . columns) ,
9011+ if self . include { " INCLUDE" } else { "" }
9012+ )
9013+ }
9014+ }
9015+
88569016/// An `IAM_ROLE` option in the AWS ecosystem
88579017///
88589018/// [Redshift COPY](https://docs.aws.amazon.com/redshift/latest/dg/copy-parameters-authorization.html#copy-iam-role)
0 commit comments