This is an automated email from the ASF dual-hosted git repository. github-bot pushed a commit to branch gh-readonly-queue/main/pr-2231-8afcad8fcb915d0366d4cdda9aa9958365f968ae in repository https://gitbox.apache.org/repos/asf/datafusion-sqlparser-rs.git
commit e87241a153609f0d4716954797b24e205424b945 Author: Yoabot <[email protected]> AuthorDate: Thu Feb 26 12:00:53 2026 +0100 Snowflake: support wildcard with EXCLUDE in function arguments (#2231) --- src/ast/mod.rs | 5 +++++ src/ast/spans.rs | 2 ++ src/parser/mod.rs | 21 ++++++++++++++++++++- tests/sqlparser_common.rs | 16 ++++++++++++++++ 4 files changed, 43 insertions(+), 1 deletion(-) diff --git a/src/ast/mod.rs b/src/ast/mod.rs index 7b1e9447..1e430171 100644 --- a/src/ast/mod.rs +++ b/src/ast/mod.rs @@ -7625,6 +7625,10 @@ pub enum FunctionArgExpr { QualifiedWildcard(ObjectName), /// An unqualified `*` wildcard. Wildcard, + /// An unqualified `*` wildcard with additional options, e.g. `* EXCLUDE(col)`. + /// + /// Used in Snowflake to support expressions like `HASH(* EXCLUDE(col))`. + WildcardWithOptions(WildcardAdditionalOptions), } impl From<Expr> for FunctionArgExpr { @@ -7643,6 +7647,7 @@ impl fmt::Display for FunctionArgExpr { FunctionArgExpr::Expr(expr) => write!(f, "{expr}"), FunctionArgExpr::QualifiedWildcard(prefix) => write!(f, "{prefix}.*"), FunctionArgExpr::Wildcard => f.write_str("*"), + FunctionArgExpr::WildcardWithOptions(opts) => write!(f, "*{opts}"), } } } diff --git a/src/ast/spans.rs b/src/ast/spans.rs index 1e216208..0b95c3ed 100644 --- a/src/ast/spans.rs +++ b/src/ast/spans.rs @@ -2130,6 +2130,7 @@ impl Spanned for FunctionArg { /// /// Missing spans: /// - [FunctionArgExpr::Wildcard] +/// - [FunctionArgExpr::WildcardWithOptions] impl Spanned for FunctionArgExpr { fn span(&self) -> Span { match self { @@ -2138,6 +2139,7 @@ impl Spanned for FunctionArgExpr { union_spans(object_name.0.iter().map(|i| i.span())) } FunctionArgExpr::Wildcard => Span::empty(), + FunctionArgExpr::WildcardWithOptions(_) => Span::empty(), } } } diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 667a1535..bea566bb 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -17576,7 +17576,26 @@ impl<'a> Parser<'a> { if let Some(arg) = arg { return Ok(arg); } - Ok(FunctionArg::Unnamed(self.parse_wildcard_expr()?.into())) + let wildcard_expr = self.parse_wildcard_expr()?; + let arg_expr: FunctionArgExpr = match wildcard_expr { + Expr::Wildcard(ref token) if self.dialect.supports_select_wildcard_exclude() => { + // Support `* EXCLUDE(col1, col2, ...)` inside function calls (e.g. Snowflake's + // `HASH(* EXCLUDE(col))`). Parse the options the same way SELECT items do. + let opts = self.parse_wildcard_additional_options(token.0.clone())?; + if opts.opt_exclude.is_some() + || opts.opt_except.is_some() + || opts.opt_replace.is_some() + || opts.opt_rename.is_some() + || opts.opt_ilike.is_some() + { + FunctionArgExpr::WildcardWithOptions(opts) + } else { + wildcard_expr.into() + } + } + other => other.into(), + }; + Ok(FunctionArg::Unnamed(arg_expr)) } fn parse_function_named_arg_operator(&mut self) -> Result<FunctionArgOperator, ParserError> { diff --git a/tests/sqlparser_common.rs b/tests/sqlparser_common.rs index 3f0ca96a..982bf108 100644 --- a/tests/sqlparser_common.rs +++ b/tests/sqlparser_common.rs @@ -18583,3 +18583,19 @@ fn parse_array_subscript() { dialects.verified_stmt("SELECT arr[1][2]"); dialects.verified_stmt("SELECT arr[:][:]"); } + +#[test] +fn test_wildcard_func_arg() { + // Wildcard (*) and wildcard with EXCLUDE as a function argument. + // Documented for Snowflake's HASH function but parsed for any dialect that + // supports the wildcard-EXCLUDE select syntax. + let dialects = all_dialects_where(|d| d.supports_select_wildcard_exclude()); + + // Wildcard with EXCLUDE — canonical form has a space before the parenthesised column list. + dialects.one_statement_parses_to( + "SELECT HASH(* EXCLUDE(col1)) FROM t", + "SELECT HASH(* EXCLUDE (col1)) FROM t", + ); + dialects.verified_expr("HASH(* EXCLUDE (col1))"); + dialects.verified_expr("HASH(* EXCLUDE (col1, col2))"); +} --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
