Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions src/ast/helpers/stmt_data_loading.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,26 @@ pub enum AlterStageOperation {
},
}

/// An operation supported by Snowflake's `ALTER FILE FORMAT` statement.
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub enum AlterFileFormatOperation {
/// Rename a named file format.
RenameTo {
/// New file format name.
#[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
new_name: ObjectName,
},
/// Set one or more format-specific properties or the comment.
Set {
/// Format-specific options.
options: KeyValueOptions,
/// Optional comment replacement.
comment: Option<String>,
},
}

/// This enum enables support for both standard SQL select item expressions
/// and Snowflake-specific ones for data loading.
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
Expand Down
73 changes: 72 additions & 1 deletion src/ast/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@ use alloc::{
};
use helpers::{
attached_token::AttachedToken,
stmt_data_loading::{AlterStageOperation, FileStagingCommand, StageLoadSelectItemKind},
stmt_data_loading::{
AlterFileFormatOperation, AlterStageOperation, FileStagingCommand, StageLoadSelectItemKind,
},
};

use core::cmp::Ordering;
Expand Down Expand Up @@ -4244,6 +4246,15 @@ pub enum Statement {
show_options: ShowStatementOptions,
},
/// ```sql
/// SHOW FILE FORMATS [ LIKE '<pattern>' ] [ IN { ACCOUNT | DATABASE | SCHEMA } ]
/// ```
/// Snowflake-specific statement.
/// <https://docs.snowflake.com/en/sql-reference/sql/show-file-formats>
ShowFileFormats {
/// Additional options for filtering and scoping the file format listing.
show_options: ShowStatementOptions,
},
/// ```sql
/// SHOW VIEWS
/// ```
ShowViews {
Expand Down Expand Up @@ -4547,6 +4558,18 @@ pub enum Statement {
operation: AlterStageOperation,
},
/// ```sql
/// ALTER FILE FORMAT
/// ```
/// See <https://docs.snowflake.com/en/sql-reference/sql/alter-file-format>
AlterFileFormat {
/// `IF EXISTS` flag.
if_exists: bool,
/// File format name.
name: ObjectName,
/// File format alteration to perform.
operation: AlterFileFormatOperation,
},
/// ```sql
/// CREATE FILE FORMAT
/// ```
/// See <https://docs.snowflake.com/en/sql-reference/sql/create-file-format>
Expand Down Expand Up @@ -4685,6 +4708,18 @@ pub enum Statement {
stage_name: ObjectName,
},
/// ```sql
/// DESC[RIBE] FILE FORMAT <name>
/// ```
/// Snowflake-specific statement.
/// <https://docs.snowflake.com/en/sql-reference/sql/desc-file-format>
DescribeFileFormat {
/// `DESC | DESCRIBE` spelling used by the input statement.
describe_alias: DescribeAlias,
/// File format name.
#[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
name: ObjectName,
},
/// ```sql
/// [EXPLAIN | DESC | DESCRIBE] <statement>
/// ```
Explain {
Expand Down Expand Up @@ -5185,6 +5220,10 @@ impl fmt::Display for Statement {
describe_alias,
stage_name,
} => write!(f, "{describe_alias} STAGE {stage_name}"),
Statement::DescribeFileFormat {
describe_alias,
name,
} => write!(f, "{describe_alias} FILE FORMAT {name}"),
Statement::Explain {
describe_alias,
verbose,
Expand Down Expand Up @@ -5999,6 +6038,9 @@ impl fmt::Display for Statement {
Statement::ShowStages { show_options } => {
write!(f, "SHOW STAGES{show_options}")
}
Statement::ShowFileFormats { show_options } => {
write!(f, "SHOW FILE FORMATS{show_options}")
}
Statement::ShowViews {
terse,
materialized,
Expand Down Expand Up @@ -6356,6 +6398,32 @@ impl fmt::Display for Statement {
}
}
}
Statement::AlterFileFormat {
if_exists,
name,
operation,
} => {
write!(
f,
"ALTER FILE FORMAT {if_exists}{name}",
if_exists = if *if_exists { "IF EXISTS " } else { "" },
)?;
match operation {
AlterFileFormatOperation::RenameTo { new_name } => {
write!(f, " RENAME TO {new_name}")
}
AlterFileFormatOperation::Set { options, comment } => {
write!(f, " SET")?;
if !options.options.is_empty() {
write!(f, " {options}")?;
}
if let Some(comment) = comment {
write!(f, " COMMENT='{comment}'")?;
}
Ok(())
}
}
}
Statement::CreateFileFormat {
or_replace,
temporary,
Expand Down Expand Up @@ -8686,6 +8754,8 @@ pub enum ObjectType {
Sequence,
/// A stage.
Stage,
/// A named file format.
FileFormat,
/// A type definition.
Type,
/// A user.
Expand All @@ -8707,6 +8777,7 @@ impl fmt::Display for ObjectType {
ObjectType::Role => "ROLE",
ObjectType::Sequence => "SEQUENCE",
ObjectType::Stage => "STAGE",
ObjectType::FileFormat => "FILE FORMAT",
ObjectType::Type => "TYPE",
ObjectType::User => "USER",
ObjectType::Stream => "STREAM",
Expand Down
6 changes: 6 additions & 0 deletions src/ast/spans.rs
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,7 @@ impl Spanned for Values {
/// - [Statement::ShowColumns]
/// - [Statement::ShowTables]
/// - [Statement::ShowStages]
/// - [Statement::ShowFileFormats]
/// - [Statement::ShowCollation]
/// - [Statement::StartTransaction]
/// - [Statement::Comment]
Expand All @@ -300,6 +301,7 @@ impl Spanned for Values {
/// - [Statement::CreateMacro]
/// - [Statement::CreateStage]
/// - [Statement::AlterStage]
/// - [Statement::AlterFileFormat]
/// - [Statement::Assert]
/// - [Statement::Grant]
/// - [Statement::Revoke]
Expand All @@ -309,6 +311,7 @@ impl Spanned for Values {
/// - [Statement::Kill]
/// - [Statement::ExplainTable]
/// - [Statement::DescribeStage]
/// - [Statement::DescribeFileFormat]
/// - [Statement::Explain]
/// - [Statement::Savepoint]
/// - [Statement::ReleaseSavepoint]
Expand Down Expand Up @@ -447,6 +450,7 @@ impl Spanned for Statement {
Statement::ShowColumns { .. } => Span::empty(),
Statement::ShowTables { .. } => Span::empty(),
Statement::ShowStages { .. } => Span::empty(),
Statement::ShowFileFormats { .. } => Span::empty(),
Statement::ShowCollation { .. } => Span::empty(),
Statement::ShowCharset { .. } => Span::empty(),
Statement::Use(u) => u.span(),
Expand All @@ -465,6 +469,7 @@ impl Spanned for Statement {
Statement::CreateMacro { .. } => Span::empty(),
Statement::CreateStage { .. } => Span::empty(),
Statement::AlterStage { .. } => Span::empty(),
Statement::AlterFileFormat { .. } => Span::empty(),
Statement::CreateFileFormat { .. } => Span::empty(),
Statement::Assert { .. } => Span::empty(),
Statement::Grant { .. } => Span::empty(),
Expand All @@ -476,6 +481,7 @@ impl Spanned for Statement {
Statement::Kill { .. } => Span::empty(),
Statement::ExplainTable { .. } => Span::empty(),
Statement::DescribeStage { .. } => Span::empty(),
Statement::DescribeFileFormat { .. } => Span::empty(),
Statement::Explain { .. } => Span::empty(),
Statement::Savepoint { .. } => Span::empty(),
Statement::ReleaseSavepoint { .. } => Span::empty(),
Expand Down
6 changes: 6 additions & 0 deletions src/dialect/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1257,6 +1257,12 @@ pub trait Dialect: Debug + Any {
false
}

/// Returns true if this dialect supports Snowflake-style named file format
/// lifecycle commands (`ALTER`, `DROP`, `SHOW`, and `DESCRIBE`).
fn supports_file_format_commands(&self) -> bool {
false
}

/// Returns true if this dialect supports the `COMMENT` statement
fn supports_comment_on(&self) -> bool {
false
Expand Down
43 changes: 41 additions & 2 deletions src/dialect/snowflake.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ use crate::ast::helpers::key_value_options::{
use crate::ast::helpers::stmt_create_database::CreateDatabaseBuilder;
use crate::ast::helpers::stmt_create_table::CreateTableBuilder;
use crate::ast::helpers::stmt_data_loading::{
AlterStageOperation, FileStagingCommand, StageLoadSelectItem, StageLoadSelectItemKind,
StageParamsObject,
AlterFileFormatOperation, AlterStageOperation, FileStagingCommand, StageLoadSelectItem,
StageLoadSelectItemKind, StageParamsObject,
};
use crate::ast::{
AlterTable, AlterTableOperation, AlterTableType, CatalogSyncNamespaceMode, CloudProviderParams,
Expand Down Expand Up @@ -303,6 +303,10 @@ impl Dialect for SnowflakeDialect {
return Some(parse_alter_stage(parser));
}

if parser.parse_keywords(&[Keyword::ALTER, Keyword::FILE, Keyword::FORMAT]) {
return Some(parse_alter_file_format(parser));
}

if parser.parse_keyword(Keyword::CREATE) {
// possibly CREATE STAGE
//[ OR REPLACE ]
Expand Down Expand Up @@ -492,6 +496,10 @@ impl Dialect for SnowflakeDialect {
true
}

fn supports_file_format_commands(&self) -> bool {
true
}

fn supports_left_associative_joins_without_parens(&self) -> bool {
false
}
Expand Down Expand Up @@ -1459,6 +1467,37 @@ fn parse_alter_stage(parser: &mut Parser) -> Result<Statement, ParserError> {
})
}

fn parse_alter_file_format(parser: &mut Parser) -> Result<Statement, ParserError> {
let if_exists = parser.parse_keywords(&[Keyword::IF, Keyword::EXISTS]);
let name = parser.parse_object_name(false)?;
let operation = if parser.parse_keyword(Keyword::RENAME) {
parser.expect_keyword(Keyword::TO)?;
AlterFileFormatOperation::RenameTo {
new_name: parser.parse_object_name(false)?,
}
} else if parser.parse_keyword(Keyword::SET) {
let options = parser.parse_key_value_options(false, &[Keyword::COMMENT])?;
let comment = if parser.parse_keyword(Keyword::COMMENT) {
parser.expect_token(&Token::Eq)?;
Some(parser.parse_comment_value()?)
} else {
None
};
if options.options.is_empty() && comment.is_none() {
return parser.expected_ref("a file format property", parser.peek_token_ref());
}
AlterFileFormatOperation::Set { options, comment }
} else {
return parser.expected_ref("RENAME TO or SET", parser.peek_token_ref());
};

Ok(Statement::AlterFileFormat {
if_exists,
name,
operation,
})
}

pub fn parse_create_file_format(
or_replace: bool,
temporary: bool,
Expand Down
1 change: 1 addition & 0 deletions src/keywords.rs
Original file line number Diff line number Diff line change
Expand Up @@ -448,6 +448,7 @@ define_keywords!(
FORCE_QUOTE,
FOREIGN,
FORMAT,
FORMATS,
FORMATTED,
FORWARD,
FRAME_ROW,
Expand Down
28 changes: 27 additions & 1 deletion src/parser/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7394,6 +7394,10 @@ impl<'a> Parser<'a> {
ObjectType::Sequence
} else if self.parse_keyword(Keyword::STAGE) {
ObjectType::Stage
} else if self.dialect.supports_file_format_commands()
&& self.parse_keywords(&[Keyword::FILE, Keyword::FORMAT])
{
ObjectType::FileFormat
} else if self.parse_keyword(Keyword::TYPE) {
ObjectType::Type
} else if self.parse_keyword(Keyword::USER) {
Expand Down Expand Up @@ -7427,7 +7431,7 @@ impl<'a> Parser<'a> {
};
} else {
return self.expected_ref(
"COLLATION, CONNECTOR, DATABASE, EXTENSION, FUNCTION, INDEX, OPERATOR, POLICY, PROCEDURE, ROLE, SCHEMA, SECRET, SEQUENCE, STAGE, TABLE, TRIGGER, TYPE, VIEW, MATERIALIZED VIEW or USER after DROP",
"COLLATION, CONNECTOR, DATABASE, EXTENSION, FILE FORMAT, FUNCTION, INDEX, OPERATOR, POLICY, PROCEDURE, ROLE, SCHEMA, SECRET, SEQUENCE, STAGE, TABLE, TRIGGER, TYPE, VIEW, MATERIALIZED VIEW or USER after DROP",
self.peek_token_ref(),
);
};
Expand Down Expand Up @@ -14030,6 +14034,16 @@ impl<'a> Parser<'a> {
});
}

if describe_alias != DescribeAlias::Explain
&& self.dialect.supports_file_format_commands()
&& self.parse_keywords(&[Keyword::FILE, Keyword::FORMAT])
{
return Ok(Statement::DescribeFileFormat {
describe_alias,
name: self.parse_object_name(false)?,
});
}

match self.maybe_parse(|parser| parser.parse_statement())? {
Some(Statement::Explain { .. }) | Some(Statement::ExplainTable { .. }) => Err(
ParserError::ParserError("Explain must be root of the plan".to_string()),
Expand Down Expand Up @@ -15540,6 +15554,18 @@ impl<'a> Parser<'a> {
Ok(Statement::ShowStages {
show_options: self.parse_show_stmt_options()?,
})
} else if self.dialect.supports_file_format_commands()
&& self.parse_keywords(&[Keyword::FILE, Keyword::FORMATS])
{
if terse || extended || full || session || global || external {
Err(ParserError::ParserError(
"SHOW FILE FORMATS does not support SHOW modifiers".to_string(),
))
} else {
Ok(Statement::ShowFileFormats {
show_options: self.parse_show_stmt_options()?,
})
}
} else if self.parse_keywords(&[Keyword::MATERIALIZED, Keyword::VIEWS]) {
Ok(self.parse_show_views(terse, true)?)
} else if self.parse_keyword(Keyword::VIEWS) {
Expand Down
Loading
Loading