Skip to content

Commit 4fd295d

Browse files
Preserve projection for inline scan (#15825)
* Preserve projection for inline scan * fix --------- Co-authored-by: Vadim Piven <[email protected]>
1 parent 5d98d2c commit 4fd295d

File tree

2 files changed

+56
-3
lines changed

2 files changed

+56
-3
lines changed

datafusion/core/tests/execution/logical_plan.rs

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,19 @@
1919
//! create them and depend on them. Test executable semantics of logical plans.
2020
2121
use arrow::array::Int64Array;
22-
use arrow::datatypes::{DataType, Field};
22+
use arrow::datatypes::{DataType, Field, Schema};
23+
use datafusion::datasource::{provider_as_source, ViewTable};
2324
use datafusion::execution::session_state::SessionStateBuilder;
24-
use datafusion_common::{Column, DFSchema, Result, ScalarValue, Spans};
25+
use datafusion_common::{Column, DFSchema, DFSchemaRef, Result, ScalarValue, Spans};
2526
use datafusion_execution::TaskContext;
2627
use datafusion_expr::expr::{AggregateFunction, AggregateFunctionParams};
2728
use datafusion_expr::logical_plan::{LogicalPlan, Values};
28-
use datafusion_expr::{Aggregate, AggregateUDF, Expr};
29+
use datafusion_expr::{
30+
Aggregate, AggregateUDF, EmptyRelation, Expr, LogicalPlanBuilder, UNNAMED_TABLE,
31+
};
2932
use datafusion_functions_aggregate::count::Count;
3033
use datafusion_physical_plan::collect;
34+
use insta::assert_snapshot;
3135
use std::collections::HashMap;
3236
use std::fmt::Debug;
3337
use std::ops::Deref;
@@ -96,3 +100,37 @@ where
96100
};
97101
element
98102
}
103+
104+
#[test]
105+
fn inline_scan_projection_test() -> Result<()> {
106+
let name = UNNAMED_TABLE;
107+
let column = "a";
108+
109+
let schema = Schema::new(vec![
110+
Field::new("a", DataType::Int32, false),
111+
Field::new("b", DataType::Int32, false),
112+
]);
113+
let projection = vec![schema.index_of(column)?];
114+
115+
let provider = ViewTable::new(
116+
LogicalPlan::EmptyRelation(EmptyRelation {
117+
produce_one_row: false,
118+
schema: DFSchemaRef::new(DFSchema::try_from(schema)?),
119+
}),
120+
None,
121+
);
122+
let source = provider_as_source(Arc::new(provider));
123+
124+
let plan = LogicalPlanBuilder::scan(name, source, Some(projection))?.build()?;
125+
126+
assert_snapshot!(
127+
format!("{plan}"),
128+
@r"
129+
SubqueryAlias: ?table?
130+
Projection: a
131+
EmptyRelation
132+
"
133+
);
134+
135+
Ok(())
136+
}

datafusion/expr/src/logical_plan/builder.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -501,6 +501,21 @@ impl LogicalPlanBuilder {
501501
if table_scan.filters.is_empty() {
502502
if let Some(p) = table_scan.source.get_logical_plan() {
503503
let sub_plan = p.into_owned();
504+
505+
if let Some(proj) = table_scan.projection {
506+
let projection_exprs = proj
507+
.into_iter()
508+
.map(|i| {
509+
Expr::Column(Column::from(
510+
sub_plan.schema().qualified_field(i),
511+
))
512+
})
513+
.collect::<Vec<_>>();
514+
return Self::new(sub_plan)
515+
.project(projection_exprs)?
516+
.alias(table_scan.table_name);
517+
}
518+
504519
// Ensures that the reference to the inlined table remains the
505520
// same, meaning we don't have to change any of the parent nodes
506521
// that reference this table.

0 commit comments

Comments
 (0)