Class ExternalSourceAggregatePushdown
java.lang.Object
org.elasticsearch.xpack.esql.optimizer.rules.physical.local.ExternalSourceAggregatePushdown
Shared helpers for the aggregate pushdown rule (
PushStatsToExternalSource) and the
split-discovery gate (ComputeService.canSkipForAggregateOverExternal) that extract an
ExternalSourceExec from the plan tree and resolve filtered metadata using
SplitFilterClassifier.-
Method Summary
Modifier and TypeMethodDescriptionstatic booleancanServeAllFromStats(List<? extends NamedExpression> aggregates, SplitStats stats, boolean implicitNullsForAbsentColumn, Set<String> pathDerivedColumns) Whether EVERY aggregate inaggregateswould resolve fromstats— the boolean twin ofPushStatsToExternalSource's value-collecting loop.static List<Expression> extractAggregateFunctions(List<? extends Expression> aggregates) Unwraps theAggregateFunctionoperands of an ungrouped aggregate's output, dropping any non-aggregate expressions (e.g.static ExternalSourceExecfindExternalSource(PhysicalPlan child) Light-weight projection ofextractExternalSource(PhysicalPlan)that returns just theExternalSourceExec(ornull) for callers that don't need the alias map or filter condition.partitionColumnNames(Map<String, Object> sourceMetadata) The columns whose values are derived from the file's directory PATH (Hive-style partition keys), not its payload.
-
Method Details
-
extractAggregateFunctions
Unwraps theAggregateFunctionoperands of an ungrouped aggregate's output, dropping any non-aggregate expressions (e.g. bare literals). This is the input every format'sAggregatePushdownSupport.canPushAggregates(java.util.List<org.elasticsearch.xpack.esql.core.expression.Expression>, java.util.List<org.elasticsearch.xpack.esql.core.expression.Expression>)type-gate consumes — shared byPushStatsToExternalSource(fold) andComputeService.canSkipForAggregateOverExternal(split-discovery gate) so both feed the gate the same function list. -
canServeAllFromStats
public static boolean canServeAllFromStats(List<? extends NamedExpression> aggregates, SplitStats stats, boolean implicitNullsForAbsentColumn, Set<String> pathDerivedColumns) Whether EVERY aggregate inaggregateswould resolve fromstats— the boolean twin ofPushStatsToExternalSource's value-collecting loop. The split-discovery gate (ComputeService.canSkipSplitDiscovery) must consult THIS check, not just the type-levelAggregatePushdownSupport.canPushAggregates(java.util.List<org.elasticsearch.xpack.esql.core.expression.Expression>, java.util.List<org.elasticsearch.xpack.esql.core.expression.Expression>): the two previously diverged on per-column servability, so the gate would skip discovery (leaving a zero-split scan) for an aggregate the fold then safe-missed, and the scan's un-pruned union_by_name mapping trippedSchemaAdaptingIterator's width guard (the union_by_name zero-split servability guard). SharingresolveFromStatswith the fold guarantees "gate skips" implies "fold serves". The bail conditions here must stay identical toPushStatsToExternalSource's value loop. -
partitionColumnNames
The columns whose values are derived from the file's directory PATH (Hive-style partition keys), not its payload. They are absent from every file's column stats, so the implicit-nulls contract reads them as all-null — anyCOUNTover one would serve 0. Both the fold and the split-discovery gate feed this set toresolveFromStats(org.elasticsearch.xpack.esql.core.expression.Expression, org.elasticsearch.xpack.esql.datasources.spi.SplitStats, boolean, java.util.Set<java.lang.String>)so a partition-column aggregate safe-misses on footer formats.Read from the SERIALIZED
sourceMetadata(stamped at resolution — seeSourceStatisticsSerializer#PARTITION_COLUMNS_KEY), NOT theFileList: the fileList that carriesPartitionMetadatais coordinator-only and deserializes toUNRESOLVEDon a data node, so the data-node fold would otherwise see an empty set and foldCOUNT(partition_col)to 0. Empty when the source is not partitioned (nohive_partitioning). -
findExternalSource
Light-weight projection ofextractExternalSource(PhysicalPlan)that returns just theExternalSourceExec(ornull) for callers that don't need the alias map or filter condition. Cross-package callers (the planner, other optimizer rules) use this so they share the same set of recognized wrapper shapes — adding a new shape here automatically propagates.
-