Search in sources :

Example 6 with JoinType

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

the class SqlToRelConverter method convertFrom.

/**
 * Converts a FROM clause into a relational expression.
 *
 * @param bb   Scope within which to resolve identifiers
 * @param from FROM clause of a query. Examples include:
 *
 *             <ul>
 *             <li>a single table ("SALES.EMP"),
 *             <li>an aliased table ("EMP AS E"),
 *             <li>a list of tables ("EMP, DEPT"),
 *             <li>an ANSI Join expression ("EMP JOIN DEPT ON EMP.DEPTNO =
 *             DEPT.DEPTNO"),
 *             <li>a VALUES clause ("VALUES ('Fred', 20)"),
 *             <li>a query ("(SELECT * FROM EMP WHERE GENDER = 'F')"),
 *             <li>or any combination of the above.
 *             </ul>
 */
protected void convertFrom(Blackboard bb, SqlNode from) {
    if (from == null) {
        bb.setRoot(LogicalValues.createOneRow(cluster), false);
        return;
    }
    final SqlCall call;
    final SqlNode[] operands;
    switch(from.getKind()) {
        case MATCH_RECOGNIZE:
            convertMatchRecognize(bb, (SqlCall) from);
            return;
        case AS:
            call = (SqlCall) from;
            convertFrom(bb, call.operand(0));
            if (call.operandCount() > 2 && bb.root instanceof Values) {
                final List<String> fieldNames = new ArrayList<>();
                for (SqlNode node : Util.skip(call.getOperandList(), 2)) {
                    fieldNames.add(((SqlIdentifier) node).getSimple());
                }
                bb.setRoot(relBuilder.push(bb.root).rename(fieldNames).build(), true);
            }
            return;
        case WITH_ITEM:
            convertFrom(bb, ((SqlWithItem) from).query);
            return;
        case WITH:
            convertFrom(bb, ((SqlWith) from).body);
            return;
        case TABLESAMPLE:
            operands = ((SqlBasicCall) from).getOperands();
            SqlSampleSpec sampleSpec = SqlLiteral.sampleValue(operands[1]);
            if (sampleSpec instanceof SqlSampleSpec.SqlSubstitutionSampleSpec) {
                String sampleName = ((SqlSampleSpec.SqlSubstitutionSampleSpec) sampleSpec).getName();
                datasetStack.push(sampleName);
                convertFrom(bb, operands[0]);
                datasetStack.pop();
            } else if (sampleSpec instanceof SqlSampleSpec.SqlTableSampleSpec) {
                SqlSampleSpec.SqlTableSampleSpec tableSampleSpec = (SqlSampleSpec.SqlTableSampleSpec) sampleSpec;
                convertFrom(bb, operands[0]);
                RelOptSamplingParameters params = new RelOptSamplingParameters(tableSampleSpec.isBernoulli(), tableSampleSpec.getSamplePercentage(), tableSampleSpec.isRepeatable(), tableSampleSpec.getRepeatableSeed());
                bb.setRoot(new Sample(cluster, bb.root, params), false);
            } else {
                throw new AssertionError("unknown TABLESAMPLE type: " + sampleSpec);
            }
            return;
        case IDENTIFIER:
            convertIdentifier(bb, (SqlIdentifier) from, null);
            return;
        case EXTEND:
            call = (SqlCall) from;
            SqlIdentifier id = (SqlIdentifier) call.getOperandList().get(0);
            SqlNodeList extendedColumns = (SqlNodeList) call.getOperandList().get(1);
            convertIdentifier(bb, id, extendedColumns);
            return;
        case JOIN:
            final SqlJoin join = (SqlJoin) from;
            final SqlValidatorScope scope = validator.getJoinScope(from);
            final Blackboard fromBlackboard = createBlackboard(scope, null, false);
            SqlNode left = join.getLeft();
            SqlNode right = join.getRight();
            final boolean isNatural = join.isNatural();
            final JoinType joinType = join.getJoinType();
            final SqlValidatorScope leftScope = Util.first(validator.getJoinScope(left), ((DelegatingScope) bb.scope).getParent());
            final Blackboard leftBlackboard = createBlackboard(leftScope, null, false);
            final SqlValidatorScope rightScope = Util.first(validator.getJoinScope(right), ((DelegatingScope) bb.scope).getParent());
            final Blackboard rightBlackboard = createBlackboard(rightScope, null, false);
            convertFrom(leftBlackboard, left);
            RelNode leftRel = leftBlackboard.root;
            convertFrom(rightBlackboard, right);
            RelNode rightRel = rightBlackboard.root;
            JoinRelType convertedJoinType = convertJoinType(joinType);
            RexNode conditionExp;
            final SqlValidatorNamespace leftNamespace = validator.getNamespace(left);
            final SqlValidatorNamespace rightNamespace = validator.getNamespace(right);
            if (isNatural) {
                final RelDataType leftRowType = leftNamespace.getRowType();
                final RelDataType rightRowType = rightNamespace.getRowType();
                final List<String> columnList = SqlValidatorUtil.deriveNaturalJoinColumnList(leftRowType, rightRowType);
                conditionExp = convertUsing(leftNamespace, rightNamespace, columnList);
            } else {
                conditionExp = convertJoinCondition(fromBlackboard, leftNamespace, rightNamespace, join.getCondition(), join.getConditionType(), leftRel, rightRel);
            }
            final RelNode joinRel = createJoin(fromBlackboard, leftRel, rightRel, conditionExp, convertedJoinType);
            bb.setRoot(joinRel, false);
            return;
        case SELECT:
        case INTERSECT:
        case EXCEPT:
        case UNION:
            final RelNode rel = convertQueryRecursive(from, false, null).project();
            bb.setRoot(rel, true);
            return;
        case VALUES:
            convertValuesImpl(bb, (SqlCall) from, null);
            return;
        case UNNEST:
            call = (SqlCall) from;
            final List<SqlNode> nodes = call.getOperandList();
            final SqlUnnestOperator operator = (SqlUnnestOperator) call.getOperator();
            for (SqlNode node : nodes) {
                replaceSubQueries(bb, node, RelOptUtil.Logic.TRUE_FALSE_UNKNOWN);
            }
            final List<RexNode> exprs = new ArrayList<>();
            final List<String> fieldNames = new ArrayList<>();
            for (Ord<SqlNode> node : Ord.zip(nodes)) {
                exprs.add(bb.convertExpression(node.e));
                fieldNames.add(validator.deriveAlias(node.e, node.i));
            }
            RelNode child = (null != bb.root) ? bb.root : LogicalValues.createOneRow(cluster);
            relBuilder.push(child).projectNamed(exprs, fieldNames, false);
            Uncollect uncollect = new Uncollect(cluster, cluster.traitSetOf(Convention.NONE), relBuilder.build(), operator.withOrdinality);
            bb.setRoot(uncollect, true);
            return;
        case COLLECTION_TABLE:
            call = (SqlCall) from;
            // Dig out real call; TABLE() wrapper is just syntactic.
            assert call.getOperandList().size() == 1;
            final SqlCall call2 = call.operand(0);
            convertCollectionTable(bb, call2);
            return;
        default:
            throw new AssertionError("not a join operator " + from);
    }
}
Also used : SqlValidatorScope(org.apache.calcite.sql.validate.SqlValidatorScope) Uncollect(org.apache.calcite.rel.core.Uncollect) Values(org.apache.calcite.rel.core.Values) LogicalValues(org.apache.calcite.rel.logical.LogicalValues) ArrayList(java.util.ArrayList) SqlUnnestOperator(org.apache.calcite.sql.SqlUnnestOperator) RelDataType(org.apache.calcite.rel.type.RelDataType) NlsString(org.apache.calcite.util.NlsString) SqlIdentifier(org.apache.calcite.sql.SqlIdentifier) RelOptSamplingParameters(org.apache.calcite.plan.RelOptSamplingParameters) SqlNode(org.apache.calcite.sql.SqlNode) SqlCall(org.apache.calcite.sql.SqlCall) Sample(org.apache.calcite.rel.core.Sample) SqlSampleSpec(org.apache.calcite.sql.SqlSampleSpec) JoinType(org.apache.calcite.sql.JoinType) SemiJoinType(org.apache.calcite.sql.SemiJoinType) JoinRelType(org.apache.calcite.rel.core.JoinRelType) RelNode(org.apache.calcite.rel.RelNode) SqlJoin(org.apache.calcite.sql.SqlJoin) SqlNodeList(org.apache.calcite.sql.SqlNodeList) SqlValidatorNamespace(org.apache.calcite.sql.validate.SqlValidatorNamespace) RexNode(org.apache.calcite.rex.RexNode)

Example 7 with JoinType

use of org.apache.calcite.sql.JoinType in project calcite 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);
    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);
        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)

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