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

alamb pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/datafusion.git


The following commit(s) were added to refs/heads/main by this push:
     new e2b335ce01 Use // for unparsing DuckDB division operator (#13509)
e2b335ce01 is described below

commit e2b335ce019f0b158be5cb2b13292b475ac6a981
Author: Qianqian <[email protected]>
AuthorDate: Sat Nov 30 04:41:40 2024 -0800

    Use // for unparsing DuckDB division operator (#13509)
    
    * Use // as DuckDB division operator
    
    * Fix clippy error
---
 datafusion/sql/src/unparser/dialect.rs | 27 ++++++++++++++++++++++++++-
 datafusion/sql/src/unparser/expr.rs    | 28 +++++++++++++++++++++++++++-
 2 files changed, 53 insertions(+), 2 deletions(-)

diff --git a/datafusion/sql/src/unparser/dialect.rs 
b/datafusion/sql/src/unparser/dialect.rs
index 57c89f74f5..e979d8fd4e 100644
--- a/datafusion/sql/src/unparser/dialect.rs
+++ b/datafusion/sql/src/unparser/dialect.rs
@@ -21,7 +21,7 @@ use arrow_schema::TimeUnit;
 use datafusion_expr::Expr;
 use regex::Regex;
 use sqlparser::{
-    ast::{self, Function, Ident, ObjectName, TimezoneInfo},
+    ast::{self, BinaryOperator, Function, Ident, ObjectName, TimezoneInfo},
     keywords::ALL_KEYWORDS,
 };
 
@@ -131,6 +131,13 @@ pub trait Dialect: Send + Sync {
         false
     }
 
+    /// The division operator for the dialect
+    /// Most dialect uses ` BinaryOperator::Divide` (/)
+    /// But DuckDB dialect uses `BinaryOperator::DuckIntegerDivide` (//)
+    fn division_operator(&self) -> BinaryOperator {
+        BinaryOperator::Divide
+    }
+
     /// Allows the dialect to override scalar function unparsing if the 
dialect has specific rules.
     /// Returns None if the default unparsing should be used, or 
Some(ast::Expr) if there is
     /// a custom implementation for the function.
@@ -298,6 +305,10 @@ impl Dialect for DuckDBDialect {
         CharacterLengthStyle::Length
     }
 
+    fn division_operator(&self) -> BinaryOperator {
+        BinaryOperator::DuckIntegerDivide
+    }
+
     fn scalar_function_to_sql_overrides(
         &self,
         unparser: &Unparser,
@@ -435,6 +446,7 @@ pub struct CustomDialect {
     date32_cast_dtype: ast::DataType,
     supports_column_alias_in_table_alias: bool,
     requires_derived_table_alias: bool,
+    division_operator: BinaryOperator,
     full_qualified_col: bool,
 }
 
@@ -460,6 +472,7 @@ impl Default for CustomDialect {
             date32_cast_dtype: ast::DataType::Date,
             supports_column_alias_in_table_alias: true,
             requires_derived_table_alias: false,
+            division_operator: BinaryOperator::Divide,
             full_qualified_col: false,
         }
     }
@@ -562,6 +575,10 @@ impl Dialect for CustomDialect {
         self.requires_derived_table_alias
     }
 
+    fn division_operator(&self) -> BinaryOperator {
+        self.division_operator.clone()
+    }
+
     fn full_qualified_col(&self) -> bool {
         self.full_qualified_col
     }
@@ -598,6 +615,7 @@ pub struct CustomDialectBuilder {
     date32_cast_dtype: ast::DataType,
     supports_column_alias_in_table_alias: bool,
     requires_derived_table_alias: bool,
+    division_operator: BinaryOperator,
     full_qualified_col: bool,
 }
 
@@ -629,6 +647,7 @@ impl CustomDialectBuilder {
             date32_cast_dtype: ast::DataType::Date,
             supports_column_alias_in_table_alias: true,
             requires_derived_table_alias: false,
+            division_operator: BinaryOperator::Divide,
             full_qualified_col: false,
         }
     }
@@ -652,6 +671,7 @@ impl CustomDialectBuilder {
             supports_column_alias_in_table_alias: self
                 .supports_column_alias_in_table_alias,
             requires_derived_table_alias: self.requires_derived_table_alias,
+            division_operator: self.division_operator,
             full_qualified_col: self.full_qualified_col,
         }
     }
@@ -770,6 +790,11 @@ impl CustomDialectBuilder {
         self
     }
 
+    pub fn with_division_operator(mut self, division_operator: BinaryOperator) 
-> Self {
+        self.division_operator = division_operator;
+        self
+    }
+
     /// Customize the dialect to allow full qualified column names
     pub fn with_full_qualified_col(mut self, full_qualified_col: bool) -> Self 
{
         self.full_qualified_col = full_qualified_col;
diff --git a/datafusion/sql/src/unparser/expr.rs 
b/datafusion/sql/src/unparser/expr.rs
index 7024636045..48dfc425ee 100644
--- a/datafusion/sql/src/unparser/expr.rs
+++ b/datafusion/sql/src/unparser/expr.rs
@@ -882,7 +882,7 @@ impl Unparser<'_> {
             Operator::Plus => Ok(BinaryOperator::Plus),
             Operator::Minus => Ok(BinaryOperator::Minus),
             Operator::Multiply => Ok(BinaryOperator::Multiply),
-            Operator::Divide => Ok(BinaryOperator::Divide),
+            Operator::Divide => Ok(self.dialect.division_operator()),
             Operator::Modulo => Ok(BinaryOperator::Modulo),
             Operator::And => Ok(BinaryOperator::And),
             Operator::Or => Ok(BinaryOperator::Or),
@@ -2584,6 +2584,32 @@ mod tests {
         Ok(())
     }
 
+    #[test]
+    fn custom_dialect_division_operator() -> Result<()> {
+        let default_dialect = CustomDialectBuilder::new().build();
+        let duckdb_dialect = CustomDialectBuilder::new()
+            .with_division_operator(BinaryOperator::DuckIntegerDivide)
+            .build();
+
+        for (dialect, expected) in
+            [(default_dialect, "(a / b)"), (duckdb_dialect, "(a // b)")]
+        {
+            let unparser = Unparser::new(&dialect);
+            let expr = Expr::BinaryExpr(BinaryExpr {
+                left: Box::new(col("a")),
+                op: Operator::Divide,
+                right: Box::new(col("b")),
+            });
+            let ast = unparser.expr_to_sql(&expr)?;
+
+            let actual = format!("{}", ast);
+            let expected = expected.to_string();
+
+            assert_eq!(actual, expected);
+        }
+        Ok(())
+    }
+
     #[test]
     fn test_cast_value_to_dict_expr() {
         let tests = [(


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

Reply via email to