Search in sources :

Example 41 with RexInputRef

use of org.apache.calcite.rex.RexInputRef in project calcite by apache.

the class RelDecorrelator method decorrelateRel.

/**
 * Rewrite Correlate into a left outer join.
 *
 * @param rel Correlator
 */
public Frame decorrelateRel(LogicalCorrelate rel) {
    // 
    // Rewrite logic:
    // 
    // The original left input will be joined with the new right input that
    // has generated correlated variables propagated up. For any generated
    // corVars that are not used in the join key, pass them along to be
    // joined later with the Correlates that produce them.
    // 
    // the right input to Correlate should produce correlated variables
    final RelNode oldLeft = rel.getInput(0);
    final RelNode oldRight = rel.getInput(1);
    final Frame leftFrame = getInvoke(oldLeft, rel);
    final Frame rightFrame = getInvoke(oldRight, rel);
    if (leftFrame == null || rightFrame == null) {
        // If any input has not been rewritten, do not rewrite this rel.
        return null;
    }
    if (rightFrame.corDefOutputs.isEmpty()) {
        return null;
    }
    assert rel.getRequiredColumns().cardinality() <= rightFrame.corDefOutputs.keySet().size();
    // Change correlator rel into a join.
    // Join all the correlated variables produced by this correlator rel
    // with the values generated and propagated from the right input
    final SortedMap<CorDef, Integer> corDefOutputs = new TreeMap<>(rightFrame.corDefOutputs);
    final List<RexNode> conditions = new ArrayList<>();
    final List<RelDataTypeField> newLeftOutput = leftFrame.r.getRowType().getFieldList();
    int newLeftFieldCount = newLeftOutput.size();
    final List<RelDataTypeField> newRightOutput = rightFrame.r.getRowType().getFieldList();
    for (Map.Entry<CorDef, Integer> rightOutput : new ArrayList<>(corDefOutputs.entrySet())) {
        final CorDef corDef = rightOutput.getKey();
        if (!corDef.corr.equals(rel.getCorrelationId())) {
            continue;
        }
        final int newLeftPos = leftFrame.oldToNewOutputs.get(corDef.field);
        final int newRightPos = rightOutput.getValue();
        conditions.add(relBuilder.call(SqlStdOperatorTable.EQUALS, RexInputRef.of(newLeftPos, newLeftOutput), new RexInputRef(newLeftFieldCount + newRightPos, newRightOutput.get(newRightPos).getType())));
        // remove this corVar from output position mapping
        corDefOutputs.remove(corDef);
    }
    // vars that are not used in the join key.
    for (CorDef corDef : corDefOutputs.keySet()) {
        int newPos = corDefOutputs.get(corDef) + newLeftFieldCount;
        corDefOutputs.put(corDef, newPos);
    }
    // then add any corVar from the left input. Do not need to change
    // output positions.
    corDefOutputs.putAll(leftFrame.corDefOutputs);
    // Create the mapping between the output of the old correlation rel
    // and the new join rel
    final Map<Integer, Integer> mapOldToNewOutputs = new HashMap<>();
    int oldLeftFieldCount = oldLeft.getRowType().getFieldCount();
    int oldRightFieldCount = oldRight.getRowType().getFieldCount();
    assert rel.getRowType().getFieldCount() == oldLeftFieldCount + oldRightFieldCount;
    // Left input positions are not changed.
    mapOldToNewOutputs.putAll(leftFrame.oldToNewOutputs);
    // Right input positions are shifted by newLeftFieldCount.
    for (int i = 0; i < oldRightFieldCount; i++) {
        mapOldToNewOutputs.put(i + oldLeftFieldCount, rightFrame.oldToNewOutputs.get(i) + newLeftFieldCount);
    }
    final RexNode condition = RexUtil.composeConjunction(relBuilder.getRexBuilder(), conditions, false);
    RelNode newJoin = LogicalJoin.create(leftFrame.r, rightFrame.r, condition, ImmutableSet.<CorrelationId>of(), rel.getJoinType().toJoinType());
    return register(rel, newJoin, mapOldToNewOutputs, corDefOutputs);
}
Also used : HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) TreeMap(java.util.TreeMap) RelDataTypeField(org.apache.calcite.rel.type.RelDataTypeField) RelNode(org.apache.calcite.rel.RelNode) RexInputRef(org.apache.calcite.rex.RexInputRef) Map(java.util.Map) ImmutableSortedMap(com.google.common.collect.ImmutableSortedMap) TreeMap(java.util.TreeMap) ImmutableMap(com.google.common.collect.ImmutableMap) NavigableMap(java.util.NavigableMap) SortedMap(java.util.SortedMap) HashMap(java.util.HashMap) RexNode(org.apache.calcite.rex.RexNode)

Example 42 with RexInputRef

use of org.apache.calcite.rex.RexInputRef in project calcite by apache.

the class RelBuilder method field.

/**
 * As {@link #field(int, int, int)}, but if {@code alias} is true, the method
 * may apply an alias to make sure that the field has the same name as in the
 * input frame. If no alias is applied the expression is definitely a
 * {@link RexInputRef}.
 */
private RexNode field(int inputCount, int inputOrdinal, int fieldOrdinal, boolean alias) {
    final Frame frame = peek_(inputCount, inputOrdinal);
    final RelNode input = frame.rel;
    final RelDataType rowType = input.getRowType();
    if (fieldOrdinal < 0 || fieldOrdinal > rowType.getFieldCount()) {
        throw new IllegalArgumentException("field ordinal [" + fieldOrdinal + "] out of range; input fields are: " + rowType.getFieldNames());
    }
    final RelDataTypeField field = rowType.getFieldList().get(fieldOrdinal);
    final int offset = inputOffset(inputCount, inputOrdinal);
    final RexInputRef ref = cluster.getRexBuilder().makeInputRef(field.getType(), offset + fieldOrdinal);
    final RelDataTypeField aliasField = frame.fields().get(fieldOrdinal);
    if (!alias || field.getName().equals(aliasField.getName())) {
        return ref;
    } else {
        return alias(ref, aliasField.getName());
    }
}
Also used : RelDataTypeField(org.apache.calcite.rel.type.RelDataTypeField) RelNode(org.apache.calcite.rel.RelNode) RexInputRef(org.apache.calcite.rex.RexInputRef) RelDataType(org.apache.calcite.rel.type.RelDataType)

Example 43 with RexInputRef

use of org.apache.calcite.rex.RexInputRef in project calcite by apache.

the class RelBuilder method inferAlias.

/**
 * Infers the alias of an expression.
 *
 * <p>If the expression was created by {@link #alias}, replaces the expression
 * in the project list.
 */
private String inferAlias(List<RexNode> exprList, RexNode expr) {
    switch(expr.getKind()) {
        case INPUT_REF:
            final RexInputRef ref = (RexInputRef) expr;
            return stack.peek().fields.get(ref.getIndex()).getValue().getName();
        case CAST:
            return inferAlias(exprList, ((RexCall) expr).getOperands().get(0));
        case AS:
            final RexCall call = (RexCall) expr;
            for (; ; ) {
                final int i = exprList.indexOf(expr);
                if (i < 0) {
                    break;
                }
                exprList.set(i, call.getOperands().get(0));
            }
            return ((NlsString) ((RexLiteral) call.getOperands().get(1)).getValue()).getValue();
        default:
            return null;
    }
}
Also used : RexCall(org.apache.calcite.rex.RexCall) RexInputRef(org.apache.calcite.rex.RexInputRef) NlsString(org.apache.calcite.util.NlsString)

Example 44 with RexInputRef

use of org.apache.calcite.rex.RexInputRef in project calcite by apache.

the class RelBuilder method match.

/**
 * Creates a {@link org.apache.calcite.rel.core.Match}.
 */
public RelBuilder match(RexNode pattern, boolean strictStart, boolean strictEnd, Map<String, RexNode> patternDefinitions, Iterable<? extends RexNode> measureList, RexNode after, Map<String, ? extends SortedSet<String>> subsets, boolean allRows, Iterable<? extends RexNode> partitionKeys, Iterable<? extends RexNode> orderKeys, RexNode interval) {
    final List<RelFieldCollation> fieldCollations = new ArrayList<>();
    for (RexNode orderKey : orderKeys) {
        final RelFieldCollation.Direction direction;
        switch(orderKey.getKind()) {
            case DESCENDING:
                direction = RelFieldCollation.Direction.DESCENDING;
                orderKey = ((RexCall) orderKey).getOperands().get(0);
                break;
            case NULLS_FIRST:
            case NULLS_LAST:
                throw new AssertionError();
            default:
                direction = RelFieldCollation.Direction.ASCENDING;
                break;
        }
        final RelFieldCollation.NullDirection nullDirection = direction.defaultNullDirection();
        final RexInputRef ref = (RexInputRef) orderKey;
        fieldCollations.add(new RelFieldCollation(ref.getIndex(), direction, nullDirection));
    }
    final RelDataTypeFactory.Builder typeBuilder = cluster.getTypeFactory().builder();
    for (RexNode partitionKey : partitionKeys) {
        typeBuilder.add(partitionKey.toString(), partitionKey.getType());
    }
    if (allRows) {
        for (RexNode orderKey : orderKeys) {
            if (!typeBuilder.nameExists(orderKey.toString())) {
                typeBuilder.add(orderKey.toString(), orderKey.getType());
            }
        }
        final RelDataType inputRowType = peek().getRowType();
        for (RelDataTypeField fs : inputRowType.getFieldList()) {
            if (!typeBuilder.nameExists(fs.getName())) {
                typeBuilder.add(fs);
            }
        }
    }
    final ImmutableMap.Builder<String, RexNode> measures = ImmutableMap.builder();
    for (RexNode measure : measureList) {
        List<RexNode> operands = ((RexCall) measure).getOperands();
        String alias = operands.get(1).toString();
        typeBuilder.add(alias, operands.get(0).getType());
        measures.put(alias, operands.get(0));
    }
    final RelNode match = matchFactory.createMatch(peek(), pattern, typeBuilder.build(), strictStart, strictEnd, patternDefinitions, measures.build(), after, subsets, allRows, ImmutableList.copyOf(partitionKeys), RelCollations.of(fieldCollations), interval);
    stack.push(new Frame(match));
    return this;
}
Also used : ArrayList(java.util.ArrayList) RelDataType(org.apache.calcite.rel.type.RelDataType) NlsString(org.apache.calcite.util.NlsString) ImmutableMap(com.google.common.collect.ImmutableMap) RexCall(org.apache.calcite.rex.RexCall) RelDataTypeField(org.apache.calcite.rel.type.RelDataTypeField) RelNode(org.apache.calcite.rel.RelNode) RelFieldCollation(org.apache.calcite.rel.RelFieldCollation) RelDataTypeFactory(org.apache.calcite.rel.type.RelDataTypeFactory) RexInputRef(org.apache.calcite.rex.RexInputRef) RexNode(org.apache.calcite.rex.RexNode)

Example 45 with RexInputRef

use of org.apache.calcite.rex.RexInputRef in project calcite by apache.

the class RelStructuredTypeFlattener method flattenProjection.

private void flattenProjection(RewriteRexShuttle shuttle, RexNode exp, String fieldName, List<Pair<RexNode, String>> flattenedExps) {
    if (exp.getType().isStruct()) {
        if (exp instanceof RexInputRef) {
            RexInputRef inputRef = (RexInputRef) exp;
            int newOffset = getNewForOldInput(inputRef.getIndex());
            // expand to range
            RelDataType flattenedType = SqlTypeUtil.flattenRecordType(rexBuilder.getTypeFactory(), exp.getType(), null);
            List<RelDataTypeField> fieldList = flattenedType.getFieldList();
            int n = fieldList.size();
            for (int j = 0; j < n; ++j) {
                RelDataTypeField field = fieldList.get(j);
                flattenedExps.add(Pair.<RexNode, String>of(new RexInputRef(newOffset + j, field.getType()), fieldName));
            }
        } else if (isConstructor(exp) || exp.isA(SqlKind.CAST)) {
            // REVIEW jvs 27-Feb-2005:  for cast, see corresponding note
            // in RewriteRexShuttle
            RexCall call = (RexCall) exp;
            if (exp.isA(SqlKind.NEW_SPECIFICATION)) {
                // For object constructors, prepend a FALSE null
                // indicator.
                flattenedExps.add(Pair.<RexNode, String>of(rexBuilder.makeLiteral(false), fieldName));
            } else if (exp.isA(SqlKind.CAST)) {
                if (RexLiteral.isNullLiteral(((RexCall) exp).operands.get(0))) {
                    // Translate CAST(NULL AS UDT) into
                    // the correct number of null fields.
                    flattenNullLiteral(exp.getType(), flattenedExps);
                    return;
                }
            }
            flattenProjections(new RewriteRexShuttle(), call.getOperands(), Collections.<String>nCopies(call.getOperands().size(), null), fieldName, flattenedExps);
        } else if (exp instanceof RexCall) {
            // NOTE jvs 10-Feb-2005:  This is a lame hack to keep special
            // functions which return row types working.
            int j = 0;
            RexNode newExp = exp;
            List<RexNode> oldOperands = ((RexCall) exp).getOperands();
            if (oldOperands.get(0) instanceof RexInputRef) {
                RexInputRef inputRef = (RexInputRef) oldOperands.get(0);
                int newOffset = getNewForOldInput(inputRef.getIndex());
                newExp = rexBuilder.makeCall(exp.getType(), ((RexCall) exp).getOperator(), ImmutableList.of(rexBuilder.makeInputRef(inputRef.getType(), newOffset), oldOperands.get(1)));
            }
            for (RelDataTypeField field : newExp.getType().getFieldList()) {
                flattenedExps.add(Pair.of(rexBuilder.makeFieldAccess(newExp, field.getIndex()), fieldName + "$" + (j++)));
            }
        } else {
            throw Util.needToImplement(exp);
        }
    } else {
        flattenedExps.add(Pair.of(exp.accept(shuttle), fieldName));
    }
}
Also used : RexCall(org.apache.calcite.rex.RexCall) RelDataTypeField(org.apache.calcite.rel.type.RelDataTypeField) RexInputRef(org.apache.calcite.rex.RexInputRef) RelDataType(org.apache.calcite.rel.type.RelDataType) RexNode(org.apache.calcite.rex.RexNode)

Aggregations

RexInputRef (org.apache.calcite.rex.RexInputRef)241 RexNode (org.apache.calcite.rex.RexNode)200 ArrayList (java.util.ArrayList)103 RelNode (org.apache.calcite.rel.RelNode)85 RelDataTypeField (org.apache.calcite.rel.type.RelDataTypeField)80 RexCall (org.apache.calcite.rex.RexCall)67 RelDataType (org.apache.calcite.rel.type.RelDataType)63 RexBuilder (org.apache.calcite.rex.RexBuilder)54 ImmutableBitSet (org.apache.calcite.util.ImmutableBitSet)52 HashMap (java.util.HashMap)47 AggregateCall (org.apache.calcite.rel.core.AggregateCall)36 List (java.util.List)35 HashSet (java.util.HashSet)32 Pair (org.apache.calcite.util.Pair)32 RexLiteral (org.apache.calcite.rex.RexLiteral)29 Map (java.util.Map)24 RelOptUtil (org.apache.calcite.plan.RelOptUtil)24 Set (java.util.Set)20 ImmutableList (com.google.common.collect.ImmutableList)19 LinkedHashMap (java.util.LinkedHashMap)19