Search in sources :

Example 96 with RelDataTypeField

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

the class DelegatingScope method resolveInNamespace.

/**
 * If a record type allows implicit references to fields, recursively looks
 * into the fields. Otherwise returns immediately.
 */
void resolveInNamespace(SqlValidatorNamespace ns, boolean nullable, List<String> names, SqlNameMatcher nameMatcher, Path path, Resolved resolved) {
    if (names.isEmpty()) {
        resolved.found(ns, nullable, this, path, null);
        return;
    }
    final RelDataType rowType = ns.getRowType();
    if (rowType.isStruct()) {
        SqlValidatorTable validatorTable = ns.getTable();
        if (validatorTable instanceof Prepare.PreparingTable) {
            Table t = ((Prepare.PreparingTable) validatorTable).unwrap(Table.class);
            if (t instanceof CustomColumnResolvingTable) {
                final List<Pair<RelDataTypeField, List<String>>> entries = ((CustomColumnResolvingTable) t).resolveColumn(rowType, validator.getTypeFactory(), names);
                for (Pair<RelDataTypeField, List<String>> entry : entries) {
                    final RelDataTypeField field = entry.getKey();
                    final List<String> remainder = entry.getValue();
                    final SqlValidatorNamespace ns2 = new FieldNamespace(validator, field.getType());
                    final Step path2 = path.plus(rowType, field.getIndex(), field.getName(), StructKind.FULLY_QUALIFIED);
                    resolveInNamespace(ns2, nullable, remainder, nameMatcher, path2, resolved);
                }
                return;
            }
        }
        final String name = names.get(0);
        final RelDataTypeField field0 = nameMatcher.field(rowType, name);
        if (field0 != null) {
            final SqlValidatorNamespace ns2 = ns.lookupChild(field0.getName());
            final Step path2 = path.plus(rowType, field0.getIndex(), field0.getName(), StructKind.FULLY_QUALIFIED);
            resolveInNamespace(ns2, nullable, names.subList(1, names.size()), nameMatcher, path2, resolved);
        } else {
            for (RelDataTypeField field : rowType.getFieldList()) {
                switch(field.getType().getStructKind()) {
                    case PEEK_FIELDS:
                    case PEEK_FIELDS_DEFAULT:
                    case PEEK_FIELDS_NO_EXPAND:
                        final Step path2 = path.plus(rowType, field.getIndex(), field.getName(), field.getType().getStructKind());
                        final SqlValidatorNamespace ns2 = ns.lookupChild(field.getName());
                        resolveInNamespace(ns2, nullable, names, nameMatcher, path2, resolved);
                }
            }
        }
    }
}
Also used : Table(org.apache.calcite.schema.Table) CustomColumnResolvingTable(org.apache.calcite.schema.CustomColumnResolvingTable) RelDataType(org.apache.calcite.rel.type.RelDataType) CustomColumnResolvingTable(org.apache.calcite.schema.CustomColumnResolvingTable) RelDataTypeField(org.apache.calcite.rel.type.RelDataTypeField) ArrayList(java.util.ArrayList) List(java.util.List) ImmutableList(com.google.common.collect.ImmutableList) SqlNodeList(org.apache.calcite.sql.SqlNodeList) Pair(org.apache.calcite.util.Pair)

Example 97 with RelDataTypeField

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

the class SetopOperandTypeChecker method checkOperandTypes.

public boolean checkOperandTypes(SqlCallBinding callBinding, boolean throwOnFailure) {
    assert callBinding.getOperandCount() == 2 : "setops are binary (for now)";
    final RelDataType[] argTypes = new RelDataType[callBinding.getOperandCount()];
    int colCount = -1;
    final SqlValidator validator = callBinding.getValidator();
    for (int i = 0; i < argTypes.length; i++) {
        final RelDataType argType = argTypes[i] = callBinding.getOperandType(i);
        if (!argType.isStruct()) {
            if (throwOnFailure) {
                throw new AssertionError("setop arg must be a struct");
            } else {
                return false;
            }
        }
        // Each operand must have the same number of columns.
        final List<RelDataTypeField> fields = argType.getFieldList();
        if (i == 0) {
            colCount = fields.size();
            continue;
        }
        if (fields.size() != colCount) {
            if (throwOnFailure) {
                SqlNode node = callBinding.operand(i);
                if (node instanceof SqlSelect) {
                    node = ((SqlSelect) node).getSelectList();
                }
                throw validator.newValidationError(node, RESOURCE.columnCountMismatchInSetop(callBinding.getOperator().getName()));
            } else {
                return false;
            }
        }
    }
    // column j.
    for (int i = 0; i < colCount; i++) {
        final int i2 = i;
        final RelDataType type = callBinding.getTypeFactory().leastRestrictive(new AbstractList<RelDataType>() {

            public RelDataType get(int index) {
                return argTypes[index].getFieldList().get(i2).getType();
            }

            public int size() {
                return argTypes.length;
            }
        });
        if (type == null) {
            if (throwOnFailure) {
                SqlNode field = SqlUtil.getSelectListItem(callBinding.operand(0), i);
                throw validator.newValidationError(field, // 1-based
                RESOURCE.columnTypeMismatchInSetop(// 1-based
                i + 1, callBinding.getOperator().getName()));
            } else {
                return false;
            }
        }
    }
    return true;
}
Also used : RelDataTypeField(org.apache.calcite.rel.type.RelDataTypeField) SqlSelect(org.apache.calcite.sql.SqlSelect) SqlValidator(org.apache.calcite.sql.validate.SqlValidator) RelDataType(org.apache.calcite.rel.type.RelDataType) SqlNode(org.apache.calcite.sql.SqlNode)

Example 98 with RelDataTypeField

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

the class ProjectWindowTransposeRule method onMatch.

@Override
public void onMatch(RelOptRuleCall call) {
    final LogicalProject project = call.rel(0);
    final LogicalWindow window = call.rel(1);
    final RelOptCluster cluster = window.getCluster();
    final List<RelDataTypeField> rowTypeWindowInput = window.getInput().getRowType().getFieldList();
    final int windowInputColumn = rowTypeWindowInput.size();
    // Record the window input columns which are actually referred
    // either in the LogicalProject above LogicalWindow or LogicalWindow itself
    // (Note that the constants used in LogicalWindow are not considered here)
    final ImmutableBitSet beReferred = findReference(project, window);
    // it is impossible to trim anyone of them out
    if (beReferred.cardinality() == windowInputColumn) {
        return;
    }
    // Put a DrillProjectRel below LogicalWindow
    final List<RexNode> exps = new ArrayList<>();
    final RelDataTypeFactory.Builder builder = cluster.getTypeFactory().builder();
    // Keep only the fields which are referred
    for (int index : BitSets.toIter(beReferred)) {
        final RelDataTypeField relDataTypeField = rowTypeWindowInput.get(index);
        exps.add(new RexInputRef(index, relDataTypeField.getType()));
        builder.add(relDataTypeField);
    }
    final LogicalProject projectBelowWindow = new LogicalProject(cluster, window.getTraitSet(), window.getInput(), exps, builder.build());
    // Create a new LogicalWindow with necessary inputs only
    final List<Window.Group> groups = new ArrayList<>();
    // As the un-referred columns are trimmed by the LogicalProject,
    // the indices specified in LogicalWindow would need to be adjusted
    final RexShuttle indexAdjustment = new RexShuttle() {

        @Override
        public RexNode visitInputRef(RexInputRef inputRef) {
            final int newIndex = getAdjustedIndex(inputRef.getIndex(), beReferred, windowInputColumn);
            return new RexInputRef(newIndex, inputRef.getType());
        }

        @Override
        public RexNode visitCall(final RexCall call) {
            if (call instanceof Window.RexWinAggCall) {
                boolean[] update = { false };
                final List<RexNode> clonedOperands = visitList(call.operands, update);
                if (update[0]) {
                    return new Window.RexWinAggCall((SqlAggFunction) call.getOperator(), call.getType(), clonedOperands, ((Window.RexWinAggCall) call).ordinal, ((Window.RexWinAggCall) call).distinct);
                } else {
                    return call;
                }
            } else {
                return super.visitCall(call);
            }
        }
    };
    int aggCallIndex = windowInputColumn;
    final RelDataTypeFactory.Builder outputBuilder = cluster.getTypeFactory().builder();
    outputBuilder.addAll(projectBelowWindow.getRowType().getFieldList());
    for (Window.Group group : window.groups) {
        final ImmutableBitSet.Builder keys = ImmutableBitSet.builder();
        final List<RelFieldCollation> orderKeys = new ArrayList<>();
        final List<Window.RexWinAggCall> aggCalls = new ArrayList<>();
        // Adjust keys
        for (int index : group.keys) {
            keys.set(getAdjustedIndex(index, beReferred, windowInputColumn));
        }
        // Adjust orderKeys
        for (RelFieldCollation relFieldCollation : group.orderKeys.getFieldCollations()) {
            final int index = relFieldCollation.getFieldIndex();
            orderKeys.add(relFieldCollation.copy(getAdjustedIndex(index, beReferred, windowInputColumn)));
        }
        // Adjust Window Functions
        for (Window.RexWinAggCall rexWinAggCall : group.aggCalls) {
            aggCalls.add((Window.RexWinAggCall) rexWinAggCall.accept(indexAdjustment));
            final RelDataTypeField relDataTypeField = window.getRowType().getFieldList().get(aggCallIndex);
            outputBuilder.add(relDataTypeField);
            ++aggCallIndex;
        }
        groups.add(new Window.Group(keys.build(), group.isRows, group.lowerBound, group.upperBound, RelCollations.of(orderKeys), aggCalls));
    }
    final LogicalWindow newLogicalWindow = LogicalWindow.create(window.getTraitSet(), projectBelowWindow, window.constants, outputBuilder.build(), groups);
    // Modify the top LogicalProject
    final List<RexNode> topProjExps = new ArrayList<>();
    for (RexNode rexNode : project.getChildExps()) {
        topProjExps.add(rexNode.accept(indexAdjustment));
    }
    final LogicalProject newTopProj = project.copy(newLogicalWindow.getTraitSet(), newLogicalWindow, topProjExps, project.getRowType());
    if (ProjectRemoveRule.isTrivial(newTopProj)) {
        call.transformTo(newLogicalWindow);
    } else {
        call.transformTo(newTopProj);
    }
}
Also used : RelOptCluster(org.apache.calcite.plan.RelOptCluster) ImmutableBitSet(org.apache.calcite.util.ImmutableBitSet) ArrayList(java.util.ArrayList) RexCall(org.apache.calcite.rex.RexCall) LogicalWindow(org.apache.calcite.rel.logical.LogicalWindow) RelDataTypeFactory(org.apache.calcite.rel.type.RelDataTypeFactory) Window(org.apache.calcite.rel.core.Window) LogicalWindow(org.apache.calcite.rel.logical.LogicalWindow) RexShuttle(org.apache.calcite.rex.RexShuttle) RelDataTypeField(org.apache.calcite.rel.type.RelDataTypeField) RelFieldCollation(org.apache.calcite.rel.RelFieldCollation) RexInputRef(org.apache.calcite.rex.RexInputRef) LogicalProject(org.apache.calcite.rel.logical.LogicalProject) RexNode(org.apache.calcite.rex.RexNode)

Example 99 with RelDataTypeField

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

the class SemiJoinJoinTransposeRule method onMatch.

// ~ Methods ----------------------------------------------------------------
// implement RelOptRule
public void onMatch(RelOptRuleCall call) {
    SemiJoin semiJoin = call.rel(0);
    final Join join = call.rel(1);
    if (join instanceof SemiJoin) {
        return;
    }
    final ImmutableIntList leftKeys = semiJoin.getLeftKeys();
    final ImmutableIntList rightKeys = semiJoin.getRightKeys();
    // X is the left child of the join below the semi-join
    // Y is the right child of the join below the semi-join
    // Z is the right child of the semi-join
    int nFieldsX = join.getLeft().getRowType().getFieldList().size();
    int nFieldsY = join.getRight().getRowType().getFieldList().size();
    int nFieldsZ = semiJoin.getRight().getRowType().getFieldList().size();
    int nTotalFields = nFieldsX + nFieldsY + nFieldsZ;
    List<RelDataTypeField> fields = new ArrayList<RelDataTypeField>();
    // create a list of fields for the full join result; note that
    // we can't simply use the fields from the semi-join because the
    // row-type of a semi-join only includes the left hand side fields
    List<RelDataTypeField> joinFields = semiJoin.getRowType().getFieldList();
    for (int i = 0; i < (nFieldsX + nFieldsY); i++) {
        fields.add(joinFields.get(i));
    }
    joinFields = semiJoin.getRight().getRowType().getFieldList();
    for (int i = 0; i < nFieldsZ; i++) {
        fields.add(joinFields.get(i));
    }
    // determine which operands below the semi-join are the actual
    // Rels that participate in the semi-join
    int nKeysFromX = 0;
    for (int leftKey : leftKeys) {
        if (leftKey < nFieldsX) {
            nKeysFromX++;
        }
    }
    // otherwise, a semi-join wouldn't have been created
    assert (nKeysFromX == 0) || (nKeysFromX == leftKeys.size());
    // need to convert the semi-join condition and possibly the keys
    RexNode newSemiJoinFilter;
    List<Integer> newLeftKeys;
    int[] adjustments = new int[nTotalFields];
    if (nKeysFromX > 0) {
        // (X, Y, Z) --> (X, Z, Y)
        // semiJoin(X, Z)
        // pass 0 as Y's adjustment because there shouldn't be any
        // references to Y in the semi-join filter
        setJoinAdjustments(adjustments, nFieldsX, nFieldsY, nFieldsZ, 0, -nFieldsY);
        newSemiJoinFilter = semiJoin.getCondition().accept(new RelOptUtil.RexInputConverter(semiJoin.getCluster().getRexBuilder(), fields, adjustments));
        newLeftKeys = leftKeys;
    } else {
        // (X, Y, Z) --> (X, Y, Z)
        // semiJoin(Y, Z)
        setJoinAdjustments(adjustments, nFieldsX, nFieldsY, nFieldsZ, -nFieldsX, -nFieldsX);
        newSemiJoinFilter = semiJoin.getCondition().accept(new RelOptUtil.RexInputConverter(semiJoin.getCluster().getRexBuilder(), fields, adjustments));
        newLeftKeys = RelOptUtil.adjustKeys(leftKeys, -nFieldsX);
    }
    // create the new join
    RelNode leftSemiJoinOp;
    if (nKeysFromX > 0) {
        leftSemiJoinOp = join.getLeft();
    } else {
        leftSemiJoinOp = join.getRight();
    }
    SemiJoin newSemiJoin = SemiJoin.create(leftSemiJoinOp, semiJoin.getRight(), newSemiJoinFilter, ImmutableIntList.copyOf(newLeftKeys), rightKeys);
    RelNode leftJoinRel;
    RelNode rightJoinRel;
    if (nKeysFromX > 0) {
        leftJoinRel = newSemiJoin;
        rightJoinRel = join.getRight();
    } else {
        leftJoinRel = join.getLeft();
        rightJoinRel = newSemiJoin;
    }
    RelNode newJoinRel = join.copy(join.getTraitSet(), join.getCondition(), leftJoinRel, rightJoinRel, join.getJoinType(), join.isSemiJoinDone());
    call.transformTo(newJoinRel);
}
Also used : ArrayList(java.util.ArrayList) SemiJoin(org.apache.calcite.rel.core.SemiJoin) Join(org.apache.calcite.rel.core.Join) RelDataTypeField(org.apache.calcite.rel.type.RelDataTypeField) RelNode(org.apache.calcite.rel.RelNode) SemiJoin(org.apache.calcite.rel.core.SemiJoin) ImmutableIntList(org.apache.calcite.util.ImmutableIntList) RexNode(org.apache.calcite.rex.RexNode)

Example 100 with RelDataTypeField

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

the class RexSubQuery method scalar.

/**
 * Creates a scalar sub-query.
 */
public static RexSubQuery scalar(RelNode rel) {
    final List<RelDataTypeField> fieldList = rel.getRowType().getFieldList();
    assert fieldList.size() == 1;
    final RelDataTypeFactory typeFactory = rel.getCluster().getTypeFactory();
    final RelDataType type = typeFactory.createTypeWithNullability(fieldList.get(0).getType(), true);
    return new RexSubQuery(type, SqlStdOperatorTable.SCALAR_QUERY, ImmutableList.<RexNode>of(), rel);
}
Also used : RelDataTypeField(org.apache.calcite.rel.type.RelDataTypeField) RelDataTypeFactory(org.apache.calcite.rel.type.RelDataTypeFactory) RelDataType(org.apache.calcite.rel.type.RelDataType)

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