Java Code Examples for org.apache.calcite.rel.core.AggregateCall#getAggregation()
The following examples show how to use
org.apache.calcite.rel.core.AggregateCall#getAggregation() .
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: RexBuilder.java From calcite with Apache License 2.0 | 6 votes |
/** * Creates a reference to an aggregate call, checking for repeated calls. * * <p>Argument types help to optimize for repeated aggregates. * For instance count(42) is equivalent to count(*).</p> * * @param aggCall aggregate call to be added * @param groupCount number of groups in the aggregate relation * @param aggCalls destination list of aggregate calls * @param aggCallMapping the dictionary of already added calls * @param aggArgTypes Argument types, not null * * @return Rex expression for the given aggregate call */ public RexNode addAggCall(AggregateCall aggCall, int groupCount, List<AggregateCall> aggCalls, Map<AggregateCall, RexNode> aggCallMapping, final List<RelDataType> aggArgTypes) { if (aggCall.getAggregation() instanceof SqlCountAggFunction && !aggCall.isDistinct()) { final List<Integer> args = aggCall.getArgList(); final List<Integer> nullableArgs = nullableArgs(args, aggArgTypes); if (!nullableArgs.equals(args)) { aggCall = aggCall.copy(nullableArgs, aggCall.filterArg, aggCall.collation); } } RexNode rex = aggCallMapping.get(aggCall); if (rex == null) { int index = aggCalls.size() + groupCount; aggCalls.add(aggCall); rex = makeInputRef(aggCall.getType(), index); aggCallMapping.put(aggCall, rex); } return rex; }
Example 2
Source File: SolrAggregate.java From lucene-solr with Apache License 2.0 | 6 votes |
@SuppressWarnings({"fallthrough"}) private Pair<String, String> toSolrMetric(Implementor implementor, AggregateCall aggCall, List<String> inNames) { SqlAggFunction aggregation = aggCall.getAggregation(); List<Integer> args = aggCall.getArgList(); switch (args.size()) { case 0: if (aggregation.equals(SqlStdOperatorTable.COUNT)) { return new Pair<>(aggregation.getName(), "*"); } case 1: String inName = inNames.get(args.get(0)); String name = implementor.fieldMappings.getOrDefault(inName, inName); if(SUPPORTED_AGGREGATIONS.contains(aggregation)) { return new Pair<>(aggregation.getName(), name); } default: throw new AssertionError("Invalid aggregation " + aggregation + " with args " + args + " with names" + inNames); } }
Example 3
Source File: RelNodeCompiler.java From streamline with Apache License 2.0 | 6 votes |
private void aggregate(AggregateCall call) { SqlAggFunction aggFunction = call.getAggregation(); String aggregationName = call.getAggregation().getName(); Type ty = typeFactory.getJavaClass(call.getType()); if (call.getArgList().size() != 1) { if (aggregationName.equals("COUNT")) { if (call.getArgList().size() != 0) { throw new UnsupportedOperationException("Count with nullable fields"); } } } if (aggFunction instanceof SqlUserDefinedAggFunction) { AggregateFunction aggregateFunction = ((SqlUserDefinedAggFunction) aggFunction).function; doAggregate((AggregateFunctionImpl) aggregateFunction, reserveAggVarName(call), ty, call.getArgList()); } else { List<BuiltinAggregateFunctions.TypeClass> typeClasses = BuiltinAggregateFunctions.TABLE.get(aggregationName); if (typeClasses == null) { throw new UnsupportedOperationException(aggregationName + " Not implemented"); } doAggregate(AggregateFunctionImpl.create(findMatchingClass(aggregationName, typeClasses, ty)), reserveAggVarName(call), ty, call.getArgList()); } }
Example 4
Source File: AggregateUnionTransposeRule.java From Bats with Apache License 2.0 | 5 votes |
private List<AggregateCall> transformAggCalls(RelNode input, int groupCount, List<AggregateCall> origCalls) { final List<AggregateCall> newCalls = new ArrayList<>(); for (Ord<AggregateCall> ord : Ord.zip(origCalls)) { final AggregateCall origCall = ord.e; if (origCall.isDistinct() || !SUPPORTED_AGGREGATES.containsKey(origCall.getAggregation() .getClass())) { return null; } final SqlAggFunction aggFun; final RelDataType aggType; if (origCall.getAggregation() == SqlStdOperatorTable.COUNT) { aggFun = SqlStdOperatorTable.SUM0; // count(any) is always not null, however nullability of sum might // depend on the number of columns in GROUP BY. // Here we use SUM0 since we are sure we will not face nullable // inputs nor we'll face empty set. aggType = null; } else { aggFun = origCall.getAggregation(); aggType = origCall.getType(); } AggregateCall newCall = AggregateCall.create(aggFun, origCall.isDistinct(), origCall.isApproximate(), ImmutableList.of(groupCount + ord.i), -1, origCall.collation, groupCount, input, aggType, origCall.getName()); newCalls.add(newCall); } return newCalls; }
Example 5
Source File: RelToSqlConverter.java From Bats with Apache License 2.0 | 5 votes |
/** @see #dispatch */ public Result visit(Aggregate e) { // "select a, b, sum(x) from ( ... ) group by a, b" final Result x = visitChild(0, e.getInput()); final Builder builder; if (e.getInput() instanceof Project) { builder = x.builder(e); builder.clauses.add(Clause.GROUP_BY); } else { builder = x.builder(e, Clause.GROUP_BY); } List<SqlNode> groupByList = FluentListUtils.list(); final List<SqlNode> selectList = new ArrayList<>(); for (int group : e.getGroupSet()) { final SqlNode field = builder.context.field(group); addSelect(selectList, field, e.getRowType()); groupByList.add(field); } for (AggregateCall aggCall : e.getAggCallList()) { SqlNode aggCallSqlNode = builder.context.toSql(aggCall); if (aggCall.getAggregation() instanceof SqlSingleValueAggFunction) { aggCallSqlNode = dialect. rewriteSingleValueExpr(aggCallSqlNode); } addSelect(selectList, aggCallSqlNode, e.getRowType()); } builder.setSelect(new SqlNodeList(selectList, POS)); if (!groupByList.isEmpty() || e.getAggCallList().isEmpty()) { // Some databases don't support "GROUP BY ()". We can omit it as long // as there is at least one aggregate function. builder.setGroupBy(new SqlNodeList(groupByList, POS)); } return builder.result(); }
Example 6
Source File: RelToSqlConverter.java From dremio-oss with Apache License 2.0 | 5 votes |
/** * @see #dispatch */ public Result visit(Aggregate e) { // "select a, b, sum(x) from ( ... ) group by a, b" final Result x = visitChild(0, e.getInput()); final Builder builder; if (e.getInput() instanceof Project) { builder = x.builder(e); builder.clauses.add(Clause.GROUP_BY); } else { builder = x.builder(e, Clause.GROUP_BY); } List<SqlNode> groupByList = Expressions.list(); final List<SqlNode> selectList = new ArrayList<>(); for (int group : e.getGroupSet()) { final SqlNode field = builder.context.field(group); addSelect(selectList, field, e.getRowType()); groupByList.add(field); } for (AggregateCall aggCall : e.getAggCallList()) { SqlNode aggCallSqlNode = builder.context.toSql(aggCall); if (aggCall.getAggregation() instanceof SqlSingleValueAggFunction) { aggCallSqlNode = dialect. rewriteSingleValueExpr(aggCallSqlNode); } addSelect(selectList, aggCallSqlNode, e.getRowType()); } builder.setSelect(new SqlNodeList(selectList, POS)); if (!groupByList.isEmpty() || e.getAggCallList().isEmpty()) { // Some databases don't support "GROUP BY ()". We can omit it as long // as there is at least one aggregate function. builder.setGroupBy(new SqlNodeList(groupByList, POS)); } return builder.result(); }
Example 7
Source File: FilterAggStarRule.java From quark with Apache License 2.0 | 5 votes |
private AggregateCall getMergedAggCall(Aggregate secondAgg, AggregateCall aggCall) { final int grouplen = secondAgg.getGroupSet().cardinality(); final int callLen = secondAgg.getAggCallList().size(); if (aggCall.getArgList().size() == 1) { final Integer arg = aggCall.getArgList().get(0); if (arg > (grouplen - 1) && arg < (grouplen + callLen)) { AggregateCall call2 = secondAgg.getAggCallList().get(arg - grouplen); if (call2.getAggregation() == aggCall.getAggregation() && call2.getArgList().size() == 1) { return call2.copy(call2.getArgList(), call2.filterArg); } } } return null; }
Example 8
Source File: OLAPAggregateRel.java From kylin with Apache License 2.0 | 5 votes |
@SuppressWarnings("deprecation") private AggregateCall rewriteAggregateCall(AggregateCall aggCall, FunctionDesc func) { // rebuild function String callName = getSqlFuncName(aggCall); RelDataType fieldType = aggCall.getType(); SqlAggFunction newAgg = aggCall.getAggregation(); Map<String, Class<?>> udafMap = func.getMeasureType().getRewriteCalciteAggrFunctions(); if (func.isCount()) { newAgg = SqlStdOperatorTable.SUM0; } else if (udafMap != null && udafMap.containsKey(callName)) { newAgg = createCustomAggFunction(callName, fieldType, udafMap.get(callName)); } // rebuild parameters List<Integer> newArgList = Lists.newArrayList(aggCall.getArgList()); if (udafMap != null && udafMap.containsKey(callName)) { newArgList = truncArgList(newArgList, udafMap.get(callName)); } if (func.needRewriteField()) { RelDataTypeField field = getInput().getRowType().getField(func.getRewriteFieldName(), true, false); if (newArgList.isEmpty()) { newArgList.add(field.getIndex()); } else { // TODO: only the first column got overwritten newArgList.set(0, field.getIndex()); } } // rebuild aggregate call AggregateCall newAggCall = new AggregateCall(newAgg, false, newArgList, fieldType, callName); return newAggCall; }
Example 9
Source File: OLAPAggregateRule.java From kylin with Apache License 2.0 | 5 votes |
private boolean containsAvg(LogicalAggregate agg) { for (AggregateCall call : agg.getAggCallList()) { SqlAggFunction func = call.getAggregation(); if (func instanceof SqlAvgAggFunction) return true; } return false; }
Example 10
Source File: OLAPAggregateRel.java From kylin-on-parquet-v2 with Apache License 2.0 | 5 votes |
@SuppressWarnings("deprecation") private AggregateCall rewriteAggregateCall(AggregateCall aggCall, FunctionDesc func) { // rebuild function String callName = getSqlFuncName(aggCall); RelDataType fieldType = aggCall.getType(); SqlAggFunction newAgg = aggCall.getAggregation(); Map<String, Class<?>> udafMap = func.getMeasureType().getRewriteCalciteAggrFunctions(); if (func.isCount()) { newAgg = SqlStdOperatorTable.SUM0; } else if (udafMap != null && udafMap.containsKey(callName)) { newAgg = createCustomAggFunction(callName, fieldType, udafMap.get(callName)); } // rebuild parameters List<Integer> newArgList = Lists.newArrayList(aggCall.getArgList()); if (udafMap != null && udafMap.containsKey(callName)) { newArgList = truncArgList(newArgList, udafMap.get(callName)); } if (func.needRewriteField()) { RelDataTypeField field = getInput().getRowType().getField(func.getRewriteFieldName(), true, false); if (newArgList.isEmpty()) { newArgList.add(field.getIndex()); } else { // TODO: only the first column got overwritten newArgList.set(0, field.getIndex()); } } // rebuild aggregate call AggregateCall newAggCall = new AggregateCall(newAgg, false, newArgList, fieldType, callName); return newAggCall; }
Example 11
Source File: PreProcessRel.java From dremio-oss with Apache License 2.0 | 5 votes |
@Override public RelNode visit(LogicalAggregate aggregate) { for(AggregateCall aggregateCall : aggregate.getAggCallList()) { if(aggregateCall.getAggregation() instanceof SqlSingleValueAggFunction) { // see DRILL-1937 unsupportedOperatorCollector.setException(SqlUnsupportedException.ExceptionType.FUNCTION, "Dremio doesn't currently support non-scalar sub-queries used in an expression"); throw new UnsupportedOperationException(); } } return visitChild(aggregate, 0, aggregate.getInput()); }
Example 12
Source File: OLAPAggregateRel.java From kylin with Apache License 2.0 | 4 votes |
@Override public void implementRewrite(RewriteImplementor implementor) { // only rewrite the innermost aggregation if (needRewrite()) { translateAggregation(); buildRewriteFieldsAndMetricsColumns(); } implementor.visitChild(this, getInput()); this.rewriting = true; // only rewrite the innermost aggregation if (needRewrite()) { // rewrite the aggCalls this.rewriteAggCalls = Lists.newArrayListWithExpectedSize(aggCalls.size()); for (int i = 0; i < this.aggCalls.size(); i++) { AggregateCall aggCall = this.hackAggCalls.get(i) != null ? this.hackAggCalls.get(i) : this.aggCalls.get(i); if (SqlStdOperatorTable.GROUPING == aggCall.getAggregation()) { this.rewriteAggCalls.add(aggCall); continue; } FunctionDesc cubeFunc = this.context.aggregations.get(i); // filter needn,t rewrite aggfunc // if it's not a cube, then the "needRewriteField func" should not resort to any rewrite fields, // which do not exist at all if (!(noPrecaculatedFieldsAvailable() && cubeFunc.needRewriteField())) { if (cubeFunc.needRewrite()) { aggCall = rewriteAggregateCall(aggCall, cubeFunc); } //if not dim as measure (using some measure), differentiate it with a new class if (cubeFunc.getMeasureType() != null && // DimCountDistinct case cubeFunc.getMeasureType().needRewriteField()) { aggCall = new KylinAggregateCall(aggCall, cubeFunc); } } else { logger.info(aggCall + "skip rewriteAggregateCall because no pre-aggregated field available"); } this.rewriteAggCalls.add(aggCall); this.context.aggrSqlCalls.add(toSqlCall(aggCall)); } } // rebuild rowType & columnRowType this.rowType = this.deriveRowType(); this.columnRowType = this.buildColumnRowType(); this.rewriting = false; }
Example 13
Source File: AggregateStarTableRule.java From calcite with Apache License 2.0 | 4 votes |
private static AggregateCall rollUp(int groupCount, RelBuilder relBuilder, AggregateCall aggregateCall, TileKey tileKey) { if (aggregateCall.isDistinct()) { return null; } final SqlAggFunction aggregation = aggregateCall.getAggregation(); final Pair<SqlAggFunction, List<Integer>> seek = Pair.of(aggregation, aggregateCall.getArgList()); final int offset = tileKey.dimensions.cardinality(); final ImmutableList<Lattice.Measure> measures = tileKey.measures; // First, try to satisfy the aggregation by rolling up an aggregate in the // materialization. final int i = find(measures, seek); tryRoll: if (i >= 0) { final SqlAggFunction roll = SubstitutionVisitor.getRollup(aggregation); if (roll == null) { break tryRoll; } return AggregateCall.create(roll, false, aggregateCall.isApproximate(), aggregateCall.ignoreNulls(), ImmutableList.of(offset + i), -1, aggregateCall.collation, groupCount, relBuilder.peek(), null, aggregateCall.name); } // Second, try to satisfy the aggregation based on group set columns. tryGroup: { List<Integer> newArgs = new ArrayList<>(); for (Integer arg : aggregateCall.getArgList()) { int z = tileKey.dimensions.indexOf(arg); if (z < 0) { break tryGroup; } newArgs.add(z); } return AggregateCall.create(aggregation, false, aggregateCall.isApproximate(), aggregateCall.ignoreNulls(), newArgs, -1, aggregateCall.collation, groupCount, relBuilder.peek(), null, aggregateCall.name); } // No roll up possible. return null; }
Example 14
Source File: RelDecorrelator.java From calcite with Apache License 2.0 | 4 votes |
private void onMatch2( RelOptRuleCall call, Correlate correlate, RelNode leftInput, Project aggOutputProject, Aggregate aggregate) { if (generatedCorRels.contains(correlate)) { // This Correlate was generated by a previous invocation of // this rule. No further work to do. return; } setCurrent(call.getPlanner().getRoot(), correlate); // check for this pattern // The pattern matching could be simplified if rules can be applied // during decorrelation, // // CorrelateRel(left correlation, condition = true) // leftInput // Project-A (a RexNode) // Aggregate (groupby (0), agg0(), agg1()...) // check aggOutputProj projects only one expression List<RexNode> aggOutputProjExprs = aggOutputProject.getProjects(); if (aggOutputProjExprs.size() != 1) { return; } JoinRelType joinType = correlate.getJoinType(); // corRel.getCondition was here, however Correlate was updated so it // never includes a join condition. The code was not modified for brevity. RexNode joinCond = relBuilder.literal(true); if ((joinType != JoinRelType.LEFT) || (joinCond != relBuilder.literal(true))) { return; } // check that the agg is on the entire input if (!aggregate.getGroupSet().isEmpty()) { return; } List<AggregateCall> aggCalls = aggregate.getAggCallList(); Set<Integer> isCount = new HashSet<>(); // remember the count() positions int i = -1; for (AggregateCall aggCall : aggCalls) { ++i; if (aggCall.getAggregation() instanceof SqlCountAggFunction) { isCount.add(i); } } // now rewrite the plan to // // Project-A' (all LHS plus transformed original projections, // replacing references to count() with case statement) // Correlate(left correlation, condition = true) // leftInput // Aggregate(groupby (0), agg0(), agg1()...) // List<RexNode> requiredNodes = correlate.getRequiredColumns().asList().stream() .map(ord -> relBuilder.getRexBuilder().makeInputRef(correlate, ord)) .collect(Collectors.toList()); Correlate newCorrelate = (Correlate) relBuilder.push(leftInput) .push(aggregate).correlate(correlate.getJoinType(), correlate.getCorrelationId(), requiredNodes).build(); // remember this rel so we don't fire rule on it again // REVIEW jhyde 29-Oct-2007: rules should not save state; rule // should recognize patterns where it does or does not need to do // work generatedCorRels.add(newCorrelate); // need to update the mapCorToCorRel Update the output position // for the corVars: only pass on the corVars that are not used in // the join key. if (cm.mapCorToCorRel.get(correlate.getCorrelationId()) == correlate) { cm.mapCorToCorRel.put(correlate.getCorrelationId(), newCorrelate); } RelNode newOutput = aggregateCorrelatorOutput(newCorrelate, aggOutputProject, isCount); call.transformTo(newOutput); }
Example 15
Source File: ProjectableSqlAggFunctions.java From dremio-oss with Apache License 2.0 | 4 votes |
@Override public boolean apply(AggregateCall call) { return call.getAggregation() instanceof ProjectableSqlAggFunction; }
Example 16
Source File: KylinAggregateCall.java From kylin with Apache License 2.0 | 4 votes |
public KylinAggregateCall(AggregateCall aggCall, FunctionDesc func) { super(aggCall.getAggregation(), aggCall.isDistinct(), aggCall.getArgList(), aggCall.type, aggCall.name); this.func = func; }
Example 17
Source File: OLAPAggregateRel.java From kylin-on-parquet-v2 with Apache License 2.0 | 4 votes |
@Override public void implementRewrite(RewriteImplementor implementor) { // only rewrite the innermost aggregation if (needRewrite()) { translateAggregation(); buildRewriteFieldsAndMetricsColumns(); } implementor.visitChild(this, getInput()); this.rewriting = true; // only rewrite the innermost aggregation if (needRewrite()) { // rewrite the aggCalls this.rewriteAggCalls = Lists.newArrayListWithExpectedSize(aggCalls.size()); for (int i = 0; i < this.aggCalls.size(); i++) { AggregateCall aggCall = this.hackAggCalls.get(i) != null ? this.hackAggCalls.get(i) : this.aggCalls.get(i); if (SqlStdOperatorTable.GROUPING == aggCall.getAggregation()) { this.rewriteAggCalls.add(aggCall); continue; } FunctionDesc cubeFunc = this.context.aggregations.get(i); // filter needn,t rewrite aggfunc // if it's not a cube, then the "needRewriteField func" should not resort to any rewrite fields, // which do not exist at all if (!(noPrecaculatedFieldsAvailable() && cubeFunc.needRewriteField())) { if (cubeFunc.needRewrite()) { aggCall = rewriteAggregateCall(aggCall, cubeFunc); } //if not dim as measure (using some measure), differentiate it with a new class if (cubeFunc.getMeasureType() != null && // DimCountDistinct case cubeFunc.getMeasureType().needRewriteField()) { aggCall = new KylinAggregateCall(aggCall, cubeFunc); } } else { logger.info(aggCall + "skip rewriteAggregateCall because no pre-aggregated field available"); } this.rewriteAggCalls.add(aggCall); this.context.aggrSqlCalls.add(toSqlCall(aggCall)); } } // rebuild rowType & columnRowType this.rowType = this.deriveRowType(); this.columnRowType = this.buildColumnRowType(); this.rewriting = false; }
Example 18
Source File: RelDecorrelator.java From flink with Apache License 2.0 | 4 votes |
private void onMatch2( RelOptRuleCall call, LogicalCorrelate correlate, RelNode leftInput, LogicalProject aggOutputProject, LogicalAggregate aggregate) { if (generatedCorRels.contains(correlate)) { // This Correlate was generated by a previous invocation of // this rule. No further work to do. return; } setCurrent(call.getPlanner().getRoot(), correlate); // check for this pattern // The pattern matching could be simplified if rules can be applied // during decorrelation, // // CorrelateRel(left correlation, condition = true) // leftInput // Project-A (a RexNode) // Aggregate (groupby (0), agg0(), agg1()...) // check aggOutputProj projects only one expression List<RexNode> aggOutputProjExprs = aggOutputProject.getProjects(); if (aggOutputProjExprs.size() != 1) { return; } JoinRelType joinType = correlate.getJoinType(); // corRel.getCondition was here, however Correlate was updated so it // never includes a join condition. The code was not modified for brevity. RexNode joinCond = relBuilder.literal(true); if ((joinType != JoinRelType.LEFT) || (joinCond != relBuilder.literal(true))) { return; } // check that the agg is on the entire input if (!aggregate.getGroupSet().isEmpty()) { return; } List<AggregateCall> aggCalls = aggregate.getAggCallList(); Set<Integer> isCount = new HashSet<>(); // remember the count() positions int i = -1; for (AggregateCall aggCall : aggCalls) { ++i; if (aggCall.getAggregation() instanceof SqlCountAggFunction) { isCount.add(i); } } // now rewrite the plan to // // Project-A' (all LHS plus transformed original projections, // replacing references to count() with case statement) // Correlate(left correlation, condition = true) // leftInput // Aggregate(groupby (0), agg0(), agg1()...) // LogicalCorrelate newCorrelate = LogicalCorrelate.create(leftInput, aggregate, correlate.getCorrelationId(), correlate.getRequiredColumns(), correlate.getJoinType()); // remember this rel so we don't fire rule on it again // REVIEW jhyde 29-Oct-2007: rules should not save state; rule // should recognize patterns where it does or does not need to do // work generatedCorRels.add(newCorrelate); // need to update the mapCorToCorRel Update the output position // for the corVars: only pass on the corVars that are not used in // the join key. if (cm.mapCorToCorRel.get(correlate.getCorrelationId()) == correlate) { cm.mapCorToCorRel.put(correlate.getCorrelationId(), newCorrelate); } RelNode newOutput = aggregateCorrelatorOutput(newCorrelate, aggOutputProject, isCount); call.transformTo(newOutput); }
Example 19
Source File: Lattice.java From calcite with Apache License 2.0 | 4 votes |
private Measure toMeasure(AggregateCall aggCall) { return new Measure(aggCall.getAggregation(), aggCall.isDistinct(), aggCall.name, Lists.transform(aggCall.getArgList(), columns::get)); }
Example 20
Source File: RelDecorrelator.java From Bats with Apache License 2.0 | 4 votes |
private void onMatch2(RelOptRuleCall call, LogicalCorrelate correlate, RelNode leftInput, LogicalProject aggOutputProject, LogicalAggregate aggregate) { if (generatedCorRels.contains(correlate)) { // This Correlate was generated by a previous invocation of // this rule. No further work to do. return; } setCurrent(call.getPlanner().getRoot(), correlate); // check for this pattern // The pattern matching could be simplified if rules can be applied // during decorrelation, // // CorrelateRel(left correlation, condition = true) // leftInput // Project-A (a RexNode) // Aggregate (groupby (0), agg0(), agg1()...) // check aggOutputProj projects only one expression List<RexNode> aggOutputProjExprs = aggOutputProject.getProjects(); if (aggOutputProjExprs.size() != 1) { return; } JoinRelType joinType = correlate.getJoinType().toJoinType(); // corRel.getCondition was here, however Correlate was updated so it // never includes a join condition. The code was not modified for brevity. RexNode joinCond = relBuilder.literal(true); if ((joinType != JoinRelType.LEFT) || (joinCond != relBuilder.literal(true))) { return; } // check that the agg is on the entire input if (!aggregate.getGroupSet().isEmpty()) { return; } List<AggregateCall> aggCalls = aggregate.getAggCallList(); Set<Integer> isCount = new HashSet<>(); // remember the count() positions int i = -1; for (AggregateCall aggCall : aggCalls) { ++i; if (aggCall.getAggregation() instanceof SqlCountAggFunction) { isCount.add(i); } } // now rewrite the plan to // // Project-A' (all LHS plus transformed original projections, // replacing references to count() with case statement) // Correlate(left correlation, condition = true) // leftInput // Aggregate(groupby (0), agg0(), agg1()...) // LogicalCorrelate newCorrelate = LogicalCorrelate.create(leftInput, aggregate, correlate.getCorrelationId(), correlate.getRequiredColumns(), correlate.getJoinType()); // remember this rel so we don't fire rule on it again // REVIEW jhyde 29-Oct-2007: rules should not save state; rule // should recognize patterns where it does or does not need to do // work generatedCorRels.add(newCorrelate); // need to update the mapCorToCorRel Update the output position // for the corVars: only pass on the corVars that are not used in // the join key. if (cm.mapCorToCorRel.get(correlate.getCorrelationId()) == correlate) { cm.mapCorToCorRel.put(correlate.getCorrelationId(), newCorrelate); } RelNode newOutput = aggregateCorrelatorOutput(newCorrelate, aggOutputProject, isCount); call.transformTo(newOutput); }