Search in sources :

Example 36 with SqlKind

use of org.apache.beam.vendor.calcite.v1_28_0.org.apache.calcite.sql.SqlKind in project flink by apache.

the class RexSimplify method simplifyNot.

private RexNode simplifyNot(RexCall call, RexUnknownAs unknownAs) {
    final RexNode a = call.getOperands().get(0);
    switch(a.getKind()) {
        case NOT:
            // NOT NOT x ==> x
            return simplify(((RexCall) a).getOperands().get(0), unknownAs);
        case LITERAL:
            if (a.getType().getSqlTypeName() == SqlTypeName.BOOLEAN && !RexLiteral.isNullLiteral(a)) {
                return rexBuilder.makeLiteral(!RexLiteral.booleanValue(a));
            }
    }
    final SqlKind negateKind = a.getKind().negate();
    if (a.getKind() != negateKind) {
        return simplify(rexBuilder.makeCall(RexUtil.op(negateKind), ((RexCall) a).getOperands()), unknownAs);
    }
    final SqlKind negateKind2 = a.getKind().negateNullSafe();
    if (a.getKind() != negateKind2) {
        return simplify(rexBuilder.makeCall(RexUtil.op(negateKind2), ((RexCall) a).getOperands()), unknownAs);
    }
    if (a.getKind() == SqlKind.AND) {
        // NOT distributivity for AND
        final List<RexNode> newOperands = new ArrayList<>();
        for (RexNode operand : ((RexCall) a).getOperands()) {
            newOperands.add(simplify(rexBuilder.makeCall(SqlStdOperatorTable.NOT, operand), unknownAs));
        }
        return simplify(rexBuilder.makeCall(SqlStdOperatorTable.OR, newOperands), unknownAs);
    }
    if (a.getKind() == SqlKind.OR) {
        // NOT distributivity for OR
        final List<RexNode> newOperands = new ArrayList<>();
        for (RexNode operand : ((RexCall) a).getOperands()) {
            newOperands.add(simplify(rexBuilder.makeCall(SqlStdOperatorTable.NOT, operand), unknownAs));
        }
        return simplify(rexBuilder.makeCall(SqlStdOperatorTable.AND, newOperands), unknownAs);
    }
    if (a.getKind() == SqlKind.CASE) {
        final List<RexNode> newOperands = new ArrayList<>();
        List<RexNode> operands = ((RexCall) a).getOperands();
        for (int i = 0; i < operands.size(); i += 2) {
            if (i + 1 == operands.size()) {
                newOperands.add(rexBuilder.makeCall(SqlStdOperatorTable.NOT, operands.get(i)));
            } else {
                newOperands.add(operands.get(i));
                newOperands.add(rexBuilder.makeCall(SqlStdOperatorTable.NOT, operands.get(i + 1)));
            }
        }
        return simplify(rexBuilder.makeCall(SqlStdOperatorTable.CASE, newOperands), unknownAs);
    }
    RexNode a2 = simplify(a, unknownAs.negate());
    if (a == a2) {
        return call;
    }
    if (a2.isAlwaysTrue()) {
        return rexBuilder.makeLiteral(false);
    }
    if (a2.isAlwaysFalse()) {
        return rexBuilder.makeLiteral(true);
    }
    return rexBuilder.makeCall(SqlStdOperatorTable.NOT, a2);
}
Also used : ArrayList(java.util.ArrayList) SqlKind(org.apache.calcite.sql.SqlKind)

Example 37 with SqlKind

use of org.apache.beam.vendor.calcite.v1_28_0.org.apache.calcite.sql.SqlKind in project flink by apache.

the class FlinkAggregateExpandDistinctAggregatesRule method rewriteUsingGroupingSets.

private void rewriteUsingGroupingSets(RelOptRuleCall call, Aggregate aggregate) {
    final Set<ImmutableBitSet> groupSetTreeSet = new TreeSet<>(ImmutableBitSet.ORDERING);
    final Map<ImmutableBitSet, Integer> groupSetToDistinctAggCallFilterArg = new HashMap<>();
    for (AggregateCall aggCall : aggregate.getAggCallList()) {
        if (!aggCall.isDistinct()) {
            groupSetTreeSet.add(aggregate.getGroupSet());
        } else {
            ImmutableBitSet groupSet = ImmutableBitSet.of(aggCall.getArgList()).setIf(aggCall.filterArg, aggCall.filterArg >= 0).union(aggregate.getGroupSet());
            groupSetToDistinctAggCallFilterArg.put(groupSet, aggCall.filterArg);
            groupSetTreeSet.add(groupSet);
        }
    }
    final com.google.common.collect.ImmutableList<ImmutableBitSet> groupSets = com.google.common.collect.ImmutableList.copyOf(groupSetTreeSet);
    final ImmutableBitSet fullGroupSet = ImmutableBitSet.union(groupSets);
    final List<AggregateCall> distinctAggCalls = new ArrayList<>();
    for (Pair<AggregateCall, String> aggCall : aggregate.getNamedAggCalls()) {
        if (!aggCall.left.isDistinct()) {
            AggregateCall newAggCall = aggCall.left.adaptTo(aggregate.getInput(), aggCall.left.getArgList(), aggCall.left.filterArg, aggregate.getGroupCount(), fullGroupSet.cardinality());
            distinctAggCalls.add(newAggCall.rename(aggCall.right));
        }
    }
    final RelBuilder relBuilder = call.builder();
    relBuilder.push(aggregate.getInput());
    final int groupCount = fullGroupSet.cardinality();
    final Map<ImmutableBitSet, Integer> filters = new LinkedHashMap<>();
    final int z = groupCount + distinctAggCalls.size();
    distinctAggCalls.add(AggregateCall.create(SqlStdOperatorTable.GROUPING, false, false, false, ImmutableIntList.copyOf(fullGroupSet), -1, RelCollations.EMPTY, groupSets.size(), relBuilder.peek(), null, "$g"));
    for (Ord<ImmutableBitSet> groupSet : Ord.zip(groupSets)) {
        filters.put(groupSet.e, z + groupSet.i);
    }
    relBuilder.aggregate(relBuilder.groupKey(fullGroupSet, groupSets), distinctAggCalls);
    final RelNode distinct = relBuilder.peek();
    // values to BOOLEAN.
    if (!filters.isEmpty()) {
        final List<RexNode> nodes = new ArrayList<>(relBuilder.fields());
        final RexNode nodeZ = nodes.remove(nodes.size() - 1);
        for (Map.Entry<ImmutableBitSet, Integer> entry : filters.entrySet()) {
            final long v = groupValue(fullGroupSet, entry.getKey());
            // Get and remap the filterArg of the distinct aggregate call.
            int distinctAggCallFilterArg = remap(fullGroupSet, groupSetToDistinctAggCallFilterArg.getOrDefault(entry.getKey(), -1));
            RexNode expr;
            if (distinctAggCallFilterArg < 0) {
                expr = relBuilder.equals(nodeZ, relBuilder.literal(v));
            } else {
                RexBuilder rexBuilder = aggregate.getCluster().getRexBuilder();
                // merge the filter of the distinct aggregate call itself.
                expr = relBuilder.and(relBuilder.equals(nodeZ, relBuilder.literal(v)), rexBuilder.makeCall(SqlStdOperatorTable.IS_TRUE, relBuilder.field(distinctAggCallFilterArg)));
            }
            nodes.add(relBuilder.alias(expr, "$g_" + v));
        }
        relBuilder.project(nodes);
    }
    int aggCallIdx = 0;
    int x = groupCount;
    final List<AggregateCall> newCalls = new ArrayList<>();
    // TODO supports more aggCalls (currently only supports COUNT)
    // Some aggregate functions (e.g. COUNT) have the special property that they can return a
    // non-null result without any input. We need to make sure we return a result in this case.
    final List<Integer> needDefaultValueAggCalls = new ArrayList<>();
    for (AggregateCall aggCall : aggregate.getAggCallList()) {
        final int newFilterArg;
        final List<Integer> newArgList;
        final SqlAggFunction aggregation;
        if (!aggCall.isDistinct()) {
            aggregation = SqlStdOperatorTable.MIN;
            newArgList = ImmutableIntList.of(x++);
            newFilterArg = filters.get(aggregate.getGroupSet());
            switch(aggCall.getAggregation().getKind()) {
                case COUNT:
                    needDefaultValueAggCalls.add(aggCallIdx);
                    break;
                default:
            }
        } else {
            aggregation = aggCall.getAggregation();
            newArgList = remap(fullGroupSet, aggCall.getArgList());
            newFilterArg = filters.get(ImmutableBitSet.of(aggCall.getArgList()).setIf(aggCall.filterArg, aggCall.filterArg >= 0).union(aggregate.getGroupSet()));
        }
        final AggregateCall newCall = AggregateCall.create(aggregation, false, aggCall.isApproximate(), false, newArgList, newFilterArg, RelCollations.EMPTY, aggregate.getGroupCount(), distinct, null, aggCall.name);
        newCalls.add(newCall);
        aggCallIdx++;
    }
    relBuilder.aggregate(relBuilder.groupKey(remap(fullGroupSet, aggregate.getGroupSet()), remap(fullGroupSet, aggregate.getGroupSets())), newCalls);
    if (!needDefaultValueAggCalls.isEmpty() && aggregate.getGroupCount() == 0) {
        final Aggregate newAgg = (Aggregate) relBuilder.peek();
        final List<RexNode> nodes = new ArrayList<>();
        for (int i = 0; i < newAgg.getGroupCount(); ++i) {
            nodes.add(RexInputRef.of(i, newAgg.getRowType()));
        }
        for (int i = 0; i < newAgg.getAggCallList().size(); ++i) {
            final RexNode inputRef = RexInputRef.of(newAgg.getGroupCount() + i, newAgg.getRowType());
            RexNode newNode = inputRef;
            if (needDefaultValueAggCalls.contains(i)) {
                SqlKind originalFunKind = aggregate.getAggCallList().get(i).getAggregation().getKind();
                switch(originalFunKind) {
                    case COUNT:
                        newNode = relBuilder.call(SqlStdOperatorTable.CASE, relBuilder.isNotNull(inputRef), inputRef, relBuilder.literal(BigDecimal.ZERO));
                        break;
                    default:
                }
            }
            nodes.add(newNode);
        }
        relBuilder.project(nodes);
    }
    relBuilder.convert(aggregate.getRowType(), true);
    call.transformTo(relBuilder.build());
}
Also used : ImmutableBitSet(org.apache.calcite.util.ImmutableBitSet) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) ArrayList(java.util.ArrayList) LinkedHashMap(java.util.LinkedHashMap) TreeSet(java.util.TreeSet) RexBuilder(org.apache.calcite.rex.RexBuilder) RelBuilder(org.apache.calcite.tools.RelBuilder) SqlAggFunction(org.apache.calcite.sql.SqlAggFunction) SqlKind(org.apache.calcite.sql.SqlKind) AggregateCall(org.apache.calcite.rel.core.AggregateCall) RelNode(org.apache.calcite.rel.RelNode) Aggregate(org.apache.calcite.rel.core.Aggregate) LogicalAggregate(org.apache.calcite.rel.logical.LogicalAggregate) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) Map(java.util.Map) RexNode(org.apache.calcite.rex.RexNode)

Example 38 with SqlKind

use of org.apache.beam.vendor.calcite.v1_28_0.org.apache.calcite.sql.SqlKind in project flink by apache.

the class SqlValidatorImpl method performUnconditionalRewrites.

/**
 * Performs expression rewrites which are always used unconditionally. These rewrites massage
 * the expression tree into a standard form so that the rest of the validation logic can be
 * simpler.
 *
 * @param node expression to be rewritten
 * @param underFrom whether node appears directly under a FROM clause
 * @return rewritten expression
 */
protected SqlNode performUnconditionalRewrites(SqlNode node, boolean underFrom) {
    if (node == null) {
        return null;
    }
    SqlNode newOperand;
    // first transform operands and invoke generic call rewrite
    if (node instanceof SqlCall) {
        if (node instanceof SqlMerge) {
            validatingSqlMerge = true;
        }
        SqlCall call = (SqlCall) node;
        final SqlKind kind = call.getKind();
        final List<SqlNode> operands = call.getOperandList();
        for (int i = 0; i < operands.size(); i++) {
            SqlNode operand = operands.get(i);
            boolean childUnderFrom;
            if (kind == SqlKind.SELECT) {
                childUnderFrom = i == SqlSelect.FROM_OPERAND;
            } else if (kind == SqlKind.AS && (i == 0)) {
                // for an aliased expression, it is under FROM if
                // the AS expression is under FROM
                childUnderFrom = underFrom;
            } else {
                childUnderFrom = false;
            }
            newOperand = performUnconditionalRewrites(operand, childUnderFrom);
            if (newOperand != null && newOperand != operand) {
                call.setOperand(i, newOperand);
            }
        }
        if (call.getOperator() instanceof SqlUnresolvedFunction) {
            assert call instanceof SqlBasicCall;
            final SqlUnresolvedFunction function = (SqlUnresolvedFunction) call.getOperator();
            // This function hasn't been resolved yet.  Perform
            // a half-hearted resolution now in case it's a
            // builtin function requiring special casing.  If it's
            // not, we'll handle it later during overload resolution.
            final List<SqlOperator> overloads = new ArrayList<>();
            opTab.lookupOperatorOverloads(function.getNameAsId(), function.getFunctionType(), SqlSyntax.FUNCTION, overloads, catalogReader.nameMatcher());
            if (overloads.size() == 1) {
                ((SqlBasicCall) call).setOperator(overloads.get(0));
            }
        }
        if (config.callRewrite()) {
            node = call.getOperator().rewriteCall(this, call);
        }
    } else if (node instanceof SqlNodeList) {
        SqlNodeList list = (SqlNodeList) node;
        for (int i = 0, count = list.size(); i < count; i++) {
            SqlNode operand = list.get(i);
            newOperand = performUnconditionalRewrites(operand, false);
            if (newOperand != null) {
                list.getList().set(i, newOperand);
            }
        }
    }
    // now transform node itself
    final SqlKind kind = node.getKind();
    switch(kind) {
        case VALUES:
            // CHECKSTYLE: IGNORE 1
            if (underFrom || true) {
                // over and over
                return node;
            } else {
                final SqlNodeList selectList = new SqlNodeList(SqlParserPos.ZERO);
                selectList.add(SqlIdentifier.star(SqlParserPos.ZERO));
                return new SqlSelect(node.getParserPosition(), null, selectList, node, null, null, null, null, null, null, null, null);
            }
        case ORDER_BY:
            {
                SqlOrderBy orderBy = (SqlOrderBy) node;
                handleOffsetFetch(orderBy.offset, orderBy.fetch);
                if (orderBy.query instanceof SqlSelect) {
                    SqlSelect select = (SqlSelect) orderBy.query;
                    // an order-sensitive function like RANK.
                    if (select.getOrderList() == null) {
                        // push ORDER BY into existing select
                        select.setOrderBy(orderBy.orderList);
                        select.setOffset(orderBy.offset);
                        select.setFetch(orderBy.fetch);
                        return select;
                    }
                }
                if (orderBy.query instanceof SqlWith && ((SqlWith) orderBy.query).body instanceof SqlSelect) {
                    SqlWith with = (SqlWith) orderBy.query;
                    SqlSelect select = (SqlSelect) with.body;
                    // an order-sensitive function like RANK.
                    if (select.getOrderList() == null) {
                        // push ORDER BY into existing select
                        select.setOrderBy(orderBy.orderList);
                        select.setOffset(orderBy.offset);
                        select.setFetch(orderBy.fetch);
                        return with;
                    }
                }
                final SqlNodeList selectList = new SqlNodeList(SqlParserPos.ZERO);
                selectList.add(SqlIdentifier.star(SqlParserPos.ZERO));
                final SqlNodeList orderList;
                if (getInnerSelect(node) != null && isAggregate(getInnerSelect(node))) {
                    orderList = SqlNode.clone(orderBy.orderList);
                    // We assume that ORDER BY item is present in SELECT list.
                    for (int i = 0; i < orderList.size(); i++) {
                        SqlNode sqlNode = orderList.get(i);
                        SqlNodeList selectList2 = getInnerSelect(node).getSelectList();
                        for (Ord<SqlNode> sel : Ord.zip(selectList2)) {
                            if (stripAs(sel.e).equalsDeep(sqlNode, Litmus.IGNORE)) {
                                orderList.set(i, SqlLiteral.createExactNumeric(Integer.toString(sel.i + 1), SqlParserPos.ZERO));
                            }
                        }
                    }
                } else {
                    orderList = orderBy.orderList;
                }
                return new SqlSelect(SqlParserPos.ZERO, null, selectList, orderBy.query, null, null, null, null, orderList, orderBy.offset, orderBy.fetch, null);
            }
        case EXPLICIT_TABLE:
            {
                // (TABLE t) is equivalent to (SELECT * FROM t)
                SqlCall call = (SqlCall) node;
                final SqlNodeList selectList = new SqlNodeList(SqlParserPos.ZERO);
                selectList.add(SqlIdentifier.star(SqlParserPos.ZERO));
                return new SqlSelect(SqlParserPos.ZERO, null, selectList, call.operand(0), null, null, null, null, null, null, null, null);
            }
        case DELETE:
            {
                SqlDelete call = (SqlDelete) node;
                SqlSelect select = createSourceSelectForDelete(call);
                call.setSourceSelect(select);
                break;
            }
        case UPDATE:
            {
                SqlUpdate call = (SqlUpdate) node;
                SqlSelect select = createSourceSelectForUpdate(call);
                call.setSourceSelect(select);
                // in which case leave it alone).
                if (!validatingSqlMerge) {
                    SqlNode selfJoinSrcExpr = getSelfJoinExprForUpdate(call.getTargetTable(), UPDATE_SRC_ALIAS);
                    if (selfJoinSrcExpr != null) {
                        node = rewriteUpdateToMerge(call, selfJoinSrcExpr);
                    }
                }
                break;
            }
        case MERGE:
            {
                SqlMerge call = (SqlMerge) node;
                rewriteMerge(call);
                break;
            }
    }
    return node;
}
Also used : Ord(org.apache.calcite.linq4j.Ord) SqlCall(org.apache.calcite.sql.SqlCall) SqlOperator(org.apache.calcite.sql.SqlOperator) SqlWith(org.apache.calcite.sql.SqlWith) ArrayList(java.util.ArrayList) SqlKind(org.apache.calcite.sql.SqlKind) SqlUpdate(org.apache.calcite.sql.SqlUpdate) SqlMerge(org.apache.calcite.sql.SqlMerge) SqlSelect(org.apache.calcite.sql.SqlSelect) SqlBasicCall(org.apache.calcite.sql.SqlBasicCall) SqlDelete(org.apache.calcite.sql.SqlDelete) SqlNodeList(org.apache.calcite.sql.SqlNodeList) SqlOrderBy(org.apache.calcite.sql.SqlOrderBy) SqlNode(org.apache.calcite.sql.SqlNode) SqlUnresolvedFunction(org.apache.calcite.sql.SqlUnresolvedFunction)

Example 39 with SqlKind

use of org.apache.beam.vendor.calcite.v1_28_0.org.apache.calcite.sql.SqlKind in project calcite by apache.

the class SqlToRelConverter method convertOver.

private RexNode convertOver(Blackboard bb, SqlNode node) {
    SqlCall call = (SqlCall) node;
    SqlCall aggCall = call.operand(0);
    SqlNode windowOrRef = call.operand(1);
    final SqlWindow window = validator.resolveWindow(windowOrRef, bb.scope, true);
    // ROW_NUMBER() expects specific kind of framing.
    if (aggCall.getKind() == SqlKind.ROW_NUMBER) {
        window.setLowerBound(SqlWindow.createUnboundedPreceding(SqlParserPos.ZERO));
        window.setUpperBound(SqlWindow.createCurrentRow(SqlParserPos.ZERO));
        window.setRows(SqlLiteral.createBoolean(true, SqlParserPos.ZERO));
    }
    final SqlNodeList partitionList = window.getPartitionList();
    final ImmutableList.Builder<RexNode> partitionKeys = ImmutableList.builder();
    for (SqlNode partition : partitionList) {
        partitionKeys.add(bb.convertExpression(partition));
    }
    RexNode lowerBound = bb.convertExpression(window.getLowerBound());
    RexNode upperBound = bb.convertExpression(window.getUpperBound());
    SqlNodeList orderList = window.getOrderList();
    if ((orderList.size() == 0) && !window.isRows()) {
        // A logical range requires an ORDER BY clause. Use the implicit
        // ordering of this relation. There must be one, otherwise it would
        // have failed validation.
        orderList = bb.scope.getOrderList();
        if (orderList == null) {
            throw new AssertionError("Relation should have sort key for implicit ORDER BY");
        }
    }
    final ImmutableList.Builder<RexFieldCollation> orderKeys = ImmutableList.builder();
    final Set<SqlKind> flags = EnumSet.noneOf(SqlKind.class);
    for (SqlNode order : orderList) {
        flags.clear();
        RexNode e = bb.convertSortExpression(order, flags);
        orderKeys.add(new RexFieldCollation(e, flags));
    }
    try {
        Preconditions.checkArgument(bb.window == null, "already in window agg mode");
        bb.window = window;
        RexNode rexAgg = exprConverter.convertCall(bb, aggCall);
        rexAgg = rexBuilder.ensureType(validator.getValidatedNodeType(call), rexAgg, false);
        // Walk over the tree and apply 'over' to all agg functions. This is
        // necessary because the returned expression is not necessarily a call
        // to an agg function. For example, AVG(x) becomes SUM(x) / COUNT(x).
        final SqlLiteral q = aggCall.getFunctionQuantifier();
        final boolean isDistinct = q != null && q.getValue() == SqlSelectKeyword.DISTINCT;
        final RexShuttle visitor = new HistogramShuttle(partitionKeys.build(), orderKeys.build(), RexWindowBound.create(window.getLowerBound(), lowerBound), RexWindowBound.create(window.getUpperBound(), upperBound), window, isDistinct);
        RexNode overNode = rexAgg.accept(visitor);
        return overNode;
    } finally {
        bb.window = null;
    }
}
Also used : RexShuttle(org.apache.calcite.rex.RexShuttle) SqlCall(org.apache.calcite.sql.SqlCall) ImmutableList(com.google.common.collect.ImmutableList) SqlKind(org.apache.calcite.sql.SqlKind) RexFieldCollation(org.apache.calcite.rex.RexFieldCollation) SqlWindow(org.apache.calcite.sql.SqlWindow) SqlNodeList(org.apache.calcite.sql.SqlNodeList) SqlLiteral(org.apache.calcite.sql.SqlLiteral) SqlNode(org.apache.calcite.sql.SqlNode) RexNode(org.apache.calcite.rex.RexNode)

Example 40 with SqlKind

use of org.apache.beam.vendor.calcite.v1_28_0.org.apache.calcite.sql.SqlKind in project calcite by apache.

the class SqlValidatorImpl method registerFrom.

/**
 * Registers scopes and namespaces implied a relational expression in the
 * FROM clause.
 *
 * <p>{@code parentScope} and {@code usingScope} are often the same. They
 * differ when the namespace are not visible within the parent. (Example
 * needed.)
 *
 * <p>Likewise, {@code enclosingNode} and {@code node} are often the same.
 * {@code enclosingNode} is the topmost node within the FROM clause, from
 * which any decorations like an alias (<code>AS alias</code>) or a table
 * sample clause are stripped away to get {@code node}. Both are recorded in
 * the namespace.
 *
 * @param parentScope   Parent scope which this scope turns to in order to
 *                      resolve objects
 * @param usingScope    Scope whose child list this scope should add itself to
 * @param node          Node which namespace is based on
 * @param enclosingNode Outermost node for namespace, including decorations
 *                      such as alias and sample clause
 * @param alias         Alias
 * @param extendList    Definitions of extended columns
 * @param forceNullable Whether to force the type of namespace to be
 *                      nullable because it is in an outer join
 * @return registered node, usually the same as {@code node}
 */
private SqlNode registerFrom(SqlValidatorScope parentScope, SqlValidatorScope usingScope, final SqlNode node, SqlNode enclosingNode, String alias, SqlNodeList extendList, boolean forceNullable) {
    final SqlKind kind = node.getKind();
    SqlNode expr;
    SqlNode newExpr;
    // Add an alias if necessary.
    SqlNode newNode = node;
    if (alias == null) {
        switch(kind) {
            case IDENTIFIER:
            case OVER:
                alias = deriveAlias(node, -1);
                if (alias == null) {
                    alias = deriveAlias(node, nextGeneratedId++);
                }
                if (shouldExpandIdentifiers()) {
                    newNode = SqlValidatorUtil.addAlias(node, alias);
                }
                break;
            case SELECT:
            case UNION:
            case INTERSECT:
            case EXCEPT:
            case VALUES:
            case UNNEST:
            case OTHER_FUNCTION:
            case COLLECTION_TABLE:
            case MATCH_RECOGNIZE:
                // give this anonymous construct a name since later
                // query processing stages rely on it
                alias = deriveAlias(node, nextGeneratedId++);
                if (shouldExpandIdentifiers()) {
                    // Since we're expanding identifiers, we should make the
                    // aliases explicit too, otherwise the expanded query
                    // will not be consistent if we convert back to SQL, e.g.
                    // "select EXPR$1.EXPR$2 from values (1)".
                    newNode = SqlValidatorUtil.addAlias(node, alias);
                }
                break;
        }
    }
    SqlCall call;
    SqlNode operand;
    SqlNode newOperand;
    switch(kind) {
        case AS:
            call = (SqlCall) node;
            if (alias == null) {
                alias = call.operand(1).toString();
            }
            SqlValidatorScope usingScope2 = usingScope;
            if (call.operandCount() > 2) {
                usingScope2 = null;
            }
            expr = call.operand(0);
            newExpr = registerFrom(parentScope, usingScope2, expr, enclosingNode, alias, extendList, forceNullable);
            if (newExpr != expr) {
                call.setOperand(0, newExpr);
            }
            // column names.
            if (call.operandCount() > 2) {
                registerNamespace(usingScope, alias, new AliasNamespace(this, call, enclosingNode), forceNullable);
            }
            return node;
        case MATCH_RECOGNIZE:
            registerMatchRecognize(parentScope, usingScope, (SqlMatchRecognize) node, enclosingNode, alias, forceNullable);
            return node;
        case TABLESAMPLE:
            call = (SqlCall) node;
            expr = call.operand(0);
            newExpr = registerFrom(parentScope, usingScope, expr, enclosingNode, alias, extendList, forceNullable);
            if (newExpr != expr) {
                call.setOperand(0, newExpr);
            }
            return node;
        case JOIN:
            final SqlJoin join = (SqlJoin) node;
            final JoinScope joinScope = new JoinScope(parentScope, usingScope, join);
            scopes.put(join, joinScope);
            final SqlNode left = join.getLeft();
            final SqlNode right = join.getRight();
            final boolean rightIsLateral = isLateral(right);
            boolean forceLeftNullable = forceNullable;
            boolean forceRightNullable = forceNullable;
            switch(join.getJoinType()) {
                case LEFT:
                    forceRightNullable = true;
                    break;
                case RIGHT:
                    forceLeftNullable = true;
                    break;
                case FULL:
                    forceLeftNullable = true;
                    forceRightNullable = true;
                    break;
            }
            final SqlNode newLeft = registerFrom(parentScope, joinScope, left, left, null, null, forceLeftNullable);
            if (newLeft != left) {
                join.setLeft(newLeft);
            }
            final SqlValidatorScope rightParentScope;
            if (rightIsLateral) {
                rightParentScope = joinScope;
            } else {
                rightParentScope = parentScope;
            }
            final SqlNode newRight = registerFrom(rightParentScope, joinScope, right, right, null, null, forceRightNullable);
            if (newRight != right) {
                join.setRight(newRight);
            }
            registerSubQueries(joinScope, join.getCondition());
            final JoinNamespace joinNamespace = new JoinNamespace(this, join);
            registerNamespace(null, null, joinNamespace, forceNullable);
            return join;
        case IDENTIFIER:
            final SqlIdentifier id = (SqlIdentifier) node;
            final IdentifierNamespace newNs = new IdentifierNamespace(this, id, extendList, enclosingNode, parentScope);
            registerNamespace(usingScope, alias, newNs, forceNullable);
            if (tableScope == null) {
                tableScope = new TableScope(parentScope, node);
            }
            tableScope.addChild(newNs, alias, forceNullable);
            if (extendList != null && extendList.size() != 0) {
                return enclosingNode;
            }
            return newNode;
        case LATERAL:
            if (tableScope != null) {
                tableScope.meetLateral();
            }
            return registerFrom(parentScope, usingScope, ((SqlCall) node).operand(0), enclosingNode, alias, extendList, forceNullable);
        case COLLECTION_TABLE:
            call = (SqlCall) node;
            operand = call.operand(0);
            newOperand = registerFrom(tableScope == null ? parentScope : tableScope, usingScope, operand, enclosingNode, alias, extendList, forceNullable);
            if (newOperand != operand) {
                call.setOperand(0, newOperand);
            }
            scopes.put(node, parentScope);
            return newNode;
        case SELECT:
        case UNION:
        case INTERSECT:
        case EXCEPT:
        case VALUES:
        case WITH:
        case UNNEST:
        case OTHER_FUNCTION:
            if (alias == null) {
                alias = deriveAlias(node, nextGeneratedId++);
            }
            registerQuery(parentScope, usingScope, node, enclosingNode, alias, forceNullable);
            return newNode;
        case OVER:
            if (!shouldAllowOverRelation()) {
                throw Util.unexpected(kind);
            }
            call = (SqlCall) node;
            final OverScope overScope = new OverScope(usingScope, call);
            scopes.put(call, overScope);
            operand = call.operand(0);
            newOperand = registerFrom(parentScope, overScope, operand, enclosingNode, alias, extendList, forceNullable);
            if (newOperand != operand) {
                call.setOperand(0, newOperand);
            }
            for (ScopeChild child : overScope.children) {
                registerNamespace(usingScope, child.name, child.namespace, forceNullable);
            }
            return newNode;
        case EXTEND:
            final SqlCall extend = (SqlCall) node;
            return registerFrom(parentScope, usingScope, extend.getOperandList().get(0), extend, alias, (SqlNodeList) extend.getOperandList().get(1), forceNullable);
        default:
            throw Util.unexpected(kind);
    }
}
Also used : SqlCall(org.apache.calcite.sql.SqlCall) SqlKind(org.apache.calcite.sql.SqlKind) SqlIdentifier(org.apache.calcite.sql.SqlIdentifier) SqlJoin(org.apache.calcite.sql.SqlJoin) SqlNode(org.apache.calcite.sql.SqlNode)

Aggregations

SqlKind (org.apache.calcite.sql.SqlKind)44 RexNode (org.apache.calcite.rex.RexNode)21 ArrayList (java.util.ArrayList)16 SqlOperator (org.apache.calcite.sql.SqlOperator)14 RelDataType (org.apache.calcite.rel.type.RelDataType)11 RexCall (org.apache.calcite.rex.RexCall)10 RexInputRef (org.apache.calcite.rex.RexInputRef)8 List (java.util.List)7 AggregateCall (org.apache.calcite.rel.core.AggregateCall)7 RexBuilder (org.apache.calcite.rex.RexBuilder)7 SqlNode (org.apache.calcite.sql.SqlNode)6 ImmutableBitSet (org.apache.calcite.util.ImmutableBitSet)6 RelDataTypeField (org.apache.calcite.rel.type.RelDataTypeField)5 SqlAggFunction (org.apache.calcite.sql.SqlAggFunction)5 SqlCall (org.apache.calcite.sql.SqlCall)5 ImmutableList (com.google.common.collect.ImmutableList)4 SqlBasicCall (org.apache.calcite.sql.SqlBasicCall)4 Aggregate (org.apache.calcite.rel.core.Aggregate)3 LogicalAggregate (org.apache.calcite.rel.logical.LogicalAggregate)3 SqlTypeName (org.apache.calcite.sql.type.SqlTypeName)3