Skip to content

Commit c7ba5c7

Browse files
adriangbclaude
andcommitted
Add preferred_ordering field to TableScan
This commit adds a new optional field `preferred_ordering` to the `TableScan` logical plan node to support sort pushdown optimizations. Changes include: - Add `preferred_ordering: Option<Vec<SortExpr>>` field to `TableScan` struct - Add `try_new_with_preferred_ordering` constructor method - Update all `TableScan` constructors throughout the codebase to include the new field - Update `Debug`, `PartialEq`, `Hash`, and `PartialOrd` implementations - Update pattern matching in optimizer and other modules The preferred_ordering field is currently not used by any optimization rules but provides the foundation for future sort pushdown implementations. This is part 2 of 2 PRs split from apache#17273 as requested in apache#17273 (comment) 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
1 parent b27fedc commit c7ba5c7

File tree

5 files changed

+32
-1
lines changed

5 files changed

+32
-1
lines changed

datafusion/expr/src/logical_plan/plan.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2608,6 +2608,8 @@ pub struct TableScan {
26082608
pub filters: Vec<Expr>,
26092609
/// Optional number of rows to read
26102610
pub fetch: Option<usize>,
2611+
/// Optional preferred ordering for the scan
2612+
pub preferred_ordering: Option<Vec<SortExpr>>,
26112613
}
26122614

26132615
impl Debug for TableScan {
@@ -2619,6 +2621,7 @@ impl Debug for TableScan {
26192621
.field("projected_schema", &self.projected_schema)
26202622
.field("filters", &self.filters)
26212623
.field("fetch", &self.fetch)
2624+
.field("preferred_ordering", &self.preferred_ordering)
26222625
.finish_non_exhaustive()
26232626
}
26242627
}
@@ -2630,6 +2633,7 @@ impl PartialEq for TableScan {
26302633
&& self.projected_schema == other.projected_schema
26312634
&& self.filters == other.filters
26322635
&& self.fetch == other.fetch
2636+
&& self.preferred_ordering == other.preferred_ordering
26332637
}
26342638
}
26352639

@@ -2649,18 +2653,22 @@ impl PartialOrd for TableScan {
26492653
pub filters: &'a Vec<Expr>,
26502654
/// Optional number of rows to read
26512655
pub fetch: &'a Option<usize>,
2656+
/// Optional preferred ordering for the scan
2657+
pub preferred_ordering: &'a Option<Vec<SortExpr>>,
26522658
}
26532659
let comparable_self = ComparableTableScan {
26542660
table_name: &self.table_name,
26552661
projection: &self.projection,
26562662
filters: &self.filters,
26572663
fetch: &self.fetch,
2664+
preferred_ordering: &self.preferred_ordering,
26582665
};
26592666
let comparable_other = ComparableTableScan {
26602667
table_name: &other.table_name,
26612668
projection: &other.projection,
26622669
filters: &other.filters,
26632670
fetch: &other.fetch,
2671+
preferred_ordering: &other.preferred_ordering,
26642672
};
26652673
comparable_self
26662674
.partial_cmp(&comparable_other)
@@ -2676,6 +2684,7 @@ impl Hash for TableScan {
26762684
self.projected_schema.hash(state);
26772685
self.filters.hash(state);
26782686
self.fetch.hash(state);
2687+
self.preferred_ordering.hash(state);
26792688
}
26802689
}
26812690

@@ -2729,8 +2738,22 @@ impl TableScan {
27292738
projected_schema,
27302739
filters,
27312740
fetch,
2741+
preferred_ordering: None,
27322742
})
27332743
}
2744+
2745+
pub fn try_new_with_preferred_ordering(
2746+
table_name: impl Into<TableReference>,
2747+
table_source: Arc<dyn TableSource>,
2748+
projection: Option<Vec<usize>>,
2749+
filters: Vec<Expr>,
2750+
fetch: Option<usize>,
2751+
preferred_ordering: Option<Vec<SortExpr>>,
2752+
) -> Result<Self> {
2753+
let mut table_scan = Self::try_new(table_name, table_source, projection, filters, fetch)?;
2754+
table_scan.preferred_ordering = preferred_ordering;
2755+
Ok(table_scan)
2756+
}
27342757
}
27352758

27362759
// Repartition the plan based on a partitioning scheme.
@@ -4823,6 +4846,7 @@ mod tests {
48234846
projected_schema: Arc::clone(&schema),
48244847
filters: vec![],
48254848
fetch: None,
4849+
preferred_ordering: None,
48264850
}));
48274851
let col = schema.field_names()[0].clone();
48284852

@@ -4853,6 +4877,7 @@ mod tests {
48534877
projected_schema: Arc::clone(&unique_schema),
48544878
filters: vec![],
48554879
fetch: None,
4880+
preferred_ordering: None,
48564881
}));
48574882
let col = schema.field_names()[0].clone();
48584883

datafusion/expr/src/logical_plan/tree_node.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -599,6 +599,7 @@ impl LogicalPlan {
599599
projected_schema,
600600
filters,
601601
fetch,
602+
preferred_ordering,
602603
}) => filters.map_elements(f)?.update_data(|filters| {
603604
LogicalPlan::TableScan(TableScan {
604605
table_name,
@@ -607,6 +608,7 @@ impl LogicalPlan {
607608
projected_schema,
608609
filters,
609610
fetch,
611+
preferred_ordering,
610612
})
611613
}),
612614
LogicalPlan::Distinct(Distinct::On(DistinctOn {

datafusion/optimizer/src/optimize_projections/mod.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,7 @@ fn optimize_projections(
260260
filters,
261261
fetch,
262262
projected_schema: _,
263+
preferred_ordering,
263264
} = table_scan;
264265

265266
// Get indices referred to in the original (schema with all fields)
@@ -268,12 +269,13 @@ fn optimize_projections(
268269
Some(projection) => indices.into_mapped_indices(|idx| projection[idx]),
269270
None => indices.into_inner(),
270271
};
271-
return TableScan::try_new(
272+
return TableScan::try_new_with_preferred_ordering(
272273
table_name,
273274
source,
274275
Some(projection),
275276
filters,
276277
fetch,
278+
preferred_ordering,
277279
)
278280
.map(LogicalPlan::TableScan)
279281
.map(Transformed::yes);

datafusion/optimizer/src/push_down_filter.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3123,6 +3123,7 @@ mod tests {
31233123
projection,
31243124
source: Arc::new(test_provider),
31253125
fetch: None,
3126+
preferred_ordering: None,
31263127
});
31273128

31283129
Ok(LogicalPlanBuilder::from(table_scan))

datafusion/proto/src/logical_plan/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,7 @@ fn from_table_source(
271271
projected_schema,
272272
filters: vec![],
273273
fetch: None,
274+
preferred_ordering: None,
274275
});
275276

276277
LogicalPlanNode::try_from_logical_plan(&r, extension_codec)

0 commit comments

Comments
 (0)