use of org.apache.calcite.rel.core.Aggregate in project flink by apache.
the class RelTimeIndicatorConverter method gatherIndicesToMaterialize.
private Set<Integer> gatherIndicesToMaterialize(Aggregate agg, RelNode newInput) {
List<RelDataType> inputFieldTypes = RelOptUtil.getFieldTypeList(newInput.getRowType());
Predicate<Integer> isTimeIndicator = idx -> isTimeIndicatorType(inputFieldTypes.get(idx));
// add arguments of agg calls
Set<Integer> aggCallArgs = agg.getAggCallList().stream().map(AggregateCall::getArgList).flatMap(List::stream).filter(isTimeIndicator).collect(Collectors.toSet());
FlinkRelMetadataQuery fmq = FlinkRelMetadataQuery.reuseOrCreate(agg.getCluster().getMetadataQuery());
RelWindowProperties windowProps = fmq.getRelWindowProperties(newInput);
// add grouping sets
Set<Integer> groupSets = agg.getGroupSets().stream().map(grouping -> {
if (windowProps != null && groupingContainsWindowStartEnd(grouping, windowProps)) {
// of window_time column
return grouping.except(windowProps.getWindowTimeColumns());
} else {
return grouping;
}
}).flatMap(set -> set.asList().stream()).filter(isTimeIndicator).collect(Collectors.toSet());
Set<Integer> timeIndicatorIndices = new HashSet<>(aggCallArgs);
timeIndicatorIndices.addAll(groupSets);
return timeIndicatorIndices;
}
use of org.apache.calcite.rel.core.Aggregate in project druid by druid-io.
the class DruidQuery method computeAggregations.
/**
* Returns aggregations corresponding to {@code aggregate.getAggCallList()}, in the same order.
*
* @param partialQuery partial query
* @param plannerContext planner context
* @param rowSignature source row signature
* @param virtualColumnRegistry re-usable virtual column references
* @param rexBuilder calcite RexBuilder
* @param finalizeAggregations true if this query should include explicit finalization for all of its
* aggregators, where required. Useful for subqueries where Druid's native query layer
* does not do this automatically.
*
* @return aggregations
*
* @throws CannotBuildQueryException if dimensions cannot be computed
*/
private static List<Aggregation> computeAggregations(final PartialDruidQuery partialQuery, final PlannerContext plannerContext, final RowSignature rowSignature, final VirtualColumnRegistry virtualColumnRegistry, final RexBuilder rexBuilder, final boolean finalizeAggregations) {
final Aggregate aggregate = Preconditions.checkNotNull(partialQuery.getAggregate());
final List<Aggregation> aggregations = new ArrayList<>();
final String outputNamePrefix = Calcites.findUnusedPrefixForDigits("a", rowSignature.getColumnNames());
for (int i = 0; i < aggregate.getAggCallList().size(); i++) {
final String aggName = outputNamePrefix + i;
final AggregateCall aggCall = aggregate.getAggCallList().get(i);
final Aggregation aggregation = GroupByRules.translateAggregateCall(plannerContext, rowSignature, virtualColumnRegistry, rexBuilder, partialQuery.getSelectProject(), aggregations, aggName, aggCall, finalizeAggregations);
if (aggregation == null) {
if (null == plannerContext.getPlanningError()) {
plannerContext.setPlanningError("Aggregation [%s] is not supported", aggCall);
}
throw new CannotBuildQueryException(aggregate, aggCall);
}
aggregations.add(aggregation);
}
return aggregations;
}
use of org.apache.calcite.rel.core.Aggregate in project druid by druid-io.
the class DruidQuery method computeSubtotals.
/**
* Builds a {@link Subtotals} object based on {@link Aggregate#getGroupSets()}.
*/
private static Subtotals computeSubtotals(final PartialDruidQuery partialQuery, final RowSignature rowSignature) {
final Aggregate aggregate = partialQuery.getAggregate();
// dimBitMapping maps from input field position to group set position (dimension number).
final int[] dimBitMapping;
if (partialQuery.getSelectProject() != null) {
dimBitMapping = new int[partialQuery.getSelectProject().getRowType().getFieldCount()];
} else {
dimBitMapping = new int[rowSignature.size()];
}
int i = 0;
for (int dimBit : aggregate.getGroupSet()) {
dimBitMapping[dimBit] = i++;
}
// Use dimBitMapping to remap groupSets (which is input-field-position based) into subtotals (which is
// dimension-list-position based).
final List<IntList> subtotals = new ArrayList<>();
for (ImmutableBitSet groupSet : aggregate.getGroupSets()) {
final IntList subtotal = new IntArrayList();
for (int dimBit : groupSet) {
subtotal.add(dimBitMapping[dimBit]);
}
subtotals.add(subtotal);
}
return new Subtotals(subtotals);
}
use of org.apache.calcite.rel.core.Aggregate in project beam by apache.
the class BeamAggregationRule method onMatch.
@Override
public void onMatch(RelOptRuleCall call) {
final Aggregate aggregate = call.rel(0);
final Project project = call.rel(1);
if (aggregate.getGroupType() != Aggregate.Group.SIMPLE) {
return;
}
RelNode x = updateWindow(aggregate, project);
if (x == null) {
// Non-windowed case should be handled by the BeamBasicAggregationRule
return;
}
call.transformTo(x);
}
use of org.apache.calcite.rel.core.Aggregate in project druid by druid-io.
the class ProjectAggregatePruneUnusedCallRule method onMatch.
@Override
public void onMatch(final RelOptRuleCall call) {
final Project project = call.rel(0);
final Aggregate aggregate = call.rel(1);
final ImmutableBitSet projectBits = RelOptUtil.InputFinder.bits(project.getChildExps(), null);
final int fieldCount = aggregate.getGroupCount() + aggregate.getAggCallList().size();
if (fieldCount != aggregate.getRowType().getFieldCount()) {
throw new ISE("Expected[%s] to have[%s] fields but it had[%s]", aggregate, fieldCount, aggregate.getRowType().getFieldCount());
}
final ImmutableBitSet callsToKeep = projectBits.intersect(ImmutableBitSet.range(aggregate.getGroupCount(), fieldCount));
if (callsToKeep.cardinality() < aggregate.getAggCallList().size()) {
// There are some aggregate calls to prune.
final List<AggregateCall> newAggregateCalls = new ArrayList<>();
for (int i : callsToKeep) {
newAggregateCalls.add(aggregate.getAggCallList().get(i - aggregate.getGroupCount()));
}
final Aggregate newAggregate = aggregate.copy(aggregate.getTraitSet(), aggregate.getInput(), aggregate.getGroupSet(), aggregate.getGroupSets(), newAggregateCalls);
// Project that will match the old Aggregate in its row type, so we can layer the original "project" on top.
final List<RexNode> fixUpProjects = new ArrayList<>();
final RexBuilder rexBuilder = aggregate.getCluster().getRexBuilder();
// Project the group set unchanged.
for (int i = 0; i < aggregate.getGroupCount(); i++) {
fixUpProjects.add(rexBuilder.makeInputRef(newAggregate, i));
}
// Replace pruned-out aggregators with NULLs.
for (int i = aggregate.getGroupCount(), j = aggregate.getGroupCount(); i < fieldCount; i++) {
if (callsToKeep.get(i)) {
fixUpProjects.add(rexBuilder.makeInputRef(newAggregate, j++));
} else {
fixUpProjects.add(rexBuilder.makeNullLiteral(aggregate.getRowType().getFieldList().get(i).getType()));
}
}
call.transformTo(call.builder().push(newAggregate).project(fixUpProjects).project(project.getChildExps()).build());
call.getPlanner().setImportance(project, 0.0);
}
}
Aggregations