Skip to content

Commit 347b2b6

Browse files
authored
Add Projection struct w/ helper methods to manipulate projections (#18176)
I'm hoping these will help with #14993. For now they're just an internal refactor + exposing some functionality as `pub` and lots of new tests. Written with AI assistance.
1 parent 77a4cb7 commit 347b2b6

File tree

7 files changed

+1115
-338
lines changed

7 files changed

+1115
-338
lines changed

datafusion/core/src/physical_planner.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3063,7 +3063,7 @@ mod tests {
30633063
let execution_plan = plan(&logical_plan).await?;
30643064
// verify that the plan correctly adds cast from Int64(1) to Utf8, and the const will be evaluated.
30653065

3066-
let expected = "expr: [ProjectionExpr { expr: BinaryExpr { left: BinaryExpr { left: Column { name: \"c1\", index: 0 }, op: Eq, right: Literal { value: Utf8(\"a\"), field: Field { name: \"lit\", data_type: Utf8, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} } }, fail_on_overflow: false }, op: Or, right: BinaryExpr { left: Column { name: \"c1\", index: 0 }, op: Eq, right: Literal { value: Utf8(\"1\"), field: Field { name: \"lit\", data_type: Utf8, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} } }, fail_on_overflow: false }, fail_on_overflow: false }";
3066+
let expected = "exprs: [ProjectionExpr { expr: BinaryExpr { left: BinaryExpr { left: Column { name: \"c1\", index: 0 }, op: Eq, right: Literal { value: Utf8(\"a\"), field: Field { name: \"lit\", data_type: Utf8, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} } }, fail_on_overflow: false }, op: Or, right: BinaryExpr { left: Column { name: \"c1\", index: 0 }, op: Eq, right: Literal { value: Utf8(\"1\"), field: Field { name: \"lit\", data_type: Utf8, nullable: false, dict_id: 0, dict_is_ordered: false, metadata: {} } }, fail_on_overflow: false }, fail_on_overflow: false }";
30673067

30683068
assert_contains!(format!("{execution_plan:?}"), expected);
30693069

datafusion/physical-expr/src/equivalence/class.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,10 @@ use std::ops::Deref;
2020
use std::sync::Arc;
2121
use std::vec::IntoIter;
2222

23-
use super::projection::ProjectionTargets;
2423
use super::ProjectionMapping;
2524
use crate::expressions::Literal;
2625
use crate::physical_expr::add_offset_to_expr;
26+
use crate::projection::ProjectionTargets;
2727
use crate::{PhysicalExpr, PhysicalExprRef, PhysicalSortExpr, PhysicalSortRequirement};
2828

2929
use datafusion_common::tree_node::{Transformed, TransformedResult, TreeNode};

datafusion/physical-expr/src/equivalence/mod.rs

Lines changed: 4 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,13 @@ use datafusion_physical_expr_common::sort_expr::{LexOrdering, PhysicalSortExpr};
2525

2626
mod class;
2727
mod ordering;
28-
mod projection;
2928
mod properties;
3029

3130
pub use class::{AcrossPartitions, ConstExpr, EquivalenceClass, EquivalenceGroup};
3231
pub use ordering::OrderingEquivalenceClass;
33-
pub use projection::{project_ordering, project_orderings, ProjectionMapping};
32+
// Re-export for backwards compatibility, we recommend importing from
33+
// datafusion_physical_expr::projection instead
34+
pub use crate::projection::{project_ordering, project_orderings, ProjectionMapping};
3435
pub use properties::{
3536
calculate_union, join_equivalence_properties, EquivalenceProperties,
3637
};
@@ -61,7 +62,7 @@ mod tests {
6162

6263
use arrow::compute::SortOptions;
6364
use arrow::datatypes::{DataType, Field, Schema, SchemaRef};
64-
use datafusion_common::{plan_err, Result};
65+
use datafusion_common::Result;
6566
use datafusion_physical_expr_common::sort_expr::PhysicalSortRequirement;
6667

6768
/// Converts a string to a physical sort expression
@@ -95,31 +96,6 @@ mod tests {
9596
sort_expr
9697
}
9798

98-
pub fn output_schema(
99-
mapping: &ProjectionMapping,
100-
input_schema: &Arc<Schema>,
101-
) -> Result<SchemaRef> {
102-
// Calculate output schema:
103-
let mut fields = vec![];
104-
for (source, targets) in mapping.iter() {
105-
let data_type = source.data_type(input_schema)?;
106-
let nullable = source.nullable(input_schema)?;
107-
for (target, _) in targets.iter() {
108-
let Some(column) = target.as_any().downcast_ref::<Column>() else {
109-
return plan_err!("Expects to have column");
110-
};
111-
fields.push(Field::new(column.name(), data_type.clone(), nullable));
112-
}
113-
}
114-
115-
let output_schema = Arc::new(Schema::new_with_metadata(
116-
fields,
117-
input_schema.metadata().clone(),
118-
));
119-
120-
Ok(output_schema)
121-
}
122-
12399
// Generate a schema which consists of 8 columns (a, b, c, d, e, f, g, h)
124100
pub fn create_test_schema() -> Result<SchemaRef> {
125101
let a = Field::new("a", DataType::Int32, true);

datafusion/physical-expr/src/equivalence/properties/dependency.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -387,11 +387,11 @@ mod tests {
387387

388388
use super::*;
389389
use crate::equivalence::tests::{
390-
convert_to_sort_reqs, create_test_params, create_test_schema, output_schema,
391-
parse_sort_expr,
390+
convert_to_sort_reqs, create_test_params, create_test_schema, parse_sort_expr,
392391
};
393392
use crate::equivalence::{convert_to_sort_exprs, ProjectionMapping};
394393
use crate::expressions::{col, BinaryExpr, CastExpr, Column};
394+
use crate::projection::tests::output_schema;
395395
use crate::{ConstExpr, EquivalenceProperties, ScalarFunctionExpr};
396396

397397
use arrow::compute::SortOptions;

datafusion/physical-expr/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ pub mod intervals;
3737
mod partitioning;
3838
mod physical_expr;
3939
pub mod planner;
40+
pub mod projection;
4041
mod scalar_function;
4142
pub mod simplifier;
4243
pub mod statistics;

0 commit comments

Comments
 (0)