Search in sources :

Example 1 with JoinType

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

the class RelToSqlConverter method visit.

/**
 * @see #dispatch
 */
public Result visit(Join e) {
    final Result leftResult = visitChild(0, e.getLeft()).resetAlias();
    final Result rightResult = visitChild(1, e.getRight()).resetAlias();
    final Context leftContext = leftResult.qualifiedContext();
    final Context rightContext = rightResult.qualifiedContext();
    SqlNode sqlCondition = null;
    SqlLiteral condType = JoinConditionType.ON.symbol(POS);
    JoinType joinType = joinType(e.getJoinType());
    if (e.getJoinType() == JoinRelType.INNER && e.getCondition().isAlwaysTrue()) {
        joinType = JoinType.COMMA;
        condType = JoinConditionType.NONE.symbol(POS);
    } else {
        sqlCondition = convertConditionToSqlNode(e.getCondition(), leftContext, rightContext, e.getLeft().getRowType().getFieldCount());
    }
    SqlNode join = new SqlJoin(POS, leftResult.asFrom(), SqlLiteral.createBoolean(false, POS), joinType.symbol(POS), rightResult.asFrom(), condType, sqlCondition);
    return result(join, leftResult, rightResult);
}
Also used : SqlJoin(org.apache.calcite.sql.SqlJoin) JoinType(org.apache.calcite.sql.JoinType) SqlLiteral(org.apache.calcite.sql.SqlLiteral) SqlNode(org.apache.calcite.sql.SqlNode)

Example 2 with JoinType

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

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

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

use of org.apache.calcite.sql.JoinType in project hive by apache.

the class HiveJdbcImplementor method visit.

@Override
public Result visit(Join e) {
    final Result leftResult = visitInput(e, 0).resetAlias();
    final Result rightResult = visitInput(e, 1).resetAlias();
    final Context leftContext = leftResult.qualifiedContext();
    final Context rightContext = rightResult.qualifiedContext();
    SqlNode sqlCondition = null;
    SqlLiteral condType = JoinConditionType.ON.symbol(POS);
    JoinType joinType = joinType(e.getJoinType());
    if (e.getJoinType() == JoinRelType.INNER && e.getCondition().isAlwaysTrue()) {
        joinType = JoinType.COMMA;
        condType = JoinConditionType.NONE.symbol(POS);
    } else {
        sqlCondition = convertConditionToSqlNode(e.getCondition(), leftContext, rightContext, e.getLeft().getRowType().getFieldCount());
    }
    SqlNode join = new SqlJoin(POS, leftResult.asFrom(), SqlLiteral.createBoolean(false, POS), joinType.symbol(POS), rightResult.asFrom(), condType, sqlCondition);
    return result(join, leftResult, rightResult);
}
Also used : SqlJoin(org.apache.calcite.sql.SqlJoin) JoinType(org.apache.calcite.sql.JoinType) SqlLiteral(org.apache.calcite.sql.SqlLiteral) SqlNode(org.apache.calcite.sql.SqlNode)

Aggregations

JoinType (org.apache.calcite.sql.JoinType)7 SqlNode (org.apache.calcite.sql.SqlNode)7 SqlJoin (org.apache.calcite.sql.SqlJoin)5 SqlNodeList (org.apache.calcite.sql.SqlNodeList)5 RelDataType (org.apache.calcite.rel.type.RelDataType)3 SqlCall (org.apache.calcite.sql.SqlCall)3 SqlIdentifier (org.apache.calcite.sql.SqlIdentifier)3 JoinConditionType (org.apache.calcite.sql.JoinConditionType)2 SqlInsert (org.apache.calcite.sql.SqlInsert)2 SqlLiteral (org.apache.calcite.sql.SqlLiteral)2 SqlSelect (org.apache.calcite.sql.SqlSelect)2 SqlUpdate (org.apache.calcite.sql.SqlUpdate)2 BitString (org.apache.calcite.util.BitString)2 ArrayList (java.util.ArrayList)1 RelOptSamplingParameters (org.apache.calcite.plan.RelOptSamplingParameters)1 RelNode (org.apache.calcite.rel.RelNode)1 JoinRelType (org.apache.calcite.rel.core.JoinRelType)1 Sample (org.apache.calcite.rel.core.Sample)1 Uncollect (org.apache.calcite.rel.core.Uncollect)1 Values (org.apache.calcite.rel.core.Values)1