Skip to content

Instantly share code, notes, and snippets.

@gianm
Created November 11, 2016 15:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gianm/1c192a47a7ce284be8af986f97e6dd8f to your computer and use it in GitHub Desktop.
Save gianm/1c192a47a7ce284be8af986f97e6dd8f to your computer and use it in GitHub Desktop.
/*
* Copyright 2016 Imply Data, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.druid.sql.calcite.rule;
import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableList;
import org.apache.calcite.plan.RelOptRule;
import org.apache.calcite.plan.RelOptRuleCall;
import org.apache.calcite.rel.core.Aggregate;
import org.apache.calcite.rel.core.AggregateCall;
import org.apache.calcite.rel.core.Values;
import org.apache.calcite.rel.logical.LogicalValues;
import org.apache.calcite.rex.RexBuilder;
import org.apache.calcite.rex.RexLiteral;
import org.apache.calcite.sql.SqlKind;
import java.math.BigDecimal;
/**
* Rule that removes a grand-total Aggregate (no grouping keys) on an empty Values.
*
* Useful because Calcite's built-in PruneEmptyRules doesn't do this. Sample query where this matters:
* <code>SELECT COUNT(*) FROM s.foo WHERE 1 = 0</code>.
*/
public class RemoveAggregateEmptyGrandTotalRule extends RelOptRule
{
private static final RemoveAggregateEmptyGrandTotalRule INSTANCE = new RemoveAggregateEmptyGrandTotalRule();
private RemoveAggregateEmptyGrandTotalRule()
{
super(
operand(
Aggregate.class,
null,
Predicates.not(Aggregate.IS_NOT_GRAND_TOTAL),
operand(Values.class, null, Values.IS_EMPTY, none())
)
);
}
public static RemoveAggregateEmptyGrandTotalRule instance()
{
return INSTANCE;
}
@Override
public void onMatch(RelOptRuleCall call)
{
final Aggregate aggregate = call.rel(0);
final Values values = call.rel(1);
final ImmutableList.Builder<RexLiteral> literals = ImmutableList.builder();
final RexBuilder rexBuilder = call.builder().getRexBuilder();
for (final AggregateCall aggregateCall : aggregate.getAggCallList()) {
final SqlKind kind = aggregateCall.getAggregation().getKind();
if (kind == SqlKind.COUNT || kind == SqlKind.SUM0) {
literals.add((RexLiteral) rexBuilder.makeLiteral(BigDecimal.ZERO, aggregateCall.getType(), false));
} else {
literals.add(rexBuilder.constantNull());
}
}
call.transformTo(
LogicalValues.create(
values.getCluster(),
aggregate.getRowType(),
ImmutableList.of(literals.build())
)
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment