Skip to content

Commit e87241a

Browse files
authored
Snowflake: support wildcard with EXCLUDE in function arguments (#2231)
1 parent 8afcad8 commit e87241a

File tree

4 files changed

+43
-1
lines changed

4 files changed

+43
-1
lines changed

src/ast/mod.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7625,6 +7625,10 @@ pub enum FunctionArgExpr {
76257625
QualifiedWildcard(ObjectName),
76267626
/// An unqualified `*` wildcard.
76277627
Wildcard,
7628+
/// An unqualified `*` wildcard with additional options, e.g. `* EXCLUDE(col)`.
7629+
///
7630+
/// Used in Snowflake to support expressions like `HASH(* EXCLUDE(col))`.
7631+
WildcardWithOptions(WildcardAdditionalOptions),
76287632
}
76297633

76307634
impl From<Expr> for FunctionArgExpr {
@@ -7643,6 +7647,7 @@ impl fmt::Display for FunctionArgExpr {
76437647
FunctionArgExpr::Expr(expr) => write!(f, "{expr}"),
76447648
FunctionArgExpr::QualifiedWildcard(prefix) => write!(f, "{prefix}.*"),
76457649
FunctionArgExpr::Wildcard => f.write_str("*"),
7650+
FunctionArgExpr::WildcardWithOptions(opts) => write!(f, "*{opts}"),
76467651
}
76477652
}
76487653
}

src/ast/spans.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2130,6 +2130,7 @@ impl Spanned for FunctionArg {
21302130
///
21312131
/// Missing spans:
21322132
/// - [FunctionArgExpr::Wildcard]
2133+
/// - [FunctionArgExpr::WildcardWithOptions]
21332134
impl Spanned for FunctionArgExpr {
21342135
fn span(&self) -> Span {
21352136
match self {
@@ -2138,6 +2139,7 @@ impl Spanned for FunctionArgExpr {
21382139
union_spans(object_name.0.iter().map(|i| i.span()))
21392140
}
21402141
FunctionArgExpr::Wildcard => Span::empty(),
2142+
FunctionArgExpr::WildcardWithOptions(_) => Span::empty(),
21412143
}
21422144
}
21432145
}

src/parser/mod.rs

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17576,7 +17576,26 @@ impl<'a> Parser<'a> {
1757617576
if let Some(arg) = arg {
1757717577
return Ok(arg);
1757817578
}
17579-
Ok(FunctionArg::Unnamed(self.parse_wildcard_expr()?.into()))
17579+
let wildcard_expr = self.parse_wildcard_expr()?;
17580+
let arg_expr: FunctionArgExpr = match wildcard_expr {
17581+
Expr::Wildcard(ref token) if self.dialect.supports_select_wildcard_exclude() => {
17582+
// Support `* EXCLUDE(col1, col2, ...)` inside function calls (e.g. Snowflake's
17583+
// `HASH(* EXCLUDE(col))`). Parse the options the same way SELECT items do.
17584+
let opts = self.parse_wildcard_additional_options(token.0.clone())?;
17585+
if opts.opt_exclude.is_some()
17586+
|| opts.opt_except.is_some()
17587+
|| opts.opt_replace.is_some()
17588+
|| opts.opt_rename.is_some()
17589+
|| opts.opt_ilike.is_some()
17590+
{
17591+
FunctionArgExpr::WildcardWithOptions(opts)
17592+
} else {
17593+
wildcard_expr.into()
17594+
}
17595+
}
17596+
other => other.into(),
17597+
};
17598+
Ok(FunctionArg::Unnamed(arg_expr))
1758017599
}
1758117600

1758217601
fn parse_function_named_arg_operator(&mut self) -> Result<FunctionArgOperator, ParserError> {

tests/sqlparser_common.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18583,3 +18583,19 @@ fn parse_array_subscript() {
1858318583
dialects.verified_stmt("SELECT arr[1][2]");
1858418584
dialects.verified_stmt("SELECT arr[:][:]");
1858518585
}
18586+
18587+
#[test]
18588+
fn test_wildcard_func_arg() {
18589+
// Wildcard (*) and wildcard with EXCLUDE as a function argument.
18590+
// Documented for Snowflake's HASH function but parsed for any dialect that
18591+
// supports the wildcard-EXCLUDE select syntax.
18592+
let dialects = all_dialects_where(|d| d.supports_select_wildcard_exclude());
18593+
18594+
// Wildcard with EXCLUDE — canonical form has a space before the parenthesised column list.
18595+
dialects.one_statement_parses_to(
18596+
"SELECT HASH(* EXCLUDE(col1)) FROM t",
18597+
"SELECT HASH(* EXCLUDE (col1)) FROM t",
18598+
);
18599+
dialects.verified_expr("HASH(* EXCLUDE (col1))");
18600+
dialects.verified_expr("HASH(* EXCLUDE (col1, col2))");
18601+
}

0 commit comments

Comments
 (0)