Unparser

Struct Unparser 

Source
pub struct Unparser<'a> {
    dialect: &'a dyn Dialect,
    pretty: bool,
    extension_unparsers: Vec<Arc<dyn UserDefinedLogicalNodeUnparser>>,
}
Expand description

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

Fields§

§dialect: &'a dyn Dialect§pretty: bool§extension_unparsers: Vec<Arc<dyn UserDefinedLogicalNodeUnparser>>

Implementations§

Source§

impl Unparser<'_>

Source

pub fn expr_to_sql(&self, expr: &Expr) -> Result<Expr>

Source

fn expr_to_sql_inner(&self, expr: &Expr) -> Result<Expr>

Source

pub fn scalar_function_to_sql( &self, func_name: &str, args: &[Expr], ) -> Result<Expr>

Source

fn scalar_function_to_sql_internal( &self, func_name: &str, args: &[Expr], ) -> Result<Expr>

Source

fn make_array_to_sql(&self, args: &[Expr]) -> Result<Expr>

Source

fn scalar_value_list_to_sql(&self, array: &ArrayRef) -> Result<Expr>

Source

fn array_element_to_sql(&self, args: &[Expr]) -> Result<Expr>

Source

fn named_struct_to_sql(&self, args: &[Expr]) -> Result<Expr>

Source

fn get_field_to_sql(&self, args: &[Expr]) -> Result<Expr>

Source

fn map_to_sql(&self, args: &[Expr]) -> Result<Expr>

Source

pub fn sort_to_sql(&self, sort: &Sort) -> Result<OrderByExpr>

Source

fn ast_type_for_date64_in_cast(&self) -> DataType

Source

pub fn col_to_sql(&self, col: &Column) -> Result<Expr>

Source

fn convert_bound(&self, bound: &WindowFrameBound) -> Result<WindowFrameBound>

Source

pub(crate) fn function_args_to_sql( &self, args: &[Expr], ) -> Result<Vec<FunctionArg>>

Source

pub(super) fn new_ident_quoted_if_needs(&self, ident: String) -> Ident

This function can create an identifier with or without quotes based on the dialect rules

Source

pub(super) fn new_ident_without_quote_style(&self, str: String) -> Ident

Source

pub(super) fn binary_op_to_sql( &self, lhs: Expr, rhs: Expr, op: BinaryOperator, ) -> Expr

Source

fn remove_unnecessary_nesting( &self, expr: Expr, left_op: &BinaryOperator, right_op: &BinaryOperator, ) -> Expr

Given an expression of the form ((a + b) * (c * d)), the parenthesis is redundant if the precedence of the nested expression is already higher than the surrounding operators’ precedence. The above expression would become (a + b) * c * d.

Also note that when fetching the precedence of a nested expression, we ignore other nested expressions, so precedence of expr (a * (b + c)) equals * and not +.

Source

fn inner_precedence(&self, expr: &Expr) -> u8

Source

pub(super) fn between_op_to_sql( &self, expr: Expr, negated: bool, low: Expr, high: Expr, ) -> Expr

Source

fn sql_op_precedence(&self, op: &BinaryOperator) -> u8

Source

fn sql_to_op(&self, op: &BinaryOperator) -> Result<Operator>

Source

fn op_to_sql(&self, op: &Operator) -> Result<BinaryOperator>

Source

fn handle_timestamp<T: ArrowTemporalType>( &self, v: &ScalarValue, tz: &Option<Arc<str>>, ) -> Result<Expr>
where i64: From<T::Native>,

Source

fn handle_time<T: ArrowTemporalType>(&self, v: &ScalarValue) -> Result<Expr>
where i64: From<T::Native>,

Source

fn cast_to_sql(&self, expr: &Expr, data_type: &DataType) -> Result<Expr>

Source

fn scalar_to_sql(&self, v: &ScalarValue) -> Result<Expr>

DataFusion ScalarValues sometimes require a ast::Expr to construct. For example ScalarValue::Date32(d) corresponds to the ast::Expr CAST(‘datestr’ as DATE)

Source

fn interval_to_mysql_expr( &self, months: i32, days: i32, microseconds: i64, ) -> Result<Expr>

MySQL requires INTERVAL sql to be in the format: INTERVAL 1 YEAR + INTERVAL 1 MONTH + INTERVAL 1 DAY etc <https://dev.mysql.com/doc/refman/8.4/en/expressions.html#temporal-intervals> Interval sequence can’t be wrapped in brackets - (INTERVAL 1 YEAR + INTERVAL 1 MONTH …) so we need to generate a single INTERVAL expression so it works correct for interval subtraction cases MySQL supports the DAY_MICROSECOND unit type (format is DAYS HOURS:MINUTES:SECONDS.MICROSECONDS), but it is not supported by sqlparser so we calculate the best single interval to represent the provided duration

Source

fn interval_scalar_to_sql(&self, v: &ScalarValue) -> Result<Expr>

Source

fn unnest_to_sql(&self, unnest: &Unnest) -> Result<Expr>

Converts an UNNEST operation to an AST expression by wrapping it as a function call, since there is no direct representation for UNNEST in the AST.

Source

fn arrow_dtype_to_ast_dtype(&self, data_type: &DataType) -> Result<DataType>

Source§

impl Unparser<'_>

Source

pub fn plan_to_sql(&self, plan: &LogicalPlan) -> Result<Statement>

Source

fn extension_to_statement( &self, node: &dyn UserDefinedLogicalNode, ) -> Result<Statement>

Try to unparse a UserDefinedLogicalNode to a SQL statement. If multiple unparsers are registered for the same UserDefinedLogicalNode, the first unparsing result will be returned.

Source

fn extension_to_sql( &self, node: &dyn UserDefinedLogicalNode, query: &mut Option<&mut QueryBuilder>, select: &mut Option<&mut SelectBuilder>, relation: &mut Option<&mut RelationBuilder>, ) -> Result<()>

Try to unparse a UserDefinedLogicalNode to a SQL statement. If multiple unparsers are registered for the same UserDefinedLogicalNode, the first unparser supporting the node will be used.

Source

fn select_to_sql_statement(&self, plan: &LogicalPlan) -> Result<Statement>

Source

fn select_to_sql_expr( &self, plan: &LogicalPlan, query: &mut Option<QueryBuilder>, ) -> Result<SetExpr>

Source

fn reconstruct_select_statement( &self, plan: &LogicalPlan, p: &Projection, select: &mut SelectBuilder, ) -> Result<()>

Reconstructs a SELECT SQL statement from a logical plan by unprojecting column expressions found in a Projection node. This requires scanning the plan tree for relevant Aggregate and Window nodes and matching column expressions to the appropriate agg or window expressions.

Source

fn derive( &self, plan: &LogicalPlan, relation: &mut RelationBuilder, alias: Option<TableAlias>, lateral: bool, ) -> Result<()>

Source

fn derive_with_dialect_alias( &self, alias: &str, plan: &LogicalPlan, relation: &mut RelationBuilder, lateral: bool, columns: Vec<Ident>, ) -> Result<()>

Source

fn select_to_sql_recursively( &self, plan: &LogicalPlan, query: &mut Option<QueryBuilder>, select: &mut SelectBuilder, relation: &mut RelationBuilder, ) -> Result<()>

Source

fn check_unnest_placeholder_with_outer_ref( expr: &Expr, ) -> Option<UnnestInputType>

Try to find the placeholder column name generated by RecursiveUnnestRewriter.

  • If the column is a placeholder column match the pattern Expr::Alias(Expr::Column("__unnest_placeholder(...)")), it means it is a scalar column, return UnnestInputType::Scalar.
  • If the column is a placeholder column match the pattern Expr::Alias(Expr::Column("__unnest_placeholder(outer_ref(...)))"), it means it is an outer reference column, return UnnestInputType::OuterReference.
  • If the column is not a placeholder column, return None.

outer_ref is the display result of Expr::OuterReferenceColumn

Source

fn try_unnest_to_table_factor_sql( &self, unnest: &Unnest, ) -> Result<Option<UnnestRelationBuilder>>

Source

fn is_scan_with_pushdown(scan: &TableScan) -> bool

Source

fn unparse_table_scan_pushdown( plan: &LogicalPlan, alias: Option<TableReference>, already_projected: bool, ) -> Result<Option<LogicalPlan>>

Try to unparse a table scan with pushdown operations into a new subquery plan. If the table scan is without any pushdown operations, return None.

Source

fn select_item_to_sql(&self, expr: &Expr) -> Result<SelectItem>

Source

fn sorts_to_sql(&self, sort_exprs: &[SortExpr]) -> Result<OrderByKind>

Source

fn join_operator_to_sql( &self, join_type: JoinType, constraint: JoinConstraint, ) -> Result<JoinOperator>

Source

fn join_using_to_sql( &self, join_conditions: &[(Expr, Expr)], ) -> Option<JoinConstraint>

Convert the components of a USING clause to the USING AST. Returns ‘None’ if the conditions are not compatible with a USING expression, e.g. non-column expressions or non-matching names.

Source

fn join_constraint_to_sql( &self, constraint: JoinConstraint, conditions: &[(Expr, Expr)], filter: Option<&Expr>, ) -> Result<JoinConstraint>

Convert a join constraint and associated conditions and filter to a SQL AST node

Source

fn join_conditions_to_sql_on( &self, join_conditions: &[(Expr, Expr)], filter: Option<&Expr>, ) -> Result<JoinConstraint>

Source

fn and_op_to_sql(&self, lhs: Expr, rhs: Expr) -> Expr

Source

fn new_table_alias(&self, alias: String, columns: Vec<Ident>) -> TableAlias

Source

fn dml_to_sql(&self, plan: &LogicalPlan) -> Result<Statement>

Source§

impl<'a> Unparser<'a>

Source

pub fn new(dialect: &'a dyn Dialect) -> Self

Source

pub fn with_pretty(self, pretty: bool) -> Self

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

((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
Source

pub fn with_extension_unparsers( self, extension_unparsers: Vec<Arc<dyn UserDefinedLogicalNodeUnparser>>, ) -> Self

Add a custom unparser for user defined logical nodes

DataFusion allows user to define custom logical nodes. This method allows to add custom child unparsers for these nodes. Implementation of UserDefinedLogicalNodeUnparser can be added to the root unparser to handle custom logical nodes.

The child unparsers are called iteratively. There are two methods in Unparser will be called:

  • extension_to_statement: This method is called when the custom logical node is a custom statement. If multiple child unparsers return a non-None value, the last unparsing result will be returned.
  • extension_to_sql: This method is called when the custom logical node is part of a statement. If multiple child unparsers are registered for the same custom logical node, all of them will be called in order.

Trait Implementations§

Source§

impl Default for Unparser<'_>

Source§

fn default() -> Self

Returns the “default value” for a type. Read more

Auto Trait Implementations§

§

impl<'a> Freeze for Unparser<'a>

§

impl<'a> !RefUnwindSafe for Unparser<'a>

§

impl<'a> !Send for Unparser<'a>

§

impl<'a> !Sync for Unparser<'a>

§

impl<'a> Unpin for Unparser<'a>

§

impl<'a> !UnwindSafe for Unparser<'a>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
§

impl<T> PolicyExt for T
where T: ?Sized,

§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns [Action::Follow] only if self and other return Action::Follow. Read more
§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns [Action::Follow] if either self or other returns Action::Follow. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

impl<T> ErasedDestructor for T
where T: 'static,