Skip to content

Commit 9c8625f

Browse files
Merge branch 'main' into postgres-regression-12
2 parents c0e0131 + 7c78d13 commit 9c8625f

23 files changed

Lines changed: 604 additions & 117 deletions

src/ast/ddl.rs

Lines changed: 64 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2113,8 +2113,7 @@ impl fmt::Display for ColumnOption {
21132113
GeneratedAs::ExpStored => "",
21142114
};
21152115
write!(f, "GENERATED {when} AS IDENTITY")?;
2116-
if sequence_options.is_some() {
2117-
let so = sequence_options.as_ref().unwrap();
2116+
if let Some(so) = sequence_options {
21182117
if !so.is_empty() {
21192118
write!(f, " (")?;
21202119
}
@@ -3021,6 +3020,9 @@ pub struct CreateTable {
30213020
/// Snowflake "EXTERNAL_VOLUME" clause for Iceberg tables
30223021
/// <https://docs.snowflake.com/en/sql-reference/sql/create-iceberg-table>
30233022
pub external_volume: Option<String>,
3023+
/// `WITH CONNECTION` clause.
3024+
/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_external_table_statement)
3025+
pub with_connection: Option<ObjectName>,
30243026
/// Snowflake "BASE_LOCATION" clause for Iceberg tables
30253027
/// <https://docs.snowflake.com/en/sql-reference/sql/create-iceberg-table>
30263028
pub base_location: Option<String>,
@@ -3060,6 +3062,20 @@ pub struct CreateTable {
30603062
/// Redshift `BACKUP` option: `BACKUP { YES | NO }`
30613063
/// <https://docs.aws.amazon.com/redshift/latest/dg/r_CREATE_TABLE_NEW.html>
30623064
pub backup: Option<bool>,
3065+
/// `MULTISET | SET` table-kind prefix.
3066+
/// `Some(true)` => `MULTISET`, `Some(false)` => `SET`.
3067+
///
3068+
/// [Teradata](https://docs.teradata.com/r/Enterprise_IntelliFlex_VMware/SQL-Data-Definition-Language-Syntax-and-Examples/Table-Statements/CREATE-TABLE-and-CREATE-TABLE-AS/Syntax-Elements/MULTISET-or-SET)
3069+
pub multiset: Option<bool>,
3070+
/// `FALLBACK` clause.
3071+
/// `Some(true)` => `FALLBACK`, `Some(false)` => `NO FALLBACK`
3072+
///
3073+
/// [Teradata](https://docs.teradata.com/r/Enterprise_IntelliFlex_VMware/SQL-Data-Definition-Language-Syntax-and-Examples/Table-Statements/CREATE-TABLE-and-CREATE-TABLE-AS/Syntax-Elements/FALLBACK-or-NO-FALLBACK)
3074+
pub fallback: Option<bool>,
3075+
/// `WITH DATA` clause on a `CREATE TABLE ... AS` statement.
3076+
///
3077+
/// [Teradata](https://docs.teradata.com/r/Enterprise_IntelliFlex_VMware/SQL-Data-Definition-Language-Syntax-and-Examples/Table-Statements/CREATE-TABLE-and-CREATE-TABLE-AS/Syntax-Elements/AS_clause/WITH-Clause-Phrase)
3078+
pub with_data: Option<WithData>,
30633079
}
30643080

30653081
impl fmt::Display for CreateTable {
@@ -3073,7 +3089,7 @@ impl fmt::Display for CreateTable {
30733089
// `CREATE TABLE t (a INT) AS SELECT a from t2`
30743090
write!(
30753091
f,
3076-
"CREATE {or_replace}{external}{global}{temporary}{transient}{volatile}{dynamic}{iceberg}{snapshot}TABLE {if_not_exists}{name}",
3092+
"CREATE {or_replace}{external}{global}{multiset}{temporary}{transient}{volatile}{dynamic}{iceberg}{snapshot}TABLE {if_not_exists}{name}",
30773093
or_replace = if self.or_replace { "OR REPLACE " } else { "" },
30783094
external = if self.external { "EXTERNAL " } else { "" },
30793095
snapshot = if self.snapshot { "SNAPSHOT " } else { "" },
@@ -3087,14 +3103,20 @@ impl fmt::Display for CreateTable {
30873103
})
30883104
.unwrap_or(""),
30893105
if_not_exists = if self.if_not_exists { "IF NOT EXISTS " } else { "" },
3106+
multiset = self
3107+
.multiset
3108+
.map(|m| if m { "MULTISET " } else { "SET " })
3109+
.unwrap_or(""),
30903110
temporary = if self.temporary { "TEMPORARY " } else { "" },
30913111
transient = if self.transient { "TRANSIENT " } else { "" },
30923112
volatile = if self.volatile { "VOLATILE " } else { "" },
3093-
// Only for Snowflake
30943113
iceberg = if self.iceberg { "ICEBERG " } else { "" },
30953114
dynamic = if self.dynamic { "DYNAMIC " } else { "" },
30963115
name = self.name,
30973116
)?;
3117+
if let Some(fallback) = self.fallback {
3118+
write!(f, ", {}", if fallback { "FALLBACK" } else { "NO FALLBACK" })?;
3119+
}
30983120
if let Some(partition_of) = &self.partition_of {
30993121
write!(f, " PARTITION OF {partition_of}")?;
31003122
}
@@ -3250,6 +3272,9 @@ impl fmt::Display for CreateTable {
32503272
if let Some(cluster_by) = self.cluster_by.as_ref() {
32513273
write!(f, " CLUSTER BY {cluster_by}")?;
32523274
}
3275+
if let Some(with_connection) = &self.with_connection {
3276+
write!(f, " WITH CONNECTION {with_connection}")?;
3277+
}
32533278
if let options @ CreateTableOptions::Options(_) = &self.table_options {
32543279
write!(f, " {options}")?;
32553280
}
@@ -3379,6 +3404,41 @@ impl fmt::Display for CreateTable {
33793404
if let Some(query) = &self.query {
33803405
write!(f, " AS {query}")?;
33813406
}
3407+
if let Some(with_data) = &self.with_data {
3408+
write!(f, " {with_data}")?;
3409+
}
3410+
Ok(())
3411+
}
3412+
}
3413+
3414+
/// `WITH DATA` clause on `CREATE TABLE ... AS` statement.
3415+
///
3416+
/// [Teradata](https://docs.teradata.com/r/Enterprise_IntelliFlex_VMware/SQL-Data-Definition-Language-Syntax-and-Examples/Table-Statements/CREATE-TABLE-and-CREATE-TABLE-AS/Syntax-Elements/AS_clause/WITH-Clause-Phrase)
3417+
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
3418+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3419+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3420+
pub struct WithData {
3421+
/// `true` for `WITH DATA`, `false` for `WITH NO DATA`.
3422+
pub data: bool,
3423+
/// `Some(true)` for `AND STATISTICS`, `Some(false)` for `AND NO STATISTICS`,
3424+
/// `None` if the `AND [NO] STATISTICS` sub-clause is omitted.
3425+
pub statistics: Option<bool>,
3426+
}
3427+
3428+
impl fmt::Display for WithData {
3429+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3430+
f.write_str("WITH ")?;
3431+
if !self.data {
3432+
f.write_str("NO ")?;
3433+
}
3434+
f.write_str("DATA")?;
3435+
if let Some(stats) = self.statistics {
3436+
f.write_str(" AND ")?;
3437+
if !stats {
3438+
f.write_str("NO ")?;
3439+
}
3440+
f.write_str("STATISTICS")?;
3441+
}
33823442
Ok(())
33833443
}
33843444
}

src/ast/helpers/stmt_create_table.rs

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ use crate::ast::{
2929
DistStyle, Expr, FileFormat, ForValues, HiveDistributionStyle, HiveFormat, Ident,
3030
InitializeKind, ObjectName, OnCommit, OneOrManyWithParens, Query, RefreshModeKind,
3131
RowAccessPolicy, Statement, StorageLifecyclePolicy, StorageSerializationPolicy,
32-
TableConstraint, TableVersion, Tag, WrappedCollection,
32+
TableConstraint, TableVersion, Tag, WithData, WrappedCollection,
3333
};
3434

3535
use crate::parser::ParserError;
@@ -157,6 +157,9 @@ pub struct CreateTableBuilder {
157157
pub base_location: Option<String>,
158158
/// Optional external volume identifier.
159159
pub external_volume: Option<String>,
160+
/// `WITH CONNECTION` clause.
161+
/// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_external_table_statement)
162+
pub with_connection: Option<ObjectName>,
160163
/// Optional catalog name.
161164
pub catalog: Option<String>,
162165
/// Optional catalog synchronization option.
@@ -183,6 +186,12 @@ pub struct CreateTableBuilder {
183186
pub sortkey: Option<Vec<Expr>>,
184187
/// Redshift `BACKUP` option.
185188
pub backup: Option<bool>,
189+
/// `MULTISET | SET` table-kind prefix.
190+
pub multiset: Option<bool>,
191+
/// `FALLBACK` clause.
192+
pub fallback: Option<bool>,
193+
/// `WITH DATA` clause.
194+
pub with_data: Option<WithData>,
186195
}
187196

188197
impl CreateTableBuilder {
@@ -235,6 +244,7 @@ impl CreateTableBuilder {
235244
with_tags: None,
236245
base_location: None,
237246
external_volume: None,
247+
with_connection: None,
238248
catalog: None,
239249
catalog_sync: None,
240250
storage_serialization_policy: None,
@@ -248,6 +258,9 @@ impl CreateTableBuilder {
248258
distkey: None,
249259
sortkey: None,
250260
backup: None,
261+
multiset: None,
262+
fallback: None,
263+
with_data: None,
251264
}
252265
}
253266
/// Set `OR REPLACE` for the CREATE TABLE statement.
@@ -488,6 +501,11 @@ impl CreateTableBuilder {
488501
self.external_volume = external_volume;
489502
self
490503
}
504+
/// Set the `WITH CONNECTION` clause.
505+
pub fn with_connection(mut self, with_connection: Option<ObjectName>) -> Self {
506+
self.with_connection = with_connection;
507+
self
508+
}
491509
/// Set the catalog name for the table.
492510
pub fn catalog(mut self, catalog: Option<String>) -> Self {
493511
self.catalog = catalog;
@@ -556,6 +574,22 @@ impl CreateTableBuilder {
556574
self.backup = backup;
557575
self
558576
}
577+
/// Set `MULTISET | SET` table-kind prefix.
578+
/// Some(true) => `MULTISET`, Some(false) => `SET`.
579+
pub fn multiset(mut self, multiset: Option<bool>) -> Self {
580+
self.multiset = multiset;
581+
self
582+
}
583+
/// Set `FALLBACK` / `NO FALLBACK` flag.
584+
pub fn fallback(mut self, fallback: Option<bool>) -> Self {
585+
self.fallback = fallback;
586+
self
587+
}
588+
/// Set `WITH DATA` clause.
589+
pub fn with_data(mut self, with_data: Option<WithData>) -> Self {
590+
self.with_data = with_data;
591+
self
592+
}
559593
/// Consume the builder and produce a `CreateTable`.
560594
pub fn build(self) -> CreateTable {
561595
CreateTable {
@@ -605,6 +639,7 @@ impl CreateTableBuilder {
605639
with_tags: self.with_tags,
606640
base_location: self.base_location,
607641
external_volume: self.external_volume,
642+
with_connection: self.with_connection,
608643
catalog: self.catalog,
609644
catalog_sync: self.catalog_sync,
610645
storage_serialization_policy: self.storage_serialization_policy,
@@ -618,6 +653,9 @@ impl CreateTableBuilder {
618653
distkey: self.distkey,
619654
sortkey: self.sortkey,
620655
backup: self.backup,
656+
multiset: self.multiset,
657+
fallback: self.fallback,
658+
with_data: self.with_data,
621659
}
622660
}
623661
}
@@ -686,6 +724,7 @@ impl From<CreateTable> for CreateTableBuilder {
686724
with_tags: table.with_tags,
687725
base_location: table.base_location,
688726
external_volume: table.external_volume,
727+
with_connection: table.with_connection,
689728
catalog: table.catalog,
690729
catalog_sync: table.catalog_sync,
691730
storage_serialization_policy: table.storage_serialization_policy,
@@ -699,6 +738,9 @@ impl From<CreateTable> for CreateTableBuilder {
699738
distkey: table.distkey,
700739
sortkey: table.sortkey,
701740
backup: table.backup,
741+
multiset: table.multiset,
742+
fallback: table.fallback,
743+
with_data: table.with_data,
702744
}
703745
}
704746
}

src/ast/helpers/stmt_data_loading.rs

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -86,18 +86,14 @@ pub struct StageLoadSelectItem {
8686

8787
impl fmt::Display for StageParamsObject {
8888
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
89-
let url = &self.url.as_ref();
90-
let storage_integration = &self.storage_integration.as_ref();
91-
let endpoint = &self.endpoint.as_ref();
92-
93-
if url.is_some() {
94-
write!(f, " URL='{}'", url.unwrap())?;
89+
if let Some(ref url) = self.url {
90+
write!(f, " URL='{url}'")?;
9591
}
96-
if storage_integration.is_some() {
97-
write!(f, " STORAGE_INTEGRATION={}", storage_integration.unwrap())?;
92+
if let Some(ref storage_integration) = self.storage_integration {
93+
write!(f, " STORAGE_INTEGRATION={storage_integration}")?;
9894
}
99-
if endpoint.is_some() {
100-
write!(f, " ENDPOINT='{}'", endpoint.unwrap())?;
95+
if let Some(ref endpoint) = self.endpoint {
96+
write!(f, " ENDPOINT='{endpoint}'")?;
10197
}
10298
if !self.credentials.options.is_empty() {
10399
write!(f, " CREDENTIALS=({})", self.credentials)?;

src/ast/mod.rs

Lines changed: 14 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ pub use self::ddl::{
8181
PartitionBoundValue, ProcedureParam, ReferentialAction, RenameTableNameKind, ReplicaIdentity,
8282
TagsColumnOption, TriggerObjectKind, Truncate, UserDefinedTypeCompositeAttributeDef,
8383
UserDefinedTypeInternalLength, UserDefinedTypeRangeOption, UserDefinedTypeRepresentation,
84-
UserDefinedTypeSqlDefinitionOption, UserDefinedTypeStorage, ViewColumnDef,
84+
UserDefinedTypeSqlDefinitionOption, UserDefinedTypeStorage, ViewColumnDef, WithData,
8585
};
8686
pub use self::dml::{
8787
Delete, Insert, Merge, MergeAction, MergeClause, MergeClauseKind, MergeInsertExpr,
@@ -99,7 +99,7 @@ pub use self::query::{
9999
JsonTableNestedColumn, LateralView, LimitClause, LockClause, LockType, MatchRecognizePattern,
100100
MatchRecognizeSymbol, Measure, NamedWindowDefinition, NamedWindowExpr, NonBlock, Offset,
101101
OffsetRows, OpenJsonTableColumn, OrderBy, OrderByExpr, OrderByKind, OrderByOptions,
102-
PipeOperator, PivotValueSource, ProjectionSelect, Query, RenameSelectItem,
102+
OrderBySort, PipeOperator, PivotValueSource, ProjectionSelect, Query, RenameSelectItem,
103103
RepetitionQuantifier, ReplaceSelectElement, ReplaceSelectItem, RowsPerMatch, Select,
104104
SelectFlavor, SelectInto, SelectItem, SelectItemQualifiedWildcardKind, SelectModifiers,
105105
SetExpr, SetOperator, SetQuantifier, Setting, SymbolDefinition, Table, TableAlias,
@@ -1883,16 +1883,10 @@ impl fmt::Display for Expr {
18831883
negated,
18841884
} => {
18851885
let not_ = if *negated { "NOT " } else { "" };
1886-
if form.is_none() {
1887-
write!(f, "{expr} IS {not_}NORMALIZED")
1886+
if let Some(form) = form {
1887+
write!(f, "{} IS {}{} NORMALIZED", expr, not_, form)
18881888
} else {
1889-
write!(
1890-
f,
1891-
"{} IS {}{} NORMALIZED",
1892-
expr,
1893-
not_,
1894-
form.as_ref().unwrap()
1895-
)
1889+
write!(f, "{expr} IS {not_}NORMALIZED")
18961890
}
18971891
}
18981892
Expr::SimilarTo {
@@ -5771,8 +5765,8 @@ impl fmt::Display for Statement {
57715765
write!(f, " SESSION")?;
57725766
}
57735767
write!(f, " STATUS")?;
5774-
if filter.is_some() {
5775-
write!(f, " {}", filter.as_ref().unwrap())?;
5768+
if let Some(filter) = filter {
5769+
write!(f, " {}", filter)?;
57765770
}
57775771
Ok(())
57785772
}
@@ -5789,8 +5783,8 @@ impl fmt::Display for Statement {
57895783
write!(f, " SESSION")?;
57905784
}
57915785
write!(f, " VARIABLES")?;
5792-
if filter.is_some() {
5793-
write!(f, " {}", filter.as_ref().unwrap())?;
5786+
if let Some(filter) = filter {
5787+
write!(f, " {}", filter)?;
57945788
}
57955789
Ok(())
57965790
}
@@ -6202,8 +6196,8 @@ impl fmt::Display for Statement {
62026196
if !copy_options.options.is_empty() {
62036197
write!(f, " COPY_OPTIONS=({copy_options})")?;
62046198
}
6205-
if comment.is_some() {
6206-
write!(f, " COMMENT='{}'", comment.as_ref().unwrap())?;
6199+
if let Some(comment) = comment {
6200+
write!(f, " COMMENT='{}'", comment)?;
62076201
}
62086202
Ok(())
62096203
}
@@ -6290,12 +6284,11 @@ impl fmt::Display for Statement {
62906284
}
62916285
Statement::Pragma { name, value, is_eq } => {
62926286
write!(f, "PRAGMA {name}")?;
6293-
if value.is_some() {
6294-
let val = value.as_ref().unwrap();
6287+
if let Some(value) = value {
62956288
if *is_eq {
6296-
write!(f, " = {val}")?;
6289+
write!(f, " = {value}")?;
62976290
} else {
6298-
write!(f, "({val})")?;
6291+
write!(f, "({value})")?;
62996292
}
63006293
}
63016294
Ok(())

0 commit comments

Comments
 (0)