use of org.apache.calcite.rel.core.Aggregate in project druid by druid-io.
the class DruidQuery method computeGrouping.
@Nonnull
private static Grouping computeGrouping(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(), "aggregate");
final Project aggregateProject = partialQuery.getAggregateProject();
final List<DimensionExpression> dimensions = computeDimensions(partialQuery, plannerContext, rowSignature, virtualColumnRegistry);
final Subtotals subtotals = computeSubtotals(partialQuery, rowSignature);
final List<Aggregation> aggregations = computeAggregations(partialQuery, plannerContext, rowSignature, virtualColumnRegistry, rexBuilder, finalizeAggregations);
final RowSignature aggregateRowSignature = RowSignatures.fromRelDataType(ImmutableList.copyOf(Iterators.concat(dimensions.stream().map(DimensionExpression::getOutputName).iterator(), aggregations.stream().map(Aggregation::getOutputName).iterator())), aggregate.getRowType());
final DimFilter havingFilter = computeHavingFilter(partialQuery, plannerContext, aggregateRowSignature);
final Grouping grouping = Grouping.create(dimensions, subtotals, aggregations, havingFilter, aggregateRowSignature);
if (aggregateProject == null) {
return grouping;
} else {
return grouping.applyProject(plannerContext, aggregateProject);
}
}
use of org.apache.calcite.rel.core.Aggregate in project druid by druid-io.
the class DruidQuery method computeDimensions.
/**
* Returns dimensions corresponding to {@code aggregate.getGroupSet()}, in the same order.
*
* @param partialQuery partial query
* @param plannerContext planner context
* @param rowSignature source row signature
* @param virtualColumnRegistry re-usable virtual column references
*
* @return dimensions
*
* @throws CannotBuildQueryException if dimensions cannot be computed
*/
private static List<DimensionExpression> computeDimensions(final PartialDruidQuery partialQuery, final PlannerContext plannerContext, final RowSignature rowSignature, final VirtualColumnRegistry virtualColumnRegistry) {
final Aggregate aggregate = Preconditions.checkNotNull(partialQuery.getAggregate());
final List<DimensionExpression> dimensions = new ArrayList<>();
final String outputNamePrefix = Calcites.findUnusedPrefixForDigits("d", rowSignature.getColumnNames());
int outputNameCounter = 0;
for (int i : aggregate.getGroupSet()) {
// Dimension might need to create virtual columns. Avoid giving it a name that would lead to colliding columns.
final RexNode rexNode = Expressions.fromFieldAccess(rowSignature, partialQuery.getSelectProject(), i);
final DruidExpression druidExpression = Expressions.toDruidExpression(plannerContext, rowSignature, rexNode);
if (druidExpression == null) {
throw new CannotBuildQueryException(aggregate, rexNode);
}
final RelDataType dataType = rexNode.getType();
final ColumnType outputType = Calcites.getColumnTypeForRelDataType(dataType);
if (Types.isNullOr(outputType, ValueType.COMPLEX)) {
// Can't group on unknown or COMPLEX types.
plannerContext.setPlanningError("SQL requires a group-by on a column of type %s that is unsupported.", outputType);
throw new CannotBuildQueryException(aggregate, rexNode);
}
final String dimOutputName = outputNamePrefix + outputNameCounter++;
if (!druidExpression.isSimpleExtraction()) {
final String virtualColumn = virtualColumnRegistry.getOrCreateVirtualColumnForExpression(druidExpression, dataType);
dimensions.add(DimensionExpression.ofVirtualColumn(virtualColumn, dimOutputName, druidExpression, outputType));
} else {
dimensions.add(DimensionExpression.ofSimpleColumn(dimOutputName, druidExpression, outputType));
}
}
return dimensions;
}
use of org.apache.calcite.rel.core.Aggregate in project hive by apache.
the class PlanModifierForASTConv method replaceEmptyGroupAggr.
private static void replaceEmptyGroupAggr(final RelNode rel, RelNode parent) {
// If this function is called, the parent should only include constant
List<RexNode> exps = parent instanceof Project ? ((Project) parent).getProjects() : Collections.emptyList();
for (RexNode rexNode : exps) {
if (!rexNode.accept(new HiveCalciteUtil.ConstantFinder())) {
throw new RuntimeException("We expect " + parent.toString() + " to contain only constants. However, " + rexNode.toString() + " is " + rexNode.getKind());
}
}
HiveAggregate oldAggRel = (HiveAggregate) rel;
RelDataTypeFactory typeFactory = oldAggRel.getCluster().getTypeFactory();
RelDataType longType = TypeConverter.convert(TypeInfoFactory.longTypeInfo, typeFactory);
RelDataType intType = TypeConverter.convert(TypeInfoFactory.intTypeInfo, typeFactory);
// Create the dummy aggregation.
SqlAggFunction countFn = SqlFunctionConverter.getCalciteAggFn("count", false, ImmutableList.of(intType), longType);
// TODO: Using 0 might be wrong; might need to walk down to find the
// proper index of a dummy.
List<Integer> argList = ImmutableList.of(0);
AggregateCall dummyCall = new AggregateCall(countFn, false, argList, longType, null);
Aggregate newAggRel = oldAggRel.copy(oldAggRel.getTraitSet(), oldAggRel.getInput(), oldAggRel.indicator, oldAggRel.getGroupSet(), oldAggRel.getGroupSets(), ImmutableList.of(dummyCall));
RelNode select = introduceDerivedTable(newAggRel);
parent.replaceInput(0, select);
}
use of org.apache.calcite.rel.core.Aggregate in project hive by apache.
the class MaterializedViewRewritingRelVisitor method visit.
@Override
public void visit(RelNode node, int ordinal, RelNode parent) {
if (node instanceof Aggregate) {
this.containsAggregate = true;
// Aggregate mode - it should be followed by union
// that we need to analyze
RelNode input = node.getInput(0);
if (input instanceof Union) {
check((Union) input);
}
} else if (node instanceof Union) {
// Non aggregate mode - analyze union operator
check((Union) node);
} else if (node instanceof Project) {
// Project operator, we can continue
super.visit(node, ordinal, parent);
}
throw new ReturnedValue(false);
}
use of org.apache.calcite.rel.core.Aggregate in project hive by apache.
the class MaterializedViewRewritingRelVisitor method check.
private void check(Union union) {
// We found the Union
if (union.getInputs().size() != 2) {
// Bail out
throw new ReturnedValue(false);
}
// First branch should have the query (with write ID filter conditions)
new RelVisitor() {
@Override
public void visit(RelNode node, int ordinal, RelNode parent) {
if (node instanceof TableScan || node instanceof Filter || node instanceof Project || node instanceof Join) {
// We can continue
super.visit(node, ordinal, parent);
} else if (node instanceof Aggregate && containsAggregate) {
Aggregate aggregate = (Aggregate) node;
for (int i = 0; i < aggregate.getAggCallList().size(); ++i) {
AggregateCall aggregateCall = aggregate.getAggCallList().get(i);
if (aggregateCall.getAggregation().getKind() == SqlKind.COUNT && aggregateCall.getArgList().size() == 0) {
countIndex = i + aggregate.getGroupCount();
break;
}
}
// We can continue
super.visit(node, ordinal, parent);
} else {
throw new ReturnedValue(false);
}
}
}.go(union.getInput(0));
// Second branch should only have the MV
new RelVisitor() {
@Override
public void visit(RelNode node, int ordinal, RelNode parent) {
if (node instanceof TableScan) {
// We can continue
// TODO: Need to check that this is the same MV that we are rebuilding
RelOptHiveTable hiveTable = (RelOptHiveTable) node.getTable();
if (!hiveTable.getHiveTableMD().isMaterializedView()) {
// If it is not a materialized view, we do not rewrite it
throw new ReturnedValue(false);
}
if (containsAggregate && !AcidUtils.isFullAcidTable(hiveTable.getHiveTableMD())) {
// we do not rewrite it (we need MERGE support)
throw new ReturnedValue(false);
}
} else if (node instanceof Project) {
// We can continue
super.visit(node, ordinal, parent);
} else {
throw new ReturnedValue(false);
}
}
}.go(union.getInput(1));
// We pass all the checks, we can rewrite
throw new ReturnedValue(true);
}
Aggregations