Skip to content

Commit fe8af19

Browse files
committed
Change: in ConstEvaluator::can_evaluate, Expr::Cast / Expr::TryCast now early-return for non-Struct targets, skipping struct-specific checks and avoiding unnecessary get_type(&DFSchema::empty())
1 parent 7b5b2a9 commit fe8af19

1 file changed

Lines changed: 26 additions & 0 deletions

File tree

datafusion/optimizer/src/simplify_expressions/expr_simplifier.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -648,6 +648,12 @@ impl ConstEvaluator {
648648
}
649649
Expr::Cast(Cast { expr, data_type })
650650
| Expr::TryCast(TryCast { expr, data_type }) => {
651+
// Fast path: only struct targets need struct-specific foldability checks.
652+
// For non-struct casts, avoid deriving the source type from an empty schema.
653+
if !matches!(data_type, DataType::Struct(_)) {
654+
return true;
655+
}
656+
651657
if let (
652658
Ok(DataType::Struct(source_fields)),
653659
DataType::Struct(target_fields),
@@ -5339,4 +5345,24 @@ mod tests {
53395345
"Struct cast with empty (0-row) array should remain unchanged"
53405346
);
53415347
}
5348+
5349+
#[test]
5350+
fn test_cast_heavy_non_struct_chain_foldable() {
5351+
// Exercise a cast-heavy, non-struct simplification path to protect against
5352+
// planner regressions in cast eligibility checks.
5353+
let expr = (0..64).fold(Expr::Literal(ScalarValue::Int32(Some(7)), None), |acc, i| {
5354+
let target_type = if i % 2 == 0 {
5355+
DataType::Int64
5356+
} else {
5357+
DataType::Int32
5358+
};
5359+
Expr::Cast(Cast::new(Box::new(acc), target_type))
5360+
});
5361+
5362+
let simplifier =
5363+
ExprSimplifier::new(SimplifyContext::default().with_schema(test_schema()));
5364+
let result = simplifier.simplify(expr).unwrap();
5365+
5366+
assert_eq!(result, Expr::Literal(ScalarValue::Int32(Some(7)), None));
5367+
}
53425368
}

0 commit comments

Comments
 (0)