@@ -48,9 +48,9 @@ use crate::ast::{
4848 HiveFormat , HiveIOFormat , HiveRowFormat , HiveSetLocation , Ident , InitializeKind ,
4949 MySQLColumnPosition , ObjectName , OnCommit , OneOrManyWithParens , OperateFunctionArg ,
5050 OrderByExpr , ProjectionSelect , Query , RefreshModeKind , RowAccessPolicy , SequenceOptions ,
51- Spanned , SqlOption , StorageSerializationPolicy , TableVersion , Tag , TriggerEvent ,
52- TriggerExecBody , TriggerObject , TriggerPeriod , TriggerReferencing , Value , ValueWithSpan ,
53- WrappedCollection ,
51+ Spanned , SqlOption , StorageLifecyclePolicy , StorageSerializationPolicy , TableVersion , Tag ,
52+ TriggerEvent , TriggerExecBody , TriggerObject , TriggerPeriod , TriggerReferencing , Value ,
53+ ValueWithSpan , WrappedCollection ,
5454} ;
5555use crate :: display_utils:: { DisplayCommaSeparated , Indent , NewLine , SpaceOrNewline } ;
5656use crate :: keywords:: Keyword ;
@@ -457,6 +457,12 @@ pub enum AlterTableOperation {
457457 } ,
458458 /// Remove the clustering key from the table.
459459 DropClusteringKey ,
460+ /// Redshift `ALTER SORTKEY (column_list)`
461+ /// <https://docs.aws.amazon.com/redshift/latest/dg/r_ALTER_TABLE.html>
462+ AlterSortKey {
463+ /// Column references in the sort key.
464+ columns : Vec < Expr > ,
465+ } ,
460466 /// Suspend background reclustering operations.
461467 SuspendRecluster ,
462468 /// Resume background reclustering operations.
@@ -993,6 +999,10 @@ impl fmt::Display for AlterTableOperation {
993999 write ! ( f, "DROP CLUSTERING KEY" ) ?;
9941000 Ok ( ( ) )
9951001 }
1002+ AlterTableOperation :: AlterSortKey { columns } => {
1003+ write ! ( f, "ALTER SORTKEY({})" , display_comma_separated( columns) ) ?;
1004+ Ok ( ( ) )
1005+ }
9961006 AlterTableOperation :: SuspendRecluster => {
9971007 write ! ( f, "SUSPEND RECLUSTER" ) ?;
9981008 Ok ( ( ) )
@@ -2903,6 +2913,9 @@ pub struct CreateTable {
29032913 pub volatile : bool ,
29042914 /// `ICEBERG` clause
29052915 pub iceberg : bool ,
2916+ /// `SNAPSHOT` clause
2917+ /// <https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_snapshot_table_statement>
2918+ pub snapshot : bool ,
29062919 /// Table name
29072920 #[ cfg_attr( feature = "visitor" , visit( with = "visit_relation" ) ) ]
29082921 pub name : ObjectName ,
@@ -2999,6 +3012,9 @@ pub struct CreateTable {
29993012 /// Snowflake "WITH ROW ACCESS POLICY" clause
30003013 /// <https://docs.snowflake.com/en/sql-reference/sql/create-table>
30013014 pub with_row_access_policy : Option < RowAccessPolicy > ,
3015+ /// Snowflake `WITH STORAGE LIFECYCLE POLICY` clause
3016+ /// <https://docs.snowflake.com/en/sql-reference/sql/create-table>
3017+ pub with_storage_lifecycle_policy : Option < StorageLifecyclePolicy > ,
30023018 /// Snowflake "WITH TAG" clause
30033019 /// <https://docs.snowflake.com/en/sql-reference/sql/create-table>
30043020 pub with_tags : Option < Vec < Tag > > ,
@@ -3037,7 +3053,13 @@ pub struct CreateTable {
30373053 pub diststyle : Option < DistStyle > ,
30383054 /// Redshift `DISTKEY` option
30393055 /// <https://docs.aws.amazon.com/redshift/latest/dg/r_CREATE_TABLE_NEW.html>
3040- pub distkey : Option < Ident > ,
3056+ pub distkey : Option < Expr > ,
3057+ /// Redshift `SORTKEY` option
3058+ /// <https://docs.aws.amazon.com/redshift/latest/dg/r_CREATE_TABLE_NEW.html>
3059+ pub sortkey : Option < Vec < Expr > > ,
3060+ /// Redshift `BACKUP` option: `BACKUP { YES | NO }`
3061+ /// <https://docs.aws.amazon.com/redshift/latest/dg/r_CREATE_TABLE_NEW.html>
3062+ pub backup : Option < bool > ,
30413063}
30423064
30433065impl fmt:: Display for CreateTable {
@@ -3051,9 +3073,10 @@ impl fmt::Display for CreateTable {
30513073 // `CREATE TABLE t (a INT) AS SELECT a from t2`
30523074 write ! (
30533075 f,
3054- "CREATE {or_replace}{external}{global}{temporary}{transient}{volatile}{dynamic}{iceberg}TABLE {if_not_exists}{name}" ,
3076+ "CREATE {or_replace}{external}{global}{temporary}{transient}{volatile}{dynamic}{iceberg}{snapshot} TABLE {if_not_exists}{name}" ,
30553077 or_replace = if self . or_replace { "OR REPLACE " } else { "" } ,
30563078 external = if self . external { "EXTERNAL " } else { "" } ,
3079+ snapshot = if self . snapshot { "SNAPSHOT " } else { "" } ,
30573080 global = self . global
30583081 . map( |global| {
30593082 if global {
@@ -3300,6 +3323,10 @@ impl fmt::Display for CreateTable {
33003323 write ! ( f, " {row_access_policy}" , ) ?;
33013324 }
33023325
3326+ if let Some ( storage_lifecycle_policy) = & self . with_storage_lifecycle_policy {
3327+ write ! ( f, " {storage_lifecycle_policy}" , ) ?;
3328+ }
3329+
33033330 if let Some ( tag) = & self . with_tags {
33043331 write ! ( f, " WITH TAG ({})" , display_comma_separated( tag. as_slice( ) ) ) ?;
33053332 }
@@ -3336,12 +3363,18 @@ impl fmt::Display for CreateTable {
33363363 if self . strict {
33373364 write ! ( f, " STRICT" ) ?;
33383365 }
3366+ if let Some ( backup) = self . backup {
3367+ write ! ( f, " BACKUP {}" , if backup { "YES" } else { "NO" } ) ?;
3368+ }
33393369 if let Some ( diststyle) = & self . diststyle {
33403370 write ! ( f, " DISTSTYLE {diststyle}" ) ?;
33413371 }
33423372 if let Some ( distkey) = & self . distkey {
33433373 write ! ( f, " DISTKEY({distkey})" ) ?;
33443374 }
3375+ if let Some ( sortkey) = & self . sortkey {
3376+ write ! ( f, " SORTKEY({})" , display_comma_separated( sortkey) ) ?;
3377+ }
33453378 if let Some ( query) = & self . query {
33463379 write ! ( f, " AS {query}" ) ?;
33473380 }
@@ -3506,6 +3539,28 @@ impl fmt::Display for CreateDomain {
35063539 }
35073540}
35083541
3542+ /// The return type of a `CREATE FUNCTION` statement.
3543+ #[ derive( Debug , Clone , PartialEq , PartialOrd , Eq , Ord , Hash ) ]
3544+ #[ cfg_attr( feature = "serde" , derive( Serialize , Deserialize ) ) ]
3545+ #[ cfg_attr( feature = "visitor" , derive( Visit , VisitMut ) ) ]
3546+ pub enum FunctionReturnType {
3547+ /// `RETURNS <type>`
3548+ DataType ( DataType ) ,
3549+ /// `RETURNS SETOF <type>`
3550+ ///
3551+ /// [PostgreSQL](https://www.postgresql.org/docs/current/sql-createfunction.html)
3552+ SetOf ( DataType ) ,
3553+ }
3554+
3555+ impl fmt:: Display for FunctionReturnType {
3556+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
3557+ match self {
3558+ FunctionReturnType :: DataType ( data_type) => write ! ( f, "{data_type}" ) ,
3559+ FunctionReturnType :: SetOf ( data_type) => write ! ( f, "SETOF {data_type}" ) ,
3560+ }
3561+ }
3562+ }
3563+
35093564#[ derive( Debug , Clone , PartialEq , PartialOrd , Eq , Ord , Hash ) ]
35103565#[ cfg_attr( feature = "serde" , derive( Serialize , Deserialize ) ) ]
35113566#[ cfg_attr( feature = "visitor" , derive( Visit , VisitMut ) ) ]
@@ -3526,7 +3581,7 @@ pub struct CreateFunction {
35263581 /// List of arguments for the function.
35273582 pub args : Option < Vec < OperateFunctionArg > > ,
35283583 /// The return type of the function.
3529- pub return_type : Option < DataType > ,
3584+ pub return_type : Option < FunctionReturnType > ,
35303585 /// The expression that defines the function.
35313586 ///
35323587 /// Examples:
@@ -4277,6 +4332,9 @@ pub struct CreateView {
42774332 pub if_not_exists : bool ,
42784333 /// if true, has SQLite `TEMP` or `TEMPORARY` clause <https://www.sqlite.org/lang_createview.html>
42794334 pub temporary : bool ,
4335+ /// Snowflake: `COPY GRANTS` clause
4336+ /// <https://docs.snowflake.com/en/sql-reference/sql/create-view>
4337+ pub copy_grants : bool ,
42804338 /// if not None, has Clickhouse `TO` clause, specify the table into which to insert results
42814339 /// <https://clickhouse.com/docs/en/sql-reference/statements/create/view#materialized-view>
42824340 pub to : Option < ObjectName > ,
@@ -4320,6 +4378,9 @@ impl fmt::Display for CreateView {
43204378 . map( |to| format!( " TO {to}" ) )
43214379 . unwrap_or_default( )
43224380 ) ?;
4381+ if self . copy_grants {
4382+ write ! ( f, " COPY GRANTS" ) ?;
4383+ }
43234384 if !self . columns . is_empty ( ) {
43244385 write ! ( f, " ({})" , display_comma_separated( & self . columns) ) ?;
43254386 }
0 commit comments