Search in sources :

Example 81 with RelDataTypeField

use of org.apache.calcite.rel.type.RelDataTypeField in project calcite by apache.

the class RelOptUtil method createRenameRel.

// to be removed before 2.0
@Deprecated
public static RelNode createRenameRel(RelDataType outputType, RelNode rel) {
    RelDataType inputType = rel.getRowType();
    List<RelDataTypeField> inputFields = inputType.getFieldList();
    int n = inputFields.size();
    List<RelDataTypeField> outputFields = outputType.getFieldList();
    assert outputFields.size() == n : "rename: field count mismatch: in=" + inputType + ", out" + outputType;
    final List<Pair<RexNode, String>> renames = new ArrayList<>();
    for (Pair<RelDataTypeField, RelDataTypeField> pair : Pair.zip(inputFields, outputFields)) {
        final RelDataTypeField inputField = pair.left;
        final RelDataTypeField outputField = pair.right;
        assert inputField.getType().equals(outputField.getType());
        final RexBuilder rexBuilder = rel.getCluster().getRexBuilder();
        renames.add(Pair.<RexNode, String>of(rexBuilder.makeInputRef(inputField.getType(), inputField.getIndex()), outputField.getName()));
    }
    final RelBuilder relBuilder = RelFactories.LOGICAL_BUILDER.create(rel.getCluster(), null);
    return relBuilder.push(rel).project(Pair.left(renames), Pair.right(renames), true).build();
}
Also used : RelDataTypeField(org.apache.calcite.rel.type.RelDataTypeField) RelBuilder(org.apache.calcite.tools.RelBuilder) ArrayList(java.util.ArrayList) RexBuilder(org.apache.calcite.rex.RexBuilder) RelDataType(org.apache.calcite.rel.type.RelDataType) Pair(org.apache.calcite.util.Pair)

Example 82 with RelDataTypeField

use of org.apache.calcite.rel.type.RelDataTypeField in project calcite by apache.

the class RelOptUtil method permute.

/**
 * Creates a relational expression which permutes the output fields of a
 * relational expression according to a permutation.
 *
 * <p>Optimizations:</p>
 *
 * <ul>
 * <li>If the relational expression is a
 * {@link org.apache.calcite.rel.logical.LogicalCalc} or
 * {@link org.apache.calcite.rel.logical.LogicalProject} that is already
 * acting as a permutation, combines the new permutation with the old;</li>
 *
 * <li>If the permutation is the identity, returns the original relational
 * expression.</li>
 * </ul>
 *
 * <p>If a permutation is combined with its inverse, these optimizations
 * would combine to remove them both.
 *
 * @param rel         Relational expression
 * @param permutation Permutation to apply to fields
 * @param fieldNames  Field names; if null, or if a particular entry is null,
 *                    the name of the permuted field is used
 * @return relational expression which permutes its input fields
 */
public static RelNode permute(RelNode rel, Permutation permutation, List<String> fieldNames) {
    if (permutation.isIdentity()) {
        return rel;
    }
    if (rel instanceof LogicalCalc) {
        LogicalCalc calc = (LogicalCalc) rel;
        Permutation permutation1 = calc.getProgram().getPermutation();
        if (permutation1 != null) {
            Permutation permutation2 = permutation.product(permutation1);
            return permute(rel, permutation2, null);
        }
    }
    if (rel instanceof LogicalProject) {
        Permutation permutation1 = ((LogicalProject) rel).getPermutation();
        if (permutation1 != null) {
            Permutation permutation2 = permutation.product(permutation1);
            return permute(rel, permutation2, null);
        }
    }
    final List<RelDataType> outputTypeList = new ArrayList<>();
    final List<String> outputNameList = new ArrayList<>();
    final List<RexNode> exprList = new ArrayList<>();
    final List<RexLocalRef> projectRefList = new ArrayList<>();
    final List<RelDataTypeField> fields = rel.getRowType().getFieldList();
    final RelOptCluster cluster = rel.getCluster();
    for (int i = 0; i < permutation.getTargetCount(); i++) {
        int target = permutation.getTarget(i);
        final RelDataTypeField targetField = fields.get(target);
        outputTypeList.add(targetField.getType());
        outputNameList.add(((fieldNames == null) || (fieldNames.size() <= i) || (fieldNames.get(i) == null)) ? targetField.getName() : fieldNames.get(i));
        exprList.add(cluster.getRexBuilder().makeInputRef(fields.get(i).getType(), i));
        final int source = permutation.getSource(i);
        projectRefList.add(new RexLocalRef(source, fields.get(source).getType()));
    }
    final RelDataTypeFactory typeFactory = cluster.getTypeFactory();
    final RexProgram program = new RexProgram(rel.getRowType(), exprList, projectRefList, null, typeFactory.createStructType(outputTypeList, outputNameList));
    return LogicalCalc.create(rel, program);
}
Also used : Permutation(org.apache.calcite.util.Permutation) RexProgram(org.apache.calcite.rex.RexProgram) ArrayList(java.util.ArrayList) RelDataType(org.apache.calcite.rel.type.RelDataType) RelDataTypeField(org.apache.calcite.rel.type.RelDataTypeField) RelDataTypeFactory(org.apache.calcite.rel.type.RelDataTypeFactory) RexLocalRef(org.apache.calcite.rex.RexLocalRef) LogicalProject(org.apache.calcite.rel.logical.LogicalProject) LogicalCalc(org.apache.calcite.rel.logical.LogicalCalc) RexNode(org.apache.calcite.rex.RexNode)

Example 83 with RelDataTypeField

use of org.apache.calcite.rel.type.RelDataTypeField in project calcite by apache.

the class RelOptUtil method splitJoinCondition.

private static void splitJoinCondition(List<RelDataTypeField> sysFieldList, List<RelNode> inputs, RexNode condition, List<List<RexNode>> joinKeys, List<Integer> filterNulls, List<SqlOperator> rangeOp, List<RexNode> nonEquiList) {
    final int sysFieldCount = sysFieldList.size();
    final RelOptCluster cluster = inputs.get(0).getCluster();
    final RexBuilder rexBuilder = cluster.getRexBuilder();
    final RelDataTypeFactory typeFactory = cluster.getTypeFactory();
    final ImmutableBitSet[] inputsRange = new ImmutableBitSet[inputs.size()];
    int totalFieldCount = 0;
    for (int i = 0; i < inputs.size(); i++) {
        final int firstField = totalFieldCount + sysFieldCount;
        totalFieldCount = firstField + inputs.get(i).getRowType().getFieldCount();
        inputsRange[i] = ImmutableBitSet.range(firstField, totalFieldCount);
    }
    // adjustment array
    int[] adjustments = new int[totalFieldCount];
    for (int i = 0; i < inputs.size(); i++) {
        final int adjustment = inputsRange[i].nextSetBit(0);
        for (int j = adjustment; j < inputsRange[i].length(); j++) {
            adjustments[j] = -adjustment;
        }
    }
    if (condition instanceof RexCall) {
        RexCall call = (RexCall) condition;
        if (call.getKind() == SqlKind.AND) {
            for (RexNode operand : call.getOperands()) {
                splitJoinCondition(sysFieldList, inputs, operand, joinKeys, filterNulls, rangeOp, nonEquiList);
            }
            return;
        }
        RexNode leftKey = null;
        RexNode rightKey = null;
        int leftInput = 0;
        int rightInput = 0;
        List<RelDataTypeField> leftFields = null;
        List<RelDataTypeField> rightFields = null;
        boolean reverse = false;
        call = collapseExpandedIsNotDistinctFromExpr(call, rexBuilder);
        SqlKind kind = call.getKind();
        // Only consider range operators if we haven't already seen one
        if ((kind == SqlKind.EQUALS) || (filterNulls != null && kind == SqlKind.IS_NOT_DISTINCT_FROM) || (rangeOp != null && rangeOp.isEmpty() && (kind == SqlKind.GREATER_THAN || kind == SqlKind.GREATER_THAN_OR_EQUAL || kind == SqlKind.LESS_THAN || kind == SqlKind.LESS_THAN_OR_EQUAL))) {
            final List<RexNode> operands = call.getOperands();
            RexNode op0 = operands.get(0);
            RexNode op1 = operands.get(1);
            final ImmutableBitSet projRefs0 = InputFinder.bits(op0);
            final ImmutableBitSet projRefs1 = InputFinder.bits(op1);
            boolean foundBothInputs = false;
            for (int i = 0; i < inputs.size() && !foundBothInputs; i++) {
                if (projRefs0.intersects(inputsRange[i]) && projRefs0.union(inputsRange[i]).equals(inputsRange[i])) {
                    if (leftKey == null) {
                        leftKey = op0;
                        leftInput = i;
                        leftFields = inputs.get(leftInput).getRowType().getFieldList();
                    } else {
                        rightKey = op0;
                        rightInput = i;
                        rightFields = inputs.get(rightInput).getRowType().getFieldList();
                        reverse = true;
                        foundBothInputs = true;
                    }
                } else if (projRefs1.intersects(inputsRange[i]) && projRefs1.union(inputsRange[i]).equals(inputsRange[i])) {
                    if (leftKey == null) {
                        leftKey = op1;
                        leftInput = i;
                        leftFields = inputs.get(leftInput).getRowType().getFieldList();
                    } else {
                        rightKey = op1;
                        rightInput = i;
                        rightFields = inputs.get(rightInput).getRowType().getFieldList();
                        foundBothInputs = true;
                    }
                }
            }
            if ((leftKey != null) && (rightKey != null)) {
                // replace right Key input ref
                rightKey = rightKey.accept(new RelOptUtil.RexInputConverter(rexBuilder, rightFields, rightFields, adjustments));
                // left key only needs to be adjusted if there are system
                // fields, but do it for uniformity
                leftKey = leftKey.accept(new RelOptUtil.RexInputConverter(rexBuilder, leftFields, leftFields, adjustments));
                RelDataType leftKeyType = leftKey.getType();
                RelDataType rightKeyType = rightKey.getType();
                if (leftKeyType != rightKeyType) {
                    // perform casting
                    RelDataType targetKeyType = typeFactory.leastRestrictive(ImmutableList.of(leftKeyType, rightKeyType));
                    if (targetKeyType == null) {
                        throw new AssertionError("Cannot find common type for join keys " + leftKey + " (type " + leftKeyType + ") and " + rightKey + " (type " + rightKeyType + ")");
                    }
                    if (leftKeyType != targetKeyType) {
                        leftKey = rexBuilder.makeCast(targetKeyType, leftKey);
                    }
                    if (rightKeyType != targetKeyType) {
                        rightKey = rexBuilder.makeCast(targetKeyType, rightKey);
                    }
                }
            }
        }
        if ((rangeOp == null) && ((leftKey == null) || (rightKey == null))) {
            // no equality join keys found yet:
            // try transforming the condition to
            // equality "join" conditions, e.g.
            // f(LHS) > 0 ===> ( f(LHS) > 0 ) = TRUE,
            // and make the RHS produce TRUE, but only if we're strictly
            // looking for equi-joins
            final ImmutableBitSet projRefs = InputFinder.bits(condition);
            leftKey = null;
            rightKey = null;
            boolean foundInput = false;
            for (int i = 0; i < inputs.size() && !foundInput; i++) {
                if (inputsRange[i].contains(projRefs)) {
                    leftInput = i;
                    leftFields = inputs.get(leftInput).getRowType().getFieldList();
                    leftKey = condition.accept(new RelOptUtil.RexInputConverter(rexBuilder, leftFields, leftFields, adjustments));
                    rightKey = rexBuilder.makeLiteral(true);
                    // effectively performing an equality comparison
                    kind = SqlKind.EQUALS;
                    foundInput = true;
                }
            }
        }
        if ((leftKey != null) && (rightKey != null)) {
            // found suitable join keys
            // add them to key list, ensuring that if there is a
            // non-equi join predicate, it appears at the end of the
            // key list; also mark the null filtering property
            addJoinKey(joinKeys.get(leftInput), leftKey, (rangeOp != null) && !rangeOp.isEmpty());
            addJoinKey(joinKeys.get(rightInput), rightKey, (rangeOp != null) && !rangeOp.isEmpty());
            if (filterNulls != null && kind == SqlKind.EQUALS) {
                // nulls are considered not matching for equality comparison
                // add the position of the most recently inserted key
                filterNulls.add(joinKeys.get(leftInput).size() - 1);
            }
            if (rangeOp != null && kind != SqlKind.EQUALS && kind != SqlKind.IS_DISTINCT_FROM) {
                if (reverse) {
                    kind = kind.reverse();
                }
                rangeOp.add(op(kind, call.getOperator()));
            }
            return;
        }
    // else fall through and add this condition as nonEqui condition
    }
    // The operator is not of RexCall type
    // So we fail. Fall through.
    // Add this condition to the list of non-equi-join conditions.
    nonEquiList.add(condition);
}
Also used : ImmutableBitSet(org.apache.calcite.util.ImmutableBitSet) RelDataType(org.apache.calcite.rel.type.RelDataType) SqlKind(org.apache.calcite.sql.SqlKind) RexCall(org.apache.calcite.rex.RexCall) RelDataTypeField(org.apache.calcite.rel.type.RelDataTypeField) RelDataTypeFactory(org.apache.calcite.rel.type.RelDataTypeFactory) RexBuilder(org.apache.calcite.rex.RexBuilder) RexNode(org.apache.calcite.rex.RexNode)

Example 84 with RelDataTypeField

use of org.apache.calcite.rel.type.RelDataTypeField in project calcite by apache.

the class RelOptUtil method projectJoinInputs.

// to be removed before 2.0
@Deprecated
public static void projectJoinInputs(RelNode[] inputRels, List<RexNode> leftJoinKeys, List<RexNode> rightJoinKeys, int systemColCount, List<Integer> leftKeys, List<Integer> rightKeys, List<Integer> outputProj) {
    RelNode leftRel = inputRels[0];
    RelNode rightRel = inputRels[1];
    final RelOptCluster cluster = leftRel.getCluster();
    final RexBuilder rexBuilder = cluster.getRexBuilder();
    final RelDataTypeSystem typeSystem = cluster.getTypeFactory().getTypeSystem();
    int origLeftInputSize = leftRel.getRowType().getFieldCount();
    int origRightInputSize = rightRel.getRowType().getFieldCount();
    final List<RexNode> newLeftFields = new ArrayList<>();
    final List<String> newLeftFieldNames = new ArrayList<>();
    final List<RexNode> newRightFields = new ArrayList<>();
    final List<String> newRightFieldNames = new ArrayList<>();
    int leftKeyCount = leftJoinKeys.size();
    int rightKeyCount = rightJoinKeys.size();
    int i;
    for (i = 0; i < systemColCount; i++) {
        outputProj.add(i);
    }
    for (i = 0; i < origLeftInputSize; i++) {
        final RelDataTypeField field = leftRel.getRowType().getFieldList().get(i);
        newLeftFields.add(rexBuilder.makeInputRef(field.getType(), i));
        newLeftFieldNames.add(field.getName());
        outputProj.add(systemColCount + i);
    }
    int newLeftKeyCount = 0;
    for (i = 0; i < leftKeyCount; i++) {
        RexNode leftKey = leftJoinKeys.get(i);
        if (leftKey instanceof RexInputRef) {
            // already added to the projected left fields
            // only need to remember the index in the join key list
            leftKeys.add(((RexInputRef) leftKey).getIndex());
        } else {
            newLeftFields.add(leftKey);
            newLeftFieldNames.add(null);
            leftKeys.add(origLeftInputSize + newLeftKeyCount);
            newLeftKeyCount++;
        }
    }
    int leftFieldCount = origLeftInputSize + newLeftKeyCount;
    for (i = 0; i < origRightInputSize; i++) {
        final RelDataTypeField field = rightRel.getRowType().getFieldList().get(i);
        newRightFields.add(rexBuilder.makeInputRef(field.getType(), i));
        newRightFieldNames.add(field.getName());
        outputProj.add(systemColCount + leftFieldCount + i);
    }
    int newRightKeyCount = 0;
    for (i = 0; i < rightKeyCount; i++) {
        RexNode rightKey = rightJoinKeys.get(i);
        if (rightKey instanceof RexInputRef) {
            // already added to the projected left fields
            // only need to remember the index in the join key list
            rightKeys.add(((RexInputRef) rightKey).getIndex());
        } else {
            newRightFields.add(rightKey);
            newRightFieldNames.add(null);
            rightKeys.add(origRightInputSize + newRightKeyCount);
            newRightKeyCount++;
        }
    }
    final RelBuilder relBuilder = RelFactories.LOGICAL_BUILDER.create(cluster, null);
    // fields
    if (newLeftKeyCount > 0) {
        leftRel = relBuilder.push(leftRel).project(newLeftFields, newLeftFieldNames, true).build();
    }
    if (newRightKeyCount > 0) {
        rightRel = relBuilder.push(rightRel).project(newRightFields, newRightFieldNames).build();
    }
    inputRels[0] = leftRel;
    inputRels[1] = rightRel;
}
Also used : RelBuilder(org.apache.calcite.tools.RelBuilder) RelDataTypeSystem(org.apache.calcite.rel.type.RelDataTypeSystem) ArrayList(java.util.ArrayList) RelDataTypeField(org.apache.calcite.rel.type.RelDataTypeField) RelNode(org.apache.calcite.rel.RelNode) RexBuilder(org.apache.calcite.rex.RexBuilder) RexInputRef(org.apache.calcite.rex.RexInputRef) RexNode(org.apache.calcite.rex.RexNode)

Example 85 with RelDataTypeField

use of org.apache.calcite.rel.type.RelDataTypeField in project calcite by apache.

the class RelOptUtil method createNullFilter.

// to be removed before 2.0
@Deprecated
public static RelNode createNullFilter(RelNode rel, Integer[] fieldOrdinals) {
    RexNode condition = null;
    final RexBuilder rexBuilder = rel.getCluster().getRexBuilder();
    RelDataType rowType = rel.getRowType();
    int n;
    if (fieldOrdinals != null) {
        n = fieldOrdinals.length;
    } else {
        n = rowType.getFieldCount();
    }
    List<RelDataTypeField> fields = rowType.getFieldList();
    for (int i = 0; i < n; ++i) {
        int iField;
        if (fieldOrdinals != null) {
            iField = fieldOrdinals[i];
        } else {
            iField = i;
        }
        RelDataType type = fields.get(iField).getType();
        if (!type.isNullable()) {
            continue;
        }
        RexNode newCondition = rexBuilder.makeCall(SqlStdOperatorTable.IS_NOT_NULL, rexBuilder.makeInputRef(type, iField));
        if (condition == null) {
            condition = newCondition;
        } else {
            condition = rexBuilder.makeCall(SqlStdOperatorTable.AND, condition, newCondition);
        }
    }
    if (condition == null) {
        // no filtering required
        return rel;
    }
    final RelFactories.FilterFactory factory = RelFactories.DEFAULT_FILTER_FACTORY;
    return factory.createFilter(rel, condition);
}
Also used : RelDataTypeField(org.apache.calcite.rel.type.RelDataTypeField) RexBuilder(org.apache.calcite.rex.RexBuilder) RelDataType(org.apache.calcite.rel.type.RelDataType) RelFactories(org.apache.calcite.rel.core.RelFactories) RexNode(org.apache.calcite.rex.RexNode)

Aggregations

RelDataTypeField (org.apache.calcite.rel.type.RelDataTypeField)388 RelDataType (org.apache.calcite.rel.type.RelDataType)210 RexNode (org.apache.calcite.rex.RexNode)185 ArrayList (java.util.ArrayList)175 RelNode (org.apache.calcite.rel.RelNode)130 RexBuilder (org.apache.calcite.rex.RexBuilder)76 RexInputRef (org.apache.calcite.rex.RexInputRef)72 ImmutableBitSet (org.apache.calcite.util.ImmutableBitSet)65 Pair (org.apache.calcite.util.Pair)55 RelDataTypeFactory (org.apache.calcite.rel.type.RelDataTypeFactory)47 HashMap (java.util.HashMap)39 Map (java.util.Map)35 AggregateCall (org.apache.calcite.rel.core.AggregateCall)35 SqlNode (org.apache.calcite.sql.SqlNode)32 ImmutableList (com.google.common.collect.ImmutableList)31 RelBuilder (org.apache.calcite.tools.RelBuilder)29 RelDataTypeFieldImpl (org.apache.calcite.rel.type.RelDataTypeFieldImpl)26 List (java.util.List)23 LinkedHashSet (java.util.LinkedHashSet)22 RelOptUtil (org.apache.calcite.plan.RelOptUtil)22