Databricks: support SELECT * EXCEPT (#1261)

This commit is contained in:
Joey Hain 2024-05-13 02:49:00 -07:00 committed by GitHub
parent 49d178477e
commit 5ed13b5af3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 63 additions and 34 deletions

View file

@ -54,4 +54,9 @@ impl Dialect for BigQueryDialect {
fn supports_parenthesized_set_variables(&self) -> bool {
true
}
// See https://cloud.google.com/bigquery/docs/reference/standard-sql/query-syntax#select_except
fn supports_select_wildcard_except(&self) -> bool {
true
}
}

View file

@ -29,4 +29,8 @@ impl Dialect for ClickHouseDialect {
fn supports_string_literal_backslash_escape(&self) -> bool {
true
}
fn supports_select_wildcard_except(&self) -> bool {
true
}
}

View file

@ -33,4 +33,9 @@ impl Dialect for DatabricksDialect {
fn supports_lambda_functions(&self) -> bool {
true
}
// https://docs.databricks.com/en/sql/language-manual/sql-ref-syntax-qry-select.html#syntax
fn supports_select_wildcard_except(&self) -> bool {
true
}
}

View file

@ -66,4 +66,8 @@ impl Dialect for GenericDialect {
fn supports_parenthesized_set_variables(&self) -> bool {
true
}
fn supports_select_wildcard_except(&self) -> bool {
true
}
}

View file

@ -226,6 +226,16 @@ pub trait Dialect: Debug + Any {
fn supports_parenthesized_set_variables(&self) -> bool {
false
}
/// Returns true if the dialect supports an `EXCEPT` clause following a
/// wildcard in a select list.
///
/// For example
/// ```sql
/// SELECT * EXCEPT order_id FROM orders;
/// ```
fn supports_select_wildcard_except(&self) -> bool {
false
}
/// Returns true if the dialect has a CONVERT function which accepts a type first
/// and an expression second, e.g. `CONVERT(varchar, 1)`
fn convert_type_before_value(&self) -> bool {

View file

@ -9704,8 +9704,7 @@ impl<'a> Parser<'a> {
} else {
None
};
let opt_except = if dialect_of!(self is GenericDialect | BigQueryDialect | ClickHouseDialect)
{
let opt_except = if self.dialect.supports_select_wildcard_except() {
self.parse_optional_select_item_except()?
} else {
None

View file

@ -1838,38 +1838,6 @@ fn parse_array_agg_func() {
}
}
#[test]
fn test_select_wildcard_with_except() {
let select = bigquery_and_generic().verified_only_select("SELECT * EXCEPT (col_a) FROM data");
let expected = SelectItem::Wildcard(WildcardAdditionalOptions {
opt_except: Some(ExceptSelectItem {
first_element: Ident::new("col_a"),
additional_elements: vec![],
}),
..Default::default()
});
assert_eq!(expected, select.projection[0]);
let select = bigquery_and_generic()
.verified_only_select("SELECT * EXCEPT (department_id, employee_id) FROM employee_table");
let expected = SelectItem::Wildcard(WildcardAdditionalOptions {
opt_except: Some(ExceptSelectItem {
first_element: Ident::new("department_id"),
additional_elements: vec![Ident::new("employee_id")],
}),
..Default::default()
});
assert_eq!(expected, select.projection[0]);
assert_eq!(
bigquery_and_generic()
.parse_sql_statements("SELECT * EXCEPT () FROM employee_table")
.unwrap_err()
.to_string(),
"sql parser error: Expected identifier, found: )"
);
}
#[test]
fn parse_big_query_declare() {
for (sql, expected_names, expected_data_type, expected_assigned_expr) in [

View file

@ -9854,3 +9854,37 @@ fn tests_select_values_without_parens_and_set_op() {
_ => panic!("Expected a SET OPERATION"),
}
}
#[test]
fn parse_select_wildcard_with_except() {
let dialects = all_dialects_where(|d| d.supports_select_wildcard_except());
let select = dialects.verified_only_select("SELECT * EXCEPT (col_a) FROM data");
let expected = SelectItem::Wildcard(WildcardAdditionalOptions {
opt_except: Some(ExceptSelectItem {
first_element: Ident::new("col_a"),
additional_elements: vec![],
}),
..Default::default()
});
assert_eq!(expected, select.projection[0]);
let select = dialects
.verified_only_select("SELECT * EXCEPT (department_id, employee_id) FROM employee_table");
let expected = SelectItem::Wildcard(WildcardAdditionalOptions {
opt_except: Some(ExceptSelectItem {
first_element: Ident::new("department_id"),
additional_elements: vec![Ident::new("employee_id")],
}),
..Default::default()
});
assert_eq!(expected, select.projection[0]);
assert_eq!(
dialects
.parse_sql_statements("SELECT * EXCEPT () FROM employee_table")
.unwrap_err()
.to_string(),
"sql parser error: Expected identifier, found: )"
);
}