You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@datafusion.apache.org by gi...@apache.org on 2026/06/08 12:57:27 UTC

(datafusion-sqlparser-rs) branch main updated: Support aliased function arguments (expr AS name) (#2368)

This is an automated email from the ASF dual-hosted git repository.

github-merge-queue[bot] pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/datafusion-sqlparser-rs.git


The following commit(s) were added to refs/heads/main by this push:
     new 0bfafea4 Support aliased function arguments (expr AS name) (#2368)
0bfafea4 is described below

commit 0bfafea45f58adda22ee29dafe069db282769fed
Author: Luca Cappelletti <ca...@gmail.com>
AuthorDate: Mon Jun 8 14:14:20 2026 +0200

    Support aliased function arguments (expr AS name) (#2368)
---
 src/ast/mod.rs              |  9 ++++-----
 src/dialect/generic.rs      |  4 ++++
 src/dialect/mod.rs          |  6 ++++++
 src/dialect/postgresql.rs   |  4 ++++
 src/parser/mod.rs           | 13 +++++++++++++
 tests/sqlparser_common.rs   | 14 ++++++++++++++
 tests/sqlparser_postgres.rs | 18 ++++++++++++++++++
 7 files changed, 63 insertions(+), 5 deletions(-)

diff --git a/src/ast/mod.rs b/src/ast/mod.rs
index e494553c..447d89bb 100644
--- a/src/ast/mod.rs
+++ b/src/ast/mod.rs
@@ -1285,13 +1285,12 @@ pub enum Expr {
         /// Struct field definitions.
         fields: Vec<StructField>,
     },
-    /// `BigQuery` specific: An named expression in a typeless struct [1]
+    /// A named expression: `1 AS A`. Used in `BigQuery` typeless structs [1]
+    /// and in aliased function arguments, e.g. `XMLFOREST(a AS x)` in
+    /// PostgreSQL [2].
     ///
-    /// Syntax
-    /// ```sql
-    /// 1 AS A
-    /// ```
     /// [1]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-types#struct_type
+    /// [2]: https://www.postgresql.org/docs/current/functions-xml.html#FUNCTIONS-PRODUCING-XML-XMLFOREST
     Named {
         /// The expression being named.
         expr: Box<Expr>,
diff --git a/src/dialect/generic.rs b/src/dialect/generic.rs
index 25f57e3d..7ee826c2 100644
--- a/src/dialect/generic.rs
+++ b/src/dialect/generic.rs
@@ -312,4 +312,8 @@ impl Dialect for GenericDialect {
     fn supports_xml_expressions(&self) -> bool {
         true
     }
+
+    fn supports_aliased_function_args(&self) -> bool {
+        true
+    }
 }
diff --git a/src/dialect/mod.rs b/src/dialect/mod.rs
index 9b2ede40..9515c5bd 100644
--- a/src/dialect/mod.rs
+++ b/src/dialect/mod.rs
@@ -1767,6 +1767,12 @@ pub trait Dialect: Debug + Any {
         false
     }
 
+    /// Returns true if the dialect supports aliased function arguments,
+    /// e.g. `XMLFOREST(a AS x)` in PostgreSQL.
+    fn supports_aliased_function_args(&self) -> bool {
+        false
+    }
+
     /// Returns true if the dialect supports `USING <format>` in `CREATE TABLE`.
     ///
     /// Example:
diff --git a/src/dialect/postgresql.rs b/src/dialect/postgresql.rs
index c40d6d67..8b52ef6e 100644
--- a/src/dialect/postgresql.rs
+++ b/src/dialect/postgresql.rs
@@ -323,6 +323,10 @@ impl Dialect for PostgreSqlDialect {
         true
     }
 
+    fn supports_aliased_function_args(&self) -> bool {
+        true
+    }
+
     /// Postgres supports query optimizer hints via the `pg_hint_plan` extension,
     /// using the same comment-prefixed-with-`+` syntax as MySQL and Oracle.
     ///
diff --git a/src/parser/mod.rs b/src/parser/mod.rs
index 006a0c6f..a7e641f9 100644
--- a/src/parser/mod.rs
+++ b/src/parser/mod.rs
@@ -18496,6 +18496,19 @@ impl<'a> Parser<'a> {
             }
             other => other.into(),
         };
+        // Aliased argument, e.g. `XMLFOREST(a AS x)` in PostgreSQL
+        let arg_expr = match arg_expr {
+            FunctionArgExpr::Expr(expr)
+                if self.dialect.supports_aliased_function_args()
+                    && self.parse_keyword(Keyword::AS) =>
+            {
+                FunctionArgExpr::Expr(Expr::Named {
+                    expr: expr.into(),
+                    name: self.parse_identifier()?,
+                })
+            }
+            other => other,
+        };
         Ok(FunctionArg::Unnamed(arg_expr))
     }
 
diff --git a/tests/sqlparser_common.rs b/tests/sqlparser_common.rs
index 0d49d0fa..b561f893 100644
--- a/tests/sqlparser_common.rs
+++ b/tests/sqlparser_common.rs
@@ -19000,6 +19000,20 @@ fn parse_non_pg_dialects_keep_xml_names_as_regular_identifiers() {
     dialects.verified_only_select("SELECT xml FROM t");
 }
 
+#[test]
+fn parse_aliased_function_args() {
+    let dialects = all_dialects_where(|d| d.supports_aliased_function_args());
+    dialects.verified_only_select("SELECT foo(a AS x, b)");
+    dialects.verified_only_select("SELECT foo('bar' AS x)");
+    dialects.verified_only_select("SELECT foo(1 + 2 AS x)");
+    dialects.verified_only_select("SELECT foo(lower(a) AS x, b AS y)");
+    dialects.verified_only_select(r#"SELECT foo(a AS "x y")"#);
+    dialects.verified_only_select("SELECT foo(bar(a AS x) AS y)");
+    assert!(all_dialects_except(|d| d.supports_aliased_function_args())
+        .parse_sql_statements("SELECT foo(a AS x)")
+        .is_err());
+}
+
 /// Regression test for the 2^N parse-time blowup in `parse_compound_expr` on
 /// inputs like `IF a0.a1...aN.#`. The parse is run on a worker thread and the
 /// main thread asserts that it reports back within a generous timeout. Post-fix
diff --git a/tests/sqlparser_postgres.rs b/tests/sqlparser_postgres.rs
index 274988be..713d465a 100644
--- a/tests/sqlparser_postgres.rs
+++ b/tests/sqlparser_postgres.rs
@@ -3933,6 +3933,24 @@ fn parse_on_commit() {
     pg_and_generic().verified_stmt("CREATE TEMPORARY TABLE table (COL INT) ON COMMIT DROP");
 }
 
+#[test]
+fn parse_xmlforest_aliased_arguments() {
+    let select = pg_and_generic().verified_only_select("SELECT XMLFOREST(a AS x, b)");
+    assert_eq!(
+        expr_from_projection(&select.projection[0]),
+        &call(
+            "XMLFOREST",
+            [
+                Expr::Named {
+                    expr: Expr::Identifier(Ident::new("a")).into(),
+                    name: Ident::new("x"),
+                },
+                Expr::Identifier(Ident::new("b")),
+            ]
+        )
+    );
+}
+
 #[test]
 fn parse_xml_typed_string() {
     // xml '...' should parse as a TypedString on PostgreSQL and Generic


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@datafusion.apache.org
For additional commands, e-mail: commits-help@datafusion.apache.org