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
5 changes: 5 additions & 0 deletions src/dialect/databricks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,4 +79,9 @@ impl Dialect for DatabricksDialect {
fn supports_group_by_with_modifier(&self) -> bool {
true
}

/// See <https://docs.databricks.com/en/sql/language-manual/sql-ref-syntax-qry-select-values.html>
fn supports_values_as_table_factor(&self) -> bool {
true
}
}
16 changes: 16 additions & 0 deletions src/dialect/generic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,22 @@ impl Dialect for GenericDialect {
true
}

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

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

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

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

fn supports_create_index_with_clause(&self) -> bool {
true
}
Expand Down
81 changes: 81 additions & 0 deletions src/dialect/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -856,6 +856,87 @@ pub trait Dialect: Debug + Any {
false
}

/// Returns true if this dialect supports the `EXTRACT` function
/// with a comma separator instead of `FROM`.
///
/// Example:
/// ```sql
/// SELECT EXTRACT(YEAR, date_column) FROM table;
/// ```
///
/// [Snowflake](https://docs.snowflake.com/en/sql-reference/functions/extract)
fn supports_extract_comma_syntax(&self) -> bool {
false
}

/// Returns true if this dialect supports a subquery passed to a function
/// as the only argument without enclosing parentheses.
///
/// Example:
/// ```sql
/// SELECT FLATTEN(SELECT * FROM tbl);
/// ```
///
/// [Snowflake](https://docs.snowflake.com/en/sql-reference/functions/flatten)
fn supports_subquery_as_function_arg(&self) -> bool {
false
}

/// Returns true if this dialect supports the `COMMENT` clause in
/// `CREATE VIEW` statements using the `COMMENT = 'comment'` syntax.
///
/// Example:
/// ```sql
/// CREATE VIEW v COMMENT = 'my comment' AS SELECT 1;
/// ```
///
/// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-view#optional-parameters)
fn supports_create_view_comment_syntax(&self) -> bool {
false
}

/// Returns true if this dialect supports the `ARRAY` type without
/// specifying an element type.
///
/// Example:
/// ```sql
/// CREATE TABLE t (a ARRAY);
/// ```
///
/// [Snowflake](https://docs.snowflake.com/en/sql-reference/data-types-semistructured#array)
fn supports_array_typedef_without_element_type(&self) -> bool {
false
}

/// Returns true if this dialect supports extra parentheses around
/// lone table names or derived tables in the `FROM` clause.
///
/// Example:
/// ```sql
/// SELECT * FROM (mytable);
/// SELECT * FROM ((SELECT 1));
/// SELECT * FROM (mytable) AS alias;
/// ```
///
/// [Snowflake](https://docs.snowflake.com/en/sql-reference/constructs/from)
fn supports_parens_around_table_factor(&self) -> bool {
false
}

/// Returns true if this dialect supports `VALUES` as a table factor
/// without requiring parentheses around the entire clause.
///
/// Example:
/// ```sql
/// SELECT * FROM VALUES (1, 'a'), (2, 'b') AS t (col1, col2);
/// ```
///
/// [Snowflake](https://docs.snowflake.com/en/sql-reference/constructs/values)
/// [Databricks](https://docs.databricks.com/en/sql/language-manual/sql-ref-syntax-qry-select-values.html)
fn supports_values_as_table_factor(&self) -> bool {
false
}

/// Returns true if this dialect allows dollar placeholders
/// e.g. `SELECT $var` (SQLite)
fn supports_dollar_placeholder(&self) -> bool {
Expand Down
30 changes: 30 additions & 0 deletions src/dialect/snowflake.rs
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,36 @@ impl Dialect for SnowflakeDialect {
true
}

/// See [doc](https://docs.snowflake.com/en/sql-reference/functions/extract)
fn supports_extract_comma_syntax(&self) -> bool {
true
}

/// See [doc](https://docs.snowflake.com/en/sql-reference/functions/flatten)
fn supports_subquery_as_function_arg(&self) -> bool {
true
}

/// See [doc](https://docs.snowflake.com/en/sql-reference/sql/create-view#optional-parameters)
fn supports_create_view_comment_syntax(&self) -> bool {
true
}

/// See [doc](https://docs.snowflake.com/en/sql-reference/data-types-semistructured#array)
fn supports_array_typedef_without_element_type(&self) -> bool {
true
}

/// See [doc](https://docs.snowflake.com/en/sql-reference/constructs/from)
fn supports_parens_around_table_factor(&self) -> bool {
true
}

/// See [doc](https://docs.snowflake.com/en/sql-reference/constructs/values)
fn supports_values_as_table_factor(&self) -> bool {
true
}

fn parse_statement(&self, parser: &mut Parser) -> Option<Result<Statement, ParserError>> {
if parser.parse_keyword(Keyword::BEGIN) {
return Some(parser.parse_begin_exception_end());
Expand Down
13 changes: 6 additions & 7 deletions src/parser/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2293,7 +2293,7 @@ impl<'a> Parser<'a> {

// Snowflake permits a subquery to be passed as an argument without
// an enclosing set of parens if it's the only argument.
if dialect_of!(self is SnowflakeDialect) && self.peek_sub_query() {
if self.dialect.supports_subquery_as_function_arg() && self.peek_sub_query() {
let subquery = self.parse_query()?;
self.expect_token(&Token::RParen)?;
return Ok(Function {
Expand Down Expand Up @@ -2683,8 +2683,7 @@ impl<'a> Parser<'a> {

let syntax = if self.parse_keyword(Keyword::FROM) {
ExtractSyntax::From
} else if self.consume_token(&Token::Comma)
&& dialect_of!(self is SnowflakeDialect | GenericDialect)
} else if self.dialect.supports_extract_comma_syntax() && self.consume_token(&Token::Comma)
{
ExtractSyntax::Comma
} else {
Expand Down Expand Up @@ -6228,7 +6227,7 @@ impl<'a> Parser<'a> {
None
};

let comment = if dialect_of!(self is SnowflakeDialect | GenericDialect)
let comment = if self.dialect.supports_create_view_comment_syntax()
&& self.parse_keyword(Keyword::COMMENT)
{
self.expect_token(&Token::Eq)?;
Expand Down Expand Up @@ -11790,7 +11789,7 @@ impl<'a> Parser<'a> {
Keyword::ENUM16 => Ok(DataType::Enum(self.parse_enum_values()?, Some(16))),
Keyword::SET => Ok(DataType::Set(self.parse_string_values()?)),
Keyword::ARRAY => {
if dialect_of!(self is SnowflakeDialect) {
if self.dialect.supports_array_typedef_without_element_type() {
Ok(DataType::Array(ArrayElemTypeDef::None))
} else if dialect_of!(self is ClickHouseDialect) {
Ok(self.parse_sub_type(|internal_type| {
Expand Down Expand Up @@ -14989,7 +14988,7 @@ impl<'a> Parser<'a> {
table_with_joins: Box::new(table_and_joins),
alias,
})
} else if dialect_of!(self is SnowflakeDialect | GenericDialect) {
} else if self.dialect.supports_parens_around_table_factor() {
// Dialect-specific behavior: Snowflake diverges from the
// standard and from most of the other implementations by
// allowing extra parentheses not only around a join (B), but
Expand Down Expand Up @@ -15035,7 +15034,7 @@ impl<'a> Parser<'a> {
// appearing alone in parentheses (e.g. `FROM (mytable)`)
self.expected("joined table", self.peek_token())
}
} else if dialect_of!(self is SnowflakeDialect | DatabricksDialect | GenericDialect)
} else if self.dialect.supports_values_as_table_factor()
&& matches!(
self.peek_tokens(),
[
Expand Down