Skip to content
Open
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
47 changes: 47 additions & 0 deletions src/ast/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4487,6 +4487,28 @@ pub enum Statement {
comment: Option<String>,
},
/// ```sql
/// CREATE [ OR REPLACE ] [ { TEMP | TEMPORARY | VOLATILE } ] FILE FORMAT [ IF NOT EXISTS ] <name>
/// [ TYPE = { CSV | JSON | AVRO | ORC | PARQUET | XML } [ formatTypeOptions ] ]
/// [ COMMENT = '<string_literal>' ]
/// ```
/// See <https://docs.snowflake.com/en/sql-reference/sql/create-file-format>
CreateFileFormat {
/// `OR REPLACE` flag.
or_replace: bool,
/// Whether file format is temporary.
temporary: bool,
/// Whether file format is volatile.
volatile: bool,
/// `IF NOT EXISTS` flag.
if_not_exists: bool,
/// File format name.
name: ObjectName,
/// Format type options (e.g. `TYPE`, `FIELD_DELIMITER`, `COMPRESSION`, ...).
options: KeyValueOptions,
/// Optional comment.
comment: Option<String>,
},
/// ```sql
/// ASSERT <condition> [AS <message>]
/// ```
Assert {
Expand Down Expand Up @@ -6185,6 +6207,31 @@ impl fmt::Display for Statement {
}
Ok(())
}
Statement::CreateFileFormat {
or_replace,
temporary,
volatile,
if_not_exists,
name,
options,
comment,
} => {
write!(
f,
"CREATE {or_replace}{temp}{volatile}FILE FORMAT {if_not_exists}{name}",
or_replace = if *or_replace { "OR REPLACE " } else { "" },
temp = if *temporary { "TEMPORARY " } else { "" },
volatile = if *volatile { "VOLATILE " } else { "" },
if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
)?;
if !options.options.is_empty() {
write!(f, " {options}")?;
}
if let Some(comment) = comment {
write!(f, " COMMENT='{}'", comment)?;
}
Ok(())
}
Statement::CopyIntoSnowflake {
kind,
into,
Expand Down
2 changes: 2 additions & 0 deletions src/ast/spans.rs
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,7 @@ impl Spanned for Values {
/// - [Statement::CreateProcedure]
/// - [Statement::CreateMacro]
/// - [Statement::CreateStage]
/// - [Statement::CreateFileFormat]
/// - [Statement::Assert]
/// - [Statement::Grant]
/// - [Statement::Revoke]
Expand Down Expand Up @@ -457,6 +458,7 @@ impl Spanned for Statement {
Statement::CreateProcedure { .. } => Span::empty(),
Statement::CreateMacro { .. } => Span::empty(),
Statement::CreateStage { .. } => Span::empty(),
Statement::CreateFileFormat { .. } => Span::empty(),
Statement::Assert { .. } => Span::empty(),
Statement::Grant { .. } => Span::empty(),
Statement::Deny { .. } => Span::empty(),
Expand Down
4 changes: 4 additions & 0 deletions src/dialect/mysql.rs
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,10 @@ impl Dialect for MySqlDialect {
fn supports_group_by_with_modifier(&self) -> bool {
true
}

fn supports_left_associative_joins_without_parens(&self) -> bool {
false
}
}

/// `LOCK TABLES`
Expand Down
4 changes: 4 additions & 0 deletions src/dialect/redshift.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,10 @@ impl Dialect for RedshiftSqlDialect {
true
}

fn supports_left_associative_joins_without_parens(&self) -> bool {
false
}

fn supports_select_exclude(&self) -> bool {
true
}
Expand Down
33 changes: 33 additions & 0 deletions src/dialect/snowflake.rs
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,10 @@ impl Dialect for SnowflakeDialect {
);
} else if parser.parse_keyword(Keyword::DATABASE) {
return Some(parse_create_database(or_replace, transient, parser));
} else if parser.parse_keywords(&[Keyword::FILE, Keyword::FORMAT]) {
return Some(parse_create_file_format(
or_replace, temporary, volatile, parser,
));
} else {
// need to go back with the cursor
let mut back = 1;
Expand Down Expand Up @@ -1272,6 +1276,35 @@ pub fn parse_create_stage(
})
}

/// Parse a Snowflake `CREATE FILE FORMAT` statement.
/// See <https://docs.snowflake.com/en/sql-reference/sql/create-file-format>
pub fn parse_create_file_format(
or_replace: bool,
temporary: bool,
volatile: bool,
parser: &mut Parser,
) -> Result<Statement, ParserError> {
let if_not_exists = parser.parse_keywords(&[Keyword::IF, Keyword::NOT, Keyword::EXISTS]);
let name = parser.parse_object_name(true)?;
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
};

Ok(Statement::CreateFileFormat {
or_replace,
temporary,
volatile,
if_not_exists,
name,
options,
comment,
})
}

pub fn parse_stage_name_identifier(parser: &mut Parser) -> Result<Ident, ParserError> {
let mut ident = String::new();
while let Some(next_token) = parser.next_token_no_skip() {
Expand Down
1 change: 1 addition & 0 deletions src/parser/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15994,6 +15994,7 @@ impl<'a> Parser<'a> {
if !self
.dialect
.supports_left_associative_joins_without_parens()
&& !natural
&& self.peek_parens_less_nested_join()
{
let joins = self.parse_joins()?;
Expand Down
Loading