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]

Reply via email to