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

github-merge-queue[bot] pushed a commit to branch 
gh-readonly-queue/main/pr-22094-526ed6c8c73ab62ec839bc786e705a915a0ba214
in repository https://gitbox.apache.org/repos/asf/datafusion.git

commit 04fbade7f2861914ecfc49b9658e590e14c1f78c
Author: Andrew Lamb <[email protected]>
AuthorDate: Mon May 11 23:17:43 2026 -0400

    Consolidate and document SQL AST shims (#22094)
    
    ## Which issue does this PR close?
    
    - Related to https://github.com/apache/datafusion/pull/22069
    
    ## Rationale for this change
    
    While upgrading sqlparser, it was not clear why there were feature gates
    for the `sql` feature:
    https://github.com/apache/datafusion/pull/22069/changes#r3204705488
    
    There is a mode to avoid the `sqlparser` dependency, added by @timsaucer
    in
    - #17332
    
    I think this feature makes sense but it is a little hard to understand
    because it is implemented with a bunch of `#[cfg(not(feature = "sql"))]`
    and there is no central place that explains the design.
    
    ## What changes are included in this PR?
    
    1. Consolidate the SQL AST shim structures in a separate module
    2. Document the design so it is easier to understand
    
    ## Are these changes tested?
    
    Yes by CI
    
    ## Are there any user-facing changes?
    
    <!--
    If there are user-facing changes then we may require documentation to be
    updated before approving the PR.
    -->
    
    <!--
    If there are any breaking changes to public APIs, please add the `api
    change` label.
    -->
---
 datafusion/expr/src/expr.rs             | 123 ++-------------------------
 datafusion/expr/src/lib.rs              |   2 +
 datafusion/expr/src/logical_plan/ddl.rs |   4 +-
 datafusion/expr/src/sql.rs              | 143 ++++++++++++++++++++++++++++++++
 datafusion/expr/src/utils.rs            |   2 +-
 5 files changed, 155 insertions(+), 119 deletions(-)

diff --git a/datafusion/expr/src/expr.rs b/datafusion/expr/src/expr.rs
index 582e8e41dd..8c58e8f709 100644
--- a/datafusion/expr/src/expr.rs
+++ b/datafusion/expr/src/expr.rs
@@ -46,7 +46,13 @@ use datafusion_common::{
 use datafusion_expr_common::placement::ExpressionPlacement;
 use datafusion_functions_window_common::field::WindowUDFFieldArgs;
 #[cfg(feature = "sql")]
-use sqlparser::ast::{
+pub use sqlparser::ast::{
+    ExceptSelectItem, ExcludeSelectItem, IlikeSelectItem, RenameSelectItem,
+    ReplaceSelectElement,
+};
+// Use shims for sqlparser types when the sql feature is disabled.
+#[cfg(not(feature = "sql"))]
+pub use crate::sql::{
     ExceptSelectItem, ExcludeSelectItem, IlikeSelectItem, RenameSelectItem,
     ReplaceSelectElement,
 };
@@ -1416,63 +1422,6 @@ impl Lambda {
     }
 }
 
-#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
-#[cfg(not(feature = "sql"))]
-pub struct IlikeSelectItem {
-    pub pattern: String,
-}
-#[cfg(not(feature = "sql"))]
-impl Display for IlikeSelectItem {
-    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
-        write!(f, "ILIKE '{}'", &self.pattern)?;
-        Ok(())
-    }
-}
-#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
-#[cfg(not(feature = "sql"))]
-pub enum ExcludeSelectItem {
-    Single(Ident),
-    Multiple(Vec<Ident>),
-}
-#[cfg(not(feature = "sql"))]
-impl Display for ExcludeSelectItem {
-    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
-        write!(f, "EXCLUDE")?;
-        match self {
-            Self::Single(column) => {
-                write!(f, " {column}")?;
-            }
-            Self::Multiple(columns) => {
-                write!(f, " ({})", display_comma_separated(columns))?;
-            }
-        }
-        Ok(())
-    }
-}
-#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
-#[cfg(not(feature = "sql"))]
-pub struct ExceptSelectItem {
-    pub first_element: Ident,
-    pub additional_elements: Vec<Ident>,
-}
-#[cfg(not(feature = "sql"))]
-impl Display for ExceptSelectItem {
-    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
-        write!(f, "EXCEPT ")?;
-        if self.additional_elements.is_empty() {
-            write!(f, "({})", self.first_element)?;
-        } else {
-            write!(
-                f,
-                "({}, {})",
-                self.first_element,
-                display_comma_separated(&self.additional_elements)
-            )?;
-        }
-        Ok(())
-    }
-}
-
 pub fn display_comma_separated<T>(slice: &[T]) -> String
 where
     T: Display,
@@ -1481,64 +1430,6 @@ where
     slice.iter().map(|v| format!("{v}")).join(", ")
 }
 
-#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
-#[cfg(not(feature = "sql"))]
-pub enum RenameSelectItem {
-    Single(String),
-    Multiple(Vec<String>),
-}
-#[cfg(not(feature = "sql"))]
-impl Display for RenameSelectItem {
-    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
-        write!(f, "RENAME")?;
-        match self {
-            Self::Single(column) => {
-                write!(f, " {column}")?;
-            }
-            Self::Multiple(columns) => {
-                write!(f, " ({})", display_comma_separated(columns))?;
-            }
-        }
-        Ok(())
-    }
-}
-
-#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
-#[cfg(not(feature = "sql"))]
-pub struct Ident {
-    /// The value of the identifier without quotes.
-    pub value: String,
-    /// The starting quote if any. Valid quote characters are the single quote,
-    /// double quote, backtick, and opening square bracket.
-    pub quote_style: Option<char>,
-    /// The span of the identifier in the original SQL string.
-    pub span: String,
-}
-#[cfg(not(feature = "sql"))]
-impl Display for Ident {
-    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
-        write!(f, "[{}]", self.value)
-    }
-}
-
-#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
-#[cfg(not(feature = "sql"))]
-pub struct ReplaceSelectElement {
-    pub expr: String,
-    pub column_name: Ident,
-    pub as_keyword: bool,
-}
-#[cfg(not(feature = "sql"))]
-impl Display for ReplaceSelectElement {
-    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
-        if self.as_keyword {
-            write!(f, "{} AS {}", self.expr, self.column_name)
-        } else {
-            write!(f, "{} {}", self.expr, self.column_name)
-        }
-    }
-}
-
 /// Additional options for wildcards, e.g. Snowflake `EXCLUDE`/`RENAME` and 
Bigquery `EXCEPT`.
 #[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug, Default)]
 pub struct WildcardOptions {
diff --git a/datafusion/expr/src/lib.rs b/datafusion/expr/src/lib.rs
index c0d2187d94..da7f20783b 100644
--- a/datafusion/expr/src/lib.rs
+++ b/datafusion/expr/src/lib.rs
@@ -80,6 +80,8 @@ pub mod statistics {
 mod predicate_bounds;
 pub mod preimage;
 pub mod ptr_eq;
+#[cfg(not(feature = "sql"))]
+pub mod sql;
 pub mod test;
 pub mod tree_node;
 pub mod type_coercion;
diff --git a/datafusion/expr/src/logical_plan/ddl.rs 
b/datafusion/expr/src/logical_plan/ddl.rs
index 8a46e842a8..5779fb0c4e 100644
--- a/datafusion/expr/src/logical_plan/ddl.rs
+++ b/datafusion/expr/src/logical_plan/ddl.rs
@@ -24,9 +24,9 @@ use std::{
     hash::{Hash, Hasher},
 };
 
-#[cfg(not(feature = "sql"))]
-use crate::expr::Ident;
 use crate::expr::Sort;
+#[cfg(not(feature = "sql"))]
+use crate::sql::Ident;
 use arrow::datatypes::DataType;
 use datafusion_common::tree_node::{Transformed, TreeNodeContainer, 
TreeNodeRecursion};
 use datafusion_common::{
diff --git a/datafusion/expr/src/sql.rs b/datafusion/expr/src/sql.rs
new file mode 100644
index 0000000000..c9c3fa5336
--- /dev/null
+++ b/datafusion/expr/src/sql.rs
@@ -0,0 +1,143 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+//! Local copies of [`sqlparser::ast`] structures
+//!
+//! These types are used when the `sql` feature is disabled. When `sql` is
+//! enabled, the upstream types from [`sqlparser`] are used instead.
+//!
+//! These definitions should be structurally compatible with the upstream
+//! `sqlparser` types, so that code which switches between them via `cfg` keeps
+//! compiling.
+//!
+//! See [#17332](https://github.com/apache/datafusion/pull/17332) for
+//! more detail.
+
+use crate::expr::display_comma_separated;
+use std::fmt;
+use std::fmt::{Display, Formatter};
+
+#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
+pub struct IlikeSelectItem {
+    pub pattern: String,
+}
+
+impl Display for IlikeSelectItem {
+    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
+        write!(f, "ILIKE '{}'", &self.pattern)?;
+        Ok(())
+    }
+}
+
+#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
+pub enum ExcludeSelectItem {
+    Single(Ident),
+    Multiple(Vec<Ident>),
+}
+
+impl Display for ExcludeSelectItem {
+    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
+        write!(f, "EXCLUDE")?;
+        match self {
+            Self::Single(column) => {
+                write!(f, " {column}")?;
+            }
+            Self::Multiple(columns) => {
+                write!(f, " ({})", display_comma_separated(columns))?;
+            }
+        }
+        Ok(())
+    }
+}
+
+#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
+pub struct ExceptSelectItem {
+    pub first_element: Ident,
+    pub additional_elements: Vec<Ident>,
+}
+
+impl Display for ExceptSelectItem {
+    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
+        write!(f, "EXCEPT ")?;
+        if self.additional_elements.is_empty() {
+            write!(f, "({})", self.first_element)?;
+        } else {
+            write!(
+                f,
+                "({}, {})",
+                self.first_element,
+                display_comma_separated(&self.additional_elements)
+            )?;
+        }
+        Ok(())
+    }
+}
+
+#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
+pub enum RenameSelectItem {
+    Single(String),
+    Multiple(Vec<String>),
+}
+
+impl Display for RenameSelectItem {
+    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
+        write!(f, "RENAME")?;
+        match self {
+            Self::Single(column) => {
+                write!(f, " {column}")?;
+            }
+            Self::Multiple(columns) => {
+                write!(f, " ({})", display_comma_separated(columns))?;
+            }
+        }
+        Ok(())
+    }
+}
+
+#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
+pub struct Ident {
+    /// The value of the identifier without quotes.
+    pub value: String,
+    /// The starting quote if any. Valid quote characters are the single quote,
+    /// double quote, backtick, and opening square bracket.
+    pub quote_style: Option<char>,
+    /// The span of the identifier in the original SQL string.
+    pub span: String,
+}
+
+impl Display for Ident {
+    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
+        write!(f, "[{}]", self.value)
+    }
+}
+
+#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
+pub struct ReplaceSelectElement {
+    pub expr: String,
+    pub column_name: Ident,
+    pub as_keyword: bool,
+}
+
+impl Display for ReplaceSelectElement {
+    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
+        if self.as_keyword {
+            write!(f, "{} AS {}", self.expr, self.column_name)
+        } else {
+            write!(f, "{} {}", self.expr, self.column_name)
+        }
+    }
+}
diff --git a/datafusion/expr/src/utils.rs b/datafusion/expr/src/utils.rs
index fdb4b6de78..659306d3bf 100644
--- a/datafusion/expr/src/utils.rs
+++ b/datafusion/expr/src/utils.rs
@@ -39,7 +39,7 @@ use datafusion_common::{
 };
 
 #[cfg(not(feature = "sql"))]
-use crate::expr::{ExceptSelectItem, ExcludeSelectItem};
+use crate::sql::{ExceptSelectItem, ExcludeSelectItem};
 use indexmap::IndexSet;
 #[cfg(feature = "sql")]
 use sqlparser::ast::{ExceptSelectItem, ExcludeSelectItem};


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to