Skip to content

Commit

Permalink
fix: allow snowflake to accept values without parens
Browse files Browse the repository at this point in the history
  • Loading branch information
HiranmayaGundu committed May 3, 2024
1 parent fd6ad77 commit 4e3ddea
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 3 deletions.
23 changes: 23 additions & 0 deletions src/parser/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8355,6 +8355,29 @@ 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)
&& self.parse_keyword(Keyword::VALUES)
{
// Snowflake and Databricks allow syntax like below:
// SELECT * FROM VALUES (1, 'a'), (2, 'b') AS t (col1, col2)
// where the is no parentheses around the VALUES clause.
let values = SetExpr::Values(self.parse_values(false)?);
let alias = self.parse_optional_table_alias(keywords::RESERVED_FOR_TABLE_ALIAS)?;
Ok(TableFactor::Derived {
lateral: false,
subquery: Box::new(Query {
with: None,
body: Box::new(values),
order_by: vec![],
limit: None,
limit_by: vec![],
offset: None,
fetch: None,
locks: vec![],
for_clause: None,
}),
alias,
})
} else if dialect_of!(self is BigQueryDialect | PostgreSqlDialect | GenericDialect)
&& self.parse_keyword(Keyword::UNNEST)
{
Expand Down
55 changes: 52 additions & 3 deletions tests/sqlparser_common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ use sqlparser::ast::SelectItem::UnnamedExpr;
use sqlparser::ast::TableFactor::{Pivot, Unpivot};
use sqlparser::ast::*;
use sqlparser::dialect::{
AnsiDialect, BigQueryDialect, ClickHouseDialect, Dialect, DuckDbDialect, GenericDialect,
HiveDialect, MsSqlDialect, MySqlDialect, PostgreSqlDialect, RedshiftSqlDialect, SQLiteDialect,
SnowflakeDialect,
AnsiDialect, BigQueryDialect, ClickHouseDialect, DatabricksDialect, Dialect, DuckDbDialect,
GenericDialect, HiveDialect, MsSqlDialect, MySqlDialect, PostgreSqlDialect, RedshiftSqlDialect,
SQLiteDialect, SnowflakeDialect,
};
use sqlparser::keywords::ALL_KEYWORDS;
use sqlparser::parser::{Parser, ParserError, ParserOptions};
Expand Down Expand Up @@ -9658,3 +9658,52 @@ fn test_dictionary_syntax() {
]),
)
}

#[test]
fn tests_select_values_without_parens() {
let dialects = TestedDialects {
dialects: vec![
Box::new(GenericDialect {}),
Box::new(SnowflakeDialect {}),
Box::new(DatabricksDialect {}),
],
options: None,
};
let sql = "SELECT * FROM VALUES (1, 2), (2,3) AS tbl (id, val)";
let canonical = "SELECT * FROM (VALUES (1, 2), (2, 3)) AS tbl (id, val)";
dialects.verified_only_select_with_canonical(sql, canonical);
}

#[test]
fn tests_select_values_without_parens_and_set_op() {
let dialects = TestedDialects {
dialects: vec![
Box::new(GenericDialect {}),
Box::new(SnowflakeDialect {}),
Box::new(DatabricksDialect {}),
],
options: None,
};
let sql = "SELECT id + 1, name FROM VALUES (1, 'Apple'), (2, 'Banana'), (3, 'Orange') AS fruits (id, name) UNION ALL SELECT 5, 'Strawberry'";
let canonical = "SELECT id + 1, name FROM (VALUES (1, 'Apple'), (2, 'Banana'), (3, 'Orange')) AS fruits (id, name) UNION ALL SELECT 5, 'Strawberry'";
let query = dialects.verified_query_with_canonical(sql, canonical);
match *query.body {
SetExpr::SetOperation {
op,
set_quantifier: _,
left,
right,
} => {
assert_eq!(SetOperator::Union, op);
match *left {
SetExpr::Select(_) => {}
_ => panic!("Expected a SELECT statement"),
}
match *right {
SetExpr::Select(_) => {}
_ => panic!("Expected a SELECT statement"),
}
}
_ => panic!("Expected a SET OPERATION"),
}
}

0 comments on commit 4e3ddea

Please sign in to comment.