Skip to content

Commit 028bc75

Browse files
committed
Merge remote-tracking branch 'upstream/main' into feature/2086-set-session-authorization-support
2 parents 4d56b06 + f69407b commit 028bc75

File tree

14 files changed

+262
-37
lines changed

14 files changed

+262
-37
lines changed

src/ast/ddl.rs

Lines changed: 41 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,18 @@ pub enum AlterTableOperation {
365365
DropClusteringKey,
366366
SuspendRecluster,
367367
ResumeRecluster,
368+
/// `REFRESH`
369+
///
370+
/// Note: this is Snowflake specific for dynamic tables <https://docs.snowflake.com/en/sql-reference/sql/alter-table>
371+
Refresh,
372+
/// `SUSPEND`
373+
///
374+
/// Note: this is Snowflake specific for dynamic tables <https://docs.snowflake.com/en/sql-reference/sql/alter-table>
375+
Suspend,
376+
/// `RESUME`
377+
///
378+
/// Note: this is Snowflake specific for dynamic tables <https://docs.snowflake.com/en/sql-reference/sql/alter-table>
379+
Resume,
368380
/// `ALGORITHM [=] { DEFAULT | INSTANT | INPLACE | COPY }`
369381
///
370382
/// [MySQL]-specific table alter algorithm.
@@ -845,6 +857,15 @@ impl fmt::Display for AlterTableOperation {
845857
write!(f, "RESUME RECLUSTER")?;
846858
Ok(())
847859
}
860+
AlterTableOperation::Refresh => {
861+
write!(f, "REFRESH")
862+
}
863+
AlterTableOperation::Suspend => {
864+
write!(f, "SUSPEND")
865+
}
866+
AlterTableOperation::Resume => {
867+
write!(f, "RESUME")
868+
}
848869
AlterTableOperation::AutoIncrement { equals, value } => {
849870
write!(
850871
f,
@@ -3532,6 +3553,20 @@ impl Spanned for DropExtension {
35323553
}
35333554
}
35343555

3556+
/// Table type for ALTER TABLE statements.
3557+
/// Used to distinguish between regular tables, Iceberg tables, and Dynamic tables.
3558+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3559+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3560+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
3561+
pub enum AlterTableType {
3562+
/// Iceberg table type
3563+
/// <https://docs.snowflake.com/en/sql-reference/sql/alter-iceberg-table>
3564+
Iceberg,
3565+
/// Dynamic table type
3566+
/// <https://docs.snowflake.com/en/sql-reference/sql/alter-table>
3567+
Dynamic,
3568+
}
3569+
35353570
/// ALTER TABLE statement
35363571
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
35373572
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
@@ -3548,19 +3583,18 @@ pub struct AlterTable {
35483583
/// For example: `ALTER TABLE table_name ON CLUSTER cluster_name ADD COLUMN c UInt32`
35493584
/// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/alter/update)
35503585
pub on_cluster: Option<Ident>,
3551-
/// Snowflake "ICEBERG" clause for Iceberg tables
3552-
/// <https://docs.snowflake.com/en/sql-reference/sql/alter-iceberg-table>
3553-
pub iceberg: bool,
3586+
/// Table type: None for regular tables, Some(AlterTableType) for Iceberg or Dynamic tables
3587+
pub table_type: Option<AlterTableType>,
35543588
/// Token that represents the end of the statement (semicolon or EOF)
35553589
pub end_token: AttachedToken,
35563590
}
35573591

35583592
impl fmt::Display for AlterTable {
35593593
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3560-
if self.iceberg {
3561-
write!(f, "ALTER ICEBERG TABLE ")?;
3562-
} else {
3563-
write!(f, "ALTER TABLE ")?;
3594+
match &self.table_type {
3595+
Some(AlterTableType::Iceberg) => write!(f, "ALTER ICEBERG TABLE ")?,
3596+
Some(AlterTableType::Dynamic) => write!(f, "ALTER DYNAMIC TABLE ")?,
3597+
None => write!(f, "ALTER TABLE ")?,
35643598
}
35653599

35663600
if self.if_exists {

src/ast/mod.rs

Lines changed: 50 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ pub use self::dcl::{
6161
pub use self::ddl::{
6262
AlterColumnOperation, AlterConnectorOwner, AlterIndexOperation, AlterPolicyOperation,
6363
AlterSchema, AlterSchemaOperation, AlterTable, AlterTableAlgorithm, AlterTableLock,
64-
AlterTableOperation, AlterType, AlterTypeAddValue, AlterTypeAddValuePosition,
64+
AlterTableOperation, AlterTableType, AlterType, AlterTypeAddValue, AlterTypeAddValuePosition,
6565
AlterTypeOperation, AlterTypeRename, AlterTypeRenameValue, ClusteredBy, ColumnDef,
6666
ColumnOption, ColumnOptionDef, ColumnOptions, ColumnPolicy, ColumnPolicyProperty,
6767
ConstraintCharacteristics, CreateConnector, CreateDomain, CreateExtension, CreateFunction,
@@ -2787,10 +2787,11 @@ impl fmt::Display for Declare {
27872787
}
27882788

27892789
/// Sql options of a `CREATE TABLE` statement.
2790-
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2790+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Default)]
27912791
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
27922792
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
27932793
pub enum CreateTableOptions {
2794+
#[default]
27942795
None,
27952796
/// Options specified using the `WITH` keyword.
27962797
/// e.g. `WITH (description = "123")`
@@ -2819,12 +2820,6 @@ pub enum CreateTableOptions {
28192820
TableProperties(Vec<SqlOption>),
28202821
}
28212822

2822-
impl Default for CreateTableOptions {
2823-
fn default() -> Self {
2824-
Self::None
2825-
}
2826-
}
2827-
28282823
impl fmt::Display for CreateTableOptions {
28292824
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
28302825
match self {
@@ -4273,6 +4268,14 @@ pub enum Statement {
42734268
/// ```
42744269
/// [Redshift](https://docs.aws.amazon.com/redshift/latest/dg/r_VACUUM_command.html)
42754270
Vacuum(VacuumStatement),
4271+
/// Restore the value of a run-time parameter to the default value.
4272+
///
4273+
/// ```sql
4274+
/// RESET configuration_parameter;
4275+
/// RESET ALL;
4276+
/// ```
4277+
/// [PostgreSQL](https://www.postgresql.org/docs/current/sql-reset.html)
4278+
Reset(ResetStatement),
42764279
}
42774280

42784281
impl From<Analyze> for Statement {
@@ -5767,6 +5770,7 @@ impl fmt::Display for Statement {
57675770
Statement::AlterSchema(s) => write!(f, "{s}"),
57685771
Statement::Vacuum(s) => write!(f, "{s}"),
57695772
Statement::AlterUser(s) => write!(f, "{s}"),
5773+
Statement::Reset(s) => write!(f, "{s}"),
57705774
}
57715775
}
57725776
}
@@ -10565,6 +10569,38 @@ impl fmt::Display for VacuumStatement {
1056510569
}
1056610570
}
1056710571

10572+
/// Variants of the RESET statement
10573+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10574+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10575+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10576+
pub enum Reset {
10577+
/// Resets all session parameters to their default values.
10578+
ALL,
10579+
10580+
/// Resets a specific session parameter to its default value.
10581+
ConfigurationParameter(ObjectName),
10582+
}
10583+
10584+
/// Resets a session parameter to its default value.
10585+
/// ```sql
10586+
/// RESET { ALL | <configuration_parameter> }
10587+
/// ```
10588+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10589+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10590+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10591+
pub struct ResetStatement {
10592+
pub reset: Reset,
10593+
}
10594+
10595+
impl fmt::Display for ResetStatement {
10596+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10597+
match &self.reset {
10598+
Reset::ALL => write!(f, "RESET ALL"),
10599+
Reset::ConfigurationParameter(param) => write!(f, "RESET {}", param),
10600+
}
10601+
}
10602+
}
10603+
1056810604
impl From<Set> for Statement {
1056910605
fn from(s: Set) -> Self {
1057010606
Self::Set(s)
@@ -10805,6 +10841,12 @@ impl From<VacuumStatement> for Statement {
1080510841
}
1080610842
}
1080710843

10844+
impl From<ResetStatement> for Statement {
10845+
fn from(r: ResetStatement) -> Self {
10846+
Self::Reset(r)
10847+
}
10848+
}
10849+
1080810850
#[cfg(test)]
1080910851
mod tests {
1081010852
use crate::tokenizer::Location;

src/ast/query.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3135,12 +3135,18 @@ pub struct Values {
31353135
/// Was there an explicit ROWs keyword (MySQL)?
31363136
/// <https://dev.mysql.com/doc/refman/8.0/en/values.html>
31373137
pub explicit_row: bool,
3138+
// MySql supports both VALUES and VALUE keywords.
3139+
// <https://dev.mysql.com/doc/refman/9.2/en/insert.html>
3140+
pub value_keyword: bool,
31383141
pub rows: Vec<Vec<Expr>>,
31393142
}
31403143

31413144
impl fmt::Display for Values {
31423145
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3143-
f.write_str("VALUES")?;
3146+
match self.value_keyword {
3147+
true => f.write_str("VALUE")?,
3148+
false => f.write_str("VALUES")?,
3149+
};
31443150
let prefix = if self.explicit_row { "ROW" } else { "" };
31453151
let mut delim = "";
31463152
for row in &self.rows {

src/ast/spans.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,7 @@ impl Spanned for Values {
223223
fn span(&self) -> Span {
224224
let Values {
225225
explicit_row: _, // bool,
226+
value_keyword: _,
226227
rows,
227228
} = self;
228229

@@ -475,6 +476,7 @@ impl Spanned for Statement {
475476
Statement::AlterSchema(s) => s.span(),
476477
Statement::Vacuum(..) => Span::empty(),
477478
Statement::AlterUser(..) => Span::empty(),
479+
Statement::Reset(..) => Span::empty(),
478480
}
479481
}
480482
}
@@ -1107,6 +1109,9 @@ impl Spanned for AlterTableOperation {
11071109
AlterTableOperation::DropClusteringKey => Span::empty(),
11081110
AlterTableOperation::SuspendRecluster => Span::empty(),
11091111
AlterTableOperation::ResumeRecluster => Span::empty(),
1112+
AlterTableOperation::Refresh => Span::empty(),
1113+
AlterTableOperation::Suspend => Span::empty(),
1114+
AlterTableOperation::Resume => Span::empty(),
11101115
AlterTableOperation::Algorithm { .. } => Span::empty(),
11111116
AlterTableOperation::AutoIncrement { value, .. } => value.span(),
11121117
AlterTableOperation::Lock { .. } => Span::empty(),

src/dialect/snowflake.rs

Lines changed: 50 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
#[cfg(not(feature = "std"))]
1919
use crate::alloc::string::ToString;
20+
use crate::ast::helpers::attached_token::AttachedToken;
2021
use crate::ast::helpers::key_value_options::{
2122
KeyValueOption, KeyValueOptionKind, KeyValueOptions, KeyValueOptionsDelimiter,
2223
};
@@ -26,11 +27,12 @@ use crate::ast::helpers::stmt_data_loading::{
2627
FileStagingCommand, StageLoadSelectItem, StageLoadSelectItemKind, StageParamsObject,
2728
};
2829
use crate::ast::{
29-
CatalogSyncNamespaceMode, ColumnOption, ColumnPolicy, ColumnPolicyProperty, ContactEntry,
30-
CopyIntoSnowflakeKind, CreateTableLikeKind, DollarQuotedString, Ident, IdentityParameters,
31-
IdentityProperty, IdentityPropertyFormatKind, IdentityPropertyKind, IdentityPropertyOrder,
32-
InitializeKind, ObjectName, ObjectNamePart, RefreshModeKind, RowAccessPolicy, ShowObjects,
33-
SqlOption, Statement, StorageSerializationPolicy, TagsColumnOption, Value, WrappedCollection,
30+
AlterTable, AlterTableOperation, AlterTableType, CatalogSyncNamespaceMode, ColumnOption,
31+
ColumnPolicy, ColumnPolicyProperty, ContactEntry, CopyIntoSnowflakeKind, CreateTableLikeKind,
32+
DollarQuotedString, Ident, IdentityParameters, IdentityProperty, IdentityPropertyFormatKind,
33+
IdentityPropertyKind, IdentityPropertyOrder, InitializeKind, ObjectName, ObjectNamePart,
34+
RefreshModeKind, RowAccessPolicy, ShowObjects, SqlOption, Statement,
35+
StorageSerializationPolicy, TagsColumnOption, Value, WrappedCollection,
3436
};
3537
use crate::dialect::{Dialect, Precedence};
3638
use crate::keywords::Keyword;
@@ -214,6 +216,11 @@ impl Dialect for SnowflakeDialect {
214216
return Some(parser.parse_begin_exception_end());
215217
}
216218

219+
if parser.parse_keywords(&[Keyword::ALTER, Keyword::DYNAMIC, Keyword::TABLE]) {
220+
// ALTER DYNAMIC TABLE
221+
return Some(parse_alter_dynamic_table(parser));
222+
}
223+
217224
if parser.parse_keywords(&[Keyword::ALTER, Keyword::SESSION]) {
218225
// ALTER SESSION
219226
let set = match parser.parse_one_of_keywords(&[Keyword::SET, Keyword::UNSET]) {
@@ -604,6 +611,44 @@ fn parse_file_staging_command(kw: Keyword, parser: &mut Parser) -> Result<Statem
604611
}
605612
}
606613

614+
/// Parse snowflake alter dynamic table.
615+
/// <https://docs.snowflake.com/en/sql-reference/sql/alter-table>
616+
fn parse_alter_dynamic_table(parser: &mut Parser) -> Result<Statement, ParserError> {
617+
// Use parse_object_name(true) to support IDENTIFIER() function
618+
let table_name = parser.parse_object_name(true)?;
619+
620+
// Parse the operation (REFRESH, SUSPEND, or RESUME)
621+
let operation = if parser.parse_keyword(Keyword::REFRESH) {
622+
AlterTableOperation::Refresh
623+
} else if parser.parse_keyword(Keyword::SUSPEND) {
624+
AlterTableOperation::Suspend
625+
} else if parser.parse_keyword(Keyword::RESUME) {
626+
AlterTableOperation::Resume
627+
} else {
628+
return parser.expected(
629+
"REFRESH, SUSPEND, or RESUME after ALTER DYNAMIC TABLE",
630+
parser.peek_token(),
631+
);
632+
};
633+
634+
let end_token = if parser.peek_token_ref().token == Token::SemiColon {
635+
parser.peek_token_ref().clone()
636+
} else {
637+
parser.get_current_token().clone()
638+
};
639+
640+
Ok(Statement::AlterTable(AlterTable {
641+
name: table_name,
642+
if_exists: false,
643+
only: false,
644+
operations: vec![operation],
645+
location: None,
646+
on_cluster: None,
647+
table_type: Some(AlterTableType::Dynamic),
648+
end_token: AttachedToken(end_token),
649+
}))
650+
}
651+
607652
/// Parse snowflake alter session.
608653
/// <https://docs.snowflake.com/en/sql-reference/sql/alter-session>
609654
fn parse_alter_session(parser: &mut Parser, set: bool) -> Result<Statement, ParserError> {

src/keywords.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -783,6 +783,7 @@ define_keywords!(
783783
REF,
784784
REFERENCES,
785785
REFERENCING,
786+
REFRESH,
786787
REFRESH_MODE,
787788
REGCLASS,
788789
REGEXP,

0 commit comments

Comments
 (0)