@@ -17597,7 +17597,26 @@ impl<'a> Parser<'a> {
1759717597 if let Some(arg) = arg {
1759817598 return Ok(arg);
1759917599 }
17600- Ok(FunctionArg::Unnamed(self.parse_wildcard_expr()?.into()))
17600+ let wildcard_expr = self.parse_wildcard_expr()?;
17601+ let arg_expr: FunctionArgExpr = match wildcard_expr {
17602+ Expr::Wildcard(ref token) if self.dialect.supports_select_wildcard_exclude() => {
17603+ // Support `* EXCLUDE(col1, col2, ...)` inside function calls (e.g. Snowflake's
17604+ // `HASH(* EXCLUDE(col))`). Parse the options the same way SELECT items do.
17605+ let opts = self.parse_wildcard_additional_options(token.0.clone())?;
17606+ if opts.opt_exclude.is_some()
17607+ || opts.opt_except.is_some()
17608+ || opts.opt_replace.is_some()
17609+ || opts.opt_rename.is_some()
17610+ || opts.opt_ilike.is_some()
17611+ {
17612+ FunctionArgExpr::WildcardWithOptions(opts)
17613+ } else {
17614+ wildcard_expr.into()
17615+ }
17616+ }
17617+ other => other.into(),
17618+ };
17619+ Ok(FunctionArg::Unnamed(arg_expr))
1760117620 }
1760217621
1760317622 fn parse_function_named_arg_operator(&mut self) -> Result<FunctionArgOperator, ParserError> {
@@ -17885,13 +17904,24 @@ impl<'a> Parser<'a> {
1788517904 None
1788617905 };
1788717906
17907+ let opt_alias = if self.dialect.supports_select_wildcard_with_alias() {
17908+ if self.parse_keyword(Keyword::AS) {
17909+ Some(self.parse_identifier()?)
17910+ } else {
17911+ None
17912+ }
17913+ } else {
17914+ None
17915+ };
17916+
1788817917 Ok(WildcardAdditionalOptions {
1788917918 wildcard_token: wildcard_token.into(),
1789017919 opt_ilike,
1789117920 opt_exclude,
1789217921 opt_except,
1789317922 opt_rename,
1789417923 opt_replace,
17924+ opt_alias,
1789517925 })
1789617926 }
1789717927
@@ -18574,6 +18604,9 @@ impl<'a> Parser<'a> {
1857418604
1857518605 /// Parse a SQL `EXECUTE` statement
1857618606 pub fn parse_execute(&mut self) -> Result<Statement, ParserError> {
18607+ // Track whether the procedure/expression name itself was wrapped in parens,
18608+ // i.e. `EXEC (@sql)` (dynamic string execution) vs `EXEC sp_name`.
18609+ // When the name has parens there are no additional parameters.
1857718610 let name = if self.dialect.supports_execute_immediate()
1857818611 && self.parse_keyword(Keyword::IMMEDIATE)
1857918612 {
@@ -18584,10 +18617,18 @@ impl<'a> Parser<'a> {
1858418617 if has_parentheses {
1858518618 self.expect_token(&Token::RParen)?;
1858618619 }
18587- Some(name)
18620+ Some(( name, has_parentheses) )
1858818621 };
1858918622
18590- let has_parentheses = self.consume_token(&Token::LParen);
18623+ let name_had_parentheses = name.as_ref().map(|(_, p)| *p).unwrap_or(false);
18624+
18625+ // Only look for a parameter list when the name was NOT wrapped in parens.
18626+ // `EXEC (@sql)` is dynamic SQL execution and takes no parameters here.
18627+ let has_parentheses = if name_had_parentheses {
18628+ false
18629+ } else {
18630+ self.consume_token(&Token::LParen)
18631+ };
1859118632
1859218633 let end_kws = &[Keyword::USING, Keyword::OUTPUT, Keyword::DEFAULT];
1859318634 let end_token = match (has_parentheses, self.peek_token().token) {
@@ -18597,12 +18638,18 @@ impl<'a> Parser<'a> {
1859718638 (false, _) => Token::SemiColon,
1859818639 };
1859918640
18600- let parameters = self.parse_comma_separated0(Parser::parse_expr, end_token)?;
18641+ let parameters = if name_had_parentheses {
18642+ vec![]
18643+ } else {
18644+ self.parse_comma_separated0(Parser::parse_expr, end_token)?
18645+ };
1860118646
1860218647 if has_parentheses {
1860318648 self.expect_token(&Token::RParen)?;
1860418649 }
1860518650
18651+ let name = name.map(|(n, _)| n);
18652+
1860618653 let into = if self.parse_keyword(Keyword::INTO) {
1860718654 self.parse_comma_separated(Self::parse_identifier)?
1860818655 } else {
0 commit comments