Search in sources :

Example 41 with SqlNodeList

use of org.apache.calcite.sql.SqlNodeList in project flink by apache.

the class SqlValidatorImpl method rewriteMerge.

private void rewriteMerge(SqlMerge call) {
    SqlNodeList selectList;
    SqlUpdate updateStmt = call.getUpdateCall();
    if (updateStmt != null) {
        // if we have an update statement, just clone the select list
        // from the update statement's source since it's the same as
        // what we want for the select list of the merge source -- '*'
        // followed by the update set expressions
        selectList = SqlNode.clone(updateStmt.getSourceSelect().getSelectList());
    } else {
        // otherwise, just use select *
        selectList = new SqlNodeList(SqlParserPos.ZERO);
        selectList.add(SqlIdentifier.star(SqlParserPos.ZERO));
    }
    SqlNode targetTable = call.getTargetTable();
    if (call.getAlias() != null) {
        targetTable = SqlValidatorUtil.addAlias(targetTable, call.getAlias().getSimple());
    }
    // Provided there is an insert substatement, the source select for
    // the merge is a left outer join between the source in the USING
    // clause and the target table; otherwise, the join is just an
    // inner join.  Need to clone the source table reference in order
    // for validation to work
    SqlNode sourceTableRef = call.getSourceTableRef();
    SqlInsert insertCall = call.getInsertCall();
    JoinType joinType = (insertCall == null) ? JoinType.INNER : JoinType.LEFT;
    final SqlNode leftJoinTerm = SqlNode.clone(sourceTableRef);
    SqlNode outerJoin = new SqlJoin(SqlParserPos.ZERO, leftJoinTerm, SqlLiteral.createBoolean(false, SqlParserPos.ZERO), joinType.symbol(SqlParserPos.ZERO), targetTable, JoinConditionType.ON.symbol(SqlParserPos.ZERO), call.getCondition());
    SqlSelect select = new SqlSelect(SqlParserPos.ZERO, null, selectList, outerJoin, null, null, null, null, null, null, null, null);
    call.setSourceSelect(select);
    // that via the from clause on the select
    if (insertCall != null) {
        SqlCall valuesCall = (SqlCall) insertCall.getSource();
        SqlCall rowCall = valuesCall.operand(0);
        selectList = new SqlNodeList(rowCall.getOperandList(), SqlParserPos.ZERO);
        final SqlNode insertSource = SqlNode.clone(sourceTableRef);
        select = new SqlSelect(SqlParserPos.ZERO, null, selectList, insertSource, null, null, null, null, null, null, null, null);
        insertCall.setSource(select);
    }
}
Also used : SqlSelect(org.apache.calcite.sql.SqlSelect) SqlJoin(org.apache.calcite.sql.SqlJoin) SqlCall(org.apache.calcite.sql.SqlCall) SqlNodeList(org.apache.calcite.sql.SqlNodeList) JoinType(org.apache.calcite.sql.JoinType) SqlInsert(org.apache.calcite.sql.SqlInsert) SqlUpdate(org.apache.calcite.sql.SqlUpdate) SqlNode(org.apache.calcite.sql.SqlNode)

Example 42 with SqlNodeList

use of org.apache.calcite.sql.SqlNodeList in project flink by apache.

the class SqlValidatorImpl method validateJoin.

protected void validateJoin(SqlJoin join, SqlValidatorScope scope) {
    SqlNode left = join.getLeft();
    SqlNode right = join.getRight();
    SqlNode condition = join.getCondition();
    boolean natural = join.isNatural();
    final JoinType joinType = join.getJoinType();
    final JoinConditionType conditionType = join.getConditionType();
    final SqlValidatorScope joinScope = scopes.get(join);
    validateFrom(left, unknownType, joinScope);
    validateFrom(right, unknownType, joinScope);
    // Validate condition.
    switch(conditionType) {
        case NONE:
            Preconditions.checkArgument(condition == null);
            break;
        case ON:
            Preconditions.checkArgument(condition != null);
            SqlNode expandedCondition = expand(condition, joinScope);
            join.setOperand(5, expandedCondition);
            condition = join.getCondition();
            validateWhereOrOn(joinScope, condition, "ON");
            checkRollUp(null, join, condition, joinScope, "ON");
            break;
        case USING:
            SqlNodeList list = (SqlNodeList) condition;
            // Parser ensures that using clause is not empty.
            Preconditions.checkArgument(list.size() > 0, "Empty USING clause");
            for (SqlNode node : list) {
                SqlIdentifier id = (SqlIdentifier) node;
                final RelDataType leftColType = validateUsingCol(id, left);
                final RelDataType rightColType = validateUsingCol(id, right);
                if (!SqlTypeUtil.isComparable(leftColType, rightColType)) {
                    throw newValidationError(id, RESOURCE.naturalOrUsingColumnNotCompatible(id.getSimple(), leftColType.toString(), rightColType.toString()));
                }
                checkRollUpInUsing(id, left, scope);
                checkRollUpInUsing(id, right, scope);
            }
            break;
        default:
            throw Util.unexpected(conditionType);
    }
    // Validate NATURAL.
    if (natural) {
        if (condition != null) {
            throw newValidationError(condition, RESOURCE.naturalDisallowsOnOrUsing());
        }
        // Join on fields that occur exactly once on each side. Ignore
        // fields that occur more than once on either side.
        final RelDataType leftRowType = getNamespace(left).getRowType();
        final RelDataType rightRowType = getNamespace(right).getRowType();
        final SqlNameMatcher nameMatcher = catalogReader.nameMatcher();
        List<String> naturalColumnNames = SqlValidatorUtil.deriveNaturalJoinColumnList(nameMatcher, leftRowType, rightRowType);
        // Check compatibility of the chosen columns.
        for (String name : naturalColumnNames) {
            final RelDataType leftColType = nameMatcher.field(leftRowType, name).getType();
            final RelDataType rightColType = nameMatcher.field(rightRowType, name).getType();
            if (!SqlTypeUtil.isComparable(leftColType, rightColType)) {
                throw newValidationError(join, RESOURCE.naturalOrUsingColumnNotCompatible(name, leftColType.toString(), rightColType.toString()));
            }
        }
    }
    // a NATURAL keyword?
    switch(joinType) {
        case LEFT_SEMI_JOIN:
            if (!this.config.sqlConformance().isLiberal()) {
                throw newValidationError(join.getJoinTypeNode(), RESOURCE.dialectDoesNotSupportFeature("LEFT SEMI JOIN"));
            }
        // fall through
        case INNER:
        case LEFT:
        case RIGHT:
        case FULL:
            if ((condition == null) && !natural) {
                throw newValidationError(join, RESOURCE.joinRequiresCondition());
            }
            break;
        case COMMA:
        case CROSS:
            if (condition != null) {
                throw newValidationError(join.getConditionTypeNode(), RESOURCE.crossJoinDisallowsCondition());
            }
            if (natural) {
                throw newValidationError(join.getConditionTypeNode(), RESOURCE.crossJoinDisallowsCondition());
            }
            break;
        default:
            throw Util.unexpected(joinType);
    }
}
Also used : JoinConditionType(org.apache.calcite.sql.JoinConditionType) JoinType(org.apache.calcite.sql.JoinType) SqlNodeList(org.apache.calcite.sql.SqlNodeList) RelDataType(org.apache.calcite.rel.type.RelDataType) BitString(org.apache.calcite.util.BitString) SqlIdentifier(org.apache.calcite.sql.SqlIdentifier) SqlNode(org.apache.calcite.sql.SqlNode)

Example 43 with SqlNodeList

use of org.apache.calcite.sql.SqlNodeList in project flink by apache.

the class SqlValidatorImpl method validateModality.

public boolean validateModality(SqlSelect select, SqlModality modality, boolean fail) {
    final SelectScope scope = getRawSelectScope(select);
    switch(modality) {
        case STREAM:
            if (scope.children.size() == 1) {
                for (ScopeChild child : scope.children) {
                    if (!child.namespace.supportsModality(modality)) {
                        if (fail) {
                            throw newValidationError(child.namespace.getNode(), Static.RESOURCE.cannotConvertToStream(child.name));
                        } else {
                            return false;
                        }
                    }
                }
            } else {
                int supportsModalityCount = 0;
                for (ScopeChild child : scope.children) {
                    if (child.namespace.supportsModality(modality)) {
                        ++supportsModalityCount;
                    }
                }
                if (supportsModalityCount == 0) {
                    if (fail) {
                        String inputs = String.join(", ", scope.getChildNames());
                        throw newValidationError(select, Static.RESOURCE.cannotStreamResultsForNonStreamingInputs(inputs));
                    } else {
                        return false;
                    }
                }
            }
            break;
        default:
            for (ScopeChild child : scope.children) {
                if (!child.namespace.supportsModality(modality)) {
                    if (fail) {
                        throw newValidationError(child.namespace.getNode(), Static.RESOURCE.cannotConvertToRelation(child.name));
                    } else {
                        return false;
                    }
                }
            }
    }
    // Make sure that aggregation is possible.
    final SqlNode aggregateNode = getAggregate(select);
    if (aggregateNode != null) {
        switch(modality) {
            case STREAM:
                SqlNodeList groupList = select.getGroup();
                if (groupList == null || !SqlValidatorUtil.containsMonotonic(scope, groupList)) {
                    if (fail) {
                        throw newValidationError(aggregateNode, Static.RESOURCE.streamMustGroupByMonotonic());
                    } else {
                        return false;
                    }
                }
        }
    }
    // Make sure that ORDER BY is possible.
    final SqlNodeList orderList = select.getOrderList();
    if (orderList != null && orderList.size() > 0) {
        switch(modality) {
            case STREAM:
                if (!hasSortedPrefix(scope, orderList)) {
                    if (fail) {
                        throw newValidationError(orderList.get(0), Static.RESOURCE.streamMustOrderByMonotonic());
                    } else {
                        return false;
                    }
                }
        }
    }
    return true;
}
Also used : SqlNodeList(org.apache.calcite.sql.SqlNodeList) BitString(org.apache.calcite.util.BitString) SqlNode(org.apache.calcite.sql.SqlNode)

Example 44 with SqlNodeList

use of org.apache.calcite.sql.SqlNodeList in project flink by apache.

the class SqlValidatorImpl method expandExprFromJoin.

private static SqlNode expandExprFromJoin(SqlJoin join, SqlIdentifier identifier, SelectScope scope) {
    if (join.getConditionType() != JoinConditionType.USING) {
        return identifier;
    }
    for (SqlNode node : (SqlNodeList) join.getCondition()) {
        final String name = ((SqlIdentifier) node).getSimple();
        if (identifier.getSimple().equals(name)) {
            final List<SqlNode> qualifiedNode = new ArrayList<>();
            for (ScopeChild child : scope.children) {
                if (child.namespace.getRowType().getFieldNames().indexOf(name) >= 0) {
                    final SqlIdentifier exp = new SqlIdentifier(ImmutableList.of(child.name, name), identifier.getParserPosition());
                    qualifiedNode.add(exp);
                }
            }
            assert qualifiedNode.size() == 2;
            final SqlNode finalNode = SqlStdOperatorTable.AS.createCall(SqlParserPos.ZERO, SqlStdOperatorTable.COALESCE.createCall(SqlParserPos.ZERO, qualifiedNode.get(0), qualifiedNode.get(1)), new SqlIdentifier(name, SqlParserPos.ZERO));
            return finalNode;
        }
    }
    // Only need to try to expand the expr from the left input of join
    // since it is always left-deep join.
    final SqlNode node = join.getLeft();
    if (node instanceof SqlJoin) {
        return expandExprFromJoin((SqlJoin) node, identifier, scope);
    } else {
        return identifier;
    }
}
Also used : SqlJoin(org.apache.calcite.sql.SqlJoin) ArrayList(java.util.ArrayList) SqlNodeList(org.apache.calcite.sql.SqlNodeList) BitString(org.apache.calcite.util.BitString) SqlIdentifier(org.apache.calcite.sql.SqlIdentifier) SqlNode(org.apache.calcite.sql.SqlNode)

Example 45 with SqlNodeList

use of org.apache.calcite.sql.SqlNodeList in project flink by apache.

the class SqlValidatorImpl method validateDefinitions.

private void validateDefinitions(SqlMatchRecognize mr, MatchRecognizeScope scope) {
    final Set<String> aliases = catalogReader.nameMatcher().createSet();
    for (SqlNode item : mr.getPatternDefList().getList()) {
        final String alias = alias(item);
        if (!aliases.add(alias)) {
            throw newValidationError(item, Static.RESOURCE.patternVarAlreadyDefined(alias));
        }
        scope.addPatternVar(alias);
    }
    final List<SqlNode> sqlNodes = new ArrayList<>();
    for (SqlNode item : mr.getPatternDefList().getList()) {
        final String alias = alias(item);
        SqlNode expand = expand(item, scope);
        expand = navigationInDefine(expand, alias);
        setOriginal(expand, item);
        inferUnknownTypes(booleanType, scope, expand);
        expand.validate(this, scope);
        // Some extra work need required here.
        // In PREV, NEXT, FINAL and LAST, only one pattern variable is allowed.
        sqlNodes.add(SqlStdOperatorTable.AS.createCall(SqlParserPos.ZERO, expand, new SqlIdentifier(alias, SqlParserPos.ZERO)));
        final RelDataType type = deriveType(scope, expand);
        if (!SqlTypeUtil.inBooleanFamily(type)) {
            throw newValidationError(expand, RESOURCE.condMustBeBoolean("DEFINE"));
        }
        setValidatedNodeType(item, type);
    }
    SqlNodeList list = new SqlNodeList(sqlNodes, mr.getPatternDefList().getParserPosition());
    inferUnknownTypes(unknownType, scope, list);
    for (SqlNode node : list) {
        validateExpr(node, scope);
    }
    mr.setOperand(SqlMatchRecognize.OPERAND_PATTERN_DEFINES, list);
}
Also used : ArrayList(java.util.ArrayList) SqlNodeList(org.apache.calcite.sql.SqlNodeList) RelDataType(org.apache.calcite.rel.type.RelDataType) BitString(org.apache.calcite.util.BitString) SqlIdentifier(org.apache.calcite.sql.SqlIdentifier) SqlNode(org.apache.calcite.sql.SqlNode)

Aggregations

SqlNodeList (org.apache.calcite.sql.SqlNodeList)123 SqlNode (org.apache.calcite.sql.SqlNode)97 ArrayList (java.util.ArrayList)45 SqlIdentifier (org.apache.calcite.sql.SqlIdentifier)43 RelDataType (org.apache.calcite.rel.type.RelDataType)39 SqlCall (org.apache.calcite.sql.SqlCall)30 SqlSelect (org.apache.calcite.sql.SqlSelect)29 BitString (org.apache.calcite.util.BitString)23 RexNode (org.apache.calcite.rex.RexNode)13 SqlLiteral (org.apache.calcite.sql.SqlLiteral)11 ImmutableList (com.google.common.collect.ImmutableList)10 List (java.util.List)10 RelDataTypeField (org.apache.calcite.rel.type.RelDataTypeField)10 NlsString (org.apache.calcite.util.NlsString)9 RelNode (org.apache.calcite.rel.RelNode)8 SqlUpdate (org.apache.calcite.sql.SqlUpdate)8 SqlBasicCall (org.apache.calcite.sql.SqlBasicCall)7 SqlWriter (org.apache.calcite.sql.SqlWriter)7 SqlParserPos (org.apache.calcite.sql.parser.SqlParserPos)7 RelDataTypeFactory (org.apache.calcite.rel.type.RelDataTypeFactory)6