This is an automated email from the ASF dual-hosted git repository.
comphead 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 a2a6458e42 Minor: improve documentation for sql unparsing (#11395)
a2a6458e42 is described below
commit a2a6458e420209c7125b08966c5726b5fd104195
Author: Andrew Lamb <[email protected]>
AuthorDate: Fri Jul 12 11:53:03 2024 -0400
Minor: improve documentation for sql unparsing (#11395)
---
datafusion/sql/src/lib.rs | 6 +++-
datafusion/sql/src/unparser/expr.rs | 29 ++++++++++++-----
datafusion/sql/src/unparser/mod.rs | 64 +++++++++++++++++++++++++++++++++++--
datafusion/sql/src/unparser/plan.rs | 24 ++++++++++----
4 files changed, 105 insertions(+), 18 deletions(-)
diff --git a/datafusion/sql/src/lib.rs b/datafusion/sql/src/lib.rs
index eb5fec7a3c..f53cab5df8 100644
--- a/datafusion/sql/src/lib.rs
+++ b/datafusion/sql/src/lib.rs
@@ -17,7 +17,7 @@
// Make cheap clones clear: https://github.com/apache/datafusion/issues/11143
#![deny(clippy::clone_on_ref_ptr)]
-//! This module provides:
+//! This crate provides:
//!
//! 1. A SQL parser, [`DFParser`], that translates SQL query text into
//! an abstract syntax tree (AST), [`Statement`].
@@ -25,10 +25,14 @@
//! 2. A SQL query planner [`SqlToRel`] that creates [`LogicalPlan`]s
//! from [`Statement`]s.
//!
+//! 3. A SQL [`unparser`] that converts [`Expr`]s and [`LogicalPlan`]s
+//! into SQL query text.
+//!
//! [`DFParser`]: parser::DFParser
//! [`Statement`]: parser::Statement
//! [`SqlToRel`]: planner::SqlToRel
//! [`LogicalPlan`]: datafusion_expr::logical_plan::LogicalPlan
+//! [`Expr`]: datafusion_expr::expr::Expr
mod cte;
mod expr;
diff --git a/datafusion/sql/src/unparser/expr.rs
b/datafusion/sql/src/unparser/expr.rs
index e0d05c400c..eb149c819c 100644
--- a/datafusion/sql/src/unparser/expr.rs
+++ b/datafusion/sql/src/unparser/expr.rs
@@ -72,21 +72,34 @@ impl Display for Unparsed {
}
}
-/// Convert a DataFusion [`Expr`] to `sqlparser::ast::Expr`
+/// Convert a DataFusion [`Expr`] to [`ast::Expr`]
///
-/// This function is the opposite of `SqlToRel::sql_to_expr` and can
-/// be used to, among other things, convert [`Expr`]s to strings.
-/// Throws an error if [`Expr`] can not be represented by an
`sqlparser::ast::Expr`
+/// This function is the opposite of [`SqlToRel::sql_to_expr`] and can be used
+/// to, among other things, convert [`Expr`]s to SQL strings. Such strings
could
+/// be used to pass filters or other expressions to another SQL engine.
+///
+/// # Errors
+///
+/// Throws an error if [`Expr`] can not be represented by an [`ast::Expr`]
+///
+/// # See Also
+///
+/// * [`Unparser`] for more control over the conversion to SQL
+/// * [`plan_to_sql`] for converting a [`LogicalPlan`] to SQL
///
/// # 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)")
+/// let expr = col("a").gt(lit(4)); // form an expression `a > 4`
+/// let sql = expr_to_sql(&expr).unwrap(); // convert to ast::Expr
+/// // use the Display impl to convert to SQL text
+/// assert_eq!(sql.to_string(), "(a > 4)")
/// ```
+///
+/// [`SqlToRel::sql_to_expr`]: crate::planner::SqlToRel::sql_to_expr
+/// [`plan_to_sql`]: crate::unparser::plan_to_sql
+/// [`LogicalPlan`]: datafusion_expr::logical_plan::LogicalPlan
pub fn expr_to_sql(expr: &Expr) -> Result<ast::Expr> {
let unparser = Unparser::default();
unparser.expr_to_sql(expr)
diff --git a/datafusion/sql/src/unparser/mod.rs
b/datafusion/sql/src/unparser/mod.rs
index e5ffbc8a21..83ae64ba23 100644
--- a/datafusion/sql/src/unparser/mod.rs
+++ b/datafusion/sql/src/unparser/mod.rs
@@ -15,6 +15,8 @@
// specific language governing permissions and limitations
// under the License.
+//! [`Unparser`] for converting `Expr` to SQL text
+
mod ast;
mod expr;
mod plan;
@@ -27,6 +29,29 @@ pub use plan::plan_to_sql;
use self::dialect::{DefaultDialect, Dialect};
pub mod dialect;
+/// Convert a DataFusion [`Expr`] to [`sqlparser::ast::Expr`]
+///
+/// See [`expr_to_sql`] for background. `Unparser` allows greater control of
+/// the conversion, but with a more complicated API.
+///
+/// To get more human-readable output, see [`Self::with_pretty`]
+///
+/// # Example
+/// ```
+/// use datafusion_expr::{col, lit};
+/// use datafusion_sql::unparser::Unparser;
+/// let expr = col("a").gt(lit(4)); // form an expression `a > 4`
+/// let unparser = Unparser::default();
+/// let sql = unparser.expr_to_sql(&expr).unwrap();// convert to AST
+/// // use the Display impl to convert to SQL text
+/// assert_eq!(sql.to_string(), "(a > 4)");
+/// // now convert to pretty sql
+/// let unparser = unparser.with_pretty(true);
+/// let sql = unparser.expr_to_sql(&expr).unwrap();
+/// assert_eq!(sql.to_string(), "a > 4"); // note lack of parenthesis
+/// ```
+///
+/// [`Expr`]: datafusion_expr::Expr
pub struct Unparser<'a> {
dialect: &'a dyn Dialect,
pretty: bool,
@@ -40,9 +65,42 @@ impl<'a> Unparser<'a> {
}
}
- /// Allow unparser to remove parenthesis according to the precedence rules
of DataFusion.
- /// This might make it invalid SQL for other SQL query engines with
different precedence
- /// rules, even if its valid for DataFusion.
+ /// Create pretty SQL output, better suited for human consumption
+ ///
+ /// See example on the struct level documentation
+ ///
+ /// # Pretty Output
+ ///
+ /// By default, `Unparser` generates SQL text that will parse back to the
+ /// same parsed [`Expr`], which is useful for creating machine readable
+ /// expressions to send to other systems. However, the resulting
expressions are
+ /// not always nice to read for humans.
+ ///
+ /// For example
+ ///
+ /// ```sql
+ /// ((a + 4) > 5)
+ /// ```
+ ///
+ /// This method removes parenthesis using to the precedence rules of
+ /// DataFusion. If the output is reparsed, the resulting [`Expr`] produces
+ /// same value as the original in DataFusion, but with a potentially
+ /// different order of operations.
+ ///
+ /// Note that this setting may create invalid SQL for other SQL query
+ /// engines with different precedence rules
+ ///
+ /// # Example
+ /// ```
+ /// use datafusion_expr::{col, lit};
+ /// use datafusion_sql::unparser::Unparser;
+ /// let expr = col("a").gt(lit(4)).and(col("b").lt(lit(5))); // form an
expression `a > 4 AND b < 5`
+ /// let unparser = Unparser::default().with_pretty(true);
+ /// let sql = unparser.expr_to_sql(&expr).unwrap();
+ /// assert_eq!(sql.to_string(), "a > 4 AND b < 5"); // note lack of
parenthesis
+ /// ```
+ ///
+ /// [`Expr`]: datafusion_expr::Expr
pub fn with_pretty(mut self, pretty: bool) -> Self {
self.pretty = pretty;
self
diff --git a/datafusion/sql/src/unparser/plan.rs
b/datafusion/sql/src/unparser/plan.rs
index 15137403c5..41a8c96884 100644
--- a/datafusion/sql/src/unparser/plan.rs
+++ b/datafusion/sql/src/unparser/plan.rs
@@ -33,10 +33,18 @@ use super::{
Unparser,
};
-/// Convert a DataFusion [`LogicalPlan`] to `sqlparser::ast::Statement`
+/// Convert a DataFusion [`LogicalPlan`] to [`ast::Statement`]
///
-/// This function is the opposite of `SqlToRel::sql_statement_to_plan` and can
-/// be used to, among other things, convert `LogicalPlan`s to strings.
+/// This function is the opposite of [`SqlToRel::sql_statement_to_plan`] and
can
+/// be used to, among other things, to convert `LogicalPlan`s to SQL strings.
+///
+/// # Errors
+///
+/// This function returns an error if the plan cannot be converted to SQL.
+///
+/// # See Also
+///
+/// * [`expr_to_sql`] for converting [`Expr`], a single expression to SQL
///
/// # Example
/// ```
@@ -47,16 +55,20 @@ use super::{
/// Field::new("id", DataType::Utf8, false),
/// Field::new("value", DataType::Utf8, false),
/// ]);
+/// // Scan 'table' and select columns 'id' and 'value'
/// let plan = table_scan(Some("table"), &schema, None)
/// .unwrap()
/// .project(vec![col("id"), col("value")])
/// .unwrap()
/// .build()
/// .unwrap();
-/// let sql = plan_to_sql(&plan).unwrap();
-///
-/// assert_eq!(format!("{}", sql), "SELECT \"table\".id, \"table\".\"value\"
FROM \"table\"")
+/// let sql = plan_to_sql(&plan).unwrap(); // convert to AST
+/// // use the Display impl to convert to SQL text
+/// assert_eq!(sql.to_string(), "SELECT \"table\".id, \"table\".\"value\" FROM
\"table\"")
/// ```
+///
+/// [`SqlToRel::sql_statement_to_plan`]:
crate::planner::SqlToRel::sql_statement_to_plan
+/// [`expr_to_sql`]: crate::unparser::expr_to_sql
pub fn plan_to_sql(plan: &LogicalPlan) -> Result<ast::Statement> {
let unparser = Unparser::default();
unparser.plan_to_sql(plan)
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]