pub enum LogicalPlan {
Show 25 variants Projection(Projection),
Filter(Filter),
Window(Window),
Aggregate(Aggregate),
Sort(Sort),
Join(Join),
Repartition(Repartition),
Union(Union),
TableScan(TableScan),
EmptyRelation(EmptyRelation),
Subquery(Subquery),
SubqueryAlias(SubqueryAlias),
Limit(Limit),
Statement(Statement),
Values(Values),
Explain(Explain),
Analyze(Analyze),
Extension(Extension),
Distinct(Distinct),
Dml(DmlStatement),
Ddl(DdlStatement),
Copy(CopyTo),
DescribeTable(DescribeTable),
Unnest(Unnest),
RecursiveQuery(RecursiveQuery),
}
Expand description
A LogicalPlan
is a node in a tree of relational operators (such as Projection or Filter).
Represents transforming an input relation (table) to an output relation (table) with a potentially different schema. Plans form a dataflow tree where data flows from leaves up to the root to produce the query result.
LogicalPlan
s can be created by the SQL query planner, the DataFrame API, or programmatically (for example custom query languages).
Expr
: For the expressions that are evaluated by the planLogicalPlanBuilder
: For building LogicalPlan
stree_node
: To inspect and rewrite LogicalPlan
sLogicalPlan
s
Using the tree_node
API, you can recursively walk all nodes in a LogicalPlan
. For example, to find all column references in a plan:
let plan = table_scan(Some("employee"), &employee_schema(), None)?
.filter(col("salary").gt(lit(1000)))?
.project(vec![col("name")])?
.build()?;
let mut expressions = HashSet::new();
plan.apply(|node| {
node.apply_expressions(|expr| {
expressions.insert(expr.clone());
Ok(TreeNodeRecursion::Continue) })?;
Ok(TreeNodeRecursion::Continue) }).unwrap();
assert_eq!(expressions.len(), 2);
println!("Found expressions: {:?}", expressions);
let salary = Expr::Column(Column::new(Some("employee"), "salary"));
assert!(expressions.contains(&salary.gt(lit(1000))));
let name = Expr::Column(Column::new(Some("employee"), "name"));
assert!(expressions.contains(&name));
You can also rewrite plans using the tree_node
API. For example, to replace the filter predicate in a plan:
use datafusion_common::tree_node::Transformed;
let plan = table_scan(Some("employee"), &employee_schema(), None)?
.filter(col("salary").gt(lit(1000)))?
.project(vec![col("name")])?
.build()?;
let transformed_result = plan.transform(|node| {
if let LogicalPlan::Filter(mut filter) = node {
filter.predicate = Expr::Column(Column::new(Some("employee"), "salary")).lt(lit(2000));
let new_plan = LogicalPlan::Filter(filter);
return Ok(Transformed::yes(new_plan)); }
Ok(Transformed::no(node))
}).unwrap();
assert!(transformed_result.transformed);
let rewritten_plan = transformed_result.data;
assert_eq!(rewritten_plan.display_indent().to_string(),
"Projection: employee.name\
\n Filter: employee.salary < Int32(2000)\
\n TableScan: employee");
§
Evaluates an arbitrary list of expressions (essentially a SELECT with an expression list) on its input.
§Filters rows from its input that do not match an expression (essentially a WHERE clause with a predicate expression).
Semantically, <predicate>
is evaluated for each row of the input; If the value of <predicate>
is true, the input row is passed to the output. If the value of <predicate>
is false (or null), the row is discarded.
Windows input based on a set of window spec and window function (e.g. SUM or RANK). This is used to implement SQL window functions, and the OVER
clause.
See Window
for more details
Aggregates its input based on a set of grouping and aggregate expressions (e.g. SUM). This is used to implement SQL aggregates and GROUP BY
.
See Aggregate
for more details
Sorts its input according to a list of sort expressions. This is used to implement SQL ORDER BY
Join two logical plans on one or more join columns. This is used to implement SQL JOIN
Repartitions the input based on a partitioning scheme. This is used to add parallelism and is sometimes referred to as an “exchange” operator in other systems
§Union multiple inputs with the same schema into a single output stream. This is used to implement SQL UNION [ALL]
and INTERSECT [ALL]
.
Produces rows from a TableSource
, used to implement SQL FROM
tables or views.
Produces no rows: An empty relation with an empty schema that produces 0 or 1 row. This is used to implement SQL SELECT
that has no values in the FROM
clause.
Produces the output of running another query. This is used to implement SQL subqueries
§Aliased relation provides, or changes, the name of a relation.
§Skip some number of rows, and then fetch some number of rows.
§A DataFusion Statement
such as SET VARIABLE
or START TRANSACTION
Values expression. See Postgres VALUES documentation for more details. This is used to implement SQL such as VALUES (1, 2), (3, 4)
Produces a relation with string representations of various parts of the plan. This is used to implement SQL EXPLAIN
.
Runs the input, and prints annotated physical plan as a string with execution metric. This is used to implement SQL EXPLAIN ANALYZE
.
Extension operator defined outside of DataFusion. This is used to extend DataFusion with custom relational operations that
§Remove duplicate rows from the input. This is used to implement SQL SELECT DISTINCT ...
.
Data Manipulation Language (DML): Insert / Update / Delete
§Data Definition Language (DDL): CREATE / DROP TABLES / VIEWS / SCHEMAS
§COPY TO
for writing plan results to files
Describe the schema of the table. This is used to implement the SQL DESCRIBE
command from MySQL.
Unnest a column that contains a nested list type such as an ARRAY. This is used to implement SQL UNNEST
A variadic query (e.g. “Recursive CTEs”)
Source§ SourceGet a reference to the logical plan’s schema
SourceUsed for normalizing columns, as the fallback schemas to the main schema of the plan.
SourceReturns the (fixed) output schema for explain plans
SourceReturns the (fixed) output schema for DESCRIBE
plans
Returns all expressions (non-recursively) evaluated by the current logical plan node. This does not include expressions in any children.
Note this method clone
s all the expressions. When possible, the tree_node
API should be used instead of this API.
The returned expressions do not necessarily represent or even contributed to the output schema of this node. For example, LogicalPlan::Filter
returns the filter expression even though the output of a Filter has the same columns as the input.
The expressions do contain all the columns that are used by this plan, so if there are columns not referenced by these expressions then DataFusion’s optimizer attempts to optimize them away.
SourceReturns all the out reference(correlated) expressions (recursively) in the current logical plan nodes and all its descendant nodes.
SourceReturns all inputs / children of this LogicalPlan
node.
Note does not include inputs to inputs, or subqueries.
Sourcereturns all Using
join columns in a logical plan
returns the first output expression of this LogicalPlan
node.
Recomputes schema and type information for this LogicalPlan if needed.
Some LogicalPlan
s may need to recompute their schema if the number or type of expressions have been changed (for example due to type coercion). For example LogicalPlan::Projection
s schema depends on its expressions.
Some LogicalPlan
s schema is unaffected by any changes to their expressions. For example LogicalPlan::Filter
schema is always the same as its input schema.
This is useful after modifying a plans Expr
s (or input plans) via methods such as Self::map_children and Self::map_expressions. Unlike Self::with_new_exprs, this method does not require a new set of expressions or inputs plans.
Returns an error if there is some issue recomputing the schema.
§NotesReturns a new LogicalPlan
based on self
with inputs and expressions replaced.
Note this method creates an entirely new node, which requires a large amount of clone’ing. When possible, the tree_node
API should be used instead of this API.
The exprs correspond to the same order of expressions returned by Self::expressions
. This function is used by optimizers to rewrite plans using the following pattern:
let new_inputs = optimize_children(..., plan, props);
// get the plans expressions to optimize
let exprs = plan.expressions();
// potentially rewrite plan expressions
let rewritten_exprs = rewrite_exprs(exprs);
// create new plan using rewritten_exprs in same position
let new_plan = plan.new_with_exprs(rewritten_exprs, new_inputs);
Source
checks that the plan conforms to the listed invariant level, returning an Error if not
SourceReplaces placeholder param values (like $1
, $2
) in LogicalPlan
with the specified param_values
.
Prepare
statements are converted to their inner logical plan for execution.
use datafusion_common::ScalarValue;
let plan = table_scan(Some("t1"), &schema, None).unwrap()
.filter(col("id").eq(placeholder("$1"))).unwrap()
.build().unwrap();
assert_eq!(
"Filter: t1.id = $1\
\n TableScan: t1",
plan.display_indent().to_string()
);
let plan = plan.with_param_values(vec![
ScalarValue::from(3i32) ]).unwrap();
assert_eq!(
"Filter: t1.id = Int32(3)\
\n TableScan: t1",
plan.display_indent().to_string()
);
let plan = table_scan(Some("t1"), &schema, None).unwrap()
.filter(col("id").eq(placeholder("$my_param"))).unwrap()
.build().unwrap()
.with_param_values(vec![
("my_param", ScalarValue::from(3i32)),
]).unwrap();
assert_eq!(
"Filter: t1.id = Int32(3)\
\n TableScan: t1",
plan.display_indent().to_string()
);
Source
Returns the maximum number of rows that this plan can output, if known.
If None
, the plan can return any number of rows. If Some(n)
then the plan can return at most n
rows but may return fewer.
If this node’s expressions contains any references to an outer subquery
SourceGet the output expressions and their corresponding columns.
The parent node may reference the output columns of the plan by expressions, such as projection over aggregate or window functions. This method helps to convert the referenced expressions into columns.
See also: crate::utils::columnize_expr
Return a LogicalPlan
with all placeholders (e.g $1 $2, …) replaced with corresponding values provided in params_values
See Self::with_param_values
for examples and usage with an owned ParamValues
Walk the logical plan, find any Placeholder
tokens, and return a set of their names.
Walk the logical plan, find any Placeholder
tokens, and return a map of their IDs and DataTypes
Return a format
able structure that produces a single line per node.
Projection: employee.id
Filter: employee.state Eq Utf8(\"CO\")\
CsvScan: employee projection=Some([0, 3])
use arrow::datatypes::{Field, Schema, DataType};
use datafusion_expr::{lit, col, LogicalPlanBuilder, logical_plan::table_scan};
let schema = Schema::new(vec![
Field::new("id", DataType::Int32, false),
]);
let plan = table_scan(Some("t1"), &schema, None).unwrap()
.filter(col("id").eq(lit(5))).unwrap()
.build().unwrap();
let display_string = format!("{}", plan.display_indent());
assert_eq!("Filter: t1.id = Int32(5)\n TableScan: t1",
display_string);
Source
Return a format
able structure that produces a single line per node that includes the output schema. For example:
Projection: employee.id [id:Int32]\
Filter: employee.state = Utf8(\"CO\") [id:Int32, state:Utf8]\
TableScan: employee projection=[0, 3] [id:Int32, state:Utf8]";
use arrow::datatypes::{Field, Schema, DataType};
use datafusion_expr::{lit, col, LogicalPlanBuilder, logical_plan::table_scan};
let schema = Schema::new(vec![
Field::new("id", DataType::Int32, false),
]);
let plan = table_scan(Some("t1"), &schema, None).unwrap()
.filter(col("id").eq(lit(5))).unwrap()
.build().unwrap();
let display_string = format!("{}", plan.display_indent_schema());
assert_eq!("Filter: t1.id = Int32(5) [id:Int32]\
\n TableScan: t1 [id:Int32]",
display_string);
Source
Return a displayable structure that produces plan in postgresql JSON format.
Users can use this format to visualize the plan in existing plan visualization tools, for example dalibo
SourceReturn a format
able structure that produces lines meant for graphical display using the DOT
language. This format can be visualized using software from graphviz
This currently produces two graphs – one with the basic structure, and one with additional details such as schema.
use arrow::datatypes::{Field, Schema, DataType};
use datafusion_expr::{lit, col, LogicalPlanBuilder, logical_plan::table_scan};
let schema = Schema::new(vec![
Field::new("id", DataType::Int32, false),
]);
let plan = table_scan(Some("t1"), &schema, None).unwrap()
.filter(col("id").eq(lit(5))).unwrap()
.build().unwrap();
let graphviz_string = format!("{}", plan.display_graphviz());
If graphviz string is saved to a file such as /tmp/example.dot
, the following commands can be used to render it as a pdf:
dot -Tpdf < /tmp/example.dot > /tmp/example.pdf
Source
Return a format
able structure with the a human readable description of this LogicalPlan node per node, not including children. For example:
use arrow::datatypes::{Field, Schema, DataType};
use datafusion_expr::{lit, col, LogicalPlanBuilder, logical_plan::table_scan};
let schema = Schema::new(vec![
Field::new("id", DataType::Int32, false),
]);
let plan = table_scan(Some("t1"), &schema, None).unwrap()
.build().unwrap();
let display_string = format!("{}", plan.display());
assert_eq!("TableScan: t1", display_string);
Source§ Source
Calls f
on all expressions in the current LogicalPlan
node.
TreeNode::apply
but for this node’s expressions.LogicalPlan
nodesRewrites all expressions in the current LogicalPlan
node using f
.
Returns the current node.
§NotesTreeNode::map_children
but for this node’s expressions.Visits a plan similarly to Self::visit
, including subqueries that may appear in expressions such as IN (SELECT ...)
.
Similarly to Self::rewrite
, rewrites this node and its inputs using f
, including subqueries that may appear in expressions such as IN (SELECT ...)
.
Similarly to Self::apply
, calls f
on this node and all its inputs, including subqueries that may appear in expressions such as IN (SELECT ...)
.
Similarly to Self::transform
, rewrites this node and its inputs using f
, including subqueries that may appear in expressions such as IN (SELECT ...)
.
Similarly to Self::transform_down
, rewrites this node and its inputs using f
, including subqueries that may appear in expressions such as IN (SELECT ...)
.
Similarly to Self::transform_up
, rewrites this node and its inputs using f
, including subqueries that may appear in expressions such as IN (SELECT ...)
.
Similarly to Self::transform_down
, rewrites this node and its inputs using f
, including subqueries that may appear in expressions such as IN (SELECT ...)
.
Similarly to Self::apply
, calls f
on this node and its inputs including subqueries that may appear in expressions such as IN (SELECT ...)
.
Similarly to Self::map_children
, rewrites all subqueries that may appear in expressions such as IN (SELECT ...)
using f
.
Returns the current node.
Source§ Source§ Source§ Source§ Source§ Source§Converts to this type from the input type.
Source§ Source§ Source§Tests for self
and other
values to be equal, and is used by ==
.
Tests for !=
. The default implementation is almost always sufficient, and should not be overridden without very good reason.
This method returns an ordering between
self
and
other
values if one exists.
Read more 1.0.0 · Source§Tests less than (for
self
and
other
) and is used by the
<
operator.
Read more 1.0.0 · Source§Tests less than or equal to (for
self
and
other
) and is used by the
<=
operator.
Read more 1.0.0 · Source§Tests greater than (for
self
and
other
) and is used by the
>
operator.
Read more 1.0.0 · Source§Tests greater than or equal to (for
self
and
other
) and is used by the
>=
operator.
Read more Source§ Source§Create a stringified plan with the specified type
Source§ Source§Applies f
to each child (input) of this plan node, rewriting them in place.
Inputs include ONLY direct children, not embedded LogicalPlan
s for subqueries, for example such as are in Expr::Exists
.
Low-level API used to implement other APIs.
Read more Source§ Source§ Source§Applies
f
to the node then each of its children, recursively (a top-down, pre-order traversal).
Read more Source§Recursively rewrite the node’s children and then the node using
f
(a bottom-up post-order traversal).
Read more Source§Recursively rewrite the tree using
f
in a top-down (pre-order) fashion.
Read more Source§Recursively rewrite the node using
f
in a bottom-up (post-order) fashion.
Read more Source§Transforms the node using
f_down
while traversing the tree top-down (pre-order), and using
f_up
while traversing the tree bottom-up (post-order).
Read more Source§Returns true if
f
returns true for any node in the tree.
Read more Source§ Source§Applies
f
to all elements of the container. This method is usually called from
TreeNode::apply_children
implementations as a node is actually a container of the node’s children.
Source§Maps all elements of the container with
f
. This method is usually called from
TreeNode::map_children
implementations as a node is actually a container of the node’s children.
Source§ Source§RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4