Search in sources :

Example 41 with SqlSelect

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

the class SqlValidatorImpl method validateSelectList.

protected RelDataType validateSelectList(final SqlNodeList selectItems, SqlSelect select, RelDataType targetRowType) {
    // First pass, ensure that aliases are unique. "*" and "TABLE.*" items
    // are ignored.
    // Validate SELECT list. Expand terms of the form "*" or "TABLE.*".
    final SqlValidatorScope selectScope = getSelectScope(select);
    final List<SqlNode> expandedSelectItems = new ArrayList<>();
    final Set<String> aliases = new HashSet<>();
    final List<Map.Entry<String, RelDataType>> fieldList = new ArrayList<>();
    for (SqlNode selectItem : selectItems) {
        if (selectItem instanceof SqlSelect) {
            handleScalarSubQuery(select, (SqlSelect) selectItem, expandedSelectItems, aliases, fieldList);
        } else {
            // Use the field list size to record the field index
            // because the select item may be a STAR(*), which could have been expanded.
            final int fieldIdx = fieldList.size();
            final RelDataType fieldType = targetRowType.isStruct() && targetRowType.getFieldCount() > fieldIdx ? targetRowType.getFieldList().get(fieldIdx).getType() : unknownType;
            expandSelectItem(selectItem, select, fieldType, expandedSelectItems, aliases, fieldList, false);
        }
    }
    // Create the new select list with expanded items.  Pass through
    // the original parser position so that any overall failures can
    // still reference the original input text.
    SqlNodeList newSelectList = new SqlNodeList(expandedSelectItems, selectItems.getParserPosition());
    if (config.identifierExpansion()) {
        select.setSelectList(newSelectList);
    }
    getRawSelectScope(select).setExpandedSelectList(expandedSelectItems);
    // TODO: when SELECT appears as a value sub-query, should be using
    // something other than unknownType for targetRowType
    inferUnknownTypes(targetRowType, selectScope, newSelectList);
    for (SqlNode selectItem : expandedSelectItems) {
        validateNoAggs(groupFinder, selectItem, "SELECT");
        validateExpr(selectItem, selectScope);
    }
    return typeFactory.createStructType(fieldList);
}
Also used : ArrayList(java.util.ArrayList) RelDataType(org.apache.calcite.rel.type.RelDataType) BitString(org.apache.calcite.util.BitString) SqlSelect(org.apache.calcite.sql.SqlSelect) SqlNodeList(org.apache.calcite.sql.SqlNodeList) SqlNode(org.apache.calcite.sql.SqlNode) HashSet(java.util.HashSet)

Example 42 with SqlSelect

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

the class SqlValidatorImpl method registerQuery.

/**
 * Registers a query in a parent scope.
 *
 * @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 Query node
 * @param alias Name of this query within its parent. Must be specified if usingScope != null
 * @param checkUpdate if true, validate that the update feature is supported if validating the
 *     update statement
 */
private void registerQuery(SqlValidatorScope parentScope, SqlValidatorScope usingScope, SqlNode node, SqlNode enclosingNode, String alias, boolean forceNullable, boolean checkUpdate) {
    Objects.requireNonNull(node);
    Objects.requireNonNull(enclosingNode);
    Preconditions.checkArgument(usingScope == null || alias != null);
    SqlCall call;
    List<SqlNode> operands;
    switch(node.getKind()) {
        case SELECT:
            final SqlSelect select = (SqlSelect) node;
            final SelectNamespace selectNs = createSelectNamespace(select, enclosingNode);
            registerNamespace(usingScope, alias, selectNs, forceNullable);
            final SqlValidatorScope windowParentScope = (usingScope != null) ? usingScope : parentScope;
            SelectScope selectScope = new SelectScope(parentScope, windowParentScope, select);
            scopes.put(select, selectScope);
            // Start by registering the WHERE clause
            clauseScopes.put(IdPair.of(select, Clause.WHERE), selectScope);
            registerOperandSubQueries(selectScope, select, SqlSelect.WHERE_OPERAND);
            // Register FROM with the inherited scope 'parentScope', not
            // 'selectScope', otherwise tables in the FROM clause would be
            // able to see each other.
            final SqlNode from = select.getFrom();
            if (from != null) {
                final SqlNode newFrom = registerFrom(parentScope, selectScope, true, from, from, null, null, false, false);
                if (newFrom != from) {
                    select.setFrom(newFrom);
                }
            }
            // If this is an aggregating query, the SELECT list and HAVING
            // clause use a different scope, where you can only reference
            // columns which are in the GROUP BY clause.
            SqlValidatorScope aggScope = selectScope;
            if (isAggregate(select)) {
                aggScope = new AggregatingSelectScope(selectScope, select, false);
                clauseScopes.put(IdPair.of(select, Clause.SELECT), aggScope);
            } else {
                clauseScopes.put(IdPair.of(select, Clause.SELECT), selectScope);
            }
            if (select.getGroup() != null) {
                GroupByScope groupByScope = new GroupByScope(selectScope, select.getGroup(), select);
                clauseScopes.put(IdPair.of(select, Clause.GROUP_BY), groupByScope);
                registerSubQueries(groupByScope, select.getGroup());
            }
            registerOperandSubQueries(aggScope, select, SqlSelect.HAVING_OPERAND);
            registerSubQueries(aggScope, select.getSelectList());
            final SqlNodeList orderList = select.getOrderList();
            if (orderList != null) {
                // available to the ORDER BY clause.
                if (select.isDistinct()) {
                    aggScope = new AggregatingSelectScope(selectScope, select, true);
                }
                OrderByScope orderScope = new OrderByScope(aggScope, orderList, select);
                clauseScopes.put(IdPair.of(select, Clause.ORDER), orderScope);
                registerSubQueries(orderScope, orderList);
                if (!isAggregate(select)) {
                    // Since this is not an aggregating query,
                    // there cannot be any aggregates in the ORDER BY clause.
                    SqlNode agg = aggFinder.findAgg(orderList);
                    if (agg != null) {
                        throw newValidationError(agg, RESOURCE.aggregateIllegalInOrderBy());
                    }
                }
            }
            break;
        case INTERSECT:
            validateFeature(RESOURCE.sQLFeature_F302(), node.getParserPosition());
            registerSetop(parentScope, usingScope, node, node, alias, forceNullable);
            break;
        case EXCEPT:
            validateFeature(RESOURCE.sQLFeature_E071_03(), node.getParserPosition());
            registerSetop(parentScope, usingScope, node, node, alias, forceNullable);
            break;
        case UNION:
            registerSetop(parentScope, usingScope, node, node, alias, forceNullable);
            break;
        case WITH:
            registerWith(parentScope, usingScope, (SqlWith) node, enclosingNode, alias, forceNullable, checkUpdate);
            break;
        case VALUES:
            call = (SqlCall) node;
            scopes.put(call, parentScope);
            final TableConstructorNamespace tableConstructorNamespace = new TableConstructorNamespace(this, call, parentScope, enclosingNode);
            registerNamespace(usingScope, alias, tableConstructorNamespace, forceNullable);
            operands = call.getOperandList();
            for (int i = 0; i < operands.size(); ++i) {
                assert operands.get(i).getKind() == SqlKind.ROW;
                // FIXME jvs 9-Feb-2005:  Correlation should
                // be illegal in these sub-queries.  Same goes for
                // any non-lateral SELECT in the FROM list.
                registerOperandSubQueries(parentScope, call, i);
            }
            break;
        case INSERT:
            SqlInsert insertCall = (SqlInsert) node;
            InsertNamespace insertNs = new InsertNamespace(this, insertCall, enclosingNode, parentScope);
            registerNamespace(usingScope, null, insertNs, forceNullable);
            registerQuery(parentScope, usingScope, insertCall.getSource(), enclosingNode, null, false);
            break;
        case DELETE:
            SqlDelete deleteCall = (SqlDelete) node;
            DeleteNamespace deleteNs = new DeleteNamespace(this, deleteCall, enclosingNode, parentScope);
            registerNamespace(usingScope, null, deleteNs, forceNullable);
            registerQuery(parentScope, usingScope, deleteCall.getSourceSelect(), enclosingNode, null, false);
            break;
        case UPDATE:
            if (checkUpdate) {
                validateFeature(RESOURCE.sQLFeature_E101_03(), node.getParserPosition());
            }
            SqlUpdate updateCall = (SqlUpdate) node;
            UpdateNamespace updateNs = new UpdateNamespace(this, updateCall, enclosingNode, parentScope);
            registerNamespace(usingScope, null, updateNs, forceNullable);
            registerQuery(parentScope, usingScope, updateCall.getSourceSelect(), enclosingNode, null, false);
            break;
        case MERGE:
            validateFeature(RESOURCE.sQLFeature_F312(), node.getParserPosition());
            SqlMerge mergeCall = (SqlMerge) node;
            MergeNamespace mergeNs = new MergeNamespace(this, mergeCall, enclosingNode, parentScope);
            registerNamespace(usingScope, null, mergeNs, forceNullable);
            registerQuery(parentScope, usingScope, mergeCall.getSourceSelect(), enclosingNode, null, false);
            // validation check
            if (mergeCall.getUpdateCall() != null) {
                registerQuery(clauseScopes.get(IdPair.of(mergeCall.getSourceSelect(), Clause.WHERE)), null, mergeCall.getUpdateCall(), enclosingNode, null, false, false);
            }
            if (mergeCall.getInsertCall() != null) {
                registerQuery(parentScope, null, mergeCall.getInsertCall(), enclosingNode, null, false);
            }
            break;
        case UNNEST:
            call = (SqlCall) node;
            final UnnestNamespace unnestNs = new UnnestNamespace(this, call, parentScope, enclosingNode);
            registerNamespace(usingScope, alias, unnestNs, forceNullable);
            registerOperandSubQueries(parentScope, call, 0);
            scopes.put(node, parentScope);
            break;
        case OTHER_FUNCTION:
            call = (SqlCall) node;
            ProcedureNamespace procNs = new ProcedureNamespace(this, parentScope, call, enclosingNode);
            registerNamespace(usingScope, alias, procNs, forceNullable);
            registerSubQueries(parentScope, call);
            break;
        case MULTISET_QUERY_CONSTRUCTOR:
        case MULTISET_VALUE_CONSTRUCTOR:
            validateFeature(RESOURCE.sQLFeature_S271(), node.getParserPosition());
            call = (SqlCall) node;
            CollectScope cs = new CollectScope(parentScope, usingScope, call);
            final CollectNamespace tableConstructorNs = new CollectNamespace(call, cs, enclosingNode);
            final String alias2 = deriveAlias(node, nextGeneratedId++);
            registerNamespace(usingScope, alias2, tableConstructorNs, forceNullable);
            operands = call.getOperandList();
            for (int i = 0; i < operands.size(); i++) {
                registerOperandSubQueries(parentScope, call, i);
            }
            break;
        default:
            throw Util.unexpected(node.getKind());
    }
}
Also used : BitString(org.apache.calcite.util.BitString) SqlInsert(org.apache.calcite.sql.SqlInsert) SqlUpdate(org.apache.calcite.sql.SqlUpdate) SqlSelect(org.apache.calcite.sql.SqlSelect) SqlNode(org.apache.calcite.sql.SqlNode) SqlCall(org.apache.calcite.sql.SqlCall) SqlMerge(org.apache.calcite.sql.SqlMerge) SqlDelete(org.apache.calcite.sql.SqlDelete) SqlNodeList(org.apache.calcite.sql.SqlNodeList)

Example 43 with SqlSelect

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

the class SqlValidatorImpl method declareCursor.

// implement SqlValidator
public void declareCursor(SqlSelect select, SqlValidatorScope parentScope) {
    cursorSet.add(select);
    // add the cursor to a map that maps the cursor to its select based on
    // the position of the cursor relative to other cursors in that call
    FunctionParamInfo funcParamInfo = functionCallStack.peek();
    Map<Integer, SqlSelect> cursorMap = funcParamInfo.cursorPosToSelectMap;
    int numCursors = cursorMap.size();
    cursorMap.put(numCursors, select);
    // create a namespace associated with the result of the select
    // that is the argument to the cursor constructor; register it
    // with a scope corresponding to the cursor
    SelectScope cursorScope = new SelectScope(parentScope, null, select);
    clauseScopes.put(IdPair.of(select, Clause.CURSOR), cursorScope);
    final SelectNamespace selectNs = createSelectNamespace(select, select);
    String alias = deriveAlias(select, nextGeneratedId++);
    registerNamespace(cursorScope, alias, selectNs, false);
}
Also used : BigInteger(java.math.BigInteger) SqlSelect(org.apache.calcite.sql.SqlSelect) BitString(org.apache.calcite.util.BitString)

Example 44 with SqlSelect

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

the class SqlValidatorImpl method rewriteUpdateToMerge.

private SqlNode rewriteUpdateToMerge(SqlUpdate updateCall, SqlNode selfJoinSrcExpr) {
    // Make sure target has an alias.
    if (updateCall.getAlias() == null) {
        updateCall.setAlias(new SqlIdentifier(UPDATE_TGT_ALIAS, SqlParserPos.ZERO));
    }
    SqlNode selfJoinTgtExpr = getSelfJoinExprForUpdate(updateCall.getTargetTable(), updateCall.getAlias().getSimple());
    assert selfJoinTgtExpr != null;
    // Create join condition between source and target exprs,
    // creating a conjunction with the user-level WHERE
    // clause if one was supplied
    SqlNode condition = updateCall.getCondition();
    SqlNode selfJoinCond = SqlStdOperatorTable.EQUALS.createCall(SqlParserPos.ZERO, selfJoinSrcExpr, selfJoinTgtExpr);
    if (condition == null) {
        condition = selfJoinCond;
    } else {
        condition = SqlStdOperatorTable.AND.createCall(SqlParserPos.ZERO, selfJoinCond, condition);
    }
    SqlNode target = updateCall.getTargetTable().clone(SqlParserPos.ZERO);
    // For the source, we need to anonymize the fields, so
    // that for a statement like UPDATE T SET I = I + 1,
    // there's no ambiguity for the "I" in "I + 1";
    // this is OK because the source and target have
    // identical values due to the self-join.
    // Note that we anonymize the source rather than the
    // target because downstream, the optimizer rules
    // don't want to see any projection on top of the target.
    IdentifierNamespace ns = new IdentifierNamespace(this, target, null, null);
    RelDataType rowType = ns.getRowType();
    SqlNode source = updateCall.getTargetTable().clone(SqlParserPos.ZERO);
    final SqlNodeList selectList = new SqlNodeList(SqlParserPos.ZERO);
    int i = 1;
    for (RelDataTypeField field : rowType.getFieldList()) {
        SqlIdentifier col = new SqlIdentifier(field.getName(), SqlParserPos.ZERO);
        selectList.add(SqlValidatorUtil.addAlias(col, UPDATE_ANON_PREFIX + i));
        ++i;
    }
    source = new SqlSelect(SqlParserPos.ZERO, null, selectList, source, null, null, null, null, null, null, null, null);
    source = SqlValidatorUtil.addAlias(source, UPDATE_SRC_ALIAS);
    SqlMerge mergeCall = new SqlMerge(updateCall.getParserPosition(), target, condition, source, updateCall, null, null, updateCall.getAlias());
    rewriteMerge(mergeCall);
    return mergeCall;
}
Also used : RelDataTypeField(org.apache.calcite.rel.type.RelDataTypeField) SqlSelect(org.apache.calcite.sql.SqlSelect) SqlMerge(org.apache.calcite.sql.SqlMerge) SqlNodeList(org.apache.calcite.sql.SqlNodeList) RelDataType(org.apache.calcite.rel.type.RelDataType) SqlIdentifier(org.apache.calcite.sql.SqlIdentifier) SqlNode(org.apache.calcite.sql.SqlNode)

Example 45 with SqlSelect

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

the class MysqlSqlDialect method rewriteSingleValueExpr.

@Override
public SqlNode rewriteSingleValueExpr(SqlNode aggCall) {
    final SqlNode operand = ((SqlBasicCall) aggCall).operand(0);
    final SqlLiteral nullLiteral = SqlLiteral.createNull(SqlParserPos.ZERO);
    final SqlNode unionOperand = new SqlSelect(SqlParserPos.ZERO, SqlNodeList.EMPTY, SqlNodeList.of(nullLiteral), null, null, null, null, SqlNodeList.EMPTY, null, null, null);
    // For MySQL, generate
    // CASE COUNT(*)
    // WHEN 0 THEN NULL
    // WHEN 1 THEN <result>
    // ELSE (SELECT NULL UNION ALL SELECT NULL)
    // END
    final SqlNode caseExpr = new SqlCase(SqlParserPos.ZERO, SqlStdOperatorTable.COUNT.createCall(SqlParserPos.ZERO, operand), SqlNodeList.of(SqlLiteral.createExactNumeric("0", SqlParserPos.ZERO), SqlLiteral.createExactNumeric("1", SqlParserPos.ZERO)), SqlNodeList.of(nullLiteral, operand), SqlStdOperatorTable.SCALAR_QUERY.createCall(SqlParserPos.ZERO, SqlStdOperatorTable.UNION_ALL.createCall(SqlParserPos.ZERO, unionOperand, unionOperand)));
    LOGGER.debug("SINGLE_VALUE rewritten into [{}]", caseExpr);
    return caseExpr;
}
Also used : SqlSelect(org.apache.calcite.sql.SqlSelect) SqlBasicCall(org.apache.calcite.sql.SqlBasicCall) SqlCase(org.apache.calcite.sql.fun.SqlCase) SqlLiteral(org.apache.calcite.sql.SqlLiteral) SqlNode(org.apache.calcite.sql.SqlNode)

Aggregations

SqlSelect (org.apache.calcite.sql.SqlSelect)62 SqlNode (org.apache.calcite.sql.SqlNode)45 SqlNodeList (org.apache.calcite.sql.SqlNodeList)29 SqlIdentifier (org.apache.calcite.sql.SqlIdentifier)20 SqlCall (org.apache.calcite.sql.SqlCall)17 RelDataType (org.apache.calcite.rel.type.RelDataType)15 BitString (org.apache.calcite.util.BitString)12 ArrayList (java.util.ArrayList)9 SqlUpdate (org.apache.calcite.sql.SqlUpdate)8 SqlInsert (org.apache.calcite.sql.SqlInsert)7 SchemaPlus (org.apache.calcite.schema.SchemaPlus)6 SqlMerge (org.apache.calcite.sql.SqlMerge)6 SqlBasicCall (org.apache.calcite.sql.SqlBasicCall)5 SqlDelete (org.apache.calcite.sql.SqlDelete)5 SqlJoin (org.apache.calcite.sql.SqlJoin)5 RelDataTypeField (org.apache.calcite.rel.type.RelDataTypeField)4 SqlOrderBy (org.apache.calcite.sql.SqlOrderBy)4 AbstractSchema (org.apache.drill.exec.store.AbstractSchema)4 RelOptTable (org.apache.calcite.plan.RelOptTable)3 RelNode (org.apache.calcite.rel.RelNode)3