You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
ProjectionExec produces unknown statistics for all ScalarFunctionExpr outputs #21307
Is your feature request related to a problem or challenge?
ProjectionExec::project_statistics() only propagates column statistics for plain Column references and Literal values. Any ScalarFunctionExpr like get_field(), variant_get, or any UDF produces ColumnStatistics::new_unknown():
// TODO stats: estimate more statistics from expressions
// (expressions should compute their statistics themselves)
ColumnStatistics::new_unknown()
This means every column produced by a scalar function has Absent min/max/null_count/distinct_count, even when the function is a pure extraction (get_field, variant_get), a monotonic transformation (cast, abs), or any UDF where output stats are derivable from input stats
Describe the solution you'd like
Add an optional method to ScalarUdfImpl:
something like fn output_statistics(&self, input_statistics: &[ColumnStatistics]) -> Option<ColumnStatistics>
This way, ProjectionExec::project_statistics would call this before falling back to unknown
How this affects Struct + Variant queries
This matters for struct/variant queries especially, most output columns come through get_field or equivalent UDFs, so the cost model is effectively blind!
cost based join ordering can't estimate cardinality for join keys produced by udfs
aggregation planning can't estimate group count for group by on udf outputs
filterexec selectivity - can't narrow row estimates for filters on udf outputs
@friendlymatthew, this is exactly the use case #21122 (ExpressionAnalyzer) is designed for: a pluggable chain-of-responsibility for expression-level statistics (NDV, min/max, null fraction, selectivity) over any PhysicalExpr.
Users implement ExpressionAnalyzer for their functions and register it via SessionState, it's more general than output_statistics on ScalarUdfImpl since it handles composed expressions and doesn't require touching UDF implementations.
Activity
friendlymatthew commentedon Apr 1, 2026
@alamb, any chance you could tag people who are knowledgable about
ScalarUdfImpl?alamb commentedon Apr 7, 2026
Maybe this is someting that @xudong963 or @jonathanc-n have some insight into
We already have some notion of expression range analysis (that could be applied ot the problem of min/max propagation)
asolimando commentedon Apr 8, 2026
@friendlymatthew, this is exactly the use case #21122 (ExpressionAnalyzer) is designed for: a pluggable chain-of-responsibility for expression-level statistics (NDV, min/max, null fraction, selectivity) over any
PhysicalExpr.Users implement
ExpressionAnalyzerfor their functions and register it viaSessionState, it's more general thanoutput_statisticsonScalarUdfImplsince it handles composed expressions and doesn't require touching UDF implementations.Happy to elaborate if useful!
xudong963 commentedon Apr 9, 2026
I haven't had a chance to take a careful look at #21122, but it looks good.
@friendlymatthew, if the ExpressionAnalyzer can make your case work well, we can collaborate to move it forward into main.