Search in sources :

Example 36 with RexInputRef

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

the class SqlToRelConverter method convertCursor.

private RelNode convertCursor(Blackboard bb, SubQuery subQuery) {
    final SqlCall cursorCall = (SqlCall) subQuery.node;
    assert cursorCall.operandCount() == 1;
    SqlNode query = cursorCall.operand(0);
    RelNode converted = convertQuery(query, false, false).rel;
    int iCursor = bb.cursors.size();
    bb.cursors.add(converted);
    subQuery.expr = new RexInputRef(iCursor, converted.getRowType());
    return converted;
}
Also used : RelNode(org.apache.calcite.rel.RelNode) SqlCall(org.apache.calcite.sql.SqlCall) RexInputRef(org.apache.calcite.rex.RexInputRef) SqlNode(org.apache.calcite.sql.SqlNode)

Example 37 with RexInputRef

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

the class SqlToRelConverter method distinctify.

/**
 * Having translated 'SELECT ... FROM ... [GROUP BY ...] [HAVING ...]', adds
 * a relational expression to make the results unique.
 *
 * <p>If the SELECT clause contains duplicate expressions, adds
 * {@link org.apache.calcite.rel.logical.LogicalProject}s so that we are
 * grouping on the minimal set of keys. The performance gain isn't huge, but
 * it is difficult to detect these duplicate expressions later.
 *
 * @param bb               Blackboard
 * @param checkForDupExprs Check for duplicate expressions
 */
private void distinctify(Blackboard bb, boolean checkForDupExprs) {
    // Look for duplicate expressions in the project.
    // Say we have 'select x, y, x, z'.
    // Then dups will be {[2, 0]}
    // and oldToNew will be {[0, 0], [1, 1], [2, 0], [3, 2]}
    RelNode rel = bb.root;
    if (checkForDupExprs && (rel instanceof LogicalProject)) {
        LogicalProject project = (LogicalProject) rel;
        final List<RexNode> projectExprs = project.getProjects();
        final List<Integer> origins = new ArrayList<>();
        int dupCount = 0;
        for (int i = 0; i < projectExprs.size(); i++) {
            int x = findExpr(projectExprs.get(i), projectExprs, i);
            if (x >= 0) {
                origins.add(x);
                ++dupCount;
            } else {
                origins.add(i);
            }
        }
        if (dupCount == 0) {
            distinctify(bb, false);
            return;
        }
        final Map<Integer, Integer> squished = Maps.newHashMap();
        final List<RelDataTypeField> fields = rel.getRowType().getFieldList();
        final List<Pair<RexNode, String>> newProjects = Lists.newArrayList();
        for (int i = 0; i < fields.size(); i++) {
            if (origins.get(i) == i) {
                squished.put(i, newProjects.size());
                newProjects.add(RexInputRef.of2(i, fields));
            }
        }
        rel = LogicalProject.create(rel, Pair.left(newProjects), Pair.right(newProjects));
        bb.root = rel;
        distinctify(bb, false);
        rel = bb.root;
        // Create the expressions to reverse the mapping.
        // Project($0, $1, $0, $2).
        final List<Pair<RexNode, String>> undoProjects = Lists.newArrayList();
        for (int i = 0; i < fields.size(); i++) {
            final int origin = origins.get(i);
            RelDataTypeField field = fields.get(i);
            undoProjects.add(Pair.of((RexNode) new RexInputRef(squished.get(origin), field.getType()), field.getName()));
        }
        rel = LogicalProject.create(rel, Pair.left(undoProjects), Pair.right(undoProjects));
        bb.setRoot(rel, false);
        return;
    }
    // Usual case: all of the expressions in the SELECT clause are
    // different.
    final ImmutableBitSet groupSet = ImmutableBitSet.range(rel.getRowType().getFieldCount());
    rel = createAggregate(bb, groupSet, ImmutableList.of(groupSet), ImmutableList.<AggregateCall>of());
    bb.setRoot(rel, false);
}
Also used : ImmutableBitSet(org.apache.calcite.util.ImmutableBitSet) ArrayList(java.util.ArrayList) AggregateCall(org.apache.calcite.rel.core.AggregateCall) RelDataTypeField(org.apache.calcite.rel.type.RelDataTypeField) RelNode(org.apache.calcite.rel.RelNode) RexInputRef(org.apache.calcite.rex.RexInputRef) LogicalProject(org.apache.calcite.rel.logical.LogicalProject) RexNode(org.apache.calcite.rex.RexNode) Pair(org.apache.calcite.util.Pair)

Example 38 with RexInputRef

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

the class SqlToRelConverter method convertMatchRecognize.

protected void convertMatchRecognize(Blackboard bb, SqlCall call) {
    final SqlMatchRecognize matchRecognize = (SqlMatchRecognize) call;
    final SqlValidatorNamespace ns = validator.getNamespace(matchRecognize);
    final SqlValidatorScope scope = validator.getMatchRecognizeScope(matchRecognize);
    final Blackboard matchBb = createBlackboard(scope, null, false);
    final RelDataType rowType = ns.getRowType();
    // convert inner query, could be a table name or a derived table
    SqlNode expr = matchRecognize.getTableRef();
    convertFrom(matchBb, expr);
    final RelNode input = matchBb.root;
    // PARTITION BY
    final SqlNodeList partitionList = matchRecognize.getPartitionList();
    final List<RexNode> partitionKeys = new ArrayList<>();
    for (SqlNode partition : partitionList) {
        RexNode e = matchBb.convertExpression(partition);
        partitionKeys.add(e);
    }
    // ORDER BY
    final SqlNodeList orderList = matchRecognize.getOrderList();
    final List<RelFieldCollation> orderKeys = new ArrayList<>();
    for (SqlNode order : orderList) {
        final RelFieldCollation.Direction direction;
        switch(order.getKind()) {
            case DESCENDING:
                direction = RelFieldCollation.Direction.DESCENDING;
                order = ((SqlCall) order).operand(0);
                break;
            case NULLS_FIRST:
            case NULLS_LAST:
                throw new AssertionError();
            default:
                direction = RelFieldCollation.Direction.ASCENDING;
                break;
        }
        final RelFieldCollation.NullDirection nullDirection = validator.getDefaultNullCollation().last(desc(direction)) ? RelFieldCollation.NullDirection.LAST : RelFieldCollation.NullDirection.FIRST;
        RexNode e = matchBb.convertExpression(order);
        orderKeys.add(new RelFieldCollation(((RexInputRef) e).getIndex(), direction, nullDirection));
    }
    final RelCollation orders = cluster.traitSet().canonize(RelCollations.of(orderKeys));
    // convert pattern
    final Set<String> patternVarsSet = new HashSet<>();
    SqlNode pattern = matchRecognize.getPattern();
    final SqlBasicVisitor<RexNode> patternVarVisitor = new SqlBasicVisitor<RexNode>() {

        @Override
        public RexNode visit(SqlCall call) {
            List<SqlNode> operands = call.getOperandList();
            List<RexNode> newOperands = Lists.newArrayList();
            for (SqlNode node : operands) {
                newOperands.add(node.accept(this));
            }
            return rexBuilder.makeCall(validator.getUnknownType(), call.getOperator(), newOperands);
        }

        @Override
        public RexNode visit(SqlIdentifier id) {
            assert id.isSimple();
            patternVarsSet.add(id.getSimple());
            return rexBuilder.makeLiteral(id.getSimple());
        }

        @Override
        public RexNode visit(SqlLiteral literal) {
            if (literal instanceof SqlNumericLiteral) {
                return rexBuilder.makeExactLiteral(BigDecimal.valueOf(literal.intValue(true)));
            } else {
                return rexBuilder.makeLiteral(literal.booleanValue());
            }
        }
    };
    final RexNode patternNode = pattern.accept(patternVarVisitor);
    SqlLiteral interval = matchRecognize.getInterval();
    RexNode intervalNode = null;
    if (interval != null) {
        intervalNode = matchBb.convertLiteral(interval);
    }
    // convert subset
    final SqlNodeList subsets = matchRecognize.getSubsetList();
    final Map<String, TreeSet<String>> subsetMap = Maps.newHashMap();
    for (SqlNode node : subsets) {
        List<SqlNode> operands = ((SqlCall) node).getOperandList();
        SqlIdentifier left = (SqlIdentifier) operands.get(0);
        patternVarsSet.add(left.getSimple());
        SqlNodeList rights = (SqlNodeList) operands.get(1);
        final TreeSet<String> list = new TreeSet<String>();
        for (SqlNode right : rights) {
            assert right instanceof SqlIdentifier;
            list.add(((SqlIdentifier) right).getSimple());
        }
        subsetMap.put(left.getSimple(), list);
    }
    SqlNode afterMatch = matchRecognize.getAfter();
    if (afterMatch == null) {
        afterMatch = SqlMatchRecognize.AfterOption.SKIP_TO_NEXT_ROW.symbol(SqlParserPos.ZERO);
    }
    final RexNode after;
    if (afterMatch instanceof SqlCall) {
        List<SqlNode> operands = ((SqlCall) afterMatch).getOperandList();
        SqlOperator operator = ((SqlCall) afterMatch).getOperator();
        assert operands.size() == 1;
        SqlIdentifier id = (SqlIdentifier) operands.get(0);
        assert patternVarsSet.contains(id.getSimple()) : id.getSimple() + " not defined in pattern";
        RexNode rex = rexBuilder.makeLiteral(id.getSimple());
        after = rexBuilder.makeCall(validator.getUnknownType(), operator, ImmutableList.of(rex));
    } else {
        after = matchBb.convertExpression(afterMatch);
    }
    matchBb.setPatternVarRef(true);
    // convert measures
    final ImmutableMap.Builder<String, RexNode> measureNodes = ImmutableMap.builder();
    for (SqlNode measure : matchRecognize.getMeasureList()) {
        List<SqlNode> operands = ((SqlCall) measure).getOperandList();
        String alias = ((SqlIdentifier) operands.get(1)).getSimple();
        RexNode rex = matchBb.convertExpression(operands.get(0));
        measureNodes.put(alias, rex);
    }
    // convert definitions
    final ImmutableMap.Builder<String, RexNode> definitionNodes = ImmutableMap.builder();
    for (SqlNode def : matchRecognize.getPatternDefList()) {
        List<SqlNode> operands = ((SqlCall) def).getOperandList();
        String alias = ((SqlIdentifier) operands.get(1)).getSimple();
        RexNode rex = matchBb.convertExpression(operands.get(0));
        definitionNodes.put(alias, rex);
    }
    final SqlLiteral rowsPerMatch = matchRecognize.getRowsPerMatch();
    final boolean allRows = rowsPerMatch != null && rowsPerMatch.getValue() == SqlMatchRecognize.RowsPerMatchOption.ALL_ROWS;
    matchBb.setPatternVarRef(false);
    final RelFactories.MatchFactory factory = RelFactories.DEFAULT_MATCH_FACTORY;
    final RelNode rel = factory.createMatch(input, patternNode, rowType, matchRecognize.getStrictStart().booleanValue(), matchRecognize.getStrictEnd().booleanValue(), definitionNodes.build(), measureNodes.build(), after, subsetMap, allRows, partitionKeys, orders, intervalNode);
    bb.setRoot(rel, false);
}
Also used : SqlValidatorScope(org.apache.calcite.sql.validate.SqlValidatorScope) SqlOperator(org.apache.calcite.sql.SqlOperator) ArrayList(java.util.ArrayList) RelDataType(org.apache.calcite.rel.type.RelDataType) NlsString(org.apache.calcite.util.NlsString) SqlIdentifier(org.apache.calcite.sql.SqlIdentifier) TreeSet(java.util.TreeSet) SqlBasicVisitor(org.apache.calcite.sql.util.SqlBasicVisitor) RelFactories(org.apache.calcite.rel.core.RelFactories) SqlNode(org.apache.calcite.sql.SqlNode) LinkedHashSet(java.util.LinkedHashSet) HashSet(java.util.HashSet) SqlCall(org.apache.calcite.sql.SqlCall) SqlMatchRecognize(org.apache.calcite.sql.SqlMatchRecognize) ImmutableMap(com.google.common.collect.ImmutableMap) RelCollation(org.apache.calcite.rel.RelCollation) RelNode(org.apache.calcite.rel.RelNode) RelFieldCollation(org.apache.calcite.rel.RelFieldCollation) SqlNodeList(org.apache.calcite.sql.SqlNodeList) RexInputRef(org.apache.calcite.rex.RexInputRef) SqlValidatorNamespace(org.apache.calcite.sql.validate.SqlValidatorNamespace) SqlLiteral(org.apache.calcite.sql.SqlLiteral) SqlNumericLiteral(org.apache.calcite.sql.SqlNumericLiteral) RexNode(org.apache.calcite.rex.RexNode)

Example 39 with RexInputRef

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

the class SqlToRelConverter method convertIdentifier.

/**
 * Converts an identifier into an expression in a given scope. For example,
 * the "empno" in "select empno from emp join dept" becomes "emp.empno".
 */
private RexNode convertIdentifier(Blackboard bb, SqlIdentifier identifier) {
    // first check for reserved identifiers like CURRENT_USER
    final SqlCall call = SqlUtil.makeCall(opTab, identifier);
    if (call != null) {
        return bb.convertExpression(call);
    }
    String pv = null;
    if (bb.isPatternVarRef && identifier.names.size() > 1) {
        pv = identifier.names.get(0);
    }
    final SqlQualified qualified;
    if (bb.scope != null) {
        qualified = bb.scope.fullyQualify(identifier);
    } else {
        qualified = SqlQualified.create(null, 1, null, identifier);
    }
    final Pair<RexNode, Map<String, Integer>> e0 = bb.lookupExp(qualified);
    RexNode e = e0.left;
    for (String name : qualified.suffix()) {
        if (e == e0.left && e0.right != null) {
            int i = e0.right.get(name);
            e = rexBuilder.makeFieldAccess(e, i);
        } else {
            // name already fully-qualified
            final boolean caseSensitive = true;
            if (identifier.isStar() && bb.scope instanceof MatchRecognizeScope) {
                e = rexBuilder.makeFieldAccess(e, 0);
            } else {
                e = rexBuilder.makeFieldAccess(e, name, caseSensitive);
            }
        }
    }
    if (e instanceof RexInputRef) {
        // adjust the type to account for nulls introduced by outer joins
        e = adjustInputRef(bb, (RexInputRef) e);
        if (pv != null) {
            e = RexPatternFieldRef.of(pv, (RexInputRef) e);
        }
    }
    if (e0.left instanceof RexCorrelVariable) {
        assert e instanceof RexFieldAccess;
        final RexNode prev = bb.mapCorrelateToRex.put(((RexCorrelVariable) e0.left).id, (RexFieldAccess) e);
        assert prev == null;
    }
    return e;
}
Also used : RexCorrelVariable(org.apache.calcite.rex.RexCorrelVariable) SqlCall(org.apache.calcite.sql.SqlCall) SqlQualified(org.apache.calcite.sql.validate.SqlQualified) RexInputRef(org.apache.calcite.rex.RexInputRef) NlsString(org.apache.calcite.util.NlsString) Map(java.util.Map) ImmutableMap(com.google.common.collect.ImmutableMap) HashMap(java.util.HashMap) RexFieldAccess(org.apache.calcite.rex.RexFieldAccess) RexNode(org.apache.calcite.rex.RexNode) MatchRecognizeScope(org.apache.calcite.sql.validate.MatchRecognizeScope)

Example 40 with RexInputRef

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

the class RelDecorrelator method projectJoinOutputWithNullability.

/**
 * Pulls project above the join from its RHS input. Enforces nullability
 * for join output.
 *
 * @param join          Join
 * @param project       Original project as the right-hand input of the join
 * @param nullIndicatorPos Position of null indicator
 * @return the subtree with the new Project at the root
 */
private RelNode projectJoinOutputWithNullability(LogicalJoin join, LogicalProject project, int nullIndicatorPos) {
    final RelDataTypeFactory typeFactory = join.getCluster().getTypeFactory();
    final RelNode left = join.getLeft();
    final JoinRelType joinType = join.getJoinType();
    RexInputRef nullIndicator = new RexInputRef(nullIndicatorPos, typeFactory.createTypeWithNullability(join.getRowType().getFieldList().get(nullIndicatorPos).getType(), true));
    // now create the new project
    List<Pair<RexNode, String>> newProjExprs = Lists.newArrayList();
    // project everything from the LHS and then those from the original
    // projRel
    List<RelDataTypeField> leftInputFields = left.getRowType().getFieldList();
    for (int i = 0; i < leftInputFields.size(); i++) {
        newProjExprs.add(RexInputRef.of2(i, leftInputFields));
    }
    // Marked where the projected expr is coming from so that the types will
    // become nullable for the original projections which are now coming out
    // of the nullable side of the OJ.
    boolean projectPulledAboveLeftCorrelator = joinType.generatesNullsOnRight();
    for (Pair<RexNode, String> pair : project.getNamedProjects()) {
        RexNode newProjExpr = removeCorrelationExpr(pair.left, projectPulledAboveLeftCorrelator, nullIndicator);
        newProjExprs.add(Pair.of(newProjExpr, pair.right));
    }
    return relBuilder.push(join).projectNamed(Pair.left(newProjExprs), Pair.right(newProjExprs), true).build();
}
Also used : JoinRelType(org.apache.calcite.rel.core.JoinRelType) RelDataTypeField(org.apache.calcite.rel.type.RelDataTypeField) RelNode(org.apache.calcite.rel.RelNode) RelDataTypeFactory(org.apache.calcite.rel.type.RelDataTypeFactory) RexInputRef(org.apache.calcite.rex.RexInputRef) Pair(org.apache.calcite.util.Pair) 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