You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@datafusion.apache.org by gi...@apache.org on 2026/04/15 23:09:55 UTC
(datafusion) branch main updated: Remove `as_any` on the `PhysicalExpr` trait (#21573)
This is an automated email from the ASF dual-hosted git repository.
github-bot pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/datafusion.git
The following commit(s) were added to refs/heads/main by this push:
new dc6142ea49 Remove `as_any` on the `PhysicalExpr` trait (#21573)
dc6142ea49 is described below
commit dc6142ea4927e0853cf3a671e7055c41a1cad659
Author: Tim Saucer <ti...@gmail.com>
AuthorDate: Wed Apr 15 19:07:43 2026 -0400
Remove `as_any` on the `PhysicalExpr` trait (#21573)
## Which issue does this PR close?
- Addresses part of https://github.com/apache/datafusion/issues/21572
## Rationale for this change
This PR reduces the amount of boilerplate code that users need to write
for Physical Expressions.
## What changes are included in this PR?
Now that we have [trait
upcasting](https://blog.rust-lang.org/2025/04/03/Rust-1.86.0/) since
rust 1.86, we no longer need every implementation of this trait to have
the as_any function that returns &self. This PR makes Any an supertrait
and makes the appropriate casts when necessary.
## Are these changes tested?
Existing unit tests.
## Are there any user-facing changes?
Yes, the users simply need to remove the as_any function. The upgrade
guide is updated.
---------
Co-authored-by: Claude Opus 4.6 (1M context) <no...@anthropic.com>
---
.../custom_data_source/custom_file_casts.rs | 2 +-
.../examples/data_io/json_shredding.rs | 10 +-
.../examples/proto/expression_deduplication.rs | 1 -
datafusion/core/src/datasource/mod.rs | 2 +-
.../core/tests/fuzz_cases/equivalence/utils.rs | 10 +-
.../fuzz_cases/sort_preserving_repartition_fuzz.rs | 8 +-
datafusion/core/tests/parquet/expr_adapter.rs | 2 +-
.../tests/physical_optimizer/filter_pushdown.rs | 2 +-
.../tests/physical_optimizer/join_selection.rs | 1 -
.../replace_with_order_preserving_variants.rs | 4 +-
datafusion/datasource-parquet/src/metadata.rs | 16 +--
datafusion/datasource-parquet/src/opener.rs | 6 +-
datafusion/datasource-parquet/src/row_filter.rs | 15 +-
.../datasource-parquet/src/supported_predicates.rs | 7 +-
datafusion/datasource/src/file_scan_config/mod.rs | 13 +-
.../src/file_scan_config/sort_pushdown.rs | 4 +-
datafusion/datasource/src/projection.rs | 6 +-
datafusion/datasource/src/statistics.rs | 2 +-
datafusion/execution/src/cache/cache_unit.rs | 4 -
datafusion/ffi/src/physical_expr/mod.rs | 7 +-
datafusion/functions-aggregate/src/count.rs | 7 +-
datafusion/functions-aggregate/src/min_max.rs | 5 +-
datafusion/functions-aggregate/src/nth_value.rs | 1 -
datafusion/functions-aggregate/src/string_agg.rs | 2 +-
datafusion/functions-window/src/lead_lag.rs | 3 +-
datafusion/functions-window/src/utils.rs | 1 -
.../physical-expr-adapter/src/schema_rewriter.rs | 30 ++--
.../physical-expr-common/src/physical_expr.rs | 32 +++--
datafusion/physical-expr-common/src/sort_expr.rs | 1 -
datafusion/physical-expr/src/analysis.rs | 4 +-
.../physical-expr/src/async_scalar_function.rs | 12 +-
datafusion/physical-expr/src/equivalence/class.rs | 11 +-
.../src/equivalence/properties/mod.rs | 18 ++-
datafusion/physical-expr/src/expressions/binary.rs | 12 +-
datafusion/physical-expr/src/expressions/case.rs | 23 ++-
.../expressions/case/literal_lookup_table/mod.rs | 6 +-
datafusion/physical-expr/src/expressions/cast.rs | 6 -
datafusion/physical-expr/src/expressions/column.rs | 8 +-
.../src/expressions/dynamic_filters.rs | 8 +-
.../physical-expr/src/expressions/in_list.rs | 6 -
.../physical-expr/src/expressions/is_not_null.rs | 7 +-
.../physical-expr/src/expressions/is_null.rs | 7 +-
datafusion/physical-expr/src/expressions/like.rs | 6 +-
.../physical-expr/src/expressions/literal.rs | 6 -
.../physical-expr/src/expressions/negative.rs | 6 -
datafusion/physical-expr/src/expressions/no_op.rs | 6 -
datafusion/physical-expr/src/expressions/not.rs | 6 -
.../physical-expr/src/expressions/try_cast.rs | 6 -
.../src/expressions/unknown_column.rs | 6 -
.../physical-expr/src/intervals/cp_solver.rs | 19 +--
datafusion/physical-expr/src/intervals/utils.rs | 11 +-
datafusion/physical-expr/src/physical_expr.rs | 7 +-
datafusion/physical-expr/src/planner.rs | 1 -
datafusion/physical-expr/src/projection.rs | 35 ++---
datafusion/physical-expr/src/scalar_function.rs | 14 +-
.../src/simplifier/const_evaluator.rs | 15 +-
datafusion/physical-expr/src/simplifier/mod.rs | 31 ++---
datafusion/physical-expr/src/simplifier/not.rs | 10 +-
.../physical-expr/src/simplifier/unwrap_cast.rs | 109 +++++----------
.../physical-expr/src/statistics/stats_solver.rs | 2 +-
datafusion/physical-expr/src/utils/guarantee.rs | 28 ++--
datafusion/physical-expr/src/utils/mod.rs | 23 ++-
.../src/enforce_sorting/sort_pushdown.rs | 14 +-
.../physical-optimizer/src/projection_pushdown.rs | 8 +-
.../physical-optimizer/src/topk_aggregation.rs | 5 +-
datafusion/physical-plan/src/aggregates/mod.rs | 8 +-
datafusion/physical-plan/src/async_func.rs | 3 +-
datafusion/physical-plan/src/column_rewriter.rs | 2 +-
datafusion/physical-plan/src/filter.rs | 6 +-
datafusion/physical-plan/src/filter_pushdown.rs | 2 +-
.../physical-plan/src/joins/hash_join/exec.rs | 10 +-
.../src/joins/hash_join/partitioned_hash_eval.rs | 10 +-
.../physical-plan/src/joins/stream_join_utils.rs | 2 +-
datafusion/physical-plan/src/joins/utils.rs | 5 +-
.../physical-plan/src/operator_statistics/mod.rs | 4 +-
datafusion/physical-plan/src/projection.rs | 23 ++-
datafusion/proto/src/physical_plan/to_proto.rs | 5 +-
.../proto/tests/cases/roundtrip_physical_plan.rs | 20 +--
datafusion/pruning/src/pruning_predicate.rs | 58 +++-----
docs/source/library-user-guide/upgrading/54.0.0.md | 155 ++-------------------
80 files changed, 295 insertions(+), 724 deletions(-)
diff --git a/datafusion-examples/examples/custom_data_source/custom_file_casts.rs b/datafusion-examples/examples/custom_data_source/custom_file_casts.rs
index 6db0cda565..71addc6d1b 100644
--- a/datafusion-examples/examples/custom_data_source/custom_file_casts.rs
+++ b/datafusion-examples/examples/custom_data_source/custom_file_casts.rs
@@ -185,7 +185,7 @@ impl PhysicalExprAdapter for CustomCastsPhysicalExprAdapter {
// kernel / expression. For example, DataFusion Comet has a custom cast
// kernel in its native Spark expression implementation.
expr.transform(|expr| {
- if let Some(cast) = expr.as_any().downcast_ref::<CastExpr>() {
+ if let Some(cast) = expr.downcast_ref::<CastExpr>() {
let input_data_type =
cast.expr().data_type(&self.physical_file_schema)?;
let output_data_type = cast.target_field().data_type();
diff --git a/datafusion-examples/examples/data_io/json_shredding.rs b/datafusion-examples/examples/data_io/json_shredding.rs
index a6d328a396..72fbb56773 100644
--- a/datafusion-examples/examples/data_io/json_shredding.rs
+++ b/datafusion-examples/examples/data_io/json_shredding.rs
@@ -311,20 +311,16 @@ impl ShreddedJsonRewriter {
expr: Arc<dyn PhysicalExpr>,
physical_file_schema: &Schema,
) -> Result<Transformed<Arc<dyn PhysicalExpr>>> {
- if let Some(func) = expr.as_any().downcast_ref::<ScalarFunctionExpr>()
+ if let Some(func) = expr.downcast_ref::<ScalarFunctionExpr>()
&& func.name() == "json_get_str"
&& func.args().len() == 2
{
// Get the key from the first argument
- if let Some(literal) = func.args()[0]
- .as_any()
- .downcast_ref::<expressions::Literal>()
+ if let Some(literal) = func.args()[0].downcast_ref::<expressions::Literal>()
&& let ScalarValue::Utf8(Some(field_name)) = literal.value()
{
// Get the column from the second argument
- if let Some(column) = func.args()[1]
- .as_any()
- .downcast_ref::<expressions::Column>()
+ if let Some(column) = func.args()[1].downcast_ref::<expressions::Column>()
{
let column_name = column.name();
// Check if there's a flat column with underscore prefix
diff --git a/datafusion-examples/examples/proto/expression_deduplication.rs b/datafusion-examples/examples/proto/expression_deduplication.rs
index 9f3940c82d..ec076b5249 100644
--- a/datafusion-examples/examples/proto/expression_deduplication.rs
+++ b/datafusion-examples/examples/proto/expression_deduplication.rs
@@ -129,7 +129,6 @@ pub async fn expression_deduplication() -> Result<()> {
};
let predicate = Arc::clone(filter_exec.predicate());
let binary_expr = predicate
- .as_any()
.downcast_ref::<BinaryExpr>()
.expect("Predicate is not a BinaryExpr");
let left = &binary_expr.left();
diff --git a/datafusion/core/src/datasource/mod.rs b/datafusion/core/src/datasource/mod.rs
index 55bd7851ee..3fad65ae0d 100644
--- a/datafusion/core/src/datasource/mod.rs
+++ b/datafusion/core/src/datasource/mod.rs
@@ -167,7 +167,7 @@ mod tests {
impl PhysicalExprAdapter for TestPhysicalExprAdapter {
fn rewrite(&self, expr: Arc<dyn PhysicalExpr>) -> Result<Arc<dyn PhysicalExpr>> {
expr.transform(|e| {
- if let Some(column) = e.as_any().downcast_ref::<Column>() {
+ if let Some(column) = e.downcast_ref::<Column>() {
// If column is "extra_column" and missing from physical schema, inject "foo"
if column.name() == "extra_column"
&& self.physical_file_schema.index_of("extra_column").is_err()
diff --git a/datafusion/core/tests/fuzz_cases/equivalence/utils.rs b/datafusion/core/tests/fuzz_cases/equivalence/utils.rs
index e8e4ea8b62..8350cafb21 100644
--- a/datafusion/core/tests/fuzz_cases/equivalence/utils.rs
+++ b/datafusion/core/tests/fuzz_cases/equivalence/utils.rs
@@ -49,7 +49,7 @@ pub fn output_schema(
let data_type = source.data_type(input_schema)?;
let nullable = source.nullable(input_schema)?;
for (target, _) in targets.iter() {
- let Some(column) = target.as_any().downcast_ref::<Column>() else {
+ let Some(column) = target.downcast_ref::<Column>() else {
return plan_err!("Expects to have column");
};
fields.push(Field::new(column.name(), data_type.clone(), nullable));
@@ -282,7 +282,7 @@ fn get_representative_arr(
schema: SchemaRef,
) -> Option<ArrayRef> {
for expr in eq_group.iter() {
- let col = expr.as_any().downcast_ref::<Column>().unwrap();
+ let col = expr.downcast_ref::<Column>().unwrap();
let (idx, _field) = schema.column_with_name(col.name()).unwrap();
if let Some(res) = &existing_vec[idx] {
return Some(Arc::clone(res));
@@ -370,7 +370,7 @@ pub fn generate_table_for_eq_properties(
// Fill constant columns
for constant in eq_properties.constants() {
- let col = constant.expr.as_any().downcast_ref::<Column>().unwrap();
+ let col = constant.expr.downcast_ref::<Column>().unwrap();
let (idx, _field) = schema.column_with_name(col.name()).unwrap();
let arr =
Arc::new(Float64Array::from_iter_values(vec![0 as f64; n_elem])) as ArrayRef;
@@ -382,7 +382,7 @@ pub fn generate_table_for_eq_properties(
let (sort_columns, indices): (Vec<_>, Vec<_>) = ordering
.iter()
.map(|PhysicalSortExpr { expr, options }| {
- let col = expr.as_any().downcast_ref::<Column>().unwrap();
+ let col = expr.downcast_ref::<Column>().unwrap();
let (idx, _field) = schema.column_with_name(col.name()).unwrap();
let arr = generate_random_array(n_elem, n_distinct);
(
@@ -408,7 +408,7 @@ pub fn generate_table_for_eq_properties(
.unwrap_or_else(|| generate_random_array(n_elem, n_distinct));
for expr in eq_group.iter() {
- let col = expr.as_any().downcast_ref::<Column>().unwrap();
+ let col = expr.downcast_ref::<Column>().unwrap();
let (idx, _field) = schema.column_with_name(col.name()).unwrap();
schema_vec[idx] = Some(Arc::clone(&representative_array));
}
diff --git a/datafusion/core/tests/fuzz_cases/sort_preserving_repartition_fuzz.rs b/datafusion/core/tests/fuzz_cases/sort_preserving_repartition_fuzz.rs
index 8f3b8ea053..a1f38f161d 100644
--- a/datafusion/core/tests/fuzz_cases/sort_preserving_repartition_fuzz.rs
+++ b/datafusion/core/tests/fuzz_cases/sort_preserving_repartition_fuzz.rs
@@ -118,7 +118,7 @@ mod sp_repartition_fuzz_tests {
schema: SchemaRef,
) -> Option<ArrayRef> {
for expr in eq_group.iter() {
- let col = expr.as_any().downcast_ref::<Column>().unwrap();
+ let col = expr.downcast_ref::<Column>().unwrap();
let (idx, _field) = schema.column_with_name(col.name()).unwrap();
if let Some(res) = &existing_vec[idx] {
return Some(res.clone());
@@ -149,7 +149,7 @@ mod sp_repartition_fuzz_tests {
// Fill constant columns
for constant in eq_properties.constants() {
- let col = constant.expr.as_any().downcast_ref::<Column>().unwrap();
+ let col = constant.expr.downcast_ref::<Column>().unwrap();
let (idx, _field) = schema.column_with_name(col.name()).unwrap();
let arr =
Arc::new(UInt64Array::from_iter_values(vec![0; n_elem])) as ArrayRef;
@@ -161,7 +161,7 @@ mod sp_repartition_fuzz_tests {
let (sort_columns, indices): (Vec<_>, Vec<_>) = ordering
.iter()
.map(|PhysicalSortExpr { expr, options }| {
- let col = expr.as_any().downcast_ref::<Column>().unwrap();
+ let col = expr.downcast_ref::<Column>().unwrap();
let (idx, _field) = schema.column_with_name(col.name()).unwrap();
let arr = generate_random_array(n_elem, n_distinct);
(
@@ -187,7 +187,7 @@ mod sp_repartition_fuzz_tests {
.unwrap_or_else(|| generate_random_array(n_elem, n_distinct));
for expr in eq_group.iter() {
- let col = expr.as_any().downcast_ref::<Column>().unwrap();
+ let col = expr.downcast_ref::<Column>().unwrap();
let (idx, _field) = schema.column_with_name(col.name()).unwrap();
schema_vec[idx] = Some(representative_array.clone());
}
diff --git a/datafusion/core/tests/parquet/expr_adapter.rs b/datafusion/core/tests/parquet/expr_adapter.rs
index cf32efbd70..fd70d74a91 100644
--- a/datafusion/core/tests/parquet/expr_adapter.rs
+++ b/datafusion/core/tests/parquet/expr_adapter.rs
@@ -490,7 +490,7 @@ impl PhysicalExprAdapter for CustomPhysicalExprAdapter {
fn rewrite(&self, mut expr: Arc<dyn PhysicalExpr>) -> Result<Arc<dyn PhysicalExpr>> {
expr = expr
.transform(|expr| {
- if let Some(column) = expr.as_any().downcast_ref::<Column>() {
+ if let Some(column) = expr.downcast_ref::<Column>() {
let field_name = column.name();
if self
.physical_file_schema
diff --git a/datafusion/core/tests/physical_optimizer/filter_pushdown.rs b/datafusion/core/tests/physical_optimizer/filter_pushdown.rs
index d058e44a85..4fa7b637ca 100644
--- a/datafusion/core/tests/physical_optimizer/filter_pushdown.rs
+++ b/datafusion/core/tests/physical_optimizer/filter_pushdown.rs
@@ -2959,7 +2959,7 @@ async fn test_discover_dynamic_filters_via_expressions_api() {
// Check expressions from this node using apply_expressions
let _ = plan.apply_expressions(&mut |expr| {
- if let Some(_df) = expr.as_any().downcast_ref::<DynamicFilterPhysicalExpr>() {
+ if let Some(_df) = expr.downcast_ref::<DynamicFilterPhysicalExpr>() {
count += 1;
}
Ok(TreeNodeRecursion::Continue)
diff --git a/datafusion/core/tests/physical_optimizer/join_selection.rs b/datafusion/core/tests/physical_optimizer/join_selection.rs
index ee22e7b616..050baa9e79 100644
--- a/datafusion/core/tests/physical_optimizer/join_selection.rs
+++ b/datafusion/core/tests/physical_optimizer/join_selection.rs
@@ -759,7 +759,6 @@ async fn test_hash_join_swap_on_joins_with_projections(
fn assert_col_expr(expr: &Arc<dyn PhysicalExpr>, name: &str, index: usize) {
let col = expr
- .as_any()
.downcast_ref::<Column>()
.expect("Projection items should be Column expression");
assert_eq!(col.name(), name);
diff --git a/datafusion/core/tests/physical_optimizer/replace_with_order_preserving_variants.rs b/datafusion/core/tests/physical_optimizer/replace_with_order_preserving_variants.rs
index cdfed50116..601667ea02 100644
--- a/datafusion/core/tests/physical_optimizer/replace_with_order_preserving_variants.rs
+++ b/datafusion/core/tests/physical_optimizer/replace_with_order_preserving_variants.rs
@@ -1127,8 +1127,8 @@ fn hash_join_exec(
) -> Arc<dyn ExecutionPlan> {
let left_on = col("c", &left.schema()).unwrap();
let right_on = col("c", &right.schema()).unwrap();
- let left_col = left_on.as_any().downcast_ref::<Column>().unwrap();
- let right_col = right_on.as_any().downcast_ref::<Column>().unwrap();
+ let left_col = left_on.downcast_ref::<Column>().unwrap();
+ let right_col = right_on.downcast_ref::<Column>().unwrap();
Arc::new(
HashJoinExec::try_new(
left,
diff --git a/datafusion/datasource-parquet/src/metadata.rs b/datafusion/datasource-parquet/src/metadata.rs
index 86c12b11c0..3d4d051abb 100644
--- a/datafusion/datasource-parquet/src/metadata.rs
+++ b/datafusion/datasource-parquet/src/metadata.rs
@@ -713,17 +713,13 @@ impl FileMetadata for CachedParquetMetaData {
pub(crate) fn sort_expr_to_sorting_column(
sort_expr: &PhysicalSortExpr,
) -> Result<SortingColumn> {
- let column = sort_expr
- .expr
- .as_any()
- .downcast_ref::<Column>()
- .ok_or_else(|| {
- DataFusionError::Plan(format!(
- "Parquet sorting_columns only supports simple column references, \
+ let column = sort_expr.expr.downcast_ref::<Column>().ok_or_else(|| {
+ DataFusionError::Plan(format!(
+ "Parquet sorting_columns only supports simple column references, \
but got expression: {}",
- sort_expr.expr
- ))
- })?;
+ sort_expr.expr
+ ))
+ })?;
let column_idx: i32 = column.index().try_into().map_err(|_| {
DataFusionError::Plan(format!(
diff --git a/datafusion/datasource-parquet/src/opener.rs b/datafusion/datasource-parquet/src/opener.rs
index 1db055880d..6d1c22c0b0 100644
--- a/datafusion/datasource-parquet/src/opener.rs
+++ b/datafusion/datasource-parquet/src/opener.rs
@@ -1916,8 +1916,8 @@ mod test {
.try_map_exprs(|expr| replace_columns_with_literals(expr, &constants))
.unwrap();
let exprs = rewritten.as_ref();
- assert!(exprs[0].expr.as_any().downcast_ref::<Literal>().is_some());
- assert!(exprs[1].expr.as_any().downcast_ref::<Column>().is_some());
+ assert!(exprs[0].expr.downcast_ref::<Literal>().is_some());
+ assert!(exprs[1].expr.downcast_ref::<Column>().is_some());
// Only column `b` should remain in the projection mask
assert_eq!(rewritten.column_indices(), vec![1]);
@@ -1930,7 +1930,7 @@ mod test {
let expr: Arc<dyn PhysicalExpr> = Arc::new(Column::new("a", 0));
let rewritten = replace_columns_with_literals(expr, &constants).unwrap();
- assert!(rewritten.as_any().downcast_ref::<Literal>().is_some());
+ assert!(rewritten.downcast_ref::<Literal>().is_some());
}
async fn count_batches_and_rows(
diff --git a/datafusion/datasource-parquet/src/row_filter.rs b/datafusion/datasource-parquet/src/row_filter.rs
index 67b65321d9..c5c3720558 100644
--- a/datafusion/datasource-parquet/src/row_filter.rs
+++ b/datafusion/datasource-parquet/src/row_filter.rs
@@ -420,10 +420,7 @@ impl TreeNodeVisitor<'_> for PushdownChecker<'_> {
{
let args = func.args();
- if let Some(column) = args
- .first()
- .and_then(|a| a.as_any().downcast_ref::<Column>())
- {
+ if let Some(column) = args.first().and_then(|a| a.downcast_ref::<Column>()) {
// for Map columns, get_field performs a runtime key lookup rather than a
// schema-level field access so the entire Map column must be read,
// we skip the struct field optimization and defer to normal Column traversal
@@ -451,7 +448,7 @@ impl TreeNodeVisitor<'_> for PushdownChecker<'_> {
let field_path = args[1..]
.iter()
.map(|arg| {
- arg.as_any().downcast_ref::<Literal>().and_then(|lit| {
+ arg.downcast_ref::<Literal>().and_then(|lit| {
lit.value().try_as_str().flatten().map(|s| s.to_string())
})
})
@@ -481,7 +478,7 @@ impl TreeNodeVisitor<'_> for PushdownChecker<'_> {
}
}
- if let Some(column) = node.as_any().downcast_ref::<Column>()
+ if let Some(column) = node.downcast_ref::<Column>()
&& let Some(recursion) = self.check_single_column(column.name())
{
return Ok(recursion);
@@ -611,14 +608,12 @@ pub(crate) fn build_projection_read_plan(
// fast path: if every expression is a plain Column reference, skip all
// struct analysis and use root-level projection directly
let exprs = exprs.into_iter().collect::<Vec<_>>();
- let all_plain_columns = exprs
- .iter()
- .all(|e| e.as_any().downcast_ref::<Column>().is_some());
+ let all_plain_columns = exprs.iter().all(|e| e.downcast_ref::<Column>().is_some());
if all_plain_columns {
let mut root_indices: Vec<usize> = exprs
.iter()
- .map(|e| e.as_any().downcast_ref::<Column>().unwrap().index())
+ .map(|e| e.downcast_ref::<Column>().unwrap().index())
.collect();
root_indices.sort_unstable();
root_indices.dedup();
diff --git a/datafusion/datasource-parquet/src/supported_predicates.rs b/datafusion/datasource-parquet/src/supported_predicates.rs
index a205c12dd0..5c6b5f3ec9 100644
--- a/datafusion/datasource-parquet/src/supported_predicates.rs
+++ b/datafusion/datasource-parquet/src/supported_predicates.rs
@@ -70,8 +70,8 @@ impl SupportsListPushdown for dyn PhysicalExpr {
///
/// These checks are universally supported for all column types.
fn is_null_check(expr: &dyn PhysicalExpr) -> bool {
- expr.as_any().downcast_ref::<IsNullExpr>().is_some()
- || expr.as_any().downcast_ref::<IsNotNullExpr>().is_some()
+ expr.downcast_ref::<IsNullExpr>().is_some()
+ || expr.downcast_ref::<IsNotNullExpr>().is_some()
}
/// Checks if an expression is a scalar function registered for list pushdown.
@@ -86,8 +86,7 @@ fn is_supported_scalar_function(expr: &dyn PhysicalExpr) -> bool {
}
fn scalar_function_name(expr: &dyn PhysicalExpr) -> Option<&str> {
- expr.as_any()
- .downcast_ref::<ScalarFunctionExpr>()
+ expr.downcast_ref::<ScalarFunctionExpr>()
.map(ScalarFunctionExpr::name)
}
diff --git a/datafusion/datasource/src/file_scan_config/mod.rs b/datafusion/datasource/src/file_scan_config/mod.rs
index f4e4e0a4de..c1afd35da3 100644
--- a/datafusion/datasource/src/file_scan_config/mod.rs
+++ b/datafusion/datasource/src/file_scan_config/mod.rs
@@ -620,7 +620,7 @@ impl DataSource for FileScanConfig {
.iter()
.map(|proj_expr| {
if let Some(column) =
- proj_expr.expr.as_any().downcast_ref::<Column>()
+ proj_expr.expr.downcast_ref::<Column>()
{
if column.name() == proj_expr.alias {
column.name().to_string()
@@ -1075,7 +1075,7 @@ impl FileScanConfig {
// (e.g. due to unnecessary projections being removed)
reassign_expr_columns(Arc::clone(expr), schema)
.ok()
- .and_then(|expr| match expr.as_any().downcast_ref::<BinaryExpr>() {
+ .and_then(|expr| match expr.downcast_ref::<BinaryExpr>() {
Some(expr) if expr.op() == &Operator::Eq => {
Some((Arc::clone(expr.left()), Arc::clone(expr.right())))
}
@@ -1918,7 +1918,7 @@ mod tests {
for class in eq_group.iter() {
for expr in class.iter() {
- if let Some(col) = expr.as_any().downcast_ref::<Column>() {
+ if let Some(col) = expr.downcast_ref::<Column>() {
assert_ne!(
col.name(),
"c2",
@@ -2350,10 +2350,7 @@ mod tests {
Partitioning::Hash(exprs, num_partitions) => {
assert_eq!(num_partitions, 3);
assert_eq!(exprs.len(), 1);
- assert_eq!(
- exprs[0].as_any().downcast_ref::<Column>().unwrap().name(),
- "date"
- );
+ assert_eq!(exprs[0].downcast_ref::<Column>().unwrap().name(), "date");
}
_ => panic!("Expected Hash partitioning"),
}
@@ -2383,7 +2380,7 @@ mod tests {
assert_eq!(exprs.len(), 2);
let col_names: Vec<_> = exprs
.iter()
- .map(|e| e.as_any().downcast_ref::<Column>().unwrap().name())
+ .map(|e| e.downcast_ref::<Column>().unwrap().name())
.collect();
assert_eq!(col_names, vec!["year", "month"]);
}
diff --git a/datafusion/datasource/src/file_scan_config/sort_pushdown.rs b/datafusion/datasource/src/file_scan_config/sort_pushdown.rs
index db4019071f..af08ed71b9 100644
--- a/datafusion/datasource/src/file_scan_config/sort_pushdown.rs
+++ b/datafusion/datasource/src/file_scan_config/sort_pushdown.rs
@@ -389,7 +389,7 @@ pub(crate) fn ordered_column_indices_from_projection(
projection
.expr_iter()
.map(|e| {
- let index = e.as_any().downcast_ref::<Column>()?.index();
+ let index = e.downcast_ref::<Column>()?.index();
Some(index)
})
.collect::<Option<Vec<usize>>>()
@@ -402,7 +402,7 @@ fn sort_columns_from_physical_sort_exprs_nullable(
) -> Option<Vec<Column>> {
order
.iter()
- .map(|expr| expr.expr.as_any().downcast_ref::<Column>().cloned())
+ .map(|expr| expr.expr.downcast_ref::<Column>().cloned())
.collect()
}
diff --git a/datafusion/datasource/src/projection.rs b/datafusion/datasource/src/projection.rs
index 9a0cb494e4..ac33a96ca8 100644
--- a/datafusion/datasource/src/projection.rs
+++ b/datafusion/datasource/src/projection.rs
@@ -122,7 +122,7 @@ fn inject_partition_columns_into_projection(
let expr = Arc::clone(&projection.expr)
.transform(|expr| {
let original_expr = Arc::clone(&expr);
- if let Some(column) = expr.as_any().downcast_ref::<Column>() {
+ if let Some(column) = expr.downcast_ref::<Column>() {
// Check if this column index corresponds to a partition column
if let Some(pci) = partition_columns
.iter()
@@ -199,7 +199,7 @@ impl SplitProjection {
proj_expr
.expr
.apply(|expr| {
- if let Some(column) = expr.as_any().downcast_ref::<Column>() {
+ if let Some(column) = expr.downcast_ref::<Column>() {
all_columns
.entry(column.index())
.or_insert_with(|| column.name().to_string());
@@ -250,7 +250,7 @@ impl SplitProjection {
let expr = Arc::clone(&proj_expr.expr)
.transform(|expr| {
let original_expr = Arc::clone(&expr);
- if let Some(column) = expr.as_any().downcast_ref::<Column>()
+ if let Some(column) = expr.downcast_ref::<Column>()
&& let Some(new_column) = column_mapping.get(&column.index())
{
return Ok(Transformed::yes(Arc::clone(new_column)));
diff --git a/datafusion/datasource/src/statistics.rs b/datafusion/datasource/src/statistics.rs
index 5835e47bba..e7fef49539 100644
--- a/datafusion/datasource/src/statistics.rs
+++ b/datafusion/datasource/src/statistics.rs
@@ -280,7 +280,7 @@ fn sort_columns_from_physical_sort_exprs(
) -> Option<Vec<&Column>> {
sort_order
.iter()
- .map(|expr| expr.expr.as_any().downcast_ref::<Column>())
+ .map(|expr| expr.expr.downcast_ref::<Column>())
.collect()
}
diff --git a/datafusion/execution/src/cache/cache_unit.rs b/datafusion/execution/src/cache/cache_unit.rs
index 59bb3f0702..49e16ca4b6 100644
--- a/datafusion/execution/src/cache/cache_unit.rs
+++ b/datafusion/execution/src/cache/cache_unit.rs
@@ -185,10 +185,6 @@ mod tests {
}
impl PhysicalExpr for MockExpr {
- fn as_any(&self) -> &dyn std::any::Any {
- self
- }
-
fn data_type(
&self,
_input_schema: &Schema,
diff --git a/datafusion/ffi/src/physical_expr/mod.rs b/datafusion/ffi/src/physical_expr/mod.rs
index 189a1e4782..a82adffd85 100644
--- a/datafusion/ffi/src/physical_expr/mod.rs
+++ b/datafusion/ffi/src/physical_expr/mod.rs
@@ -18,7 +18,6 @@
pub(crate) mod partitioning;
pub(crate) mod sort;
-use std::any::Any;
use std::ffi::c_void;
use std::fmt::{Display, Formatter};
use std::hash::{DefaultHasher, Hash, Hasher};
@@ -448,7 +447,7 @@ impl Drop for FFI_PhysicalExpr {
impl From<Arc<dyn PhysicalExpr>> for FFI_PhysicalExpr {
/// Creates a new [`FFI_PhysicalExpr`].
fn from(expr: Arc<dyn PhysicalExpr>) -> Self {
- if let Some(expr) = expr.as_any().downcast_ref::<ForeignPhysicalExpr>() {
+ if let Some(expr) = expr.downcast_ref::<ForeignPhysicalExpr>() {
return expr.expr.clone();
}
@@ -522,10 +521,6 @@ impl Clone for FFI_PhysicalExpr {
}
impl PhysicalExpr for ForeignPhysicalExpr {
- fn as_any(&self) -> &dyn Any {
- self
- }
-
fn data_type(&self, input_schema: &Schema) -> Result<DataType> {
unsafe {
let schema = WrappedSchema::from(Arc::new(input_schema.clone()));
diff --git a/datafusion/functions-aggregate/src/count.rs b/datafusion/functions-aggregate/src/count.rs
index 81b6eda3f9..0edfc152ff 100644
--- a/datafusion/functions-aggregate/src/count.rs
+++ b/datafusion/functions-aggregate/src/count.rs
@@ -369,7 +369,7 @@ impl AggregateUDFImpl for Count {
if statistics_args.is_distinct {
// Only column references can be resolved from statistics;
// expressions like casts or literals are not supported.
- let col_expr = expr.as_any().downcast_ref::<expressions::Column>()?;
+ let col_expr = expr.downcast_ref::<expressions::Column>()?;
if let Precision::Exact(dc) = col_stats[col_expr.index()].distinct_count {
let dc = i64::try_from(dc).ok()?;
return Some(ScalarValue::Int64(Some(dc)));
@@ -382,13 +382,12 @@ impl AggregateUDFImpl for Count {
};
// TODO optimize with exprs other than Column
- if let Some(col_expr) = expr.as_any().downcast_ref::<expressions::Column>() {
+ if let Some(col_expr) = expr.downcast_ref::<expressions::Column>() {
if let Precision::Exact(val) = col_stats[col_expr.index()].null_count {
let count = i64::try_from(num_rows - val).ok()?;
return Some(ScalarValue::Int64(Some(count)));
}
- } else if let Some(lit_expr) =
- expr.as_any().downcast_ref::<expressions::Literal>()
+ } else if let Some(lit_expr) = expr.downcast_ref::<expressions::Literal>()
&& lit_expr.value() == &COUNT_STAR_EXPANSION
{
let num_rows = i64::try_from(num_rows).ok()?;
diff --git a/datafusion/functions-aggregate/src/min_max.rs b/datafusion/functions-aggregate/src/min_max.rs
index 9d05c57b02..939ee2a2d8 100644
--- a/datafusion/functions-aggregate/src/min_max.rs
+++ b/datafusion/functions-aggregate/src/min_max.rs
@@ -171,9 +171,8 @@ trait FromColumnStatistics {
let col_stats = &statistics_args.statistics.column_statistics;
if statistics_args.exprs.len() == 1 {
// TODO optimize with exprs other than Column
- if let Some(col_expr) = statistics_args.exprs[0]
- .as_any()
- .downcast_ref::<expressions::Column>()
+ if let Some(col_expr) =
+ statistics_args.exprs[0].downcast_ref::<expressions::Column>()
{
return self.value_from_column_statistics(
&col_stats[col_expr.index()],
diff --git a/datafusion/functions-aggregate/src/nth_value.rs b/datafusion/functions-aggregate/src/nth_value.rs
index 0d76451955..d131bb7a84 100644
--- a/datafusion/functions-aggregate/src/nth_value.rs
+++ b/datafusion/functions-aggregate/src/nth_value.rs
@@ -125,7 +125,6 @@ impl AggregateUDFImpl for NthValueAgg {
fn accumulator(&self, acc_args: AccumulatorArgs) -> Result<Box<dyn Accumulator>> {
let n = match acc_args.exprs[1]
- .as_any()
.downcast_ref::<Literal>()
.map(|lit| lit.value())
{
diff --git a/datafusion/functions-aggregate/src/string_agg.rs b/datafusion/functions-aggregate/src/string_agg.rs
index e62b26da99..f0757818af 100644
--- a/datafusion/functions-aggregate/src/string_agg.rs
+++ b/datafusion/functions-aggregate/src/string_agg.rs
@@ -120,7 +120,7 @@ impl StringAgg {
/// Extract the delimiter string from the second argument expression.
fn extract_delimiter(args: &AccumulatorArgs) -> Result<String> {
- let Some(lit) = args.exprs[1].as_any().downcast_ref::<Literal>() else {
+ let Some(lit) = args.exprs[1].downcast_ref::<Literal>() else {
return not_impl_err!("string_agg delimiter must be a string literal");
};
diff --git a/datafusion/functions-window/src/lead_lag.rs b/datafusion/functions-window/src/lead_lag.rs
index 604f1d4a0e..b78709b22c 100644
--- a/datafusion/functions-window/src/lead_lag.rs
+++ b/datafusion/functions-window/src/lead_lag.rs
@@ -314,8 +314,7 @@ impl WindowUDFImpl for WindowShift {
}
match args {
[_, expr, ..] => {
- let Some(lit) = expr.as_any().downcast_ref::<expressions::Literal>()
- else {
+ let Some(lit) = expr.downcast_ref::<expressions::Literal>() else {
return LimitEffect::Unknown;
};
let ScalarValue::Int64(Some(amount)) = lit.value() else {
diff --git a/datafusion/functions-window/src/utils.rs b/datafusion/functions-window/src/utils.rs
index 4d0c4d181a..95b60864cc 100644
--- a/datafusion/functions-window/src/utils.rs
+++ b/datafusion/functions-window/src/utils.rs
@@ -39,7 +39,6 @@ pub(crate) fn get_scalar_value_from_args(
) -> Result<Option<ScalarValue>> {
Ok(if let Some(field) = args.get(index) {
let tmp = field
- .as_any()
.downcast_ref::<Literal>()
.ok_or_else(|| DataFusionError::NotImplemented(
format!("There is only support Literal types for field at idx: {index} in Window Function"),
diff --git a/datafusion/physical-expr-adapter/src/schema_rewriter.rs b/datafusion/physical-expr-adapter/src/schema_rewriter.rs
index 5805f933a9..9fb4950317 100644
--- a/datafusion/physical-expr-adapter/src/schema_rewriter.rs
+++ b/datafusion/physical-expr-adapter/src/schema_rewriter.rs
@@ -69,7 +69,7 @@ where
V: Borrow<ScalarValue>,
{
expr.transform_down(|expr| {
- if let Some(column) = expr.as_any().downcast_ref::<Column>()
+ if let Some(column) = expr.downcast_ref::<Column>()
&& let Some(replacement_value) = replacements.get(column.name())
{
return Ok(Transformed::yes(expressions::lit(
@@ -117,7 +117,7 @@ where
/// impl PhysicalExprAdapter for CustomPhysicalExprAdapter {
/// fn rewrite(&self, expr: Arc<dyn PhysicalExpr>) -> Result<Arc<dyn PhysicalExpr>> {
/// expr.transform(|expr| {
-/// if let Some(column) = expr.as_any().downcast_ref::<Column>() {
+/// if let Some(column) = expr.downcast_ref::<Column>() {
/// // Check if the column exists in the physical schema
/// if self.physical_file_schema.index_of(column.name()).is_err() {
/// // If the column is missing, fill it with a default value instead of null
@@ -281,7 +281,7 @@ impl DefaultPhysicalExprAdapterRewriter {
return Ok(Transformed::yes(transformed));
}
- if let Some(column) = expr.as_any().downcast_ref::<Column>() {
+ if let Some(column) = expr.downcast_ref::<Column>() {
return self.rewrite_column(Arc::clone(&expr), column);
}
@@ -311,10 +311,7 @@ impl DefaultPhysicalExprAdapterRewriter {
None => return Ok(None),
};
- let lit = match field_name_expr
- .as_any()
- .downcast_ref::<expressions::Literal>()
- {
+ let lit = match field_name_expr.downcast_ref::<expressions::Literal>() {
Some(lit) => lit,
None => return Ok(None),
};
@@ -324,7 +321,7 @@ impl DefaultPhysicalExprAdapterRewriter {
None => return Ok(None),
};
- let column = match source_expr.as_any().downcast_ref::<Column>() {
+ let column = match source_expr.downcast_ref::<Column>() {
Some(column) => column,
None => return Ok(None),
};
@@ -639,15 +636,12 @@ mod tests {
use datafusion_physical_expr::expressions::{Column, Literal, col};
fn assert_cast_expr(expr: &Arc<dyn PhysicalExpr>) -> &CastExpr {
- expr.as_any()
- .downcast_ref::<CastExpr>()
- .expect("Expected CastExpr")
+ expr.downcast_ref::<CastExpr>().expect("Expected CastExpr")
}
fn assert_cast_input_column(cast_expr: &CastExpr, name: &str, index: usize) {
let inner_col = cast_expr
.expr()
- .as_any()
.downcast_ref::<Column>()
.expect("Expected inner Column");
assert_eq!(inner_col.name(), name);
@@ -696,7 +690,7 @@ mod tests {
let result = adapter.rewrite(column_expr).unwrap();
// Should be wrapped in a cast expression
- assert!(result.as_any().downcast_ref::<CastExpr>().is_some());
+ assert!(result.downcast_ref::<CastExpr>().is_some());
}
#[test]
@@ -757,14 +751,12 @@ mod tests {
let result = adapter.rewrite(Arc::new(expr)).unwrap();
let outer = result
- .as_any()
.downcast_ref::<expressions::BinaryExpr>()
.expect("Expected outer BinaryExpr");
assert_eq!(*outer.op(), Operator::Or);
let left = outer
.left()
- .as_any()
.downcast_ref::<expressions::BinaryExpr>()
.expect("Expected left BinaryExpr");
assert_eq!(*left.op(), Operator::Plus);
@@ -775,13 +767,11 @@ mod tests {
let right = outer
.right()
- .as_any()
.downcast_ref::<expressions::BinaryExpr>()
.expect("Expected right BinaryExpr");
assert_eq!(*right.op(), Operator::Gt);
let null_literal = right
.left()
- .as_any()
.downcast_ref::<Literal>()
.expect("Expected null literal");
assert_eq!(*null_literal.value(), ScalarValue::Float64(None));
@@ -882,7 +872,7 @@ mod tests {
let result = adapter.rewrite(column_expr)?;
// Should be replaced with a literal null
- if let Some(literal) = result.as_any().downcast_ref::<Literal>() {
+ if let Some(literal) = result.downcast_ref::<Literal>() {
assert_eq!(*literal.value(), ScalarValue::Float64(None));
} else {
panic!("Expected literal expression");
@@ -909,7 +899,6 @@ mod tests {
let result = adapter.rewrite(Arc::new(Column::new("b", 1)))?;
let literal = result
- .as_any()
.downcast_ref::<Literal>()
.expect("Expected literal expression");
@@ -975,7 +964,6 @@ mod tests {
// Should be replaced with the partition value
let literal = result
- .as_any()
.downcast_ref::<Literal>()
.expect("Expected literal expression");
assert_eq!(*literal.value(), partition_value);
@@ -992,7 +980,7 @@ mod tests {
Arc::new(Column::new("partition_col", 0)) as Arc<dyn PhysicalExpr>;
let result = replace_columns_with_literals(column_expr, &replacements)?;
- assert!(result.as_any().downcast_ref::<Column>().is_some());
+ assert!(result.downcast_ref::<Column>().is_some());
Ok(())
}
diff --git a/datafusion/physical-expr-common/src/physical_expr.rs b/datafusion/physical-expr-common/src/physical_expr.rs
index 7107b0a900..a42a1560cb 100644
--- a/datafusion/physical-expr-common/src/physical_expr.rs
+++ b/datafusion/physical-expr-common/src/physical_expr.rs
@@ -72,9 +72,6 @@ pub type PhysicalExprRef = Arc<dyn PhysicalExpr>;
/// [`create_physical_expr`]: https://docs.rs/datafusion/latest/datafusion/physical_expr/fn.create_physical_expr.html
/// [`Column`]: https://docs.rs/datafusion/latest/datafusion/physical_expr/expressions/struct.Column.html
pub trait PhysicalExpr: Any + Send + Sync + Display + Debug + DynEq + DynHash {
- /// Returns the physical expression as [`Any`] so that it can be
- /// downcast to a specific implementation.
- fn as_any(&self) -> &dyn Any;
/// Get the data type of this expression, given the schema of the input
fn data_type(&self, input_schema: &Schema) -> Result<DataType> {
Ok(self.return_field(input_schema)?.data_type().to_owned())
@@ -449,9 +446,29 @@ pub trait PhysicalExpr: Any + Send + Sync + Display + Debug + DynEq + DynHash {
)]
pub use datafusion_expr_common::dyn_eq::{DynEq, DynHash};
+impl dyn PhysicalExpr {
+ /// Returns `true` if the expression is of type `T`.
+ ///
+ /// Prefer this over `downcast_ref::<T>().is_some()`. Works correctly when
+ /// called on `Arc<dyn PhysicalExpr>` via auto-deref.
+ pub fn is<T: PhysicalExpr>(&self) -> bool {
+ (self as &dyn Any).is::<T>()
+ }
+
+ /// Attempts to downcast this expression to a concrete type `T`, returning
+ /// `None` if the expression is not of that type.
+ ///
+ /// Works correctly when called on `Arc<dyn PhysicalExpr>` via auto-deref,
+ /// unlike `(&arc as &dyn Any).downcast_ref::<T>()` which would attempt to
+ /// downcast the `Arc` itself.
+ pub fn downcast_ref<T: PhysicalExpr>(&self) -> Option<&T> {
+ (self as &dyn Any).downcast_ref()
+ }
+}
+
impl PartialEq for dyn PhysicalExpr {
fn eq(&self, other: &Self) -> bool {
- self.dyn_eq(other.as_any())
+ self.dyn_eq(other as &dyn Any)
}
}
impl Eq for dyn PhysicalExpr {}
@@ -528,7 +545,6 @@ where
/// # Example
/// ```
/// # // The boilerplate needed to create a `PhysicalExpr` for the example
-/// # use std::any::Any;
/// use std::collections::HashMap;
/// # use std::fmt::Formatter;
/// # use std::sync::Arc;
@@ -539,7 +555,7 @@ where
/// # use datafusion_physical_expr_common::physical_expr::{fmt_sql, DynEq, PhysicalExpr};
/// # #[derive(Debug, PartialEq, Eq, Hash)]
/// # struct MyExpr {}
-/// # impl PhysicalExpr for MyExpr {fn as_any(&self) -> &dyn Any { unimplemented!() }
+/// # impl PhysicalExpr for MyExpr {
/// # fn data_type(&self, input_schema: &Schema) -> Result<DataType> { unimplemented!() }
/// # fn nullable(&self, input_schema: &Schema) -> Result<bool> { unimplemented!() }
/// # fn evaluate(&self, batch: &RecordBatch) -> Result<ColumnarValue> { unimplemented!() }
@@ -684,10 +700,6 @@ mod test {
struct TestExpr {}
impl PhysicalExpr for TestExpr {
- fn as_any(&self) -> &dyn std::any::Any {
- self
- }
-
fn data_type(&self, _schema: &Schema) -> datafusion_common::Result<DataType> {
Ok(DataType::Int64)
}
diff --git a/datafusion/physical-expr-common/src/sort_expr.rs b/datafusion/physical-expr-common/src/sort_expr.rs
index fa961981c0..84ffb92eaa 100644
--- a/datafusion/physical-expr-common/src/sort_expr.rs
+++ b/datafusion/physical-expr-common/src/sort_expr.rs
@@ -53,7 +53,6 @@ use indexmap::IndexSet;
/// # #[derive(Clone, Debug, PartialEq, Eq, Hash)]
/// # struct MyPhysicalExpr;
/// # impl PhysicalExpr for MyPhysicalExpr {
-/// # fn as_any(&self) -> &dyn Any {todo!() }
/// # fn data_type(&self, input_schema: &Schema) -> Result<DataType> {todo!()}
/// # fn nullable(&self, input_schema: &Schema) -> Result<bool> {todo!() }
/// # fn evaluate(&self, batch: &RecordBatch) -> Result<ColumnarValue> {todo!() }
diff --git a/datafusion/physical-expr/src/analysis.rs b/datafusion/physical-expr/src/analysis.rs
index ad54d382c9..1dca36b75f 100644
--- a/datafusion/physical-expr/src/analysis.rs
+++ b/datafusion/physical-expr/src/analysis.rs
@@ -202,7 +202,7 @@ pub fn analyze(
let target_expr_and_indices = graph.gather_node_indices(columns.as_slice());
for (expr, index) in &target_expr_and_indices {
- if let Some(column) = expr.as_any().downcast_ref::<Column>()
+ if let Some(column) = expr.downcast_ref::<Column>()
&& let Some(bound) =
target_boundaries.iter().find(|b| b.column == *column)
{
@@ -241,7 +241,7 @@ fn shrink_boundaries(
) -> Result<AnalysisContext> {
let initial_boundaries = target_boundaries.clone();
target_expr_and_indices.iter().for_each(|(expr, i)| {
- if let Some(column) = expr.as_any().downcast_ref::<Column>()
+ if let Some(column) = expr.downcast_ref::<Column>()
&& let Some(bound) = target_boundaries
.iter_mut()
.find(|bound| bound.column.eq(column))
diff --git a/datafusion/physical-expr/src/async_scalar_function.rs b/datafusion/physical-expr/src/async_scalar_function.rs
index 9f58d7c77a..5612e63b53 100644
--- a/datafusion/physical-expr/src/async_scalar_function.rs
+++ b/datafusion/physical-expr/src/async_scalar_function.rs
@@ -26,7 +26,6 @@ use datafusion_expr::ScalarFunctionArgs;
use datafusion_expr::async_udf::AsyncScalarUDF;
use datafusion_expr_common::columnar_value::ColumnarValue;
use datafusion_physical_expr_common::physical_expr::PhysicalExpr;
-use std::any::Any;
use std::fmt::Display;
use std::hash::{Hash, Hasher};
use std::sync::Arc;
@@ -68,7 +67,7 @@ impl AsyncFuncExpr {
func: Arc<dyn PhysicalExpr>,
schema: &Schema,
) -> Result<Self> {
- let Some(_) = func.as_any().downcast_ref::<ScalarFunctionExpr>() else {
+ let Some(_) = func.downcast_ref::<ScalarFunctionExpr>() else {
return internal_err!(
"unexpected function type, expected ScalarFunctionExpr, got: {:?}",
func
@@ -99,7 +98,7 @@ impl AsyncFuncExpr {
/// Return the ideal batch size for this function
pub fn ideal_batch_size(&self) -> Result<Option<usize>> {
- if let Some(expr) = self.func.as_any().downcast_ref::<ScalarFunctionExpr>()
+ if let Some(expr) = self.func.downcast_ref::<ScalarFunctionExpr>()
&& let Some(udf) = expr.fun().inner().downcast_ref::<AsyncScalarUDF>()
{
return Ok(udf.ideal_batch_size());
@@ -115,8 +114,7 @@ impl AsyncFuncExpr {
batch: &RecordBatch,
config_options: Arc<ConfigOptions>,
) -> Result<ColumnarValue> {
- let Some(scalar_function_expr) =
- self.func.as_any().downcast_ref::<ScalarFunctionExpr>()
+ let Some(scalar_function_expr) = self.func.downcast_ref::<ScalarFunctionExpr>()
else {
return internal_err!(
"unexpected function type, expected ScalarFunctionExpr, got: {:?}",
@@ -209,10 +207,6 @@ impl AsyncFuncExpr {
}
impl PhysicalExpr for AsyncFuncExpr {
- fn as_any(&self) -> &dyn Any {
- self
- }
-
fn data_type(&self, input_schema: &Schema) -> Result<DataType> {
self.func.data_type(input_schema)
}
diff --git a/datafusion/physical-expr/src/equivalence/class.rs b/datafusion/physical-expr/src/equivalence/class.rs
index 2a4f88e50a..d00a4a3227 100644
--- a/datafusion/physical-expr/src/equivalence/class.rs
+++ b/datafusion/physical-expr/src/equivalence/class.rs
@@ -15,6 +15,7 @@
// specific language governing permissions and limitations
// under the License.
+use std::any::Any;
use std::fmt::Display;
use std::ops::Deref;
use std::sync::Arc;
@@ -153,7 +154,7 @@ impl From<Arc<dyn PhysicalExpr>> for ConstExpr {
// By default, assume constant expressions are not same across partitions.
// However, if we have a literal, it will have a single value that is the
// same across all partitions.
- let across = if let Some(lit) = expr.as_any().downcast_ref::<Literal>() {
+ let across = if let Some(lit) = expr.downcast_ref::<Literal>() {
AcrossPartitions::Uniform(Some(lit.value().clone()))
} else {
AcrossPartitions::Heterogeneous
@@ -201,7 +202,7 @@ impl EquivalenceClass {
/// Insert the expression into this class, meaning it is known to be equal to
/// all other expressions in this class.
pub fn push(&mut self, expr: Arc<dyn PhysicalExpr>) {
- if let Some(lit) = expr.as_any().downcast_ref::<Literal>() {
+ if let Some(lit) = expr.downcast_ref::<Literal>() {
let expr_across = AcrossPartitions::Uniform(Some(lit.value().clone()));
if let Some(across) = self.constant.as_mut() {
// TODO: Return an error if constant values do not agree.
@@ -591,7 +592,7 @@ impl EquivalenceGroup {
expr: &Arc<dyn PhysicalExpr>,
) -> Option<Arc<dyn PhysicalExpr>> {
// Literals don't need to be projected
- if expr.as_any().downcast_ref::<Literal>().is_some() {
+ if expr.downcast_ref::<Literal>().is_some() {
return Some(Arc::clone(expr));
}
@@ -734,7 +735,7 @@ impl EquivalenceGroup {
&self,
expr: &Arc<dyn PhysicalExpr>,
) -> Option<AcrossPartitions> {
- if let Some(lit) = expr.as_any().downcast_ref::<Literal>() {
+ if let Some(lit) = expr.downcast_ref::<Literal>() {
return Some(AcrossPartitions::Uniform(Some(lit.value().clone())));
}
if let Some(cls) = self.get_equivalence_class(expr)
@@ -841,7 +842,7 @@ impl EquivalenceGroup {
}
// Type equality check through reflection
- if left.as_any().type_id() != right.as_any().type_id() {
+ if (left as &dyn Any).type_id() != (right as &dyn Any).type_id() {
return false;
}
diff --git a/datafusion/physical-expr/src/equivalence/properties/mod.rs b/datafusion/physical-expr/src/equivalence/properties/mod.rs
index 214e3ca6b2..bb74cd1d9c 100644
--- a/datafusion/physical-expr/src/equivalence/properties/mod.rs
+++ b/datafusion/physical-expr/src/equivalence/properties/mod.rs
@@ -209,7 +209,7 @@ impl EquivalenceProperties {
sort_expr: &PhysicalSortExpr,
expr_type: &DataType,
) -> Option<PhysicalSortExpr> {
- let cast_expr = r_expr.as_any().downcast_ref::<CastExpr>()?;
+ let cast_expr = r_expr.downcast_ref::<CastExpr>()?;
(cast_expr.expr().eq(&sort_expr.expr)
&& CastExpr::check_bigger_cast(cast_expr.cast_type(), expr_type))
@@ -738,8 +738,7 @@ impl EquivalenceProperties {
// Build a map of column positions in the ordering:
let mut col_positions = HashMap::with_capacity(length);
for (pos, req) in ordering.iter().enumerate() {
- if let Some(col) = req.expr.as_any().downcast_ref::<Column>()
- {
+ if let Some(col) = req.expr.downcast_ref::<Column>() {
let nullable = col.nullable(&self.schema).unwrap_or(true);
col_positions.insert(col.index(), (pos, nullable));
}
@@ -783,8 +782,7 @@ impl EquivalenceProperties {
// Build a map of column positions in the ordering:
let mut col_positions = HashMap::with_capacity(length);
for (pos, req) in ordering.iter().enumerate() {
- if let Some(col) = req.expr.as_any().downcast_ref::<Column>()
- {
+ if let Some(col) = req.expr.downcast_ref::<Column>() {
let nullable = col.nullable(&self.schema).unwrap_or(true);
col_positions.insert(col.index(), (pos, nullable));
}
@@ -1134,7 +1132,7 @@ impl EquivalenceProperties {
.iter()
.flat_map(|(_, targets)| {
targets.iter().flat_map(|(target, _)| {
- target.as_any().downcast_ref::<Column>().map(|c| c.index())
+ target.downcast_ref::<Column>().map(|c| c.index())
})
})
.collect::<Vec<_>>();
@@ -1392,10 +1390,10 @@ fn update_properties(
// We have an intermediate (non-leaf) node, account for its children:
let children_props = node.children.iter().map(|c| c.data.clone()).collect_vec();
node.data = node.expr.get_properties(&children_props)?;
- } else if node.expr.as_any().is::<Literal>() {
+ } else if node.expr.is::<Literal>() {
// We have a Literal, which is one of the two possible leaf node types:
node.data = node.expr.get_properties(&[])?;
- } else if node.expr.as_any().is::<Column>() {
+ } else if node.expr.is::<Column>() {
// We have a Column, which is the other possible leaf node type:
node.data.range =
Interval::make_unbounded(&node.expr.data_type(eq_properties.schema())?)?
@@ -1466,13 +1464,13 @@ fn get_expr_properties(
range: Interval::make_unbounded(&expr.data_type(schema)?)?,
preserves_lex_ordering: false,
})
- } else if expr.as_any().downcast_ref::<Column>().is_some() {
+ } else if expr.downcast_ref::<Column>().is_some() {
Ok(ExprProperties {
sort_properties: SortProperties::Unordered,
range: Interval::make_unbounded(&expr.data_type(schema)?)?,
preserves_lex_ordering: false,
})
- } else if let Some(literal) = expr.as_any().downcast_ref::<Literal>() {
+ } else if let Some(literal) = expr.downcast_ref::<Literal>() {
Ok(ExprProperties {
sort_properties: SortProperties::Singleton,
range: literal.value().into(),
diff --git a/datafusion/physical-expr/src/expressions/binary.rs b/datafusion/physical-expr/src/expressions/binary.rs
index ecd8b91547..268a350a4d 100644
--- a/datafusion/physical-expr/src/expressions/binary.rs
+++ b/datafusion/physical-expr/src/expressions/binary.rs
@@ -20,7 +20,7 @@ mod kernels;
use crate::PhysicalExpr;
use crate::intervals::cp_solver::{propagate_arithmetic, propagate_comparison};
use std::hash::Hash;
-use std::{any::Any, sync::Arc};
+use std::sync::Arc;
use arrow::array::*;
use arrow::compute::kernels::boolean::{and_kleene, or_kleene};
@@ -130,7 +130,7 @@ impl std::fmt::Display for BinaryExpr {
expr: &dyn PhysicalExpr,
precedence: u8,
) -> std::fmt::Result {
- if let Some(child) = expr.as_any().downcast_ref::<BinaryExpr>() {
+ if let Some(child) = expr.downcast_ref::<BinaryExpr>() {
let p = child.op.precedence();
if p == 0 || p < precedence {
write!(f, "({child})")?;
@@ -252,11 +252,6 @@ fn duration_to_days(array: &ArrayRef) -> Result<ArrayRef> {
}
impl PhysicalExpr for BinaryExpr {
- /// Return a reference to Any that can be used for downcasting
- fn as_any(&self) -> &dyn Any {
- self
- }
-
fn data_type(&self, input_schema: &Schema) -> Result<DataType> {
BinaryTypeCoercer::new(
&self.left.data_type(input_schema)?,
@@ -590,7 +585,7 @@ impl PhysicalExpr for BinaryExpr {
expr: &dyn PhysicalExpr,
precedence: u8,
) -> std::fmt::Result {
- if let Some(child) = expr.as_any().downcast_ref::<BinaryExpr>() {
+ if let Some(child) = expr.downcast_ref::<BinaryExpr>() {
let p = child.op.precedence();
if p == 0 || p < precedence {
write!(f, "(")?;
@@ -4668,7 +4663,6 @@ mod tests {
schema: &Schema,
) -> Result<BinaryExpr> {
Ok(binary_op(left, op, right, schema)?
- .as_any()
.downcast_ref::<BinaryExpr>()
.unwrap()
.clone())
diff --git a/datafusion/physical-expr/src/expressions/case.rs b/datafusion/physical-expr/src/expressions/case.rs
index 4ac40df220..25aedecc2c 100644
--- a/datafusion/physical-expr/src/expressions/case.rs
+++ b/datafusion/physical-expr/src/expressions/case.rs
@@ -36,7 +36,7 @@ use datafusion_expr::ColumnarValue;
use indexmap::{IndexMap, IndexSet};
use std::borrow::Cow;
use std::hash::Hash;
-use std::{any::Any, sync::Arc};
+use std::sync::Arc;
use crate::expressions::case::literal_lookup_table::LiteralLookupTable;
use arrow::compute::kernels::merge::{MergeIndex, merge, merge_n};
@@ -131,7 +131,7 @@ impl CaseBody {
let mut used_column_indices = IndexSet::<usize>::new();
let mut collect_column_indices = |expr: &Arc<dyn PhysicalExpr>| {
expr.apply(|expr| {
- if let Some(column) = expr.as_any().downcast_ref::<Column>() {
+ if let Some(column) = expr.downcast_ref::<Column>() {
used_column_indices.insert(column.index());
}
Ok(TreeNodeRecursion::Continue)
@@ -162,7 +162,7 @@ impl CaseBody {
let project = |expr: &Arc<dyn PhysicalExpr>| -> Result<Arc<dyn PhysicalExpr>> {
Arc::clone(expr)
.transform_down(|e| {
- if let Some(column) = e.as_any().downcast_ref::<Column>() {
+ if let Some(column) = e.downcast_ref::<Column>() {
let original = column.index();
let projected = *column_index_map.get(&original).unwrap();
if projected != original {
@@ -281,7 +281,7 @@ impl std::fmt::Display for CaseExpr {
/// this is limited to use with Column expressions but could potentially be used for other
/// expressions in the future
fn is_cheap_and_infallible(expr: &Arc<dyn PhysicalExpr>) -> bool {
- expr.as_any().is::<Column>()
+ expr.is::<Column>()
}
/// Creates a [FilterPredicate] from a boolean array.
@@ -621,7 +621,7 @@ impl CaseExpr {
// normalize null literals to None in the else_expr (this already happens
// during SQL planning, but not necessarily for other use cases)
let else_expr = match &else_expr {
- Some(e) => match e.as_any().downcast_ref::<Literal>() {
+ Some(e) => match e.downcast_ref::<Literal>() {
Some(lit) if lit.value().is_null() => None,
_ => else_expr,
},
@@ -659,9 +659,9 @@ impl CaseExpr {
{
EvalMethod::InfallibleExprOrNull
} else if body.when_then_expr.len() == 1
- && body.when_then_expr[0].1.as_any().is::<Literal>()
+ && body.when_then_expr[0].1.is::<Literal>()
&& body.else_expr.is_some()
- && body.else_expr.as_ref().unwrap().as_any().is::<Literal>()
+ && body.else_expr.as_ref().unwrap().is::<Literal>()
{
EvalMethod::ScalarOrScalar
} else if body.when_then_expr.len() == 1 {
@@ -1194,11 +1194,6 @@ impl CaseExpr {
}
impl PhysicalExpr for CaseExpr {
- /// Return a reference to Any that can be used for down-casting
- fn as_any(&self) -> &dyn Any {
- self
- }
-
fn data_type(&self, input_schema: &Schema) -> Result<DataType> {
self.body.data_type(input_schema)
}
@@ -2207,7 +2202,7 @@ mod tests {
let expr2 = Arc::clone(&expr)
.transform(|e| {
- let transformed = match e.as_any().downcast_ref::<Literal>() {
+ let transformed = match e.downcast_ref::<Literal>() {
Some(lit_value) => match lit_value.value() {
ScalarValue::Utf8(Some(str_value)) => {
Some(lit(str_value.to_uppercase()))
@@ -2227,7 +2222,7 @@ mod tests {
let expr3 = Arc::clone(&expr)
.transform_down(|e| {
- let transformed = match e.as_any().downcast_ref::<Literal>() {
+ let transformed = match e.downcast_ref::<Literal>() {
Some(lit_value) => match lit_value.value() {
ScalarValue::Utf8(Some(str_value)) => {
Some(lit(str_value.to_uppercase()))
diff --git a/datafusion/physical-expr/src/expressions/case/literal_lookup_table/mod.rs b/datafusion/physical-expr/src/expressions/case/literal_lookup_table/mod.rs
index 67b045f998..0d4291ccc9 100644
--- a/datafusion/physical-expr/src/expressions/case/literal_lookup_table/mod.rs
+++ b/datafusion/physical-expr/src/expressions/case/literal_lookup_table/mod.rs
@@ -95,8 +95,8 @@ impl LiteralLookupTable {
.when_then_expr
.iter()
.map(|(when, then)| {
- let when_maybe_literal = when.as_any().downcast_ref::<Literal>();
- let then_maybe_literal = then.as_any().downcast_ref::<Literal>();
+ let when_maybe_literal = when.downcast_ref::<Literal>();
+ let then_maybe_literal = then.downcast_ref::<Literal>();
when_maybe_literal.zip(then_maybe_literal)
})
@@ -142,7 +142,7 @@ impl LiteralLookupTable {
};
let else_value: ScalarValue = if let Some(else_expr) = &body.else_expr {
- let literal = else_expr.as_any().downcast_ref::<Literal>()?;
+ let literal = else_expr.downcast_ref::<Literal>()?;
literal.value().clone()
} else {
diff --git a/datafusion/physical-expr/src/expressions/cast.rs b/datafusion/physical-expr/src/expressions/cast.rs
index 8d4167050b..ad214a89ce 100644
--- a/datafusion/physical-expr/src/expressions/cast.rs
+++ b/datafusion/physical-expr/src/expressions/cast.rs
@@ -15,7 +15,6 @@
// specific language governing permissions and limitations
// under the License.
-use std::any::Any;
use std::fmt;
use std::hash::Hash;
use std::sync::Arc;
@@ -229,11 +228,6 @@ impl fmt::Display for CastExpr {
}
impl PhysicalExpr for CastExpr {
- /// Return a reference to Any that can be used for downcasting
- fn as_any(&self) -> &dyn Any {
- self
- }
-
fn data_type(&self, _input_schema: &Schema) -> Result<DataType> {
Ok(self.cast_type().clone())
}
diff --git a/datafusion/physical-expr/src/expressions/column.rs b/datafusion/physical-expr/src/expressions/column.rs
index cf844790a0..ba8cd5e636 100644
--- a/datafusion/physical-expr/src/expressions/column.rs
+++ b/datafusion/physical-expr/src/expressions/column.rs
@@ -17,7 +17,6 @@
//! Physical column reference: [`Column`]
-use std::any::Any;
use std::hash::Hash;
use std::sync::Arc;
@@ -106,11 +105,6 @@ impl std::fmt::Display for Column {
}
impl PhysicalExpr for Column {
- /// Return a reference to Any that can be used for downcasting
- fn as_any(&self) -> &dyn Any {
- self
- }
-
/// Get the data type of this expression, given the schema of the input
fn data_type(&self, input_schema: &Schema) -> Result<DataType> {
self.bounds_check(input_schema)?;
@@ -189,7 +183,7 @@ pub fn with_new_schema(
) -> Result<Arc<dyn PhysicalExpr>> {
Ok(expr
.transform_up(|expr| {
- if let Some(col) = expr.as_any().downcast_ref::<Column>() {
+ if let Some(col) = expr.downcast_ref::<Column>() {
let idx = col.index();
let Some(field) = schema.fields().get(idx) else {
return plan_err!(
diff --git a/datafusion/physical-expr/src/expressions/dynamic_filters.rs b/datafusion/physical-expr/src/expressions/dynamic_filters.rs
index d285f8b377..47398d87e2 100644
--- a/datafusion/physical-expr/src/expressions/dynamic_filters.rs
+++ b/datafusion/physical-expr/src/expressions/dynamic_filters.rs
@@ -16,7 +16,7 @@
// under the License.
use parking_lot::RwLock;
-use std::{any::Any, fmt::Display, hash::Hash, sync::Arc};
+use std::{fmt::Display, hash::Hash, sync::Arc};
use tokio::sync::watch;
use crate::PhysicalExpr;
@@ -349,10 +349,6 @@ impl DynamicFilterPhysicalExpr {
}
impl PhysicalExpr for DynamicFilterPhysicalExpr {
- fn as_any(&self) -> &dyn Any {
- self
- }
-
fn children(&self) -> Vec<&Arc<dyn PhysicalExpr>> {
self.remapped_children
.as_ref()
@@ -743,7 +739,6 @@ mod test {
// with_new_children() is called which creates a new outer Arc but clones the inner Arc.
let consumer1_expr = Arc::clone(&filter).with_new_children(vec![]).unwrap();
let _consumer1 = consumer1_expr
- .as_any()
.downcast_ref::<DynamicFilterPhysicalExpr>()
.expect("Should be DynamicFilterPhysicalExpr");
@@ -756,7 +751,6 @@ mod test {
// Create another transformed consumer
let consumer2_expr = Arc::clone(&filter).with_new_children(vec![]).unwrap();
let _consumer2 = consumer2_expr
- .as_any()
.downcast_ref::<DynamicFilterPhysicalExpr>()
.expect("Should be DynamicFilterPhysicalExpr");
diff --git a/datafusion/physical-expr/src/expressions/in_list.rs b/datafusion/physical-expr/src/expressions/in_list.rs
index 3487c7e709..2377edf937 100644
--- a/datafusion/physical-expr/src/expressions/in_list.rs
+++ b/datafusion/physical-expr/src/expressions/in_list.rs
@@ -17,7 +17,6 @@
//! Implementation of `InList` expressions: [`InListExpr`]
-use std::any::Any;
use std::fmt::Debug;
use std::hash::{Hash, Hasher};
use std::sync::Arc;
@@ -725,11 +724,6 @@ impl std::fmt::Display for InListExpr {
}
impl PhysicalExpr for InListExpr {
- /// Return a reference to Any that can be used for downcasting
- fn as_any(&self) -> &dyn Any {
- self
- }
-
fn data_type(&self, _input_schema: &Schema) -> Result<DataType> {
Ok(DataType::Boolean)
}
diff --git a/datafusion/physical-expr/src/expressions/is_not_null.rs b/datafusion/physical-expr/src/expressions/is_not_null.rs
index 62be8ebbc1..86acf0a4ea 100644
--- a/datafusion/physical-expr/src/expressions/is_not_null.rs
+++ b/datafusion/physical-expr/src/expressions/is_not_null.rs
@@ -26,7 +26,7 @@ use datafusion_common::Result;
use datafusion_common::ScalarValue;
use datafusion_expr::ColumnarValue;
use std::hash::Hash;
-use std::{any::Any, sync::Arc};
+use std::sync::Arc;
/// IS NOT NULL expression
#[derive(Debug, Eq)]
@@ -67,11 +67,6 @@ impl std::fmt::Display for IsNotNullExpr {
}
impl PhysicalExpr for IsNotNullExpr {
- /// Return a reference to Any that can be used for downcasting
- fn as_any(&self) -> &dyn Any {
- self
- }
-
fn data_type(&self, _input_schema: &Schema) -> Result<DataType> {
Ok(DataType::Boolean)
}
diff --git a/datafusion/physical-expr/src/expressions/is_null.rs b/datafusion/physical-expr/src/expressions/is_null.rs
index 356fe2a866..8534ddb8d1 100644
--- a/datafusion/physical-expr/src/expressions/is_null.rs
+++ b/datafusion/physical-expr/src/expressions/is_null.rs
@@ -26,7 +26,7 @@ use datafusion_common::Result;
use datafusion_common::ScalarValue;
use datafusion_expr::ColumnarValue;
use std::hash::Hash;
-use std::{any::Any, sync::Arc};
+use std::sync::Arc;
/// IS NULL expression
#[derive(Debug, Eq)]
@@ -67,11 +67,6 @@ impl std::fmt::Display for IsNullExpr {
}
impl PhysicalExpr for IsNullExpr {
- /// Return a reference to Any that can be used for downcasting
- fn as_any(&self) -> &dyn Any {
- self
- }
-
fn data_type(&self, _input_schema: &Schema) -> Result<DataType> {
Ok(DataType::Boolean)
}
diff --git a/datafusion/physical-expr/src/expressions/like.rs b/datafusion/physical-expr/src/expressions/like.rs
index fc49ca35f0..07ceb4e7d7 100644
--- a/datafusion/physical-expr/src/expressions/like.rs
+++ b/datafusion/physical-expr/src/expressions/like.rs
@@ -22,7 +22,7 @@ use datafusion_common::{Result, assert_or_internal_err};
use datafusion_expr::{ColumnarValue, Operator};
use datafusion_physical_expr_common::datum::apply_cmp;
use std::hash::Hash;
-use std::{any::Any, sync::Arc};
+use std::sync::Arc;
// Like expression
#[derive(Debug, Eq)]
@@ -105,10 +105,6 @@ impl std::fmt::Display for LikeExpr {
}
impl PhysicalExpr for LikeExpr {
- fn as_any(&self) -> &dyn Any {
- self
- }
-
fn data_type(&self, _input_schema: &Schema) -> Result<DataType> {
Ok(DataType::Boolean)
}
diff --git a/datafusion/physical-expr/src/expressions/literal.rs b/datafusion/physical-expr/src/expressions/literal.rs
index 7ba2dc14e4..7351158c54 100644
--- a/datafusion/physical-expr/src/expressions/literal.rs
+++ b/datafusion/physical-expr/src/expressions/literal.rs
@@ -17,7 +17,6 @@
//! Literal expressions for physical operations
-use std::any::Any;
use std::hash::Hash;
use std::sync::Arc;
@@ -92,11 +91,6 @@ impl std::fmt::Display for Literal {
}
impl PhysicalExpr for Literal {
- /// Return a reference to Any that can be used for downcasting
- fn as_any(&self) -> &dyn Any {
- self
- }
-
fn data_type(&self, _input_schema: &Schema) -> Result<DataType> {
Ok(self.value.data_type())
}
diff --git a/datafusion/physical-expr/src/expressions/negative.rs b/datafusion/physical-expr/src/expressions/negative.rs
index c78bbe999e..da576f2872 100644
--- a/datafusion/physical-expr/src/expressions/negative.rs
+++ b/datafusion/physical-expr/src/expressions/negative.rs
@@ -17,7 +17,6 @@
//! Negation (-) expression
-use std::any::Any;
use std::hash::Hash;
use std::sync::Arc;
@@ -79,11 +78,6 @@ impl std::fmt::Display for NegativeExpr {
}
impl PhysicalExpr for NegativeExpr {
- /// Return a reference to Any that can be used for downcasting
- fn as_any(&self) -> &dyn Any {
- self
- }
-
fn data_type(&self, input_schema: &Schema) -> Result<DataType> {
self.arg.data_type(input_schema)
}
diff --git a/datafusion/physical-expr/src/expressions/no_op.rs b/datafusion/physical-expr/src/expressions/no_op.rs
index ff44a60a86..c866c6ab07 100644
--- a/datafusion/physical-expr/src/expressions/no_op.rs
+++ b/datafusion/physical-expr/src/expressions/no_op.rs
@@ -17,7 +17,6 @@
//! NoOp placeholder for physical operations
-use std::any::Any;
use std::hash::Hash;
use std::sync::Arc;
@@ -49,11 +48,6 @@ impl std::fmt::Display for NoOp {
}
impl PhysicalExpr for NoOp {
- /// Return a reference to Any that can be used for downcasting
- fn as_any(&self) -> &dyn Any {
- self
- }
-
fn data_type(&self, _input_schema: &Schema) -> Result<DataType> {
Ok(DataType::Null)
}
diff --git a/datafusion/physical-expr/src/expressions/not.rs b/datafusion/physical-expr/src/expressions/not.rs
index a29ab2ff40..917d3a9535 100644
--- a/datafusion/physical-expr/src/expressions/not.rs
+++ b/datafusion/physical-expr/src/expressions/not.rs
@@ -17,7 +17,6 @@
//! Not expression
-use std::any::Any;
use std::fmt;
use std::hash::Hash;
use std::sync::Arc;
@@ -70,11 +69,6 @@ impl fmt::Display for NotExpr {
}
impl PhysicalExpr for NotExpr {
- /// Return a reference to Any that can be used for downcasting
- fn as_any(&self) -> &dyn Any {
- self
- }
-
fn data_type(&self, _input_schema: &Schema) -> Result<DataType> {
Ok(DataType::Boolean)
}
diff --git a/datafusion/physical-expr/src/expressions/try_cast.rs b/datafusion/physical-expr/src/expressions/try_cast.rs
index 306f14b48f..ba59d113ac 100644
--- a/datafusion/physical-expr/src/expressions/try_cast.rs
+++ b/datafusion/physical-expr/src/expressions/try_cast.rs
@@ -15,7 +15,6 @@
// specific language governing permissions and limitations
// under the License.
-use std::any::Any;
use std::fmt;
use std::hash::Hash;
use std::sync::Arc;
@@ -77,11 +76,6 @@ impl fmt::Display for TryCastExpr {
}
impl PhysicalExpr for TryCastExpr {
- /// Return a reference to Any that can be used for downcasting
- fn as_any(&self) -> &dyn Any {
- self
- }
-
fn data_type(&self, _input_schema: &Schema) -> Result<DataType> {
Ok(self.cast_type.clone())
}
diff --git a/datafusion/physical-expr/src/expressions/unknown_column.rs b/datafusion/physical-expr/src/expressions/unknown_column.rs
index f06d880985..4969fc3374 100644
--- a/datafusion/physical-expr/src/expressions/unknown_column.rs
+++ b/datafusion/physical-expr/src/expressions/unknown_column.rs
@@ -17,7 +17,6 @@
//! UnKnownColumn expression
-use std::any::Any;
use std::hash::{Hash, Hasher};
use std::sync::Arc;
@@ -56,11 +55,6 @@ impl std::fmt::Display for UnKnownColumn {
}
impl PhysicalExpr for UnKnownColumn {
- /// Return a reference to Any that can be used for downcasting
- fn as_any(&self) -> &dyn Any {
- self
- }
-
/// Get the data type of this expression, given the schema of the input
fn data_type(&self, _input_schema: &Schema) -> Result<DataType> {
Ok(DataType::Null)
diff --git a/datafusion/physical-expr/src/intervals/cp_solver.rs b/datafusion/physical-expr/src/intervals/cp_solver.rs
index cb4c2e47bc..aee65f35dc 100644
--- a/datafusion/physical-expr/src/intervals/cp_solver.rs
+++ b/datafusion/physical-expr/src/intervals/cp_solver.rs
@@ -220,7 +220,7 @@ impl ExprIntervalGraphNode {
/// any other expression starts with an indefinite interval (`[-∞, ∞]`).
pub fn make_node(node: &ExprTreeNode<NodeIndex>, schema: &Schema) -> Result<Self> {
let expr = Arc::clone(&node.expr);
- if let Some(literal) = expr.as_any().downcast_ref::<Literal>() {
+ if let Some(literal) = expr.downcast_ref::<Literal>() {
let value = literal.value();
Interval::try_new(value.clone(), value.clone())
.map(|interval| Self::new_with_interval(expr, interval))
@@ -646,7 +646,6 @@ impl ExprIntervalGraph {
if node_interval == &Interval::TRUE
&& self.graph[node]
.expr
- .as_any()
.downcast_ref::<BinaryExpr>()
.is_some_and(|expr| expr.op() == &Operator::Or)
{
@@ -892,12 +891,12 @@ mod tests {
PropagationResult::Success,
&Schema::new(vec![
Field::new(
- left_col.as_any().downcast_ref::<Column>().unwrap().name(),
+ left_col.downcast_ref::<Column>().unwrap().name(),
DataType::$SCALAR,
true,
),
Field::new(
- right_col.as_any().downcast_ref::<Column>().unwrap().name(),
+ right_col.downcast_ref::<Column>().unwrap().name(),
DataType::$SCALAR,
true,
),
@@ -939,16 +938,8 @@ mod tests {
Interval::make(Some(100), None)?,
PropagationResult::Infeasible,
&Schema::new(vec![
- Field::new(
- left_col.as_any().downcast_ref::<Column>().unwrap().name(),
- DataType::Int32,
- true,
- ),
- Field::new(
- right_col.as_any().downcast_ref::<Column>().unwrap().name(),
- DataType::Int32,
- true,
- ),
+ Field::new(left_col.name(), DataType::Int32, true),
+ Field::new(right_col.name(), DataType::Int32, true),
]),
)
}
diff --git a/datafusion/physical-expr/src/intervals/utils.rs b/datafusion/physical-expr/src/intervals/utils.rs
index 3cada63a34..fb039a6e5f 100644
--- a/datafusion/physical-expr/src/intervals/utils.rs
+++ b/datafusion/physical-expr/src/intervals/utils.rs
@@ -36,26 +36,25 @@ use datafusion_expr::interval_arithmetic::Interval;
/// will relax as more types of `PhysicalExpr`s and `Operator`s are supported.
/// Currently, [`CastExpr`], [`NegativeExpr`], [`BinaryExpr`], [`Column`] and [`Literal`] are supported.
pub fn check_support(expr: &Arc<dyn PhysicalExpr>, schema: &SchemaRef) -> bool {
- let expr_any = expr.as_any();
- if let Some(binary_expr) = expr_any.downcast_ref::<BinaryExpr>() {
+ if let Some(binary_expr) = expr.downcast_ref::<BinaryExpr>() {
is_operator_supported(binary_expr.op())
&& check_support(binary_expr.left(), schema)
&& check_support(binary_expr.right(), schema)
- } else if let Some(column) = expr_any.downcast_ref::<Column>() {
+ } else if let Some(column) = expr.downcast_ref::<Column>() {
if let Ok(field) = schema.field_with_name(column.name()) {
is_datatype_supported(field.data_type())
} else {
false
}
- } else if let Some(literal) = expr_any.downcast_ref::<Literal>() {
+ } else if let Some(literal) = expr.downcast_ref::<Literal>() {
if let Ok(dt) = literal.data_type(schema) {
is_datatype_supported(&dt)
} else {
false
}
- } else if let Some(cast) = expr_any.downcast_ref::<CastExpr>() {
+ } else if let Some(cast) = expr.downcast_ref::<CastExpr>() {
check_support(cast.expr(), schema)
- } else if let Some(negative) = expr_any.downcast_ref::<NegativeExpr>() {
+ } else if let Some(negative) = expr.downcast_ref::<NegativeExpr>() {
check_support(negative.arg(), schema)
} else {
false
diff --git a/datafusion/physical-expr/src/physical_expr.rs b/datafusion/physical-expr/src/physical_expr.rs
index a03b58e0b5..77ede76e1d 100644
--- a/datafusion/physical-expr/src/physical_expr.rs
+++ b/datafusion/physical-expr/src/physical_expr.rs
@@ -38,7 +38,7 @@ pub fn add_offset_to_expr(
expr: Arc<dyn PhysicalExpr>,
offset: isize,
) -> Result<Arc<dyn PhysicalExpr>> {
- expr.transform_down(|e| match e.as_any().downcast_ref::<Column>() {
+ expr.transform_down(|e| match e.downcast_ref::<Column>() {
Some(col) => {
let Some(idx) = col.index().checked_add_signed(offset) else {
return plan_err!("Column index overflow");
@@ -244,7 +244,6 @@ mod tests {
use datafusion_common::ScalarValue;
use datafusion_expr::ColumnarValue;
use datafusion_expr::Operator;
- use std::any::Any;
use std::fmt;
#[test]
@@ -394,10 +393,6 @@ mod tests {
}
impl PhysicalExpr for MockVolatileExpr {
- fn as_any(&self) -> &dyn Any {
- self
- }
-
fn data_type(&self, _input_schema: &Schema) -> Result<DataType> {
Ok(DataType::Boolean)
}
diff --git a/datafusion/physical-expr/src/planner.rs b/datafusion/physical-expr/src/planner.rs
index 3227e20f68..0880f1a139 100644
--- a/datafusion/physical-expr/src/planner.rs
+++ b/datafusion/physical-expr/src/planner.rs
@@ -447,7 +447,6 @@ mod tests {
fn as_planner_cast(physical: &Arc<dyn PhysicalExpr>) -> &expressions::CastExpr {
physical
- .as_any()
.downcast_ref::<expressions::CastExpr>()
.expect("planner should lower logical CAST to CastExpr")
}
diff --git a/datafusion/physical-expr/src/projection.rs b/datafusion/physical-expr/src/projection.rs
index 5f7b5a2e96..ed4f2ff0bd 100644
--- a/datafusion/physical-expr/src/projection.rs
+++ b/datafusion/physical-expr/src/projection.rs
@@ -434,7 +434,6 @@ impl ProjectionExprs {
.iter()
.map(|e| {
e.expr
- .as_any()
.downcast_ref::<Column>()
.expect("Expected column reference in projection")
.index()
@@ -661,9 +660,9 @@ impl ProjectionExprs {
for proj_expr in self.exprs.iter() {
let expr = &proj_expr.expr;
- let col_stats = if let Some(col) = expr.as_any().downcast_ref::<Column>() {
+ let col_stats = if let Some(col) = expr.downcast_ref::<Column>() {
std::mem::take(&mut stats.column_statistics[col.index()])
- } else if let Some(literal) = expr.as_any().downcast_ref::<Literal>() {
+ } else if let Some(literal) = expr.downcast_ref::<Literal>() {
// Handle literal expressions (constants) by calculating proper statistics
let data_type = expr.data_type(output_schema)?;
@@ -926,7 +925,7 @@ pub fn update_expr(
return Ok(Transformed::no(expr));
}
- let Some(column) = expr.as_any().downcast_ref::<Column>() else {
+ let Some(column) = expr.downcast_ref::<Column>() else {
return Ok(Transformed::no(expr));
};
if unproject {
@@ -948,7 +947,7 @@ pub fn update_expr(
.iter()
.enumerate()
.find_map(|(index, proj_expr)| {
- proj_expr.expr.as_any().downcast_ref::<Column>().and_then(
+ proj_expr.expr.downcast_ref::<Column>().and_then(
|projected_column| {
(column.name().eq(projected_column.name())
&& column.index() == projected_column.index())
@@ -1044,7 +1043,7 @@ impl ProjectionMapping {
let mut map = IndexMap::<_, ProjectionTargets>::new();
for (expr_idx, (expr, name)) in expr.into_iter().enumerate() {
let target_expr = Arc::new(Column::new(&name, expr_idx)) as _;
- let source_expr = expr.transform_down(|e| match e.as_any().downcast_ref::<Column>() {
+ let source_expr = expr.transform_down(|e| match e.downcast_ref::<Column>() {
Some(col) => {
// Sometimes, an expression and its name in the input_schema
// doesn't match. This can cause problems, so we make sure
@@ -1075,17 +1074,11 @@ impl ProjectionMapping {
// p.ticker → get_field(col("details"), "ticker")
// enabling the optimizer to know that sorting by
// `details.ticker` is equivalent to sorting by `p.ticker`.
- if let Some(func_expr) =
- source_expr.as_any().downcast_ref::<ScalarFunctionExpr>()
- {
+ if let Some(func_expr) = source_expr.downcast_ref::<ScalarFunctionExpr>() {
let literal_args: Vec<Option<ScalarValue>> = func_expr
.args()
.iter()
- .map(|arg| {
- arg.as_any()
- .downcast_ref::<Literal>()
- .map(|l| l.value().clone())
- })
+ .map(|arg| arg.downcast_ref::<Literal>().map(|l| l.value().clone()))
.collect();
if let Some(field_mapping) =
@@ -1227,7 +1220,7 @@ pub fn project_ordering(
let mut projected_exprs = vec![];
for PhysicalSortExpr { expr, options } in ordering.iter() {
let transformed = Arc::clone(expr).transform_up(|expr| {
- let Some(col) = expr.as_any().downcast_ref::<Column>() else {
+ let Some(col) = expr.downcast_ref::<Column>() else {
return Ok(Transformed::no(expr));
};
@@ -1285,7 +1278,7 @@ pub(crate) mod tests {
for (target, _) in targets.iter() {
// Skip non-Column targets (e.g. struct field decomposition
// entries which are ScalarFunctionExpr targets).
- let Some(column) = target.as_any().downcast_ref::<Column>() else {
+ let Some(column) = target.downcast_ref::<Column>() else {
continue;
};
fields.push(Field::new(column.name(), data_type.clone(), nullable));
@@ -2549,11 +2542,7 @@ pub(crate) mod tests {
let result_expr = result.unwrap();
assert_eq!(
- result_expr
- .as_any()
- .downcast_ref::<Literal>()
- .unwrap()
- .value(),
+ result_expr.downcast_ref::<Literal>().unwrap().value(),
&ScalarValue::Int64(Some(42))
);
@@ -2582,17 +2571,15 @@ pub(crate) mod tests {
let result_expr = result.unwrap();
let binary = result_expr
- .as_any()
.downcast_ref::<BinaryExpr>()
.expect("Should be a BinaryExpr");
// Left side should still be the literal
- assert!(binary.left().as_any().downcast_ref::<Literal>().is_some());
+ assert!(binary.left().downcast_ref::<Literal>().is_some());
// Right side should be updated to reference column at index 5
let right_col = binary
.right()
- .as_any()
.downcast_ref::<Column>()
.expect("Right should be a Column");
assert_eq!(right_col.index(), 5);
diff --git a/datafusion/physical-expr/src/scalar_function.rs b/datafusion/physical-expr/src/scalar_function.rs
index 5e6e0aa97f..418d005c97 100644
--- a/datafusion/physical-expr/src/scalar_function.rs
+++ b/datafusion/physical-expr/src/scalar_function.rs
@@ -29,7 +29,6 @@
//! This module also has a set of coercion rules to improve user experience: if an argument i32 is passed
//! to a function that supports f64, it is coerced to f64.
-use std::any::Any;
use std::fmt::{self, Debug, Formatter};
use std::hash::{Hash, Hasher};
use std::sync::Arc;
@@ -105,11 +104,7 @@ impl ScalarFunctionExpr {
let arguments = args
.iter()
- .map(|e| {
- e.as_any()
- .downcast_ref::<Literal>()
- .map(|literal| literal.value())
- })
+ .map(|e| e.downcast_ref::<Literal>().map(|literal| literal.value()))
.collect::<Vec<_>>();
let ret_args = ReturnFieldArgs {
arg_fields: &arg_fields,
@@ -171,7 +166,7 @@ impl ScalarFunctionExpr {
where
T: ScalarUDFImpl,
{
- match expr.as_any().downcast_ref::<ScalarFunctionExpr>() {
+ match expr.downcast_ref::<ScalarFunctionExpr>() {
Some(scalar_expr) if scalar_expr.fun().inner().is::<T>() => Some(scalar_expr),
_ => None,
}
@@ -230,11 +225,6 @@ fn sorted_config_entries(config_options: &ConfigOptions) -> Vec<ConfigEntry> {
}
impl PhysicalExpr for ScalarFunctionExpr {
- /// Return a reference to Any that can be used for downcasting
- fn as_any(&self) -> &dyn Any {
- self
- }
-
fn data_type(&self, _input_schema: &Schema) -> Result<DataType> {
Ok(self.return_field.data_type().clone())
}
diff --git a/datafusion/physical-expr/src/simplifier/const_evaluator.rs b/datafusion/physical-expr/src/simplifier/const_evaluator.rs
index 148a9bdcec..34c080bfa0 100644
--- a/datafusion/physical-expr/src/simplifier/const_evaluator.rs
+++ b/datafusion/physical-expr/src/simplifier/const_evaluator.rs
@@ -48,7 +48,7 @@ pub fn simplify_const_expr(
) -> Result<Transformed<Arc<dyn PhysicalExpr>>> {
let batch = create_dummy_batch()?;
// If expr is already a const literal or can't be evaluated into one.
- if expr.as_any().is::<Literal>() || (!can_evaluate_as_constant(&expr)) {
+ if expr.is::<Literal>() || (!can_evaluate_as_constant(&expr)) {
return Ok(Transformed::no(expr));
}
@@ -90,12 +90,12 @@ pub(crate) fn simplify_const_expr_immediate(
batch: &RecordBatch,
) -> Result<Transformed<Arc<dyn PhysicalExpr>>> {
// Already a literal - nothing to do
- if expr.as_any().is::<Literal>() {
+ if expr.is::<Literal>() {
return Ok(Transformed::no(expr));
}
// Column references cannot be evaluated at plan time
- if expr.as_any().is::<Column>() {
+ if expr.is::<Column>() {
return Ok(Transformed::no(expr));
}
@@ -107,10 +107,7 @@ pub(crate) fn simplify_const_expr_immediate(
// Since transform visits bottom-up, children have already been simplified.
// If all children are now Literals, this node can be const-evaluated.
// This is O(k) where k = number of children, instead of O(subtree).
- let all_children_literal = expr
- .children()
- .iter()
- .all(|child| child.as_any().is::<Literal>());
+ let all_children_literal = expr.children().iter().all(|child| child.is::<Literal>());
if !all_children_literal {
return Ok(Transformed::no(expr));
@@ -169,7 +166,7 @@ fn can_evaluate_as_constant(expr: &Arc<dyn PhysicalExpr>) -> bool {
let mut can_evaluate = true;
expr.apply(|e| {
- if e.as_any().is::<Column>() || e.is_volatile_node() {
+ if e.is::<Column>() || e.is_volatile_node() {
can_evaluate = false;
Ok(TreeNodeRecursion::Stop)
} else {
@@ -189,7 +186,7 @@ fn can_evaluate_as_constant(expr: &Arc<dyn PhysicalExpr>) -> bool {
pub fn has_column_references(expr: &Arc<dyn PhysicalExpr>) -> bool {
let mut has_columns = false;
expr.apply(|expr| {
- if expr.as_any().downcast_ref::<Column>().is_some() {
+ if expr.downcast_ref::<Column>().is_some() {
has_columns = true;
Ok(TreeNodeRecursion::Stop)
} else {
diff --git a/datafusion/physical-expr/src/simplifier/mod.rs b/datafusion/physical-expr/src/simplifier/mod.rs
index 16c2f5255f..272c1f595a 100644
--- a/datafusion/physical-expr/src/simplifier/mod.rs
+++ b/datafusion/physical-expr/src/simplifier/mod.rs
@@ -119,15 +119,13 @@ mod tests {
/// Helper function to extract a Literal from a PhysicalExpr
fn as_literal(expr: &Arc<dyn PhysicalExpr>) -> &Literal {
- expr.as_any()
- .downcast_ref::<Literal>()
+ expr.downcast_ref::<Literal>()
.unwrap_or_else(|| panic!("Expected Literal, got: {expr}"))
}
/// Helper function to extract a BinaryExpr from a PhysicalExpr
fn as_binary(expr: &Arc<dyn PhysicalExpr>) -> &BinaryExpr {
- expr.as_any()
- .downcast_ref::<BinaryExpr>()
+ expr.downcast_ref::<BinaryExpr>()
.unwrap_or_else(|| panic!("Expected BinaryExpr, got: {expr}"))
}
@@ -164,8 +162,8 @@ mod tests {
// Should be optimized to: c2 != INT64(99) (c2 is INT64, literal cast to match)
let left_expr = optimized_binary.left();
assert!(
- left_expr.as_any().downcast_ref::<CastExpr>().is_none()
- && left_expr.as_any().downcast_ref::<TryCastExpr>().is_none()
+ left_expr.downcast_ref::<CastExpr>().is_none()
+ && left_expr.downcast_ref::<TryCastExpr>().is_none()
);
let right_literal = as_literal(optimized_binary.right());
assert_eq!(right_literal.value(), &ScalarValue::Int64(Some(99)));
@@ -198,11 +196,8 @@ mod tests {
let left_binary = as_binary(or_binary.left());
let left_left_expr = left_binary.left();
assert!(
- left_left_expr.as_any().downcast_ref::<CastExpr>().is_none()
- && left_left_expr
- .as_any()
- .downcast_ref::<TryCastExpr>()
- .is_none()
+ left_left_expr.downcast_ref::<CastExpr>().is_none()
+ && left_left_expr.downcast_ref::<TryCastExpr>().is_none()
);
let left_literal = as_literal(left_binary.right());
assert_eq!(left_literal.value(), &ScalarValue::Int32(Some(5)));
@@ -211,14 +206,8 @@ mod tests {
let right_binary = as_binary(or_binary.right());
let right_left_expr = right_binary.left();
assert!(
- right_left_expr
- .as_any()
- .downcast_ref::<CastExpr>()
- .is_none()
- && right_left_expr
- .as_any()
- .downcast_ref::<TryCastExpr>()
- .is_none()
+ right_left_expr.downcast_ref::<CastExpr>().is_none()
+ && right_left_expr.downcast_ref::<TryCastExpr>().is_none()
);
let right_literal = as_literal(right_binary.right());
assert_eq!(right_literal.value(), &ScalarValue::Int64(Some(10)));
@@ -476,7 +465,7 @@ mod tests {
// If we just let `expr` go out of scope, Rust's recursive Drop will blow the stack
// even with recursive_protection, because Drop doesn't use the #[recursive] attribute.
// We peel off layers one by one to avoid deep recursion in Drop.
- while let Some(not_expr) = expr.as_any().downcast_ref::<NotExpr>() {
+ while let Some(not_expr) = expr.downcast_ref::<NotExpr>() {
// Clone the child (Arc increment).
// Now child has 2 refs: one in parent, one in `child`.
let child = Arc::clone(not_expr.arg());
@@ -577,7 +566,7 @@ mod tests {
));
let result = simplifier.simplify(expr).unwrap();
// Should remain a BinaryExpr, not become a Literal
- assert!(result.as_any().downcast_ref::<BinaryExpr>().is_some());
+ assert!(result.downcast_ref::<BinaryExpr>().is_some());
}
#[test]
diff --git a/datafusion/physical-expr/src/simplifier/not.rs b/datafusion/physical-expr/src/simplifier/not.rs
index 709260aa48..886cadd6a2 100644
--- a/datafusion/physical-expr/src/simplifier/not.rs
+++ b/datafusion/physical-expr/src/simplifier/not.rs
@@ -52,7 +52,7 @@ pub fn simplify_not_expr(
schema: &Schema,
) -> Result<Transformed<Arc<dyn PhysicalExpr>>> {
// Check if this is a NOT expression
- let not_expr = match expr.as_any().downcast_ref::<NotExpr>() {
+ let not_expr = match expr.downcast_ref::<NotExpr>() {
Some(not_expr) => not_expr,
None => return Ok(Transformed::no(expr)),
};
@@ -60,12 +60,12 @@ pub fn simplify_not_expr(
let inner_expr = not_expr.arg();
// Handle NOT(NOT(expr)) -> expr (double negation elimination)
- if let Some(inner_not) = inner_expr.as_any().downcast_ref::<NotExpr>() {
+ if let Some(inner_not) = inner_expr.downcast_ref::<NotExpr>() {
return Ok(Transformed::yes(Arc::clone(inner_not.arg())));
}
// Handle NOT(literal) -> !literal
- if let Some(literal) = inner_expr.as_any().downcast_ref::<Literal>() {
+ if let Some(literal) = inner_expr.downcast_ref::<Literal>() {
if let ScalarValue::Boolean(Some(val)) = literal.value() {
return Ok(Transformed::yes(lit(ScalarValue::Boolean(Some(!val)))));
}
@@ -75,7 +75,7 @@ pub fn simplify_not_expr(
}
// Handle NOT(IN list) -> NOT IN list
- if let Some(in_list_expr) = inner_expr.as_any().downcast_ref::<InListExpr>() {
+ if let Some(in_list_expr) = inner_expr.downcast_ref::<InListExpr>() {
let negated = !in_list_expr.negated();
let new_in_list = in_list(
Arc::clone(in_list_expr.expr()),
@@ -87,7 +87,7 @@ pub fn simplify_not_expr(
}
// Handle NOT(binary_expr)
- if let Some(binary_expr) = inner_expr.as_any().downcast_ref::<BinaryExpr>() {
+ if let Some(binary_expr) = inner_expr.downcast_ref::<BinaryExpr>() {
if let Some(negated_op) = binary_expr.op().negate() {
let new_binary = Arc::new(BinaryExpr::new(
Arc::clone(binary_expr.left()),
diff --git a/datafusion/physical-expr/src/simplifier/unwrap_cast.rs b/datafusion/physical-expr/src/simplifier/unwrap_cast.rs
index f0f48ecf97..4f4dfb2c20 100644
--- a/datafusion/physical-expr/src/simplifier/unwrap_cast.rs
+++ b/datafusion/physical-expr/src/simplifier/unwrap_cast.rs
@@ -46,7 +46,7 @@ pub(crate) fn unwrap_cast_in_comparison(
expr: Arc<dyn PhysicalExpr>,
schema: &Schema,
) -> Result<Transformed<Arc<dyn PhysicalExpr>>> {
- if let Some(binary) = expr.as_any().downcast_ref::<BinaryExpr>()
+ if let Some(binary) = expr.downcast_ref::<BinaryExpr>()
&& let Some(unwrapped) = try_unwrap_cast_binary(binary, schema)?
{
return Ok(Transformed::yes(unwrapped));
@@ -62,7 +62,7 @@ fn try_unwrap_cast_binary(
// Case 1: cast(left_expr) op literal
if let (Some((inner_expr, _cast_type)), Some(literal)) = (
extract_cast_info(binary.left()),
- binary.right().as_any().downcast_ref::<Literal>(),
+ binary.right().downcast_ref::<Literal>(),
) && binary.op().supports_propagation()
&& let Some(unwrapped) = try_unwrap_cast_comparison(
Arc::clone(inner_expr),
@@ -76,7 +76,7 @@ fn try_unwrap_cast_binary(
// Case 2: literal op cast(right_expr)
if let (Some(literal), Some((inner_expr, _cast_type))) = (
- binary.left().as_any().downcast_ref::<Literal>(),
+ binary.left().downcast_ref::<Literal>(),
extract_cast_info(binary.right()),
) {
// For literal op cast(expr), we need to swap the operator
@@ -105,9 +105,9 @@ fn try_unwrap_cast_binary(
fn extract_cast_info(
expr: &Arc<dyn PhysicalExpr>,
) -> Option<(&Arc<dyn PhysicalExpr>, &DataType)> {
- if let Some(cast) = expr.as_any().downcast_ref::<CastExpr>() {
+ if let Some(cast) = expr.downcast_ref::<CastExpr>() {
Some((cast.expr(), cast.cast_type()))
- } else if let Some(try_cast) = expr.as_any().downcast_ref::<TryCastExpr>() {
+ } else if let Some(try_cast) = expr.downcast_ref::<TryCastExpr>() {
Some((try_cast.expr(), try_cast.cast_type()))
} else {
None
@@ -143,20 +143,19 @@ mod tests {
/// Check if an expression is a cast expression
fn is_cast_expr(expr: &Arc<dyn PhysicalExpr>) -> bool {
- expr.as_any().downcast_ref::<CastExpr>().is_some()
- || expr.as_any().downcast_ref::<TryCastExpr>().is_some()
+ expr.downcast_ref::<CastExpr>().is_some()
+ || expr.downcast_ref::<TryCastExpr>().is_some()
}
/// Check if a binary expression is suitable for cast unwrapping
fn is_binary_expr_with_cast_and_literal(binary: &BinaryExpr) -> bool {
// Check if left is cast and right is literal
let left_cast_right_literal = is_cast_expr(binary.left())
- && binary.right().as_any().downcast_ref::<Literal>().is_some();
+ && binary.right().downcast_ref::<Literal>().is_some();
// Check if left is literal and right is cast
- let left_literal_right_cast =
- binary.left().as_any().downcast_ref::<Literal>().is_some()
- && is_cast_expr(binary.right());
+ let left_literal_right_cast = binary.left().downcast_ref::<Literal>().is_some()
+ && is_cast_expr(binary.right());
left_cast_right_literal || left_literal_right_cast
}
@@ -188,17 +187,13 @@ mod tests {
// The result should be: c1 > INT32(10)
let optimized = result.data;
- let optimized_binary = optimized.as_any().downcast_ref::<BinaryExpr>().unwrap();
+ let optimized_binary = optimized.downcast_ref::<BinaryExpr>().unwrap();
// Check that left side is no longer a cast
assert!(!is_cast_expr(optimized_binary.left()));
// Check that right side is a literal with the correct type and value
- let right_literal = optimized_binary
- .right()
- .as_any()
- .downcast_ref::<Literal>()
- .unwrap();
+ let right_literal = optimized_binary.right().downcast_ref::<Literal>().unwrap();
assert_eq!(right_literal.value(), &ScalarValue::Int32(Some(10)));
}
@@ -221,7 +216,7 @@ mod tests {
// The result should be equivalent to: c1 > INT32(10)
let optimized = result.data;
- let optimized_binary = optimized.as_any().downcast_ref::<BinaryExpr>().unwrap();
+ let optimized_binary = optimized.downcast_ref::<BinaryExpr>().unwrap();
// Check the operator was swapped
assert_eq!(*optimized_binary.op(), Operator::Gt);
@@ -254,9 +249,7 @@ mod tests {
let literal_expr = lit(10i64);
let binary_expr =
Arc::new(BinaryExpr::new(cast_expr, Operator::Gt, literal_expr));
- let binary_ref = binary_expr.as_any().downcast_ref::<BinaryExpr>().unwrap();
-
- assert!(is_binary_expr_with_cast_and_literal(binary_ref));
+ assert!(is_binary_expr_with_cast_and_literal(&binary_expr));
}
#[test]
@@ -288,7 +281,7 @@ mod tests {
// The result should be: decimal_col >= Decimal128(400, 9, 2)
let optimized = result.data;
- let optimized_binary = optimized.as_any().downcast_ref::<BinaryExpr>().unwrap();
+ let optimized_binary = optimized.downcast_ref::<BinaryExpr>().unwrap();
// Check operator was swapped correctly
assert_eq!(*optimized_binary.op(), Operator::GtEq);
@@ -297,11 +290,7 @@ mod tests {
assert!(!is_cast_expr(optimized_binary.left()));
// Check that right side is a literal with the correct type
- let right_literal = optimized_binary
- .right()
- .as_any()
- .downcast_ref::<Literal>()
- .unwrap();
+ let right_literal = optimized_binary.right().downcast_ref::<Literal>().unwrap();
assert_eq!(
right_literal.value().data_type(),
DataType::Decimal128(9, 2)
@@ -337,8 +326,7 @@ mod tests {
assert!(result.transformed);
let optimized = result.data;
- let optimized_binary =
- optimized.as_any().downcast_ref::<BinaryExpr>().unwrap();
+ let optimized_binary = optimized.downcast_ref::<BinaryExpr>().unwrap();
// Check the operator was swapped correctly
assert_eq!(
@@ -351,11 +339,8 @@ mod tests {
assert!(!is_cast_expr(optimized_binary.left()));
// Check that the literal was cast to the column type
- let right_literal = optimized_binary
- .right()
- .as_any()
- .downcast_ref::<Literal>()
- .unwrap();
+ let right_literal =
+ optimized_binary.right().downcast_ref::<Literal>().unwrap();
assert_eq!(right_literal.value(), &ScalarValue::Int32(Some(100)));
}
}
@@ -428,12 +413,8 @@ mod tests {
// Verify the NULL was cast to the column type
let optimized = result.data;
- let optimized_binary = optimized.as_any().downcast_ref::<BinaryExpr>().unwrap();
- let right_literal = optimized_binary
- .right()
- .as_any()
- .downcast_ref::<Literal>()
- .unwrap();
+ let optimized_binary = optimized.downcast_ref::<BinaryExpr>().unwrap();
+ let right_literal = optimized_binary.right().downcast_ref::<Literal>().unwrap();
assert_eq!(right_literal.value(), &ScalarValue::Int32(None));
}
@@ -488,20 +469,12 @@ mod tests {
// Verify the AND operator is preserved
let optimized = result.data;
- let and_binary = optimized.as_any().downcast_ref::<BinaryExpr>().unwrap();
+ let and_binary = optimized.downcast_ref::<BinaryExpr>().unwrap();
assert_eq!(*and_binary.op(), Operator::And);
// Both sides should have their casts unwrapped
- let left_binary = and_binary
- .left()
- .as_any()
- .downcast_ref::<BinaryExpr>()
- .unwrap();
- let right_binary = and_binary
- .right()
- .as_any()
- .downcast_ref::<BinaryExpr>()
- .unwrap();
+ let left_binary = and_binary.left().downcast_ref::<BinaryExpr>().unwrap();
+ let right_binary = and_binary.right().downcast_ref::<BinaryExpr>().unwrap();
assert!(!is_cast_expr(left_binary.left()));
assert!(!is_cast_expr(right_binary.left()));
@@ -525,17 +498,13 @@ mod tests {
assert!(result.transformed);
let optimized = result.data;
- let optimized_binary = optimized.as_any().downcast_ref::<BinaryExpr>().unwrap();
+ let optimized_binary = optimized.downcast_ref::<BinaryExpr>().unwrap();
// Verify the try_cast was removed
assert!(!is_cast_expr(optimized_binary.left()));
// Verify the literal was converted
- let right_literal = optimized_binary
- .right()
- .as_any()
- .downcast_ref::<Literal>()
- .unwrap();
+ let right_literal = optimized_binary.right().downcast_ref::<Literal>().unwrap();
assert_eq!(right_literal.value(), &ScalarValue::Int32(Some(100)));
}
@@ -608,34 +577,18 @@ mod tests {
// Verify both sides of the AND were optimized
let optimized = result.data;
- let and_binary = optimized.as_any().downcast_ref::<BinaryExpr>().unwrap();
+ let and_binary = optimized.downcast_ref::<BinaryExpr>().unwrap();
// Left side should be: c1 > INT32(10)
- let left_binary = and_binary
- .left()
- .as_any()
- .downcast_ref::<BinaryExpr>()
- .unwrap();
+ let left_binary = and_binary.left().downcast_ref::<BinaryExpr>().unwrap();
assert!(!is_cast_expr(left_binary.left()));
- let left_literal = left_binary
- .right()
- .as_any()
- .downcast_ref::<Literal>()
- .unwrap();
+ let left_literal = left_binary.right().downcast_ref::<Literal>().unwrap();
assert_eq!(left_literal.value(), &ScalarValue::Int32(Some(10)));
// Right side should be: c2 = INT64(20) (c2 is already INT64, literal cast to match)
- let right_binary = and_binary
- .right()
- .as_any()
- .downcast_ref::<BinaryExpr>()
- .unwrap();
+ let right_binary = and_binary.right().downcast_ref::<BinaryExpr>().unwrap();
assert!(!is_cast_expr(right_binary.left()));
- let right_literal = right_binary
- .right()
- .as_any()
- .downcast_ref::<Literal>()
- .unwrap();
+ let right_literal = right_binary.right().downcast_ref::<Literal>().unwrap();
assert_eq!(right_literal.value(), &ScalarValue::Int64(Some(20)));
}
}
diff --git a/datafusion/physical-expr/src/statistics/stats_solver.rs b/datafusion/physical-expr/src/statistics/stats_solver.rs
index 5665f7d1be..407fa6fd1f 100644
--- a/datafusion/physical-expr/src/statistics/stats_solver.rs
+++ b/datafusion/physical-expr/src/statistics/stats_solver.rs
@@ -86,7 +86,7 @@ impl ExprStatisticsGraphNode {
/// indefinite range (i.e. `[-∞, ∞]`).
pub fn make_node(node: &ExprTreeNode<NodeIndex>, schema: &Schema) -> Result<Self> {
let expr = Arc::clone(&node.expr);
- if let Some(literal) = expr.as_any().downcast_ref::<Literal>() {
+ if let Some(literal) = expr.downcast_ref::<Literal>() {
let value = literal.value();
Interval::try_new(value.clone(), value.clone())
.and_then(|interval| Self::new_uniform(expr, interval))
diff --git a/datafusion/physical-expr/src/utils/guarantee.rs b/datafusion/physical-expr/src/utils/guarantee.rs
index 00195a4df6..add7a34f70 100644
--- a/datafusion/physical-expr/src/utils/guarantee.rs
+++ b/datafusion/physical-expr/src/utils/guarantee.rs
@@ -126,9 +126,8 @@ impl LiteralGuarantee {
.fold(GuaranteeBuilder::new(), |builder, expr| {
if let Some(cel) = ColOpLit::try_new(expr) {
builder.aggregate_conjunct(&cel)
- } else if let Some(inlist) = expr
- .as_any()
- .downcast_ref::<crate::expressions::InListExpr>()
+ } else if let Some(inlist) =
+ expr.downcast_ref::<crate::expressions::InListExpr>()
{
if let Some(inlist) = ColInList::try_new(inlist) {
builder.aggregate_multi_conjunct(
@@ -393,15 +392,10 @@ impl<'a> ColOpLit<'a> {
///
/// Returns None otherwise
fn try_new(expr: &'a Arc<dyn PhysicalExpr>) -> Option<Self> {
- let binary_expr = expr
- .as_any()
- .downcast_ref::<crate::expressions::BinaryExpr>()?;
+ let binary_expr = expr.downcast_ref::<crate::expressions::BinaryExpr>()?;
- let (left, op, right) = (
- binary_expr.left().as_any(),
- binary_expr.op(),
- binary_expr.right().as_any(),
- );
+ let (left, op, right) =
+ (binary_expr.left(), binary_expr.op(), binary_expr.right());
let guarantee = match op {
Operator::Eq => Guarantee::In,
Operator::NotEq => Guarantee::NotIn,
@@ -449,15 +443,12 @@ impl<'a> ColInList<'a> {
/// Returns None otherwise
fn try_new(inlist: &'a crate::expressions::InListExpr) -> Option<Self> {
// Only support single-column inlist currently, multi-column inlist is not supported
- let col = inlist
- .expr()
- .as_any()
- .downcast_ref::<crate::expressions::Column>()?;
+ let col = inlist.expr().downcast_ref::<crate::expressions::Column>()?;
let literals = inlist
.list()
.iter()
- .map(|e| e.as_any().downcast_ref::<crate::expressions::Literal>())
+ .map(|e| e.downcast_ref::<crate::expressions::Literal>())
.collect::<Option<Vec<_>>>()?;
let guarantee = if inlist.negated() {
@@ -482,10 +473,7 @@ enum ColOpLitOrInList<'a> {
impl<'a> ColOpLitOrInList<'a> {
fn try_new(expr: &'a Arc<dyn PhysicalExpr>) -> Option<Self> {
- match expr
- .as_any()
- .downcast_ref::<crate::expressions::InListExpr>()
- {
+ match expr.downcast_ref::<crate::expressions::InListExpr>() {
Some(inlist) => Some(Self::ColInList(ColInList::try_new(inlist)?)),
None => ColOpLit::try_new(expr).map(Self::ColOpLit),
}
diff --git a/datafusion/physical-expr/src/utils/mod.rs b/datafusion/physical-expr/src/utils/mod.rs
index 6a8b49ac52..1be57c9192 100644
--- a/datafusion/physical-expr/src/utils/mod.rs
+++ b/datafusion/physical-expr/src/utils/mod.rs
@@ -71,15 +71,14 @@ impl ConstExpr {
input_eqs: &EquivalenceProperties,
) -> Option<AcrossPartitions> {
input_eqs.is_expr_constant(expr).or_else(|| {
- expr.as_any()
- .downcast_ref::<Literal>()
+ expr.downcast_ref::<Literal>()
.map(|l| AcrossPartitions::Uniform(Some(l.value().clone())))
})
}
let mut constants = Vec::new();
for conjunction in split_conjunction(predicate) {
- if let Some(binary) = conjunction.as_any().downcast_ref::<BinaryExpr>()
+ if let Some(binary) = conjunction.downcast_ref::<BinaryExpr>()
&& binary.op() == &Operator::Eq
{
// Check if either side is constant — either already known
@@ -145,7 +144,7 @@ fn split_impl<'a>(
predicate: &'a Arc<dyn PhysicalExpr>,
mut exprs: Vec<&'a Arc<dyn PhysicalExpr>>,
) -> Vec<&'a Arc<dyn PhysicalExpr>> {
- match predicate.as_any().downcast_ref::<BinaryExpr>() {
+ match predicate.downcast_ref::<BinaryExpr>() {
Some(binary) if binary.op() == &operator => {
let exprs = split_impl(operator, binary.left(), exprs);
split_impl(operator, binary.right(), exprs)
@@ -176,16 +175,14 @@ pub fn map_columns_before_projection(
let column_mapping = proj_exprs
.iter()
.filter_map(|(expr, name)| {
- expr.as_any()
- .downcast_ref::<Column>()
+ expr.downcast_ref::<Column>()
.map(|column| (name.clone(), column.clone()))
})
.collect::<HashMap<_, _>>();
parent_required
.iter()
.filter_map(|r| {
- r.as_any()
- .downcast_ref::<Column>()
+ r.downcast_ref::<Column>()
.and_then(|c| column_mapping.get(c.name()))
})
.map(|e| Arc::new(e.clone()) as _)
@@ -289,7 +286,7 @@ where
pub fn collect_columns(expr: &Arc<dyn PhysicalExpr>) -> HashSet<Column> {
let mut columns = HashSet::<Column>::new();
expr.apply(|expr| {
- if let Some(column) = expr.as_any().downcast_ref::<Column>() {
+ if let Some(column) = expr.downcast_ref::<Column>() {
columns.get_or_insert_with(column, |c| c.clone());
}
Ok(TreeNodeRecursion::Continue)
@@ -313,7 +310,7 @@ pub fn reassign_expr_columns(
schema: &Schema,
) -> Result<Arc<dyn PhysicalExpr>> {
expr.transform_down(|expr| {
- if let Some(column) = expr.as_any().downcast_ref::<Column>() {
+ if let Some(column) = expr.downcast_ref::<Column>() {
let index = schema.index_of(column.name())?;
return Ok(Transformed::yes(Arc::new(Column::new(
@@ -452,11 +449,11 @@ pub(crate) mod tests {
fn make_dummy_node(node: &ExprTreeNode<NodeIndex>) -> Result<PhysicalExprDummyNode> {
let expr = Arc::clone(&node.expr);
- let dummy_property = if expr.as_any().is::<BinaryExpr>() {
+ let dummy_property = if expr.is::<BinaryExpr>() {
"Binary"
- } else if expr.as_any().is::<Column>() {
+ } else if expr.is::<Column>() {
"Column"
- } else if expr.as_any().is::<Literal>() {
+ } else if expr.is::<Literal>() {
"Literal"
} else {
"Other"
diff --git a/datafusion/physical-optimizer/src/enforce_sorting/sort_pushdown.rs b/datafusion/physical-optimizer/src/enforce_sorting/sort_pushdown.rs
index 3677f3a45b..400161a94c 100644
--- a/datafusion/physical-optimizer/src/enforce_sorting/sort_pushdown.rs
+++ b/datafusion/physical-optimizer/src/enforce_sorting/sort_pushdown.rs
@@ -430,7 +430,7 @@ fn handle_aggregate_pushdown(
for req in parent_requirement {
// Sort above AggregateExec should reference its output columns. Map each
// output group-by column to its original input expression.
- let Some(column) = req.expr.as_any().downcast_ref::<Column>() else {
+ let Some(column) = req.expr.downcast_ref::<Column>() else {
return Ok(None);
};
if column.index() >= group_input_exprs.len() {
@@ -604,14 +604,13 @@ fn expr_source_side(
let mut right_ordering = ordering.clone();
let (mut valid_left, mut valid_right) = (true, true);
for (left, right) in ordering.iter_mut().zip(right_ordering.iter_mut()) {
- let col = left.expr.as_any().downcast_ref::<Column>()?;
+ let col = left.expr.downcast_ref::<Column>()?;
let eq_class = eq_group.get_equivalence_class(&left.expr);
if col.index() < left_columns_len {
if valid_right {
valid_right = eq_class.is_some_and(|cls| {
for expr in cls.iter() {
if expr
- .as_any()
.downcast_ref::<Column>()
.is_some_and(|c| c.index() >= left_columns_len)
{
@@ -626,7 +625,6 @@ fn expr_source_side(
valid_left = eq_class.is_some_and(|cls| {
for expr in cls.iter() {
if expr
- .as_any()
.downcast_ref::<Column>()
.is_some_and(|c| c.index() < left_columns_len)
{
@@ -652,11 +650,11 @@ fn expr_source_side(
}
JoinType::LeftSemi | JoinType::LeftAnti => ordering
.iter()
- .all(|e| e.expr.as_any().is::<Column>())
+ .all(|e| e.expr.is::<Column>())
.then_some((JoinSide::Left, ordering)),
JoinType::RightSemi | JoinType::RightAnti => ordering
.iter()
- .all(|e| e.expr.as_any().is::<Column>())
+ .all(|e| e.expr.is::<Column>())
.then_some((JoinSide::Right, ordering)),
}
}
@@ -739,7 +737,7 @@ fn handle_custom_pushdown(
let updated_columns = req
.expr
.transform_up(|expr| {
- if let Some(col) = expr.as_any().downcast_ref::<Column>() {
+ if let Some(col) = expr.downcast_ref::<Column>() {
let new_index = col.index() - sub_offset;
Ok(Transformed::yes(Arc::new(Column::new(
child_schema.field(new_index).name(),
@@ -822,7 +820,7 @@ fn handle_hash_join(
let updated_columns = req
.expr
.transform_up(|expr| {
- if let Some(col) = expr.as_any().downcast_ref::<Column>() {
+ if let Some(col) = expr.downcast_ref::<Column>() {
let index = projected_indices[col.index()].index;
Ok(Transformed::yes(Arc::new(Column::new(
child_schema.field(index).name(),
diff --git a/datafusion/physical-optimizer/src/projection_pushdown.rs b/datafusion/physical-optimizer/src/projection_pushdown.rs
index 7d8bf7aa47..fe71c21176 100644
--- a/datafusion/physical-optimizer/src/projection_pushdown.rs
+++ b/datafusion/physical-optimizer/src/projection_pushdown.rs
@@ -242,7 +242,7 @@ fn minimize_join_filter(
) -> JoinFilter {
let mut used_columns = HashSet::new();
expr.apply(|expr| {
- if let Some(col) = expr.as_any().downcast_ref::<Column>() {
+ if let Some(col) = expr.downcast_ref::<Column>() {
used_columns.insert(col.index());
}
Ok(TreeNodeRecursion::Continue)
@@ -265,7 +265,7 @@ fn minimize_join_filter(
.collect::<Fields>();
let final_expr = expr
- .transform_up(|expr| match expr.as_any().downcast_ref::<Column>() {
+ .transform_up(|expr| match expr.downcast_ref::<Column>() {
None => Ok(Transformed::no(expr)),
Some(column) => {
let new_idx = used_columns
@@ -378,7 +378,7 @@ impl<'a> JoinFilterRewriter<'a> {
// executed against the filter schema.
let new_idx = self.join_side_projections.len();
let rewritten_expr = expr.transform_up(|expr| {
- Ok(match expr.as_any().downcast_ref::<Column>() {
+ Ok(match expr.downcast_ref::<Column>() {
None => Transformed::no(expr),
Some(column) => {
let intermediate_column =
@@ -412,7 +412,7 @@ impl<'a> JoinFilterRewriter<'a> {
join_side: JoinSide,
) -> Result<bool> {
let mut result = false;
- expr.apply(|expr| match expr.as_any().downcast_ref::<Column>() {
+ expr.apply(|expr| match expr.downcast_ref::<Column>() {
None => Ok(TreeNodeRecursion::Continue),
Some(c) => {
let column_index = &self.intermediate_column_indices[c.index()];
diff --git a/datafusion/physical-optimizer/src/topk_aggregation.rs b/datafusion/physical-optimizer/src/topk_aggregation.rs
index 581edd86cd..e1779c04a6 100644
--- a/datafusion/physical-optimizer/src/topk_aggregation.rs
+++ b/datafusion/physical-optimizer/src/topk_aggregation.rs
@@ -100,7 +100,7 @@ impl TopKAggregation {
let order = sort.properties().output_ordering()?;
let order = order.iter().exactly_one().ok()?;
let order_desc = order.options.descending;
- let order = order.expr.as_any().downcast_ref::<Column>()?;
+ let order = order.expr.downcast_ref::<Column>()?;
let mut cur_col_name = order.name().to_string();
let limit = sort.fetch()?;
@@ -118,8 +118,7 @@ impl TopKAggregation {
} else if let Some(proj) = plan.downcast_ref::<ProjectionExec>() {
// track renames due to successive projections
for proj_expr in proj.expr() {
- let Some(src_col) = proj_expr.expr.as_any().downcast_ref::<Column>()
- else {
+ let Some(src_col) = proj_expr.expr.downcast_ref::<Column>() else {
continue;
};
if proj_expr.alias == cur_col_name {
diff --git a/datafusion/physical-plan/src/aggregates/mod.rs b/datafusion/physical-plan/src/aggregates/mod.rs
index 79a21d1c34..76ecb3f148 100644
--- a/datafusion/physical-plan/src/aggregates/mod.rs
+++ b/datafusion/physical-plan/src/aggregates/mod.rs
@@ -1006,7 +1006,7 @@ impl AggregateExec {
.iter()
.flat_map(|(_, target_cols)| {
target_cols.iter().flat_map(|(expr, _)| {
- expr.as_any().downcast_ref::<Column>().map(|c| c.index())
+ expr.downcast_ref::<Column>().map(|c| c.index())
})
})
.collect(),
@@ -1098,7 +1098,7 @@ impl AggregateExec {
let mut column_statistics = Statistics::unknown_column(&self.schema());
for (idx, (expr, _)) in self.group_by.expr.iter().enumerate() {
- if let Some(col) = expr.as_any().downcast_ref::<Column>() {
+ if let Some(col) = expr.downcast_ref::<Column>() {
let child_col_stats =
&child_statistics.column_statistics[col.index()];
column_statistics[idx].max_value = child_col_stats.max_value.clone();
@@ -1210,7 +1210,7 @@ impl AggregateExec {
if group_mask[j] {
continue;
}
- let col = expr.as_any().downcast_ref::<Column>()?;
+ let col = expr.downcast_ref::<Column>()?;
let col_stats = &child_statistics.column_statistics[col.index()];
let ndv = *col_stats.distinct_count.get_value()?;
let null_adjustment = match col_stats.null_count.get_value() {
@@ -1265,7 +1265,7 @@ impl AggregateExec {
// 2. arg should be only 1 column reference
if let [arg] = aggr_expr.expressions().as_slice()
- && arg.as_any().is::<Column>()
+ && arg.is::<Column>()
{
all_cols.push(Arc::clone(arg));
aggr_dyn_filters.push(PerAccumulatorDynFilter {
diff --git a/datafusion/physical-plan/src/async_func.rs b/datafusion/physical-plan/src/async_func.rs
index 23f2b9ba1e..76a68bf570 100644
--- a/datafusion/physical-plan/src/async_func.rs
+++ b/datafusion/physical-plan/src/async_func.rs
@@ -338,8 +338,7 @@ impl AsyncMapper {
) -> Result<()> {
// recursively look for references to async functions
physical_expr.apply(|expr| {
- if let Some(scalar_func_expr) =
- expr.as_any().downcast_ref::<ScalarFunctionExpr>()
+ if let Some(scalar_func_expr) = expr.downcast_ref::<ScalarFunctionExpr>()
&& scalar_func_expr.fun().as_async().is_some()
{
let next_name = self.next_column_name();
diff --git a/datafusion/physical-plan/src/column_rewriter.rs b/datafusion/physical-plan/src/column_rewriter.rs
index c42bea90f0..2df95cd614 100644
--- a/datafusion/physical-plan/src/column_rewriter.rs
+++ b/datafusion/physical-plan/src/column_rewriter.rs
@@ -50,7 +50,7 @@ impl<'a> TreeNodeRewriter for PhysicalColumnRewriter<'a> {
&mut self,
node: Self::Node,
) -> datafusion_common::Result<Transformed<Self::Node>> {
- if let Some(column) = node.as_any().downcast_ref::<Column>() {
+ if let Some(column) = node.downcast_ref::<Column>() {
if let Some(new_column) = self.column_map.get(column) {
// jump to prevent rewriting the new sub-expression again
return Ok(Transformed::new(
diff --git a/datafusion/physical-plan/src/filter.rs b/datafusion/physical-plan/src/filter.rs
index 792f46daf9..0b3ddbf1de 100644
--- a/datafusion/physical-plan/src/filter.rs
+++ b/datafusion/physical-plan/src/filter.rs
@@ -1020,7 +1020,7 @@ fn collect_columns_from_predicate_inner(
let predicates = split_conjunction(predicate);
predicates.into_iter().for_each(|p| {
- if let Some(binary) = p.as_any().downcast_ref::<BinaryExpr>() {
+ if let Some(binary) = p.downcast_ref::<BinaryExpr>() {
// Only extract pairs where at least one side is a Column reference.
// Pairs like `complex_expr = literal` should not create equivalence
// classes — the literal could appear in many unrelated expressions
@@ -1029,8 +1029,8 @@ fn collect_columns_from_predicate_inner(
// sort orderings. Constant propagation for such pairs is handled
// separately by `extend_constants`.
let has_direct_column_operand =
- binary.left().as_any().downcast_ref::<Column>().is_some()
- || binary.right().as_any().downcast_ref::<Column>().is_some();
+ binary.left().downcast_ref::<Column>().is_some()
+ || binary.right().downcast_ref::<Column>().is_some();
if !has_direct_column_operand {
return;
}
diff --git a/datafusion/physical-plan/src/filter_pushdown.rs b/datafusion/physical-plan/src/filter_pushdown.rs
index 7e82b9e823..810f9ffcbc 100644
--- a/datafusion/physical-plan/src/filter_pushdown.rs
+++ b/datafusion/physical-plan/src/filter_pushdown.rs
@@ -365,7 +365,7 @@ impl FilterRemapper {
) -> Result<Option<Arc<dyn PhysicalExpr>>> {
let mut all_valid = true;
let transformed = Arc::clone(filter).transform_down(|expr| {
- if let Some(col) = expr.as_any().downcast_ref::<Column>() {
+ if let Some(col) = expr.downcast_ref::<Column>() {
if self.allowed_indices.contains(&col.index())
&& let Ok(new_index) = self.child_schema.index_of(col.name())
{
diff --git a/datafusion/physical-plan/src/joins/hash_join/exec.rs b/datafusion/physical-plan/src/joins/hash_join/exec.rs
index d064f5ce6c..735375441f 100644
--- a/datafusion/physical-plan/src/joins/hash_join/exec.rs
+++ b/datafusion/physical-plan/src/joins/hash_join/exec.rs
@@ -1594,10 +1594,7 @@ impl ExecutionPlan for HashJoinExec {
.on
.iter()
.filter_map(|(left_key, _)| {
- left_key
- .as_any()
- .downcast_ref::<Column>()
- .map(|c| c.index())
+ left_key.downcast_ref::<Column>().map(|c| c.index())
})
.collect();
for (output_idx, ci) in column_indices.iter().enumerate() {
@@ -1611,10 +1608,7 @@ impl ExecutionPlan for HashJoinExec {
.on
.iter()
.filter_map(|(_, right_key)| {
- right_key
- .as_any()
- .downcast_ref::<Column>()
- .map(|c| c.index())
+ right_key.downcast_ref::<Column>().map(|c| c.index())
})
.collect();
for (output_idx, ci) in column_indices.iter().enumerate() {
diff --git a/datafusion/physical-plan/src/joins/hash_join/partitioned_hash_eval.rs b/datafusion/physical-plan/src/joins/hash_join/partitioned_hash_eval.rs
index f6c305fba6..0daac0bb86 100644
--- a/datafusion/physical-plan/src/joins/hash_join/partitioned_hash_eval.rs
+++ b/datafusion/physical-plan/src/joins/hash_join/partitioned_hash_eval.rs
@@ -17,7 +17,7 @@
//! Hash computation and hash table lookup expressions for dynamic filtering
-use std::{any::Any, fmt::Display, hash::Hash, sync::Arc};
+use std::{fmt::Display, hash::Hash, sync::Arc};
use arrow::{
array::{ArrayRef, UInt64Array},
@@ -154,10 +154,6 @@ impl Display for HashExpr {
}
impl PhysicalExpr for HashExpr {
- fn as_any(&self) -> &dyn Any {
- self
- }
-
fn children(&self) -> Vec<&Arc<dyn PhysicalExpr>> {
self.on_columns.iter().collect()
}
@@ -300,10 +296,6 @@ impl Display for HashTableLookupExpr {
}
impl PhysicalExpr for HashTableLookupExpr {
- fn as_any(&self) -> &dyn Any {
- self
- }
-
fn children(&self) -> Vec<&Arc<dyn PhysicalExpr>> {
self.on_columns.iter().collect()
}
diff --git a/datafusion/physical-plan/src/joins/stream_join_utils.rs b/datafusion/physical-plan/src/joins/stream_join_utils.rs
index d00b74df6b..571c199abb 100644
--- a/datafusion/physical-plan/src/joins/stream_join_utils.rs
+++ b/datafusion/physical-plan/src/joins/stream_join_utils.rs
@@ -377,7 +377,7 @@ fn convert_filter_columns(
column_map: &HashMap<Column, Column>,
) -> Result<Option<Arc<dyn PhysicalExpr>>> {
// Attempt to downcast the input expression to a Column type.
- Ok(if let Some(col) = input.as_any().downcast_ref::<Column>() {
+ Ok(if let Some(col) = input.downcast_ref::<Column>() {
// If the downcast is successful, retrieve the corresponding filter column.
column_map.get(col).map(|c| Arc::new(c.clone()) as _)
} else {
diff --git a/datafusion/physical-plan/src/joins/utils.rs b/datafusion/physical-plan/src/joins/utils.rs
index b0ecf7b789..a5ac890163 100644
--- a/datafusion/physical-plan/src/joins/utils.rs
+++ b/datafusion/physical-plan/src/joins/utils.rs
@@ -472,8 +472,8 @@ fn estimate_join_cardinality(
.iter()
.map(|(left, right)| {
match (
- left.as_any().downcast_ref::<Column>(),
- right.as_any().downcast_ref::<Column>(),
+ left.downcast_ref::<Column>(),
+ right.downcast_ref::<Column>(),
) {
(Some(left), Some(right)) => (
left_stats.column_statistics[left.index()].clone(),
@@ -3009,7 +3009,6 @@ mod tests {
fn assert_col_expr(expr: &Arc<dyn PhysicalExpr>, name: &str, index: usize) {
let col = expr
- .as_any()
.downcast_ref::<Column>()
.expect("Projection items should be Column expression");
assert_eq!(col.name(), name);
diff --git a/datafusion/physical-plan/src/operator_statistics/mod.rs b/datafusion/physical-plan/src/operator_statistics/mod.rs
index ccb437a332..20266e9768 100644
--- a/datafusion/physical-plan/src/operator_statistics/mod.rs
+++ b/datafusion/physical-plan/src/operator_statistics/mod.rs
@@ -697,7 +697,7 @@ impl StatisticsProvider for AggregateStatisticsProvider {
// Compute NDV product of GROUP BY columns
let mut ndv_product: Option<usize> = None;
for (expr, _) in agg.group_expr().expr().iter() {
- let Some(col) = expr.as_any().downcast_ref::<Column>() else {
+ let Some(col) = expr.downcast_ref::<Column>() else {
return Ok(StatisticsResult::Delegate);
};
let Some(&ndv) = input_stats
@@ -800,12 +800,10 @@ impl StatisticsProvider for JoinStatisticsProvider {
let mut ndv_divisor: usize = 1;
for (left_key, right_key) in on {
let left_ndv = left_key
- .as_any()
.downcast_ref::<Column>()
.and_then(|c| left.column_statistics.get(c.index()))
.and_then(|s| s.distinct_count.get_value().copied());
let right_ndv = right_key
- .as_any()
.downcast_ref::<Column>()
.and_then(|c| right.column_statistics.get(c.index()))
.and_then(|s| s.distinct_count.get_value().copied());
diff --git a/datafusion/physical-plan/src/projection.rs b/datafusion/physical-plan/src/projection.rs
index 9cb4382e21..e5b91fbb1c 100644
--- a/datafusion/physical-plan/src/projection.rs
+++ b/datafusion/physical-plan/src/projection.rs
@@ -442,7 +442,7 @@ impl ExecutionPlan for ProjectionExec {
// Recursively transform the expression
let mut can_pushdown = true;
let transformed = Arc::clone(&sort_expr.expr).transform(|expr| {
- if let Some(col) = expr.as_any().downcast_ref::<Column>() {
+ if let Some(col) = expr.downcast_ref::<Column>() {
// Check if column index is valid.
// This should always be true but fail gracefully if it's not.
if col.index() >= self.expr().len() {
@@ -455,9 +455,7 @@ impl ExecutionPlan for ProjectionExec {
// Check if projection expression is a simple column
// We cannot push down order by clauses that depend on
// projected computations as they would have nothing to reference.
- if let Some(child_col) =
- proj_expr.expr.as_any().downcast_ref::<Column>()
- {
+ if let Some(child_col) = proj_expr.expr.downcast_ref::<Column>() {
// Replace with the child column
Ok(Transformed::yes(Arc::new(child_col.clone()) as _))
} else {
@@ -750,7 +748,7 @@ pub fn remove_unnecessary_projections(
fn is_projection_removable(projection: &ProjectionExec) -> bool {
let exprs = projection.expr();
exprs.iter().enumerate().all(|(idx, proj_expr)| {
- let Some(col) = proj_expr.expr.as_any().downcast_ref::<Column>() else {
+ let Some(col) = proj_expr.expr.downcast_ref::<Column>() else {
return false;
};
col.name() == proj_expr.alias && col.index() == idx
@@ -763,7 +761,6 @@ pub fn all_alias_free_columns(exprs: &[ProjectionExpr]) -> bool {
exprs.iter().all(|proj_expr| {
proj_expr
.expr
- .as_any()
.downcast_ref::<Column>()
.map(|column| column.name() == proj_expr.alias)
.unwrap_or(false)
@@ -782,7 +779,6 @@ pub fn new_projections_for_columns(
.filter_map(|proj_expr| {
proj_expr
.expr
- .as_any()
.downcast_ref::<Column>()
.map(|expr| source[expr.index()])
})
@@ -801,9 +797,7 @@ pub fn make_with_child(
/// Returns `true` if all the expressions in the argument are `Column`s.
pub fn all_columns(exprs: &[ProjectionExpr]) -> bool {
- exprs
- .iter()
- .all(|proj_expr| proj_expr.expr.as_any().is::<Column>())
+ exprs.iter().all(|proj_expr| proj_expr.expr.is::<Column>())
}
/// Updates the given lexicographic ordering according to given projected
@@ -852,7 +846,6 @@ pub fn physical_to_column_exprs(
.map(|proj_expr| {
proj_expr
.expr
- .as_any()
.downcast_ref::<Column>()
.map(|col| (col.clone(), proj_expr.alias.clone()))
})
@@ -1035,7 +1028,7 @@ fn try_unifying_projections(
.expr
.apply(|expr| {
Ok({
- if let Some(column) = expr.as_any().downcast_ref::<Column>() {
+ if let Some(column) = expr.downcast_ref::<Column>() {
*column_ref_map.entry(column.clone()).or_default() += 1;
}
TreeNodeRecursion::Continue
@@ -1083,7 +1076,7 @@ fn collect_column_indices(exprs: &[ProjectionExpr]) -> Vec<usize> {
let mut seen = std::collections::HashSet::new();
let mut indices = Vec::new();
for proj_expr in exprs {
- if let Some(col) = proj_expr.expr.as_any().downcast_ref::<Column>() {
+ if let Some(col) = proj_expr.expr.downcast_ref::<Column>() {
// Simple column reference: preserve projection order.
if seen.insert(col.index()) {
indices.push(col.index());
@@ -1095,7 +1088,7 @@ fn collect_column_indices(exprs: &[ProjectionExpr]) -> Vec<usize> {
proj_expr
.expr
.apply(|expr| {
- if let Some(col) = expr.as_any().downcast_ref::<Column>()
+ if let Some(col) = expr.downcast_ref::<Column>()
&& seen.insert(col.index())
{
indices.push(col.index());
@@ -1151,7 +1144,7 @@ fn new_columns_for_join_on(
// Rewrite all columns in `on`
Arc::clone(*on)
.transform(|expr| {
- if let Some(column) = expr.as_any().downcast_ref::<Column>() {
+ if let Some(column) = expr.downcast_ref::<Column>() {
// Find the column in the projection expressions
let new_column = projection_exprs
.iter()
diff --git a/datafusion/proto/src/physical_plan/to_proto.rs b/datafusion/proto/src/physical_plan/to_proto.rs
index 990a54cf94..f8665df339 100644
--- a/datafusion/proto/src/physical_plan/to_proto.rs
+++ b/datafusion/proto/src/physical_plan/to_proto.rs
@@ -259,8 +259,7 @@ pub fn serialize_physical_expr_with_converter(
) -> Result<protobuf::PhysicalExprNode> {
// Snapshot the expr in case it has dynamic predicate state so
// it can be serialized
- let value = snapshot_physical_expr(Arc::clone(value))?;
- let expr = value.as_any();
+ let expr = snapshot_physical_expr(Arc::clone(value))?;
// HashTableLookupExpr is used for dynamic filter pushdown in hash joins.
// It contains an Arc<dyn JoinHashMapType> (the build-side hash table) which
@@ -506,7 +505,7 @@ pub fn serialize_physical_expr_with_converter(
})
} else {
let mut buf: Vec<u8> = vec![];
- match codec.try_encode_expr(&value, &mut buf) {
+ match codec.try_encode_expr(value, &mut buf) {
Ok(_) => {
let inputs: Vec<protobuf::PhysicalExprNode> = value
.children()
diff --git a/datafusion/proto/tests/cases/roundtrip_physical_plan.rs b/datafusion/proto/tests/cases/roundtrip_physical_plan.rs
index 15639bcd25..58b2771785 100644
--- a/datafusion/proto/tests/cases/roundtrip_physical_plan.rs
+++ b/datafusion/proto/tests/cases/roundtrip_physical_plan.rs
@@ -15,7 +15,6 @@
// specific language governing permissions and limitations
// under the License.
-use std::any::Any;
use std::collections::HashMap;
use std::fmt::{Display, Formatter};
use std::sync::{Arc, RwLock};
@@ -1100,10 +1099,6 @@ fn roundtrip_parquet_exec_with_custom_predicate_expr() -> Result<()> {
}
impl PhysicalExpr for CustomPredicateExpr {
- fn as_any(&self) -> &dyn Any {
- self
- }
-
fn data_type(&self, _input_schema: &Schema) -> Result<DataType> {
unreachable!()
}
@@ -1171,11 +1166,7 @@ fn roundtrip_parquet_exec_with_custom_predicate_expr() -> Result<()> {
node: &Arc<dyn PhysicalExpr>,
buf: &mut Vec<u8>,
) -> Result<()> {
- if node
- .as_any()
- .downcast_ref::<CustomPredicateExpr>()
- .is_some()
- {
+ if node.downcast_ref::<CustomPredicateExpr>().is_some() {
buf.extend_from_slice("CustomPredicateExpr".as_bytes());
Ok(())
} else {
@@ -2519,7 +2510,7 @@ fn roundtrip_hash_table_lookup_expr_to_lit() -> Result<()> {
// Verify the filter predicate is a Literal(true)
let result_filter = result.downcast_ref::<FilterExec>().unwrap();
let predicate = result_filter.predicate();
- let literal = predicate.as_any().downcast_ref::<Literal>().unwrap();
+ let literal = predicate.downcast_ref::<Literal>().unwrap();
assert_eq!(*literal.value(), ScalarValue::Boolean(Some(true)));
Ok(())
@@ -2862,10 +2853,7 @@ fn test_backward_compatibility_no_expr_id() -> Result<()> {
)?;
// Verify the result is correct
- let col = result
- .as_any()
- .downcast_ref::<Column>()
- .expect("Expected Column");
+ let col = result.downcast_ref::<Column>().expect("Expected Column");
assert_eq!(col.name(), "a");
assert_eq!(col.index(), 0);
@@ -2996,7 +2984,6 @@ fn test_deduplication_within_expr_deserialization() -> Result<()> {
// Check that deduplication worked within the deserialization
let binary1 = expr1
- .as_any()
.downcast_ref::<BinaryExpr>()
.expect("Expected BinaryExpr");
assert!(
@@ -3014,7 +3001,6 @@ fn test_deduplication_within_expr_deserialization() -> Result<()> {
// Check that the second expression was also deserialized correctly
let binary2 = expr2
- .as_any()
.downcast_ref::<BinaryExpr>()
.expect("Expected BinaryExpr");
assert!(
diff --git a/datafusion/pruning/src/pruning_predicate.rs b/datafusion/pruning/src/pruning_predicate.rs
index 8ca8264fe3..76cf14be88 100644
--- a/datafusion/pruning/src/pruning_predicate.rs
+++ b/datafusion/pruning/src/pruning_predicate.rs
@@ -695,15 +695,13 @@ impl BoolVecBuilder {
}
fn is_always_true(expr: &Arc<dyn PhysicalExpr>) -> bool {
- expr.as_any()
- .downcast_ref::<phys_expr::Literal>()
+ expr.downcast_ref::<phys_expr::Literal>()
.map(|l| matches!(l.value(), ScalarValue::Boolean(Some(true))))
.unwrap_or_default()
}
fn is_always_false(expr: &Arc<dyn PhysicalExpr>) -> bool {
- expr.as_any()
- .downcast_ref::<phys_expr::Literal>()
+ expr.downcast_ref::<phys_expr::Literal>()
.map(|l| matches!(l.value(), ScalarValue::Boolean(Some(false))))
.unwrap_or_default()
}
@@ -1113,15 +1111,10 @@ fn rewrite_expr_to_prunable(
return plan_err!("rewrite_expr_to_prunable only support compare expression");
}
- let column_expr_any = column_expr.as_any();
-
- if column_expr_any
- .downcast_ref::<phys_expr::Column>()
- .is_some()
- {
+ if column_expr.downcast_ref::<phys_expr::Column>().is_some() {
// `col op lit()`
Ok((Arc::clone(column_expr), op, Arc::clone(scalar_expr)))
- } else if let Some(cast) = column_expr_any.downcast_ref::<phys_expr::CastExpr>() {
+ } else if let Some(cast) = column_expr.downcast_ref::<phys_expr::CastExpr>() {
// `cast(col) op lit()`
let (left, op, right) = rewrite_cast_child_to_prunable(
cast.expr(),
@@ -1140,9 +1133,7 @@ fn rewrite_expr_to_prunable(
// extraction to agree with PruningPredicate on a stats representation
// for nested field expressions.
Ok((left, op, right))
- } else if let Some(try_cast) =
- column_expr_any.downcast_ref::<phys_expr::TryCastExpr>()
- {
+ } else if let Some(try_cast) = column_expr.downcast_ref::<phys_expr::TryCastExpr>() {
// `try_cast(col) op lit()`
let (left, op, right) = rewrite_cast_child_to_prunable(
try_cast.expr(),
@@ -1156,23 +1147,18 @@ fn rewrite_expr_to_prunable(
try_cast.cast_type().clone(),
));
Ok((left, op, right))
- } else if let Some(neg) = column_expr_any.downcast_ref::<phys_expr::NegativeExpr>() {
+ } else if let Some(neg) = column_expr.downcast_ref::<phys_expr::NegativeExpr>() {
// `-col > lit()` --> `col < -lit()`
let (left, op, right) =
rewrite_expr_to_prunable(neg.arg(), op, scalar_expr, schema)?;
let right = Arc::new(phys_expr::NegativeExpr::new(right));
Ok((left, reverse_operator(op)?, right))
- } else if let Some(not) = column_expr_any.downcast_ref::<phys_expr::NotExpr>() {
+ } else if let Some(not) = column_expr.downcast_ref::<phys_expr::NotExpr>() {
// `!col = true` --> `col = !true`
if op != Operator::Eq && op != Operator::NotEq {
return plan_err!("Not with operator other than Eq / NotEq is not supported");
}
- if not
- .arg()
- .as_any()
- .downcast_ref::<phys_expr::Column>()
- .is_some()
- {
+ if not.arg().downcast_ref::<phys_expr::Column>().is_some() {
let left = Arc::clone(not.arg());
let right = Arc::new(phys_expr::NotExpr::new(Arc::clone(scalar_expr)));
Ok((left, reverse_operator(op)?, right))
@@ -1249,7 +1235,7 @@ fn rewrite_column_expr(
column_new: &phys_expr::Column,
) -> Result<Arc<dyn PhysicalExpr>> {
e.transform(|expr| {
- if let Some(column) = expr.as_any().downcast_ref::<phys_expr::Column>()
+ if let Some(column) = expr.downcast_ref::<phys_expr::Column>()
&& column == column_old
{
return Ok(Transformed::yes(Arc::new(column_new.clone())));
@@ -1323,7 +1309,7 @@ fn build_is_null_column_expr(
required_columns: &mut RequiredColumns,
with_not: bool,
) -> Option<Arc<dyn PhysicalExpr>> {
- if let Some(col) = expr.as_any().downcast_ref::<phys_expr::Column>() {
+ if let Some(col) = expr.downcast_ref::<phys_expr::Column>() {
let field = schema.field_with_name(col.name()).ok()?;
let null_count_field = &Field::new(field.name(), DataType::UInt64, true);
@@ -1440,12 +1426,11 @@ fn build_predicate_expression(
return Arc::clone(expr);
}
// predicate expression can only be a binary expression
- let expr_any = expr.as_any();
- if let Some(is_null) = expr_any.downcast_ref::<phys_expr::IsNullExpr>() {
+ if let Some(is_null) = expr.downcast_ref::<phys_expr::IsNullExpr>() {
return build_is_null_column_expr(is_null.arg(), schema, required_columns, false)
.unwrap_or_else(|| unhandled_hook.handle(expr));
}
- if let Some(is_not_null) = expr_any.downcast_ref::<phys_expr::IsNotNullExpr>() {
+ if let Some(is_not_null) = expr.downcast_ref::<phys_expr::IsNotNullExpr>() {
return build_is_null_column_expr(
is_not_null.arg(),
schema,
@@ -1454,20 +1439,20 @@ fn build_predicate_expression(
)
.unwrap_or_else(|| unhandled_hook.handle(expr));
}
- if let Some(col) = expr_any.downcast_ref::<phys_expr::Column>() {
+ if let Some(col) = expr.downcast_ref::<phys_expr::Column>() {
return build_single_column_expr(col, schema, required_columns, false)
.unwrap_or_else(|| unhandled_hook.handle(expr));
}
- if let Some(not) = expr_any.downcast_ref::<phys_expr::NotExpr>() {
+ if let Some(not) = expr.downcast_ref::<phys_expr::NotExpr>() {
// match !col (don't do so recursively)
- if let Some(col) = not.arg().as_any().downcast_ref::<phys_expr::Column>() {
+ if let Some(col) = not.arg().downcast_ref::<phys_expr::Column>() {
return build_single_column_expr(col, schema, required_columns, true)
.unwrap_or_else(|| unhandled_hook.handle(expr));
} else {
return unhandled_hook.handle(expr);
}
}
- if let Some(in_list) = expr_any.downcast_ref::<phys_expr::InListExpr>() {
+ if let Some(in_list) = expr.downcast_ref::<phys_expr::InListExpr>() {
if !in_list.list().is_empty()
&& in_list.list().len() <= MAX_LIST_VALUE_SIZE_REWRITE
{
@@ -1505,13 +1490,13 @@ fn build_predicate_expression(
}
let (left, op, right) = {
- if let Some(bin_expr) = expr_any.downcast_ref::<phys_expr::BinaryExpr>() {
+ if let Some(bin_expr) = expr.downcast_ref::<phys_expr::BinaryExpr>() {
(
Arc::clone(bin_expr.left()),
*bin_expr.op(),
Arc::clone(bin_expr.right()),
)
- } else if let Some(like_expr) = expr_any.downcast_ref::<phys_expr::LikeExpr>() {
+ } else if let Some(like_expr) = expr.downcast_ref::<phys_expr::LikeExpr>() {
if like_expr.case_insensitive() {
return unhandled_hook.handle(expr);
}
@@ -1607,7 +1592,7 @@ impl ColumnReferenceCount {
fn from_expression(expr: &Arc<dyn PhysicalExpr>) -> Self {
let mut seen = HashSet::<phys_expr::Column>::new();
expr.apply(|expr| {
- if let Some(column) = expr.as_any().downcast_ref::<phys_expr::Column>() {
+ if let Some(column) = expr.downcast_ref::<phys_expr::Column>() {
seen.insert(column.clone());
if seen.len() > 1 {
return Ok(TreeNodeRecursion::Stop);
@@ -1725,7 +1710,7 @@ fn unpack_string(s: &ScalarValue) -> Option<&str> {
}
fn extract_string_literal(expr: &Arc<dyn PhysicalExpr>) -> Option<&str> {
- if let Some(lit) = expr.as_any().downcast_ref::<phys_expr::Literal>() {
+ if let Some(lit) = expr.downcast_ref::<phys_expr::Literal>() {
let s = unpack_string(lit.value())?;
return Some(s);
}
@@ -2994,8 +2979,7 @@ mod tests {
.children()
.into_iter()
.map(|child_expr| {
- let Some(col_expr) =
- child_expr.as_any().downcast_ref::<phys_expr::Column>()
+ let Some(col_expr) = child_expr.downcast_ref::<phys_expr::Column>()
else {
return Arc::clone(child_expr);
};
diff --git a/docs/source/library-user-guide/upgrading/54.0.0.md b/docs/source/library-user-guide/upgrading/54.0.0.md
index 16606a0f40..da1db6de32 100644
--- a/docs/source/library-user-guide/upgrading/54.0.0.md
+++ b/docs/source/library-user-guide/upgrading/54.0.0.md
@@ -201,89 +201,20 @@ let mut stats = Arc::unwrap_or_clone(plan.partition_statistics(None)?);
stats.column_statistics[0].min_value = ...;
```
-### Remove `as_any` from `ScalarUDFImpl`, `AggregateUDFImpl`, `WindowUDFImpl`, `ExecutionPlan`, `TableProvider`, `SchemaProvider`, `CatalogProvider`, and `CatalogProviderList`
+### Remove `as_any` from `PhysicalExpr`, `ScalarUDFImpl`, `AggregateUDFImpl`, `WindowUDFImpl`, `ExecutionPlan`, `TableProvider`, `SchemaProvider`, `CatalogProvider`, and `CatalogProviderList`
Now that we have a more recent minimum version of Rust, we can take advantage of
trait upcasting. This reduces the amount of boilerplate code that
-users need to implement. In your implementations of `ScalarUDFImpl`,
-`AggregateUDFImpl`, `WindowUDFImpl`, `ExecutionPlan`, `TableProvider`,
-`SchemaProvider`, `CatalogProvider`, and `CatalogProviderList`, you can simply
-remove the `as_any` function. The below diffs are examples from the associated
-PRs.
-
-**Scalar UDFs:**
-
-```diff
- impl ScalarUDFImpl for MyEq {
-- fn as_any(&self) -> &dyn Any {
-- self
-- }
--
- fn name(&self) -> &str {
- "my_eq"
- }
-
- ...
- }
-```
-
-**Aggregate UDFs:**
-
-```diff
- impl AggregateUDFImpl for GeoMeanUdf {
-- fn as_any(&self) -> &dyn Any {
-- self
-- }
--
- fn name(&self) -> &str {
- "geo_mean"
- }
-
- ...
- }
-```
-
-**Window UDFs:**
-
-```diff
- impl WindowUDFImpl for SmoothIt {
-- fn as_any(&self) -> &dyn Any {
-- self
-- }
--
- fn name(&self) -> &str {
- "smooth_it"
- }
-
- ...
- }
-```
-
-**Execution Plans:**
-
-```diff
- impl ExecutionPlan for MyExec {
-- fn as_any(&self) -> &dyn Any {
-- self
-- }
--
- fn name(&self) -> &'static str {
- "MyExec"
- }
-
- ...
- }
-```
-
-**Table Providers:**
+users need to implement. In your implementations of the traits listed above,
+you can simply remove the `as_any` function. For example:
```diff
- impl TableProvider for MyTable {
+ impl PhysicalExpr for MyExpr {
- fn as_any(&self) -> &dyn Any {
- self
- }
-
- fn schema(&self) -> SchemaRef {
+ fn data_type(&self, input_schema: &Schema) -> Result<DataType> {
...
}
@@ -291,79 +222,19 @@ PRs.
}
```
-**Schema Providers:**
-
-```diff
- impl SchemaProvider for MySchema {
-- fn as_any(&self) -> &dyn Any {
-- self
-- }
--
- fn table_names(&self) -> Vec<String> {
- ...
- }
-
- ...
- }
-```
+The same change applies to all of the above traits — simply delete the
+`as_any` method from each implementation.
-**Catalog Providers:**
+If you have code that is downcasting, you can drop the `.as_any()` call
+and use `downcast_ref` / `is` directly on the trait object:
```diff
- impl CatalogProvider for MyCatalog {
-- fn as_any(&self) -> &dyn Any {
-- self
-- }
--
- fn schema_names(&self) -> Vec<String> {
- ...
- }
-
- ...
- }
-```
-
-**Catalog Provider Lists:**
-
-```diff
- impl CatalogProviderList for MyCatalogList {
-- fn as_any(&self) -> &dyn Any {
-- self
-- }
--
- fn register_catalog(
- ...
- }
-
- ...
- }
-```
-
-If you have code that is downcasting, you can use the new `downcast_ref`
-and `is` methods defined directly on each trait object:
-
-**Before:**
-
-```rust,ignore
-let exec = plan.as_any().downcast_ref::<MyExec>().unwrap();
-let udf = scalar_udf.as_any().downcast_ref::<MyUdf>().unwrap();
-let table = table_provider.as_any().downcast_ref::<MyTable>().unwrap();
-```
-
-**After:**
-
-```rust,ignore
-let exec = plan.downcast_ref::<MyExec>().unwrap();
-let udf = scalar_udf.downcast_ref::<MyUdf>().unwrap();
-let table = table_provider.downcast_ref::<MyTable>().unwrap();
+-let exec = plan.as_any().downcast_ref::<MyExec>().unwrap();
++let exec = plan.downcast_ref::<MyExec>().unwrap();
```
-These methods are available on `dyn ExecutionPlan`, `dyn TableProvider`,
-`dyn SchemaProvider`, `dyn CatalogProvider`, `dyn CatalogProviderList`,
-`dyn ScalarUDFImpl`, `dyn AggregateUDFImpl`, and `dyn WindowUDFImpl`.
-They work correctly
-whether the value is a bare reference or behind an `Arc` (Rust
-auto-derefs through the `Arc`).
+These methods work correctly whether the value is a bare reference or
+behind an `Arc` (Rust auto-derefs through the `Arc`).
> **Warning:** Do not cast an `Arc<dyn Trait>` directly to `&dyn Any`.
> Writing `(&plan as &dyn Any)` gives you an `Any` reference to the
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@datafusion.apache.org
For additional commands, e-mail: commits-help@datafusion.apache.org