You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Currently when you pass a pruning predicate where the predicate has a different type as the targeted column it will not prune it, even though in theory the value is castable to the target column type.
The predicate looks like this: "month_id = '202502' AND date_id = '20250226'"
However the columns are int column not utf8. So in theory these string values can be casted to int but I don't believe this is happening. Is this something that should be added
This is our rust code btw
// delta-rs/crates/core/src/delta_datafusion/mod.rs
let pruning_predicate = PruningPredicate::try_new(predicate.clone(), logical_schema.clone())?;
let files_to_prune = pruning_predicate.prune(self.snapshot)?;
Is actually coerced so that it does string comparison rather than integer comparison (note the predicate in the plan below is CAST(foo.i AS Utf8) = Utf8("2024") rather than `foo.i = CAST("2024" as Utf8)
DataFusion CLI v46.0.0
> create table foo(i int) as values (1), (2), (3);
0 row(s) fetched.
Elapsed 0.033 seconds.
> explain select i from foo where i = '2024';
+---------------+-------------------------------------------------------+
| plan_type | plan |
+---------------+-------------------------------------------------------+
| logical_plan | Filter: CAST(foo.i AS Utf8) = Utf8("2024") |
| | TableScan: foo projection=[i] |
| physical_plan | CoalesceBatchesExec: target_batch_size=8192 |
| | FilterExec: CAST(i@0 AS Utf8) = 2024 |
| | DataSourceExec: partitions=1, partition_sizes=[1] |
| | |
+---------------+-------------------------------------------------------+
Activity
alamb commentedon Feb 28, 2025
I think the conclusion is that PruningPredicaate expects a properly coerced expression already
You can use
SessionContext::create_physical_exprto automatically perform coercsion as shown in this exampledatafusion/datafusion-examples/examples/expr_api.rs
Lines 540 to 543 in 5e49094
There are a bunch of other examples there about how to apply coercion
ion-elgreco commentedon Feb 28, 2025
@alamb this is actually already done like that, but it still doesn't prune properly:
.map(|expr| context.create_physical_expr(expr, &df_schema).unwrap());https://github.com/delta-io/delta-rs/blob/main/crates%2Fcore%2Fsrc%2Fdelta_datafusion%2Fmod.rs#L547-L550
alamb commentedon Feb 28, 2025
🤔 What are the coerced expressions?
If it is like this:
That is not going to prune because the cast is happening on
month_idThe predicate needs to be
This is done in this analyzer pass: https://github.com/apache/datafusion/blob/main/datafusion/optimizer/src/unwrap_cast_in_comparison.rs
Maybe we should do the same thing in
create_physical_exprtoo 🤔ion-elgreco commentedon Mar 1, 2025
It's like cast(month_id, 'utf8') = '202502', see below:
alamb commentedon Mar 3, 2025
So it seems like it would be a valuable thing to apply the type coercion rewriter in the expr simplifier then.
datafusion/datafusion/optimizer/src/unwrap_cast_in_comparison.rs
Lines 115 to 125 in 57a1221
I'll file a ticket.
[-]Should pruningpredicate coerce?[/-][+]Should `PruningPredicate` coerce?[/+]alamb commentedon Mar 3, 2025
Filed
SessionContext::create_physical_exprdoes not unwrap casts (and thus is not always optimal) #14987ion-elgreco commentedon Mar 3, 2025
@alamb thanks! 🙏
alamb commentedon Mar 5, 2025
UnwrapCastInComparisonintoSimplifier#15012I found that a predicate like this:
Is actually coerced so that it does string comparison rather than integer comparison (note the predicate in the plan below is
CAST(foo.i AS Utf8) = Utf8("2024")rather than `foo.i = CAST("2024" as Utf8)alamb commentedon Mar 5, 2025
So in other words, I think #15012 is necessary, but not sufficient, to fix this issue
Update: PR to add some tests:
alamb commentedon Mar 5, 2025
Also filed a ticket for unwrapping that particular comparison expression