Search in sources :

Example 1 with UNION

use of org.apache.calcite.sql.SqlKind.UNION in project calcite by apache.

the class RelBuilder method rewriteAggregateWithDuplicateGroupSets.

/**
 * The {@code GROUP_ID()} function is used to distinguish duplicate groups.
 * However, as Aggregate normalizes group sets to canonical form (i.e.,
 * flatten, sorting, redundancy removal), this information is lost in RelNode.
 * Therefore, it is impossible to implement the function in runtime.
 *
 * <p>To fill this gap, an aggregation query that contains duplicate group
 * sets is rewritten into a Union of Aggregate operators whose group sets are
 * distinct. The number of inputs to the Union is equal to the maximum number
 * of duplicates. In the {@code N}th input to the Union, calls to the
 * {@code GROUP_ID} aggregate function are replaced by the integer literal
 * {@code N}.
 *
 * <p>This method also handles the case where group sets are distinct but
 * there is a call to {@code GROUP_ID}. That call is replaced by the integer
 * literal {@code 0}.
 *
 * <p>Also see the discussion in
 * <a href="https://issues.apache.org/jira/browse/CALCITE-1824">[CALCITE-1824]
 * GROUP_ID returns wrong result</a> and
 * <a href="https://issues.apache.org/jira/browse/CALCITE-4748">[CALCITE-4748]
 * If there are duplicate GROUPING SETS, Calcite should return duplicate
 * rows</a>.
 */
private RelBuilder rewriteAggregateWithDuplicateGroupSets(ImmutableBitSet groupSet, ImmutableSortedMultiset<ImmutableBitSet> groupSets, List<AggCall> aggregateCalls) {
    final List<String> fieldNamesIfNoRewrite = Aggregate.deriveRowType(getTypeFactory(), peek().getRowType(), false, groupSet, groupSets.asList(), aggregateCalls.stream().map(c -> ((AggCallPlus) c).aggregateCall()).collect(Util.toImmutableList())).getFieldNames();
    // If n duplicates exist for a particular grouping, the {@code GROUP_ID()}
    // function produces values in the range 0 to n-1. For each value,
    // we need to figure out the corresponding group sets.
    // 
    // For example, "... GROUPING SETS (a, a, b, c, c, c, c)"
    // (i) The max value of the GROUP_ID() function returns is 3
    // (ii) GROUPING SETS (a, b, c) produces value 0,
    // GROUPING SETS (a, c) produces value 1,
    // GROUPING SETS (c) produces value 2
    // GROUPING SETS (c) produces value 3
    final Map<Integer, Set<ImmutableBitSet>> groupIdToGroupSets = new HashMap<>();
    int maxGroupId = 0;
    for (Multiset.Entry<ImmutableBitSet> entry : groupSets.entrySet()) {
        int groupId = entry.getCount() - 1;
        if (groupId > maxGroupId) {
            maxGroupId = groupId;
        }
        for (int i = 0; i <= groupId; i++) {
            groupIdToGroupSets.computeIfAbsent(i, k -> Sets.newTreeSet(ImmutableBitSet.COMPARATOR)).add(entry.getElement());
        }
    }
    // AggregateCall list without GROUP_ID function
    final List<AggCall> aggregateCallsWithoutGroupId = new ArrayList<>(aggregateCalls);
    aggregateCallsWithoutGroupId.removeIf(RelBuilder::isGroupId);
    // For each group id value, we first construct an Aggregate without
    // GROUP_ID() function call, and then create a Project node on top of it.
    // The Project adds literal value for group id in right position.
    final Frame frame = stack.pop();
    for (int groupId = 0; groupId <= maxGroupId; groupId++) {
        // Create the Aggregate node without GROUP_ID() call
        stack.push(frame);
        aggregate(groupKey(groupSet, castNonNull(groupIdToGroupSets.get(groupId))), aggregateCallsWithoutGroupId);
        final List<RexNode> selectList = new ArrayList<>();
        final int groupExprLength = groupSet.cardinality();
        // Project fields in group by expressions
        for (int i = 0; i < groupExprLength; i++) {
            selectList.add(field(i));
        }
        // Project fields in aggregate calls
        int groupIdCount = 0;
        for (int i = 0; i < aggregateCalls.size(); i++) {
            if (isGroupId(aggregateCalls.get(i))) {
                selectList.add(getRexBuilder().makeExactLiteral(BigDecimal.valueOf(groupId), getTypeFactory().createSqlType(SqlTypeName.BIGINT)));
                groupIdCount++;
            } else {
                selectList.add(field(groupExprLength + i - groupIdCount));
            }
        }
        project(selectList, fieldNamesIfNoRewrite);
    }
    return union(true, maxGroupId + 1);
}
Also used : Values(org.apache.calcite.rel.core.Values) Mappings(org.apache.calcite.util.mapping.Mappings) Arrays(java.util.Arrays) UnaryOperator(java.util.function.UnaryOperator) RESOURCE(org.apache.calcite.util.Static.RESOURCE) Contexts(org.apache.calcite.plan.Contexts) Union(org.apache.calcite.rel.core.Union) BigDecimal(java.math.BigDecimal) CorrelationId(org.apache.calcite.rel.core.CorrelationId) SqlValidatorUtil(org.apache.calcite.sql.validate.SqlValidatorUtil) Map(java.util.Map) TableFunctionReturnTypeInference(org.apache.calcite.sql.type.TableFunctionReturnTypeInference) EnumSet(java.util.EnumSet) RexWindowBound(org.apache.calcite.rex.RexWindowBound) ImmutableBitSet(org.apache.calcite.util.ImmutableBitSet) Uncollect(org.apache.calcite.rel.core.Uncollect) SqlKind(org.apache.calcite.sql.SqlKind) Minus(org.apache.calcite.rel.core.Minus) SqlCountAggFunction(org.apache.calcite.sql.fun.SqlCountAggFunction) SqlQuantifyOperator(org.apache.calcite.sql.fun.SqlQuantifyOperator) Set(java.util.Set) RelFieldCollation(org.apache.calcite.rel.RelFieldCollation) RelMetadataQuery(org.apache.calcite.rel.metadata.RelMetadataQuery) SqlStdOperatorTable(org.apache.calcite.sql.fun.SqlStdOperatorTable) RelCollation(org.apache.calcite.rel.RelCollation) RexCorrelVariable(org.apache.calcite.rex.RexCorrelVariable) RexCall(org.apache.calcite.rex.RexCall) RelOptTableImpl(org.apache.calcite.prepare.RelOptTableImpl) Iterables(com.google.common.collect.Iterables) Holder(org.apache.calcite.util.Holder) Correlate(org.apache.calcite.rel.core.Correlate) RepeatUnion(org.apache.calcite.rel.core.RepeatUnion) Ord(org.apache.calcite.linq4j.Ord) Filter(org.apache.calcite.rel.core.Filter) ListTransientTable(org.apache.calcite.schema.impl.ListTransientTable) RelDataTypeFieldImpl(org.apache.calcite.rel.type.RelDataTypeFieldImpl) Join(org.apache.calcite.rel.core.Join) TreeSet(java.util.TreeSet) RelOptTable(org.apache.calcite.plan.RelOptTable) ArrayList(java.util.ArrayList) RexFieldCollation(org.apache.calcite.rex.RexFieldCollation) SqlToRelConverter(org.apache.calcite.sql2rel.SqlToRelConverter) Optionality(org.apache.calcite.util.Optionality) Lists(com.google.common.collect.Lists) ViewExpanders(org.apache.calcite.plan.ViewExpanders) RelColumnMapping(org.apache.calcite.rel.metadata.RelColumnMapping) StreamSupport(java.util.stream.StreamSupport) SqlWindow(org.apache.calcite.sql.SqlWindow) RelDataType(org.apache.calcite.rel.type.RelDataType) NlsString(org.apache.calcite.util.NlsString) Aggregate(org.apache.calcite.rel.core.Aggregate) SqlReturnTypeInference(org.apache.calcite.sql.type.SqlReturnTypeInference) RelHomogeneousShuttle(org.apache.calcite.rel.RelHomogeneousShuttle) RexWindowBounds(org.apache.calcite.rex.RexWindowBounds) RelOptSchema(org.apache.calcite.plan.RelOptSchema) RelDistribution(org.apache.calcite.rel.RelDistribution) RexCallBinding(org.apache.calcite.rex.RexCallBinding) JoinRelType(org.apache.calcite.rel.core.JoinRelType) AggregateCall(org.apache.calcite.rel.core.AggregateCall) Preconditions(com.google.common.base.Preconditions) SqlAggFunction(org.apache.calcite.sql.SqlAggFunction) ImmutableSortedMultiset(com.google.common.collect.ImmutableSortedMultiset) ArrayDeque(java.util.ArrayDeque) Convention(org.apache.calcite.plan.Convention) RelDataTypeFactory(org.apache.calcite.rel.type.RelDataTypeFactory) SortedSet(java.util.SortedSet) LogicalFilter(org.apache.calcite.rel.logical.LogicalFilter) RelFactories(org.apache.calcite.rel.core.RelFactories) Match(org.apache.calcite.rel.core.Match) AbstractList(java.util.AbstractList) MonotonicNonNull(org.checkerframework.checker.nullness.qual.MonotonicNonNull) RexUtil(org.apache.calcite.rex.RexUtil) SqlLikeOperator(org.apache.calcite.sql.fun.SqlLikeOperator) SqlUtil(org.apache.calcite.sql.SqlUtil) RexNode(org.apache.calcite.rex.RexNode) RelHint(org.apache.calcite.rel.hint.RelHint) Locale(java.util.Locale) Intersect(org.apache.calcite.rel.core.Intersect) RelOptPredicateList(org.apache.calcite.plan.RelOptPredicateList) RelOptCluster(org.apache.calcite.plan.RelOptCluster) TableFunctionScan(org.apache.calcite.rel.core.TableFunctionScan) Litmus(org.apache.calcite.util.Litmus) ImmutableSet(com.google.common.collect.ImmutableSet) ImmutableIntList(org.apache.calcite.util.ImmutableIntList) ImmutableMap(com.google.common.collect.ImmutableMap) RexLiteral(org.apache.calcite.rex.RexLiteral) Context(org.apache.calcite.plan.Context) Nullness.castNonNull(org.apache.calcite.linq4j.Nullness.castNonNull) ImmutableNullableList(org.apache.calcite.util.ImmutableNullableList) Collectors(java.util.stream.Collectors) Sets(com.google.common.collect.Sets) RexInputRef(org.apache.calcite.rex.RexInputRef) Objects(java.util.Objects) List(java.util.List) Sort(org.apache.calcite.rel.core.Sort) RelDataTypeField(org.apache.calcite.rel.type.RelDataTypeField) Spool(org.apache.calcite.rel.core.Spool) RexSimplify(org.apache.calcite.rex.RexSimplify) Hook(org.apache.calcite.runtime.Hook) Project(org.apache.calcite.rel.core.Project) TableScan(org.apache.calcite.rel.core.TableScan) Multiset(com.google.common.collect.Multiset) Hintable(org.apache.calcite.rel.hint.Hintable) TransientTable(org.apache.calcite.schema.TransientTable) HashMap(java.util.HashMap) Deque(java.util.Deque) RelOptUtil(org.apache.calcite.plan.RelOptUtil) Function(java.util.function.Function) HashSet(java.util.HashSet) Snapshot(org.apache.calcite.rel.core.Snapshot) ImmutableList(com.google.common.collect.ImmutableList) Value(org.immutables.value.Value) Pair(org.apache.calcite.util.Pair) Mapping(org.apache.calcite.util.mapping.Mapping) Objects.requireNonNull(java.util.Objects.requireNonNull) SqlOperator(org.apache.calcite.sql.SqlOperator) RexExecutor(org.apache.calcite.rex.RexExecutor) Nullable(org.checkerframework.checker.nullness.qual.Nullable) RelCollations(org.apache.calcite.rel.RelCollations) LogicalProject(org.apache.calcite.rel.logical.LogicalProject) SqlTypeName(org.apache.calcite.sql.type.SqlTypeName) RexBuilder(org.apache.calcite.rex.RexBuilder) Experimental(org.apache.calcite.linq4j.function.Experimental) RexSubQuery(org.apache.calcite.rex.RexSubQuery) RelNode(org.apache.calcite.rel.RelNode) UNION(org.apache.calcite.sql.SqlKind.UNION) BitSet(java.util.BitSet) RexShuttle(org.apache.calcite.rex.RexShuttle) Util(org.apache.calcite.util.Util) Collections(java.util.Collections) TableSpool(org.apache.calcite.rel.core.TableSpool) EnumSet(java.util.EnumSet) ImmutableBitSet(org.apache.calcite.util.ImmutableBitSet) Set(java.util.Set) TreeSet(java.util.TreeSet) SortedSet(java.util.SortedSet) ImmutableSet(com.google.common.collect.ImmutableSet) HashSet(java.util.HashSet) BitSet(java.util.BitSet) ImmutableBitSet(org.apache.calcite.util.ImmutableBitSet) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) NlsString(org.apache.calcite.util.NlsString) RelHint(org.apache.calcite.rel.hint.RelHint) ImmutableSortedMultiset(com.google.common.collect.ImmutableSortedMultiset) Multiset(com.google.common.collect.Multiset) RexNode(org.apache.calcite.rex.RexNode)

Example 2 with UNION

use of org.apache.calcite.sql.SqlKind.UNION in project calcite by apache.

the class RelBuilder method setOp.

private RelBuilder setOp(boolean all, SqlKind kind, int n) {
    List<RelNode> inputs = new ArrayList<>();
    for (int i = 0; i < n; i++) {
        inputs.add(0, build());
    }
    switch(kind) {
        case UNION:
        case INTERSECT:
        case EXCEPT:
            if (n < 1) {
                throw new IllegalArgumentException("bad INTERSECT/UNION/EXCEPT input count");
            }
            break;
        default:
            throw new AssertionError("bad setOp " + kind);
    }
    if (n == 1) {
        return push(inputs.get(0));
    }
    if (config.simplifyValues() && kind == UNION && inputs.stream().allMatch(r -> r instanceof Values)) {
        List<RelDataType> inputTypes = Util.transform(inputs, RelNode::getRowType);
        RelDataType rowType = getTypeFactory().leastRestrictive(inputTypes);
        requireNonNull(rowType, () -> "leastRestrictive(" + inputTypes + ")");
        final List<List<RexLiteral>> tuples = new ArrayList<>();
        for (RelNode input : inputs) {
            tuples.addAll(((Values) input).tuples);
        }
        final List<List<RexLiteral>> tuples2 = all ? tuples : Util.distinctList(tuples);
        return values(tuples2, rowType);
    }
    return push(struct.setOpFactory.createSetOp(kind, inputs, all));
}
Also used : Values(org.apache.calcite.rel.core.Values) Mappings(org.apache.calcite.util.mapping.Mappings) Arrays(java.util.Arrays) UnaryOperator(java.util.function.UnaryOperator) RESOURCE(org.apache.calcite.util.Static.RESOURCE) Contexts(org.apache.calcite.plan.Contexts) Union(org.apache.calcite.rel.core.Union) BigDecimal(java.math.BigDecimal) CorrelationId(org.apache.calcite.rel.core.CorrelationId) SqlValidatorUtil(org.apache.calcite.sql.validate.SqlValidatorUtil) Map(java.util.Map) TableFunctionReturnTypeInference(org.apache.calcite.sql.type.TableFunctionReturnTypeInference) EnumSet(java.util.EnumSet) RexWindowBound(org.apache.calcite.rex.RexWindowBound) ImmutableBitSet(org.apache.calcite.util.ImmutableBitSet) Uncollect(org.apache.calcite.rel.core.Uncollect) SqlKind(org.apache.calcite.sql.SqlKind) Minus(org.apache.calcite.rel.core.Minus) SqlCountAggFunction(org.apache.calcite.sql.fun.SqlCountAggFunction) SqlQuantifyOperator(org.apache.calcite.sql.fun.SqlQuantifyOperator) Set(java.util.Set) RelFieldCollation(org.apache.calcite.rel.RelFieldCollation) RelMetadataQuery(org.apache.calcite.rel.metadata.RelMetadataQuery) SqlStdOperatorTable(org.apache.calcite.sql.fun.SqlStdOperatorTable) RelCollation(org.apache.calcite.rel.RelCollation) RexCorrelVariable(org.apache.calcite.rex.RexCorrelVariable) RexCall(org.apache.calcite.rex.RexCall) RelOptTableImpl(org.apache.calcite.prepare.RelOptTableImpl) Iterables(com.google.common.collect.Iterables) Holder(org.apache.calcite.util.Holder) Correlate(org.apache.calcite.rel.core.Correlate) RepeatUnion(org.apache.calcite.rel.core.RepeatUnion) Ord(org.apache.calcite.linq4j.Ord) Filter(org.apache.calcite.rel.core.Filter) ListTransientTable(org.apache.calcite.schema.impl.ListTransientTable) RelDataTypeFieldImpl(org.apache.calcite.rel.type.RelDataTypeFieldImpl) Join(org.apache.calcite.rel.core.Join) TreeSet(java.util.TreeSet) RelOptTable(org.apache.calcite.plan.RelOptTable) ArrayList(java.util.ArrayList) RexFieldCollation(org.apache.calcite.rex.RexFieldCollation) SqlToRelConverter(org.apache.calcite.sql2rel.SqlToRelConverter) Optionality(org.apache.calcite.util.Optionality) Lists(com.google.common.collect.Lists) ViewExpanders(org.apache.calcite.plan.ViewExpanders) RelColumnMapping(org.apache.calcite.rel.metadata.RelColumnMapping) StreamSupport(java.util.stream.StreamSupport) SqlWindow(org.apache.calcite.sql.SqlWindow) RelDataType(org.apache.calcite.rel.type.RelDataType) NlsString(org.apache.calcite.util.NlsString) Aggregate(org.apache.calcite.rel.core.Aggregate) SqlReturnTypeInference(org.apache.calcite.sql.type.SqlReturnTypeInference) RelHomogeneousShuttle(org.apache.calcite.rel.RelHomogeneousShuttle) RexWindowBounds(org.apache.calcite.rex.RexWindowBounds) RelOptSchema(org.apache.calcite.plan.RelOptSchema) RelDistribution(org.apache.calcite.rel.RelDistribution) RexCallBinding(org.apache.calcite.rex.RexCallBinding) JoinRelType(org.apache.calcite.rel.core.JoinRelType) AggregateCall(org.apache.calcite.rel.core.AggregateCall) Preconditions(com.google.common.base.Preconditions) SqlAggFunction(org.apache.calcite.sql.SqlAggFunction) ImmutableSortedMultiset(com.google.common.collect.ImmutableSortedMultiset) ArrayDeque(java.util.ArrayDeque) Convention(org.apache.calcite.plan.Convention) RelDataTypeFactory(org.apache.calcite.rel.type.RelDataTypeFactory) SortedSet(java.util.SortedSet) LogicalFilter(org.apache.calcite.rel.logical.LogicalFilter) RelFactories(org.apache.calcite.rel.core.RelFactories) Match(org.apache.calcite.rel.core.Match) AbstractList(java.util.AbstractList) MonotonicNonNull(org.checkerframework.checker.nullness.qual.MonotonicNonNull) RexUtil(org.apache.calcite.rex.RexUtil) SqlLikeOperator(org.apache.calcite.sql.fun.SqlLikeOperator) SqlUtil(org.apache.calcite.sql.SqlUtil) RexNode(org.apache.calcite.rex.RexNode) RelHint(org.apache.calcite.rel.hint.RelHint) Locale(java.util.Locale) Intersect(org.apache.calcite.rel.core.Intersect) RelOptPredicateList(org.apache.calcite.plan.RelOptPredicateList) RelOptCluster(org.apache.calcite.plan.RelOptCluster) TableFunctionScan(org.apache.calcite.rel.core.TableFunctionScan) Litmus(org.apache.calcite.util.Litmus) ImmutableSet(com.google.common.collect.ImmutableSet) ImmutableIntList(org.apache.calcite.util.ImmutableIntList) ImmutableMap(com.google.common.collect.ImmutableMap) RexLiteral(org.apache.calcite.rex.RexLiteral) Context(org.apache.calcite.plan.Context) Nullness.castNonNull(org.apache.calcite.linq4j.Nullness.castNonNull) ImmutableNullableList(org.apache.calcite.util.ImmutableNullableList) Collectors(java.util.stream.Collectors) Sets(com.google.common.collect.Sets) RexInputRef(org.apache.calcite.rex.RexInputRef) Objects(java.util.Objects) List(java.util.List) Sort(org.apache.calcite.rel.core.Sort) RelDataTypeField(org.apache.calcite.rel.type.RelDataTypeField) Spool(org.apache.calcite.rel.core.Spool) RexSimplify(org.apache.calcite.rex.RexSimplify) Hook(org.apache.calcite.runtime.Hook) Project(org.apache.calcite.rel.core.Project) TableScan(org.apache.calcite.rel.core.TableScan) Multiset(com.google.common.collect.Multiset) Hintable(org.apache.calcite.rel.hint.Hintable) TransientTable(org.apache.calcite.schema.TransientTable) HashMap(java.util.HashMap) Deque(java.util.Deque) RelOptUtil(org.apache.calcite.plan.RelOptUtil) Function(java.util.function.Function) HashSet(java.util.HashSet) Snapshot(org.apache.calcite.rel.core.Snapshot) ImmutableList(com.google.common.collect.ImmutableList) Value(org.immutables.value.Value) Pair(org.apache.calcite.util.Pair) Mapping(org.apache.calcite.util.mapping.Mapping) Objects.requireNonNull(java.util.Objects.requireNonNull) SqlOperator(org.apache.calcite.sql.SqlOperator) RexExecutor(org.apache.calcite.rex.RexExecutor) Nullable(org.checkerframework.checker.nullness.qual.Nullable) RelCollations(org.apache.calcite.rel.RelCollations) LogicalProject(org.apache.calcite.rel.logical.LogicalProject) SqlTypeName(org.apache.calcite.sql.type.SqlTypeName) RexBuilder(org.apache.calcite.rex.RexBuilder) Experimental(org.apache.calcite.linq4j.function.Experimental) RexSubQuery(org.apache.calcite.rex.RexSubQuery) RelNode(org.apache.calcite.rel.RelNode) UNION(org.apache.calcite.sql.SqlKind.UNION) BitSet(java.util.BitSet) RexShuttle(org.apache.calcite.rex.RexShuttle) Util(org.apache.calcite.util.Util) Collections(java.util.Collections) TableSpool(org.apache.calcite.rel.core.TableSpool) RelNode(org.apache.calcite.rel.RelNode) ArrayList(java.util.ArrayList) Values(org.apache.calcite.rel.core.Values) RelDataType(org.apache.calcite.rel.type.RelDataType) ArrayList(java.util.ArrayList) AbstractList(java.util.AbstractList) RelOptPredicateList(org.apache.calcite.plan.RelOptPredicateList) ImmutableIntList(org.apache.calcite.util.ImmutableIntList) ImmutableNullableList(org.apache.calcite.util.ImmutableNullableList) List(java.util.List) ImmutableList(com.google.common.collect.ImmutableList) RelHint(org.apache.calcite.rel.hint.RelHint)

Aggregations

Preconditions (com.google.common.base.Preconditions)2 ImmutableList (com.google.common.collect.ImmutableList)2 ImmutableMap (com.google.common.collect.ImmutableMap)2 ImmutableSet (com.google.common.collect.ImmutableSet)2 ImmutableSortedMultiset (com.google.common.collect.ImmutableSortedMultiset)2 Iterables (com.google.common.collect.Iterables)2 Lists (com.google.common.collect.Lists)2 Multiset (com.google.common.collect.Multiset)2 Sets (com.google.common.collect.Sets)2 BigDecimal (java.math.BigDecimal)2 AbstractList (java.util.AbstractList)2 ArrayDeque (java.util.ArrayDeque)2 ArrayList (java.util.ArrayList)2 Arrays (java.util.Arrays)2 BitSet (java.util.BitSet)2 Collections (java.util.Collections)2 Deque (java.util.Deque)2 EnumSet (java.util.EnumSet)2 HashMap (java.util.HashMap)2 HashSet (java.util.HashSet)2