Search in sources :

Example 1 with LogicalAggregate

use of org.apache.calcite.rel.logical.LogicalAggregate in project calcite by apache.

the class EnumerableAggregateRule method convert.

public RelNode convert(RelNode rel) {
    final LogicalAggregate agg = (LogicalAggregate) rel;
    final RelTraitSet traitSet = agg.getTraitSet().replace(EnumerableConvention.INSTANCE);
    try {
        return new EnumerableAggregate(rel.getCluster(), traitSet, convert(agg.getInput(), EnumerableConvention.INSTANCE), agg.indicator, agg.getGroupSet(), agg.getGroupSets(), agg.getAggCallList());
    } catch (InvalidRelException e) {
        EnumerableRules.LOGGER.debug(e.toString());
        return null;
    }
}
Also used : InvalidRelException(org.apache.calcite.rel.InvalidRelException) LogicalAggregate(org.apache.calcite.rel.logical.LogicalAggregate) RelTraitSet(org.apache.calcite.plan.RelTraitSet)

Example 2 with LogicalAggregate

use of org.apache.calcite.rel.logical.LogicalAggregate in project calcite by apache.

the class SqlToRelConverter method substituteSubQuery.

private void substituteSubQuery(Blackboard bb, SubQuery subQuery) {
    final RexNode expr = subQuery.expr;
    if (expr != null) {
        // Already done.
        return;
    }
    final SqlBasicCall call;
    final RelNode rel;
    final SqlNode query;
    final RelOptUtil.Exists converted;
    switch(subQuery.node.getKind()) {
        case CURSOR:
            convertCursor(bb, subQuery);
            return;
        case MULTISET_QUERY_CONSTRUCTOR:
        case MULTISET_VALUE_CONSTRUCTOR:
        case ARRAY_QUERY_CONSTRUCTOR:
            rel = convertMultisets(ImmutableList.of(subQuery.node), bb);
            subQuery.expr = bb.register(rel, JoinRelType.INNER);
            return;
        case IN:
        case NOT_IN:
        case SOME:
        case ALL:
            call = (SqlBasicCall) subQuery.node;
            query = call.operand(1);
            if (!config.isExpand() && !(query instanceof SqlNodeList)) {
                return;
            }
            final SqlNode leftKeyNode = call.operand(0);
            final List<RexNode> leftKeys;
            switch(leftKeyNode.getKind()) {
                case ROW:
                    leftKeys = Lists.newArrayList();
                    for (SqlNode sqlExpr : ((SqlBasicCall) leftKeyNode).getOperandList()) {
                        leftKeys.add(bb.convertExpression(sqlExpr));
                    }
                    break;
                default:
                    leftKeys = ImmutableList.of(bb.convertExpression(leftKeyNode));
            }
            if (query instanceof SqlNodeList) {
                SqlNodeList valueList = (SqlNodeList) query;
                if (!containsNullLiteral(valueList) && valueList.size() < config.getInSubQueryThreshold()) {
                    // We're under the threshold, so convert to OR.
                    subQuery.expr = convertInToOr(bb, leftKeys, valueList, (SqlInOperator) call.getOperator());
                    return;
                }
            // Otherwise, let convertExists translate
            // values list into an inline table for the
            // reference to Q below.
            }
            // Project out the search columns from the left side
            // Q1:
            // "select from emp where emp.deptno in (select col1 from T)"
            // 
            // is converted to
            // 
            // "select from
            // emp inner join (select distinct col1 from T)) q
            // on emp.deptno = q.col1
            // 
            // Q2:
            // "select from emp where emp.deptno not in (Q)"
            // 
            // is converted to
            // 
            // "select from
            // emp left outer join (select distinct col1, TRUE from T) q
            // on emp.deptno = q.col1
            // where emp.deptno <> null
            // and q.indicator <> TRUE"
            // 
            final RelDataType targetRowType = SqlTypeUtil.promoteToRowType(typeFactory, validator.getValidatedNodeType(leftKeyNode), null);
            final boolean notIn = call.getOperator().kind == SqlKind.NOT_IN;
            converted = convertExists(query, RelOptUtil.SubQueryType.IN, subQuery.logic, notIn, targetRowType);
            if (converted.indicator) {
                // Generate
                // emp CROSS JOIN (SELECT COUNT(*) AS c,
                // COUNT(deptno) AS ck FROM dept)
                final RelDataType longType = typeFactory.createSqlType(SqlTypeName.BIGINT);
                // fragile
                final RelNode seek = converted.r.getInput(0);
                final int keyCount = leftKeys.size();
                final List<Integer> args = ImmutableIntList.range(0, keyCount);
                LogicalAggregate aggregate = LogicalAggregate.create(seek, ImmutableBitSet.of(), null, ImmutableList.of(AggregateCall.create(SqlStdOperatorTable.COUNT, false, false, ImmutableList.<Integer>of(), -1, longType, null), AggregateCall.create(SqlStdOperatorTable.COUNT, false, false, args, -1, longType, null)));
                LogicalJoin join = LogicalJoin.create(bb.root, aggregate, rexBuilder.makeLiteral(true), ImmutableSet.<CorrelationId>of(), JoinRelType.INNER);
                bb.setRoot(join, false);
            }
            final RexNode rex = bb.register(converted.r, converted.outerJoin ? JoinRelType.LEFT : JoinRelType.INNER, leftKeys);
            RelOptUtil.Logic logic = subQuery.logic;
            switch(logic) {
                case TRUE_FALSE_UNKNOWN:
                case UNKNOWN_AS_TRUE:
                    if (!converted.indicator) {
                        logic = RelOptUtil.Logic.TRUE_FALSE;
                    }
            }
            subQuery.expr = translateIn(logic, bb.root, rex);
            if (notIn) {
                subQuery.expr = rexBuilder.makeCall(SqlStdOperatorTable.NOT, subQuery.expr);
            }
            return;
        case EXISTS:
            // "select from emp where exists (select a from T)"
            // 
            // is converted to the following if the sub-query is correlated:
            // 
            // "select from emp left outer join (select AGG_TRUE() as indicator
            // from T group by corr_var) q where q.indicator is true"
            // 
            // If there is no correlation, the expression is replaced with a
            // boolean indicating whether the sub-query returned 0 or >= 1 row.
            call = (SqlBasicCall) subQuery.node;
            query = call.operand(0);
            if (!config.isExpand()) {
                return;
            }
            converted = convertExists(query, RelOptUtil.SubQueryType.EXISTS, subQuery.logic, true, null);
            assert !converted.indicator;
            if (convertNonCorrelatedSubQuery(subQuery, bb, converted.r, true)) {
                return;
            }
            subQuery.expr = bb.register(converted.r, JoinRelType.LEFT);
            return;
        case SCALAR_QUERY:
            // to a constant expression.
            if (!config.isExpand()) {
                return;
            }
            call = (SqlBasicCall) subQuery.node;
            query = call.operand(0);
            converted = convertExists(query, RelOptUtil.SubQueryType.SCALAR, subQuery.logic, true, null);
            assert !converted.indicator;
            if (convertNonCorrelatedSubQuery(subQuery, bb, converted.r, false)) {
                return;
            }
            rel = convertToSingleValueSubq(query, converted.r);
            subQuery.expr = bb.register(rel, JoinRelType.LEFT);
            return;
        case SELECT:
            // This is used when converting multiset queries:
            // 
            // select * from unnest(select multiset[deptno] from emps);
            // 
            converted = convertExists(subQuery.node, RelOptUtil.SubQueryType.SCALAR, subQuery.logic, true, null);
            assert !converted.indicator;
            subQuery.expr = bb.register(converted.r, JoinRelType.LEFT);
            return;
        default:
            throw new AssertionError("unexpected kind of sub-query: " + subQuery.node);
    }
}
Also used : RelOptUtil(org.apache.calcite.plan.RelOptUtil) SqlInOperator(org.apache.calcite.sql.fun.SqlInOperator) RelDataType(org.apache.calcite.rel.type.RelDataType) LogicalAggregate(org.apache.calcite.rel.logical.LogicalAggregate) SqlBasicCall(org.apache.calcite.sql.SqlBasicCall) RelNode(org.apache.calcite.rel.RelNode) LogicalJoin(org.apache.calcite.rel.logical.LogicalJoin) SqlNodeList(org.apache.calcite.sql.SqlNodeList) RexNode(org.apache.calcite.rex.RexNode) SqlNode(org.apache.calcite.sql.SqlNode)

Example 3 with LogicalAggregate

use of org.apache.calcite.rel.logical.LogicalAggregate in project calcite by apache.

the class RelOptUtil method createExistsPlan.

/**
 * Creates a plan suitable for use in <code>EXISTS</code> or <code>IN</code>
 * statements.
 *
 * @see org.apache.calcite.sql2rel.SqlToRelConverter#convertExists
 *
 * @param seekRel    A query rel, for example the resulting rel from 'select *
 *                   from emp' or 'values (1,2,3)' or '('Foo', 34)'.
 * @param subQueryType Sub-query type
 * @param logic  Whether to use 2- or 3-valued boolean logic
 * @param notIn Whether the operator is NOT IN
 * @param relBuilder Builder for relational expressions
 *
 * @return A pair of a relational expression which outer joins a boolean
 * condition column, and a numeric offset. The offset is 2 if column 0 is
 * the number of rows and column 1 is the number of rows with not-null keys;
 * 0 otherwise.
 */
public static Exists createExistsPlan(RelNode seekRel, SubQueryType subQueryType, Logic logic, boolean notIn, RelBuilder relBuilder) {
    switch(subQueryType) {
        case SCALAR:
            return new Exists(seekRel, false, true);
    }
    switch(logic) {
        case TRUE_FALSE_UNKNOWN:
        case UNKNOWN_AS_TRUE:
            if (notIn && !containsNullableFields(seekRel)) {
                logic = Logic.TRUE_FALSE;
            }
    }
    RelNode ret = seekRel;
    final RelOptCluster cluster = seekRel.getCluster();
    final RexBuilder rexBuilder = cluster.getRexBuilder();
    final int keyCount = ret.getRowType().getFieldCount();
    final boolean outerJoin = notIn || logic == RelOptUtil.Logic.TRUE_FALSE_UNKNOWN;
    if (!outerJoin) {
        final LogicalAggregate aggregate = LogicalAggregate.create(ret, ImmutableBitSet.range(keyCount), null, ImmutableList.<AggregateCall>of());
        return new Exists(aggregate, false, false);
    }
    // for IN/NOT IN, it needs to output the fields
    final List<RexNode> exprs = new ArrayList<>();
    if (subQueryType == SubQueryType.IN) {
        for (int i = 0; i < keyCount; i++) {
            exprs.add(rexBuilder.makeInputRef(ret, i));
        }
    }
    final int projectedKeyCount = exprs.size();
    exprs.add(rexBuilder.makeLiteral(true));
    ret = relBuilder.push(ret).project(exprs).build();
    final AggregateCall aggCall = AggregateCall.create(SqlStdOperatorTable.MIN, false, false, ImmutableList.of(projectedKeyCount), -1, projectedKeyCount, ret, null, null);
    ret = LogicalAggregate.create(ret, ImmutableBitSet.range(projectedKeyCount), null, ImmutableList.of(aggCall));
    switch(logic) {
        case TRUE_FALSE_UNKNOWN:
        case UNKNOWN_AS_TRUE:
            return new Exists(ret, true, true);
        default:
            return new Exists(ret, false, true);
    }
}
Also used : AggregateCall(org.apache.calcite.rel.core.AggregateCall) LogicalAggregate(org.apache.calcite.rel.logical.LogicalAggregate) RelNode(org.apache.calcite.rel.RelNode) ArrayList(java.util.ArrayList) RexBuilder(org.apache.calcite.rex.RexBuilder) RexNode(org.apache.calcite.rex.RexNode)

Example 4 with LogicalAggregate

use of org.apache.calcite.rel.logical.LogicalAggregate in project drill by axbaretto.

the class DrillAggregateRule method onMatch.

@Override
public void onMatch(RelOptRuleCall call) {
    final LogicalAggregate aggregate = call.rel(0);
    final RelNode input = call.rel(1);
    if (aggregate.containsDistinctCall()) {
        // currently, don't use this rule if any of the aggregates contains DISTINCT
        return;
    }
    final RelTraitSet traits = aggregate.getTraitSet().plus(DrillRel.DRILL_LOGICAL);
    final RelNode convertedInput = convert(input, input.getTraitSet().plus(DrillRel.DRILL_LOGICAL).simplify());
    try {
        call.transformTo(new DrillAggregateRel(aggregate.getCluster(), traits, convertedInput, aggregate.indicator, aggregate.getGroupSet(), aggregate.getGroupSets(), aggregate.getAggCallList()));
    } catch (InvalidRelException e) {
        tracer.warn(e.toString());
    }
}
Also used : InvalidRelException(org.apache.calcite.rel.InvalidRelException) LogicalAggregate(org.apache.calcite.rel.logical.LogicalAggregate) RelNode(org.apache.calcite.rel.RelNode) RelTraitSet(org.apache.calcite.plan.RelTraitSet)

Example 5 with LogicalAggregate

use of org.apache.calcite.rel.logical.LogicalAggregate in project samza by apache.

the class LogicalAggregateTranslator method translate.

void translate(final LogicalAggregate aggregate, final TranslatorContext context) {
    validateAggregateFunctions(aggregate);
    MessageStream<SamzaSqlRelMessage> inputStream = context.getMessageStream(aggregate.getInput().getId());
    // At this point, the assumption is that only count function is supported.
    SupplierFunction<Long> initialValue = () -> (long) 0;
    FoldLeftFunction<SamzaSqlRelMessage, Long> foldCountFn = (m, c) -> c + 1;
    final ArrayList<String> aggFieldNames = getAggFieldNames(aggregate);
    MessageStream<SamzaSqlRelMessage> outputStream = inputStream.map(new TranslatorInputMetricsMapFunction(logicalOpId)).window(Windows.keyedTumblingWindow(m -> m, Duration.ofMillis(context.getExecutionContext().getSamzaSqlApplicationConfig().getWindowDurationMs()), initialValue, foldCountFn, new SamzaSqlRelMessageSerdeFactory.SamzaSqlRelMessageSerde(), new LongSerde()).setAccumulationMode(AccumulationMode.DISCARDING), changeLogStorePrefix + "_tumblingWindow_" + logicalOpId).map(windowPane -> {
        List<String> fieldNames = windowPane.getKey().getKey().getSamzaSqlRelRecord().getFieldNames();
        List<Object> fieldValues = windowPane.getKey().getKey().getSamzaSqlRelRecord().getFieldValues();
        fieldNames.add(aggFieldNames.get(0));
        fieldValues.add(windowPane.getMessage());
        return new SamzaSqlRelMessage(fieldNames, fieldValues, new SamzaSqlRelMsgMetadata(0L, 0L));
    });
    context.registerMessageStream(aggregate.getId(), outputStream);
    outputStream.map(new TranslatorOutputMetricsMapFunction(logicalOpId));
}
Also used : SqlKind(org.apache.calcite.sql.SqlKind) Windows(org.apache.samza.operators.windows.Windows) Logger(org.slf4j.Logger) SamzaSqlRelMsgMetadata(org.apache.samza.sql.data.SamzaSqlRelMsgMetadata) LoggerFactory(org.slf4j.LoggerFactory) SamzaException(org.apache.samza.SamzaException) ArrayList(java.util.ArrayList) List(java.util.List) LogicalAggregate(org.apache.calcite.rel.logical.LogicalAggregate) AccumulationMode(org.apache.samza.operators.windows.AccumulationMode) Duration(java.time.Duration) SamzaSqlRelMessage(org.apache.samza.sql.data.SamzaSqlRelMessage) SamzaSqlRelMessageSerdeFactory(org.apache.samza.sql.serializers.SamzaSqlRelMessageSerdeFactory) FoldLeftFunction(org.apache.samza.operators.functions.FoldLeftFunction) SupplierFunction(org.apache.samza.operators.functions.SupplierFunction) MessageStream(org.apache.samza.operators.MessageStream) LongSerde(org.apache.samza.serializers.LongSerde) LongSerde(org.apache.samza.serializers.LongSerde) SamzaSqlRelMsgMetadata(org.apache.samza.sql.data.SamzaSqlRelMsgMetadata) SamzaSqlRelMessage(org.apache.samza.sql.data.SamzaSqlRelMessage)

Aggregations

LogicalAggregate (org.apache.calcite.rel.logical.LogicalAggregate)11 RelNode (org.apache.calcite.rel.RelNode)7 LogicalFilter (org.apache.calcite.rel.logical.LogicalFilter)4 RelTraitSet (org.apache.calcite.plan.RelTraitSet)3 LogicalJoin (org.apache.calcite.rel.logical.LogicalJoin)3 RelDataType (org.apache.calcite.rel.type.RelDataType)3 RexBuilder (org.apache.calcite.rex.RexBuilder)3 ArrayList (java.util.ArrayList)2 InvalidRelException (org.apache.calcite.rel.InvalidRelException)2 AggregateCall (org.apache.calcite.rel.core.AggregateCall)2 LogicalProject (org.apache.calcite.rel.logical.LogicalProject)2 LogicalTableScan (org.apache.calcite.rel.logical.LogicalTableScan)2 RelMetadataQuery (org.apache.calcite.rel.metadata.RelMetadataQuery)2 RexNode (org.apache.calcite.rex.RexNode)2 Test (org.junit.Test)2 Function (com.google.common.base.Function)1 ImmutableList (com.google.common.collect.ImmutableList)1 Duration (java.time.Duration)1 List (java.util.List)1 ReflectiveSchema (org.apache.calcite.adapter.java.ReflectiveSchema)1