From 03d078fb6c8986a07036bdba94458f47d7c8767a Mon Sep 17 00:00:00 2001 From: Michiel De Backker Date: Sat, 9 Mar 2024 15:18:33 +0100 Subject: [PATCH 1/5] feat: convert Expr to SQL string --- datafusion/sql/src/lib.rs | 1 + datafusion/sql/src/unparser/dialect.rs | 52 ++++ datafusion/sql/src/unparser/expr.rs | 337 +++++++++++++++++++++++++ datafusion/sql/src/unparser/mod.rs | 24 ++ 4 files changed, 414 insertions(+) create mode 100644 datafusion/sql/src/unparser/dialect.rs create mode 100644 datafusion/sql/src/unparser/expr.rs create mode 100644 datafusion/sql/src/unparser/mod.rs diff --git a/datafusion/sql/src/lib.rs b/datafusion/sql/src/lib.rs index d805f61397e9..da66ee197adb 100644 --- a/datafusion/sql/src/lib.rs +++ b/datafusion/sql/src/lib.rs @@ -36,6 +36,7 @@ mod relation; mod select; mod set_expr; mod statement; +pub mod unparser; pub mod utils; mod values; diff --git a/datafusion/sql/src/unparser/dialect.rs b/datafusion/sql/src/unparser/dialect.rs new file mode 100644 index 000000000000..af8a6fbb99bb --- /dev/null +++ b/datafusion/sql/src/unparser/dialect.rs @@ -0,0 +1,52 @@ +pub trait Dialect { + fn identifier_quote_style(&self) -> Option; +} +pub struct DefaultDialect {} + +impl Dialect for DefaultDialect { + fn identifier_quote_style(&self) -> Option { + None + } +} + +pub struct PostgreSqlDialect {} + +impl Dialect for PostgreSqlDialect { + fn identifier_quote_style(&self) -> Option { + Some('"') + } +} + +pub struct MySqlDialect {} + +impl Dialect for MySqlDialect { + fn identifier_quote_style(&self) -> Option { + Some('`') + } +} + +pub struct SqliteDialect {} + +impl Dialect for SqliteDialect { + fn identifier_quote_style(&self) -> Option { + Some('`') + } +} + +pub struct CustomDialect { + identifier_quote_style: Option, +} + +impl CustomDialect { + pub fn new(identifier_quote_style: Option) -> Self { + Self { + identifier_quote_style, + } + } +} + +impl Dialect for CustomDialect { + fn identifier_quote_style(&self) -> Option { + self.identifier_quote_style + } +} diff --git a/datafusion/sql/src/unparser/expr.rs b/datafusion/sql/src/unparser/expr.rs new file mode 100644 index 000000000000..27243d75388a --- /dev/null +++ b/datafusion/sql/src/unparser/expr.rs @@ -0,0 +1,337 @@ +use datafusion_common::{not_impl_err, Column, Result, ScalarValue}; +use datafusion_expr::{ + expr::{Alias, InList, ScalarFunction, WindowFunction}, + Between, BinaryExpr, Case, Cast, Expr, Like, Operator, +}; +use sqlparser::ast; + +use super::Unparser; + +/// Convert a DataFusion [`Expr`] to `sqlparser::ast::Expr` +/// +/// This function is the opposite of `SqlToRel::sql_to_expr` +/// +/// Example +/// ``` +/// use datafusion_expr::{col, lit}; +/// use datafusion_sql::unparser::expr_to_sql; +/// let expr = col("a").gt(lit(4)); +/// let sql = expr_to_sql(&expr).unwrap(); +/// +/// assert_eq!(format!("{}", sql), "a > 4") +/// ``` +pub fn expr_to_sql(expr: &Expr) -> Result { + let unparser = Unparser::default(); + unparser.expr_to_sql(expr) +} + +impl Unparser<'_> { + pub fn expr_to_sql(&self, expr: &Expr) -> Result { + match expr { + Expr::InList(InList { + expr, + list: _, + negated: _, + }) => { + not_impl_err!("Unsupported expression: {expr:?}") + } + Expr::ScalarFunction(ScalarFunction { .. }) => { + not_impl_err!("Unsupported expression: {expr:?}") + } + Expr::Between(Between { + expr, + negated: _, + low: _, + high: _, + }) => { + not_impl_err!("Unsupported expression: {expr:?}") + } + Expr::Column(col) => self.col_to_sql(col), + Expr::BinaryExpr(BinaryExpr { left, op, right }) => { + let l = self.expr_to_sql(left.as_ref())?; + let r = self.expr_to_sql(right.as_ref())?; + let op = self.op_to_sql(op)?; + + Ok(self.binary_op_to_sql(l, r, op)) + } + Expr::Case(Case { + expr, + when_then_expr: _, + else_expr: _, + }) => { + not_impl_err!("Unsupported expression: {expr:?}") + } + Expr::Cast(Cast { expr, data_type: _ }) => { + not_impl_err!("Unsupported expression: {expr:?}") + } + Expr::Literal(value) => Ok(ast::Expr::Value(self.scalar_to_sql(value)?)), + Expr::Alias(Alias { expr, name: _, .. }) => self.expr_to_sql(expr), + Expr::WindowFunction(WindowFunction { + fun: _, + args: _, + partition_by: _, + order_by: _, + window_frame: _, + null_treatment: _, + }) => { + not_impl_err!("Unsupported expression: {expr:?}") + } + Expr::Like(Like { + negated: _, + expr, + pattern: _, + escape_char: _, + case_insensitive: _, + }) => { + not_impl_err!("Unsupported expression: {expr:?}") + } + _ => not_impl_err!("Unsupported expression: {expr:?}"), + } + } + + fn col_to_sql(&self, col: &Column) -> Result { + if let Some(table_ref) = &col.relation { + let mut id = table_ref.to_vec(); + id.push(col.name.to_string()); + return Ok(ast::Expr::CompoundIdentifier( + id.iter().map(|i| self.new_ident(i.to_string())).collect(), + )); + } + Ok(ast::Expr::Identifier(self.new_ident(col.name.to_string()))) + } + + fn new_ident(&self, str: String) -> ast::Ident { + ast::Ident { + value: str, + quote_style: self.dialect.identifier_quote_style(), + } + } + + fn binary_op_to_sql( + &self, + lhs: ast::Expr, + rhs: ast::Expr, + op: ast::BinaryOperator, + ) -> ast::Expr { + ast::Expr::BinaryOp { + left: Box::new(lhs), + op, + right: Box::new(rhs), + } + } + + fn op_to_sql(&self, op: &Operator) -> Result { + match op { + Operator::Eq => Ok(ast::BinaryOperator::Eq), + Operator::NotEq => Ok(ast::BinaryOperator::NotEq), + Operator::Lt => Ok(ast::BinaryOperator::Lt), + Operator::LtEq => Ok(ast::BinaryOperator::LtEq), + Operator::Gt => Ok(ast::BinaryOperator::Gt), + Operator::GtEq => Ok(ast::BinaryOperator::GtEq), + Operator::Plus => Ok(ast::BinaryOperator::Plus), + Operator::Minus => Ok(ast::BinaryOperator::Minus), + Operator::Multiply => Ok(ast::BinaryOperator::Multiply), + Operator::Divide => Ok(ast::BinaryOperator::Divide), + Operator::Modulo => Ok(ast::BinaryOperator::Modulo), + Operator::And => Ok(ast::BinaryOperator::And), + Operator::Or => Ok(ast::BinaryOperator::Or), + Operator::IsDistinctFrom => not_impl_err!("unsupported operation: {op:?}"), + Operator::IsNotDistinctFrom => not_impl_err!("unsupported operation: {op:?}"), + Operator::RegexMatch => Ok(ast::BinaryOperator::PGRegexMatch), + Operator::RegexIMatch => Ok(ast::BinaryOperator::PGRegexIMatch), + Operator::RegexNotMatch => Ok(ast::BinaryOperator::PGRegexNotMatch), + Operator::RegexNotIMatch => Ok(ast::BinaryOperator::PGRegexNotIMatch), + Operator::ILikeMatch => Ok(ast::BinaryOperator::PGILikeMatch), + Operator::NotLikeMatch => Ok(ast::BinaryOperator::PGNotLikeMatch), + Operator::LikeMatch => Ok(ast::BinaryOperator::PGLikeMatch), + Operator::NotILikeMatch => Ok(ast::BinaryOperator::PGNotILikeMatch), + Operator::BitwiseAnd => Ok(ast::BinaryOperator::BitwiseAnd), + Operator::BitwiseOr => Ok(ast::BinaryOperator::BitwiseOr), + Operator::BitwiseXor => Ok(ast::BinaryOperator::BitwiseXor), + Operator::BitwiseShiftRight => Ok(ast::BinaryOperator::PGBitwiseShiftRight), + Operator::BitwiseShiftLeft => Ok(ast::BinaryOperator::PGBitwiseShiftLeft), + Operator::StringConcat => Ok(ast::BinaryOperator::StringConcat), + Operator::AtArrow => not_impl_err!("unsupported operation: {op:?}"), + Operator::ArrowAt => not_impl_err!("unsupported operation: {op:?}"), + } + } + + fn scalar_to_sql(&self, v: &ScalarValue) -> Result { + match v { + ScalarValue::Null => Ok(ast::Value::Null), + ScalarValue::Boolean(Some(b)) => Ok(ast::Value::Boolean(b.to_owned())), + ScalarValue::Boolean(None) => Ok(ast::Value::Null), + ScalarValue::Float32(Some(f)) => Ok(ast::Value::Number(f.to_string(), false)), + ScalarValue::Float32(None) => Ok(ast::Value::Null), + ScalarValue::Float64(Some(f)) => Ok(ast::Value::Number(f.to_string(), false)), + ScalarValue::Float64(None) => Ok(ast::Value::Null), + ScalarValue::Decimal128(Some(_), ..) => { + not_impl_err!("Unsupported scalar: {v:?}") + } + ScalarValue::Decimal128(None, ..) => Ok(ast::Value::Null), + ScalarValue::Decimal256(Some(_), ..) => { + not_impl_err!("Unsupported scalar: {v:?}") + } + ScalarValue::Decimal256(None, ..) => Ok(ast::Value::Null), + ScalarValue::Int8(Some(i)) => Ok(ast::Value::Number(i.to_string(), false)), + ScalarValue::Int8(None) => Ok(ast::Value::Null), + ScalarValue::Int16(Some(i)) => Ok(ast::Value::Number(i.to_string(), false)), + ScalarValue::Int16(None) => Ok(ast::Value::Null), + ScalarValue::Int32(Some(i)) => Ok(ast::Value::Number(i.to_string(), false)), + ScalarValue::Int32(None) => Ok(ast::Value::Null), + ScalarValue::Int64(Some(i)) => Ok(ast::Value::Number(i.to_string(), false)), + ScalarValue::Int64(None) => Ok(ast::Value::Null), + ScalarValue::UInt8(Some(ui)) => Ok(ast::Value::Number(ui.to_string(), false)), + ScalarValue::UInt8(None) => Ok(ast::Value::Null), + ScalarValue::UInt16(Some(ui)) => { + Ok(ast::Value::Number(ui.to_string(), false)) + } + ScalarValue::UInt16(None) => Ok(ast::Value::Null), + ScalarValue::UInt32(Some(ui)) => { + Ok(ast::Value::Number(ui.to_string(), false)) + } + ScalarValue::UInt32(None) => Ok(ast::Value::Null), + ScalarValue::UInt64(Some(ui)) => { + Ok(ast::Value::Number(ui.to_string(), false)) + } + ScalarValue::UInt64(None) => Ok(ast::Value::Null), + ScalarValue::Utf8(Some(str)) => { + Ok(ast::Value::SingleQuotedString(str.to_string())) + } + ScalarValue::Utf8(None) => Ok(ast::Value::Null), + ScalarValue::LargeUtf8(Some(str)) => { + Ok(ast::Value::SingleQuotedString(str.to_string())) + } + ScalarValue::LargeUtf8(None) => Ok(ast::Value::Null), + ScalarValue::Binary(Some(_)) => not_impl_err!("Unsupported scalar: {v:?}"), + ScalarValue::Binary(None) => Ok(ast::Value::Null), + ScalarValue::FixedSizeBinary(..) => { + not_impl_err!("Unsupported scalar: {v:?}") + } + ScalarValue::LargeBinary(Some(_)) => { + not_impl_err!("Unsupported scalar: {v:?}") + } + ScalarValue::LargeBinary(None) => Ok(ast::Value::Null), + ScalarValue::FixedSizeList(_a) => not_impl_err!("Unsupported scalar: {v:?}"), + ScalarValue::List(_a) => not_impl_err!("Unsupported scalar: {v:?}"), + ScalarValue::LargeList(_a) => not_impl_err!("Unsupported scalar: {v:?}"), + ScalarValue::Date32(Some(_d)) => not_impl_err!("Unsupported scalar: {v:?}"), + ScalarValue::Date32(None) => Ok(ast::Value::Null), + ScalarValue::Date64(Some(_d)) => not_impl_err!("Unsupported scalar: {v:?}"), + ScalarValue::Date64(None) => Ok(ast::Value::Null), + ScalarValue::Time32Second(Some(_t)) => { + not_impl_err!("Unsupported scalar: {v:?}") + } + ScalarValue::Time32Second(None) => Ok(ast::Value::Null), + ScalarValue::Time32Millisecond(Some(_t)) => { + not_impl_err!("Unsupported scalar: {v:?}") + } + ScalarValue::Time32Millisecond(None) => Ok(ast::Value::Null), + ScalarValue::Time64Microsecond(Some(_t)) => { + not_impl_err!("Unsupported scalar: {v:?}") + } + ScalarValue::Time64Microsecond(None) => Ok(ast::Value::Null), + ScalarValue::Time64Nanosecond(Some(_t)) => { + not_impl_err!("Unsupported scalar: {v:?}") + } + ScalarValue::Time64Nanosecond(None) => Ok(ast::Value::Null), + ScalarValue::TimestampSecond(Some(_ts), _) => { + not_impl_err!("Unsupported scalar: {v:?}") + } + ScalarValue::TimestampSecond(None, _) => Ok(ast::Value::Null), + ScalarValue::TimestampMillisecond(Some(_ts), _) => { + not_impl_err!("Unsupported scalar: {v:?}") + } + ScalarValue::TimestampMillisecond(None, _) => Ok(ast::Value::Null), + ScalarValue::TimestampMicrosecond(Some(_ts), _) => { + not_impl_err!("Unsupported scalar: {v:?}") + } + ScalarValue::TimestampMicrosecond(None, _) => Ok(ast::Value::Null), + ScalarValue::TimestampNanosecond(Some(_ts), _) => { + not_impl_err!("Unsupported scalar: {v:?}") + } + ScalarValue::TimestampNanosecond(None, _) => Ok(ast::Value::Null), + ScalarValue::IntervalYearMonth(Some(_i)) => { + not_impl_err!("Unsupported scalar: {v:?}") + } + ScalarValue::IntervalYearMonth(None) => Ok(ast::Value::Null), + ScalarValue::IntervalDayTime(Some(_i)) => { + not_impl_err!("Unsupported scalar: {v:?}") + } + ScalarValue::IntervalDayTime(None) => Ok(ast::Value::Null), + ScalarValue::IntervalMonthDayNano(Some(_i)) => { + not_impl_err!("Unsupported scalar: {v:?}") + } + ScalarValue::IntervalMonthDayNano(None) => Ok(ast::Value::Null), + ScalarValue::DurationSecond(Some(_d)) => { + not_impl_err!("Unsupported scalar: {v:?}") + } + ScalarValue::DurationSecond(None) => Ok(ast::Value::Null), + ScalarValue::DurationMillisecond(Some(_d)) => { + not_impl_err!("Unsupported scalar: {v:?}") + } + ScalarValue::DurationMillisecond(None) => Ok(ast::Value::Null), + ScalarValue::DurationMicrosecond(Some(_d)) => { + not_impl_err!("Unsupported scalar: {v:?}") + } + ScalarValue::DurationMicrosecond(None) => Ok(ast::Value::Null), + ScalarValue::DurationNanosecond(Some(_d)) => { + not_impl_err!("Unsupported scalar: {v:?}") + } + ScalarValue::DurationNanosecond(None) => Ok(ast::Value::Null), + ScalarValue::Struct(_) => not_impl_err!("Unsupported scalar: {v:?}"), + ScalarValue::Dictionary(..) => not_impl_err!("Unsupported scalar: {v:?}"), + } + } +} + +#[cfg(test)] +mod tests { + use datafusion_common::TableReference; + use datafusion_expr::{col, lit}; + + use crate::unparser::dialect::CustomDialect; + + use super::*; + + #[test] + fn expr_to_sql_ok() -> Result<()> { + let tests: Vec<(Expr, &str)> = vec![ + (col("a").gt(lit(4)), r#"a > 4"#), + ( + Expr::Column(Column { + relation: Some(TableReference::partial("a", "b")), + name: "c".to_string(), + }) + .gt(lit(4)), + r#"a.b.c > 4"#, + ), + ]; + + for (expr, expected) in tests { + let ast = expr_to_sql(&expr)?; + + let actual = format!("{}", ast); + + assert_eq!(actual, expected); + } + + Ok(()) + } + + #[test] + fn custom_dialect() -> Result<()> { + let dialect = CustomDialect::new(Some('\'')); + let unparser = Unparser::new(&dialect); + + let expr = col("a").gt(lit(4)); + let ast = unparser.expr_to_sql(&expr)?; + + let actual = format!("{}", ast); + + let expected = r#"'a' > 4"#; + assert_eq!(actual, expected); + + Ok(()) + } +} diff --git a/datafusion/sql/src/unparser/mod.rs b/datafusion/sql/src/unparser/mod.rs new file mode 100644 index 000000000000..ea2556e4d0ec --- /dev/null +++ b/datafusion/sql/src/unparser/mod.rs @@ -0,0 +1,24 @@ +mod expr; + +pub use expr::expr_to_sql; + +use self::dialect::{DefaultDialect, Dialect}; +mod dialect; + +struct Unparser<'a> { + dialect: &'a dyn Dialect, +} + +impl<'a> Unparser<'a> { + pub fn new(dialect: &'a dyn Dialect) -> Self { + Self { dialect } + } +} + +impl<'a> Default for Unparser<'a> { + fn default() -> Self { + Self { + dialect: &DefaultDialect {}, + } + } +} From 2cda8b0a25040959042e3e5aef9280c3cddb7df9 Mon Sep 17 00:00:00 2001 From: Michiel De Backker Date: Sun, 10 Mar 2024 13:32:36 +0100 Subject: [PATCH 2/5] fix: add license headers --- datafusion/sql/src/unparser/dialect.rs | 19 +++++++++++++++++++ datafusion/sql/src/unparser/expr.rs | 22 ++++++++++++++++++++-- datafusion/sql/src/unparser/mod.rs | 17 +++++++++++++++++ 3 files changed, 56 insertions(+), 2 deletions(-) diff --git a/datafusion/sql/src/unparser/dialect.rs b/datafusion/sql/src/unparser/dialect.rs index af8a6fbb99bb..fc695667c041 100644 --- a/datafusion/sql/src/unparser/dialect.rs +++ b/datafusion/sql/src/unparser/dialect.rs @@ -1,3 +1,22 @@ +// 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. + +/// Dialect is used to capture dialect specific syntax. +/// Note: this trait will be moved to the SQLParser package. pub trait Dialect { fn identifier_quote_style(&self) -> Option; } diff --git a/datafusion/sql/src/unparser/expr.rs b/datafusion/sql/src/unparser/expr.rs index 27243d75388a..bb14c8a70739 100644 --- a/datafusion/sql/src/unparser/expr.rs +++ b/datafusion/sql/src/unparser/expr.rs @@ -1,3 +1,20 @@ +// 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. + use datafusion_common::{not_impl_err, Column, Result, ScalarValue}; use datafusion_expr::{ expr::{Alias, InList, ScalarFunction, WindowFunction}, @@ -9,9 +26,10 @@ use super::Unparser; /// Convert a DataFusion [`Expr`] to `sqlparser::ast::Expr` /// -/// This function is the opposite of `SqlToRel::sql_to_expr` +/// This function is the opposite of `SqlToRel::sql_to_expr` and can +/// be used to, among other things, convert `Expr`s to strings. /// -/// Example +/// # Example /// ``` /// use datafusion_expr::{col, lit}; /// use datafusion_sql::unparser::expr_to_sql; diff --git a/datafusion/sql/src/unparser/mod.rs b/datafusion/sql/src/unparser/mod.rs index ea2556e4d0ec..d35e4278f2af 100644 --- a/datafusion/sql/src/unparser/mod.rs +++ b/datafusion/sql/src/unparser/mod.rs @@ -1,3 +1,20 @@ +// 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. + mod expr; pub use expr::expr_to_sql; From 9ead24be84bb9f41801a863adeaa3ef8513f49b3 Mon Sep 17 00:00:00 2001 From: Michiel De Backker Date: Mon, 11 Mar 2024 18:31:49 +0100 Subject: [PATCH 3/5] fix: make Unparser and Dialect public --- datafusion/sql/src/unparser/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/datafusion/sql/src/unparser/mod.rs b/datafusion/sql/src/unparser/mod.rs index d35e4278f2af..77a9de0975ed 100644 --- a/datafusion/sql/src/unparser/mod.rs +++ b/datafusion/sql/src/unparser/mod.rs @@ -20,9 +20,9 @@ mod expr; pub use expr::expr_to_sql; use self::dialect::{DefaultDialect, Dialect}; -mod dialect; +pub mod dialect; -struct Unparser<'a> { +pub struct Unparser<'a> { dialect: &'a dyn Dialect, } From 07ff3e5a4a2fc109b29628930f961ca8c817fd74 Mon Sep 17 00:00:00 2001 From: Andrew Lamb Date: Mon, 11 Mar 2024 16:28:55 -0400 Subject: [PATCH 4/5] Update datafusion/sql/src/unparser/dialect.rs --- datafusion/sql/src/unparser/dialect.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/datafusion/sql/src/unparser/dialect.rs b/datafusion/sql/src/unparser/dialect.rs index fc695667c041..d5a811331270 100644 --- a/datafusion/sql/src/unparser/dialect.rs +++ b/datafusion/sql/src/unparser/dialect.rs @@ -16,7 +16,9 @@ // under the License. /// Dialect is used to capture dialect specific syntax. -/// Note: this trait will be moved to the SQLParser package. +/// Note: this trait will eventually be replaced by the Dialect in the SQLparser package +/// +/// See pub trait Dialect { fn identifier_quote_style(&self) -> Option; } From b6cff96f4ef65db2f99382cc29d83c019b2cb90a Mon Sep 17 00:00:00 2001 From: Andrew Lamb Date: Mon, 11 Mar 2024 16:30:28 -0400 Subject: [PATCH 5/5] fmt --- datafusion/sql/src/unparser/dialect.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/datafusion/sql/src/unparser/dialect.rs b/datafusion/sql/src/unparser/dialect.rs index d5a811331270..3af33ad0afda 100644 --- a/datafusion/sql/src/unparser/dialect.rs +++ b/datafusion/sql/src/unparser/dialect.rs @@ -17,7 +17,7 @@ /// Dialect is used to capture dialect specific syntax. /// Note: this trait will eventually be replaced by the Dialect in the SQLparser package -/// +/// /// See pub trait Dialect { fn identifier_quote_style(&self) -> Option;