Skip to content

Commit 9d15f7e

Browse files
authored
Support: Databricks and generic: fix for values as table name (#1278)
1 parent 5418446 commit 9d15f7e

File tree

3 files changed

+88
-2
lines changed

3 files changed

+88
-2
lines changed

src/ast/query.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,17 @@ pub enum SetExpr {
108108
Table(Box<Table>),
109109
}
110110

111+
impl SetExpr {
112+
/// If this `SetExpr` is a `SELECT`, returns the [`Select`].
113+
pub fn as_select(&self) -> Option<&Select> {
114+
if let Self::Select(select) = self {
115+
Some(&**select)
116+
} else {
117+
None
118+
}
119+
}
120+
}
121+
111122
impl fmt::Display for SetExpr {
112123
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
113124
match self {

src/parser/mod.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8594,8 +8594,19 @@ impl<'a> Parser<'a> {
85948594
self.expected("joined table", self.peek_token())
85958595
}
85968596
} else if dialect_of!(self is SnowflakeDialect | DatabricksDialect | GenericDialect)
8597-
&& self.parse_keyword(Keyword::VALUES)
8597+
&& matches!(
8598+
self.peek_tokens(),
8599+
[
8600+
Token::Word(Word {
8601+
keyword: Keyword::VALUES,
8602+
..
8603+
}),
8604+
Token::LParen
8605+
]
8606+
)
85988607
{
8608+
self.expect_keyword(Keyword::VALUES)?;
8609+
85998610
// Snowflake and Databricks allow syntax like below:
86008611
// SELECT * FROM VALUES (1, 'a'), (2, 'b') AS t (col1, col2)
86018612
// where there are no parentheses around the VALUES clause.

tests/sqlparser_databricks.rs

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use sqlparser::ast::*;
2-
use sqlparser::dialect::DatabricksDialect;
2+
use sqlparser::dialect::{DatabricksDialect, GenericDialect};
33
use sqlparser::parser::ParserError;
44
use test_utils::*;
55

@@ -13,6 +13,13 @@ fn databricks() -> TestedDialects {
1313
}
1414
}
1515

16+
fn databricks_and_generic() -> TestedDialects {
17+
TestedDialects {
18+
dialects: vec![Box::new(DatabricksDialect {}), Box::new(GenericDialect {})],
19+
options: None,
20+
}
21+
}
22+
1623
#[test]
1724
fn test_databricks_identifiers() {
1825
// databricks uses backtick for delimited identifiers
@@ -124,3 +131,60 @@ fn test_databricks_lambdas() {
124131
);
125132
databricks().verified_expr("transform(array(1, 2, 3), x -> x + 1)");
126133
}
134+
135+
#[test]
136+
fn test_values_clause() {
137+
let values = Values {
138+
explicit_row: false,
139+
rows: vec![
140+
vec![
141+
Expr::Value(Value::DoubleQuotedString("one".to_owned())),
142+
Expr::Value(number("1")),
143+
],
144+
vec![
145+
Expr::Value(Value::SingleQuotedString("two".to_owned())),
146+
Expr::Value(number("2")),
147+
],
148+
],
149+
};
150+
151+
let query = databricks().verified_query(r#"VALUES ("one", 1), ('two', 2)"#);
152+
assert_eq!(SetExpr::Values(values.clone()), *query.body);
153+
154+
// VALUES is permitted in a FROM clause without a subquery
155+
let query = databricks().verified_query_with_canonical(
156+
r#"SELECT * FROM VALUES ("one", 1), ('two', 2)"#,
157+
r#"SELECT * FROM (VALUES ("one", 1), ('two', 2))"#,
158+
);
159+
let Some(TableFactor::Derived { subquery, .. }) = query
160+
.body
161+
.as_select()
162+
.map(|select| &select.from[0].relation)
163+
else {
164+
panic!("expected subquery");
165+
};
166+
assert_eq!(SetExpr::Values(values), *subquery.body);
167+
168+
// values is also a valid table name
169+
let query = databricks_and_generic().verified_query(concat!(
170+
"WITH values AS (SELECT 42) ",
171+
"SELECT * FROM values",
172+
));
173+
assert_eq!(
174+
Some(&TableFactor::Table {
175+
name: ObjectName(vec![Ident::new("values")]),
176+
alias: None,
177+
args: None,
178+
with_hints: vec![],
179+
version: None,
180+
partitions: vec![]
181+
}),
182+
query
183+
.body
184+
.as_select()
185+
.map(|select| &select.from[0].relation)
186+
);
187+
188+
// TODO: support this example from https://docs.databricks.com/en/sql/language-manual/sql-ref-syntax-qry-select-values.html#examples
189+
// databricks().verified_query("VALUES 1, 2, 3");
190+
}

0 commit comments

Comments
 (0)