Search in sources :

Example 1 with JoinConditionType

use of org.apache.calcite.sql.JoinConditionType in project calcite 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 (int i = 0; i < list.size(); i++) {
                SqlIdentifier id = (SqlIdentifier) list.get(i);
                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);
                checkRollUpInUsing(id, right);
            }
            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();
        List<String> naturalColumnNames = SqlValidatorUtil.deriveNaturalJoinColumnList(leftRowType, rightRowType);
        // Check compatibility of the chosen columns.
        final SqlNameMatcher nameMatcher = catalogReader.nameMatcher();
        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 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 2 with JoinConditionType

use of org.apache.calcite.sql.JoinConditionType 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 3 with JoinConditionType

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

the class SqlValidatorImpl method lookupJoinHints.

private void lookupJoinHints(SqlJoin join, SqlValidatorScope scope, SqlParserPos pos, Collection<SqlMoniker> hintList) {
    SqlNode left = join.getLeft();
    SqlNode right = join.getRight();
    SqlNode condition = join.getCondition();
    lookupFromHints(left, scope, pos, hintList);
    if (hintList.size() > 0) {
        return;
    }
    lookupFromHints(right, scope, pos, hintList);
    if (hintList.size() > 0) {
        return;
    }
    final JoinConditionType conditionType = join.getConditionType();
    final SqlValidatorScope joinScope = scopes.get(join);
    switch(conditionType) {
        case ON:
            condition.findValidOptions(this, joinScope, pos, hintList);
            return;
        default:
    }
}
Also used : JoinConditionType(org.apache.calcite.sql.JoinConditionType) SqlNode(org.apache.calcite.sql.SqlNode)

Example 4 with JoinConditionType

use of org.apache.calcite.sql.JoinConditionType in project calcite by apache.

the class SqlValidatorImpl method lookupJoinHints.

private void lookupJoinHints(SqlJoin join, SqlValidatorScope scope, SqlParserPos pos, Collection<SqlMoniker> hintList) {
    SqlNode left = join.getLeft();
    SqlNode right = join.getRight();
    SqlNode condition = join.getCondition();
    lookupFromHints(left, scope, pos, hintList);
    if (hintList.size() > 0) {
        return;
    }
    lookupFromHints(right, scope, pos, hintList);
    if (hintList.size() > 0) {
        return;
    }
    final JoinConditionType conditionType = join.getConditionType();
    final SqlValidatorScope joinScope = scopes.get(join);
    switch(conditionType) {
        case ON:
            condition.findValidOptions(this, joinScope, pos, hintList);
            return;
        default:
            // Not supporting hints for other types such as 'Using' yet.
            return;
    }
}
Also used : JoinConditionType(org.apache.calcite.sql.JoinConditionType) SqlNode(org.apache.calcite.sql.SqlNode)

Aggregations

JoinConditionType (org.apache.calcite.sql.JoinConditionType)4 SqlNode (org.apache.calcite.sql.SqlNode)4 RelDataType (org.apache.calcite.rel.type.RelDataType)2 JoinType (org.apache.calcite.sql.JoinType)2 SqlIdentifier (org.apache.calcite.sql.SqlIdentifier)2 SqlNodeList (org.apache.calcite.sql.SqlNodeList)2 BitString (org.apache.calcite.util.BitString)2