Search in sources :

Example 26 with RelDataTypeFactory

use of org.apache.calcite.rel.type.RelDataTypeFactory 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 27 with RelDataTypeFactory

use of org.apache.calcite.rel.type.RelDataTypeFactory 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 28 with RelDataTypeFactory

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

the class SqlTypeUtil method makeNullableIfOperandsAre.

/**
 * Recreates a given RelDataType with nullability iff any of the operands
 * of a call are nullable.
 */
public static RelDataType makeNullableIfOperandsAre(final SqlValidator validator, final SqlValidatorScope scope, final SqlCall call, RelDataType type) {
    for (SqlNode operand : call.getOperandList()) {
        RelDataType operandType = validator.deriveType(scope, operand);
        if (containsNullable(operandType)) {
            RelDataTypeFactory typeFactory = validator.getTypeFactory();
            type = typeFactory.createTypeWithNullability(type, true);
            break;
        }
    }
    return type;
}
Also used : RelDataTypeFactory(org.apache.calcite.rel.type.RelDataTypeFactory) RelDataType(org.apache.calcite.rel.type.RelDataType) SqlNode(org.apache.calcite.sql.SqlNode)

Example 29 with RelDataTypeFactory

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

the class AbstractNamespace method convertToStruct.

protected RelDataType convertToStruct(RelDataType type) {
    // "MULTISET [<expr>, ...]" needs to be wrapped in a record if
    // <expr> has a scalar type.
    // For example, "MULTISET [8, 9]" has type
    // "RECORD(INTEGER EXPR$0 NOT NULL) NOT NULL MULTISET NOT NULL".
    final RelDataType componentType = type.getComponentType();
    if (componentType == null || componentType.isStruct()) {
        return type;
    }
    final RelDataTypeFactory typeFactory = validator.getTypeFactory();
    final RelDataType structType = toStruct(componentType, getNode());
    final RelDataType collectionType;
    switch(type.getSqlTypeName()) {
        case ARRAY:
            collectionType = typeFactory.createArrayType(structType, -1);
            break;
        case MULTISET:
            collectionType = typeFactory.createMultisetType(structType, -1);
            break;
        default:
            throw new AssertionError(type);
    }
    return typeFactory.createTypeWithNullability(collectionType, type.isNullable());
}
Also used : RelDataTypeFactory(org.apache.calcite.rel.type.RelDataTypeFactory) RelDataType(org.apache.calcite.rel.type.RelDataType)

Example 30 with RelDataTypeFactory

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

the class JoinNamespace method validateImpl.

// ~ Methods ----------------------------------------------------------------
protected RelDataType validateImpl(RelDataType targetRowType) {
    RelDataType leftType = validator.getNamespace(join.getLeft()).getRowType();
    RelDataType rightType = validator.getNamespace(join.getRight()).getRowType();
    final RelDataTypeFactory typeFactory = validator.getTypeFactory();
    switch(join.getJoinType()) {
        case LEFT:
            rightType = typeFactory.createTypeWithNullability(rightType, true);
            break;
        case RIGHT:
            leftType = typeFactory.createTypeWithNullability(leftType, true);
            break;
        case FULL:
            leftType = typeFactory.createTypeWithNullability(leftType, true);
            rightType = typeFactory.createTypeWithNullability(rightType, true);
            break;
    }
    return typeFactory.createJoinType(leftType, rightType);
}
Also used : RelDataTypeFactory(org.apache.calcite.rel.type.RelDataTypeFactory) RelDataType(org.apache.calcite.rel.type.RelDataType)

Aggregations

RelDataTypeFactory (org.apache.calcite.rel.type.RelDataTypeFactory)128 RelDataType (org.apache.calcite.rel.type.RelDataType)97 RexNode (org.apache.calcite.rex.RexNode)47 RexBuilder (org.apache.calcite.rex.RexBuilder)38 RelDataTypeField (org.apache.calcite.rel.type.RelDataTypeField)30 Test (org.junit.Test)22 ArrayList (java.util.ArrayList)20 RelNode (org.apache.calcite.rel.RelNode)20 AggregateCall (org.apache.calcite.rel.core.AggregateCall)15 SqlNode (org.apache.calcite.sql.SqlNode)14 SqlTypeFactoryImpl (org.apache.calcite.sql.type.SqlTypeFactoryImpl)14 BigDecimal (java.math.BigDecimal)12 List (java.util.List)10 RelDataTypeFactory (org.apache.beam.vendor.calcite.v1_28_0.org.apache.calcite.rel.type.RelDataTypeFactory)8 SqlAggFunction (org.apache.calcite.sql.SqlAggFunction)8 SqlTypeName (org.apache.calcite.sql.type.SqlTypeName)8 Calendar (java.util.Calendar)7 RexInputRef (org.apache.calcite.rex.RexInputRef)7 Pair (org.apache.calcite.util.Pair)7 TimestampString (org.apache.calcite.util.TimestampString)7