Search in sources :

Example 1 with SqlInsert

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

the class RelToSqlConverter method visit.

/**
 * @see #dispatch
 */
public Result visit(TableModify modify) {
    final Map<String, RelDataType> pairs = ImmutableMap.of();
    final Context context = aliasContext(pairs, false);
    // Target Table Name
    final SqlIdentifier sqlTargetTable = new SqlIdentifier(modify.getTable().getQualifiedName(), POS);
    switch(modify.getOperation()) {
        case INSERT:
            {
                // Convert the input to a SELECT query or keep as VALUES. Not all
                // dialects support naked VALUES, but all support VALUES inside INSERT.
                final SqlNode sqlSource = visitChild(0, modify.getInput()).asQueryOrValues();
                final SqlInsert sqlInsert = new SqlInsert(POS, SqlNodeList.EMPTY, sqlTargetTable, sqlSource, identifierList(modify.getInput().getRowType().getFieldNames()));
                return result(sqlInsert, ImmutableList.<Clause>of(), modify, null);
            }
        case UPDATE:
            {
                final Result input = visitChild(0, modify.getInput());
                final SqlUpdate sqlUpdate = new SqlUpdate(POS, sqlTargetTable, identifierList(modify.getUpdateColumnList()), exprList(context, modify.getSourceExpressionList()), ((SqlSelect) input.node).getWhere(), input.asSelect(), null);
                return result(sqlUpdate, input.clauses, modify, null);
            }
        case DELETE:
            {
                final Result input = visitChild(0, modify.getInput());
                final SqlDelete sqlDelete = new SqlDelete(POS, sqlTargetTable, input.asSelect().getWhere(), input.asSelect(), null);
                return result(sqlDelete, input.clauses, modify, null);
            }
        case MERGE:
        default:
            throw new AssertionError("not implemented: " + modify);
    }
}
Also used : RelDataType(org.apache.calcite.rel.type.RelDataType) SqlIdentifier(org.apache.calcite.sql.SqlIdentifier) SqlInsert(org.apache.calcite.sql.SqlInsert) SqlUpdate(org.apache.calcite.sql.SqlUpdate) SqlSelect(org.apache.calcite.sql.SqlSelect) SqlDelete(org.apache.calcite.sql.SqlDelete) SqlNode(org.apache.calcite.sql.SqlNode)

Example 2 with SqlInsert

use of org.apache.calcite.sql.SqlInsert in project calcite 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) {
    Preconditions.checkNotNull(node);
    Preconditions.checkNotNull(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
            whereScopes.put(select, 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, from, from, null, null, 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);
                selectScopes.put(select, aggScope);
            } else {
                selectScopes.put(select, selectScope);
            }
            if (select.getGroup() != null) {
                GroupByScope groupByScope = new GroupByScope(selectScope, select.getGroup(), select);
                groupByScopes.put(select, 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);
                orderScopes.put(select, 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(whereScopes.get(mergeCall.getSourceSelect()), 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 3 with SqlInsert

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

the class SqlToRelConverter method convertMerge.

private RelNode convertMerge(SqlMerge call) {
    RelOptTable targetTable = getTargetTable(call);
    // convert update column list from SqlIdentifier to String
    final List<String> targetColumnNameList = new ArrayList<>();
    final RelDataType targetRowType = targetTable.getRowType();
    SqlUpdate updateCall = call.getUpdateCall();
    if (updateCall != null) {
        for (SqlNode targetColumn : updateCall.getTargetColumnList()) {
            SqlIdentifier id = (SqlIdentifier) targetColumn;
            RelDataTypeField field = SqlValidatorUtil.getTargetField(targetRowType, typeFactory, id, catalogReader, targetTable);
            assert field != null : "column " + id.toString() + " not found";
            targetColumnNameList.add(field.getName());
        }
    }
    // replace the projection of the source select with a
    // projection that contains the following:
    // 1) the expressions corresponding to the new insert row (if there is
    // an insert)
    // 2) all columns from the target table (if there is an update)
    // 3) the set expressions in the update call (if there is an update)
    // first, convert the merge's source select to construct the columns
    // from the target table and the set expressions in the update call
    RelNode mergeSourceRel = convertSelect(call.getSourceSelect(), false);
    // then, convert the insert statement so we can get the insert
    // values expressions
    SqlInsert insertCall = call.getInsertCall();
    int nLevel1Exprs = 0;
    List<RexNode> level1InsertExprs = null;
    List<RexNode> level2InsertExprs = null;
    if (insertCall != null) {
        RelNode insertRel = convertInsert(insertCall);
        // if there are 2 level of projections in the insert source, combine
        // them into a single project; level1 refers to the topmost project;
        // the level1 projection contains references to the level2
        // expressions, except in the case where no target expression was
        // provided, in which case, the expression is the default value for
        // the column; or if the expressions directly map to the source
        // table
        level1InsertExprs = ((LogicalProject) insertRel.getInput(0)).getProjects();
        if (insertRel.getInput(0).getInput(0) instanceof LogicalProject) {
            level2InsertExprs = ((LogicalProject) insertRel.getInput(0).getInput(0)).getProjects();
        }
        nLevel1Exprs = level1InsertExprs.size();
    }
    LogicalJoin join = (LogicalJoin) mergeSourceRel.getInput(0);
    int nSourceFields = join.getLeft().getRowType().getFieldCount();
    final List<RexNode> projects = new ArrayList<>();
    for (int level1Idx = 0; level1Idx < nLevel1Exprs; level1Idx++) {
        if ((level2InsertExprs != null) && (level1InsertExprs.get(level1Idx) instanceof RexInputRef)) {
            int level2Idx = ((RexInputRef) level1InsertExprs.get(level1Idx)).getIndex();
            projects.add(level2InsertExprs.get(level2Idx));
        } else {
            projects.add(level1InsertExprs.get(level1Idx));
        }
    }
    if (updateCall != null) {
        final LogicalProject project = (LogicalProject) mergeSourceRel;
        projects.addAll(Util.skip(project.getProjects(), nSourceFields));
    }
    relBuilder.push(join).project(projects);
    return LogicalTableModify.create(targetTable, catalogReader, relBuilder.build(), LogicalTableModify.Operation.MERGE, targetColumnNameList, null, false);
}
Also used : ArrayList(java.util.ArrayList) RelDataType(org.apache.calcite.rel.type.RelDataType) NlsString(org.apache.calcite.util.NlsString) SqlIdentifier(org.apache.calcite.sql.SqlIdentifier) SqlInsert(org.apache.calcite.sql.SqlInsert) SqlUpdate(org.apache.calcite.sql.SqlUpdate) RelDataTypeField(org.apache.calcite.rel.type.RelDataTypeField) RelNode(org.apache.calcite.rel.RelNode) LogicalJoin(org.apache.calcite.rel.logical.LogicalJoin) RexInputRef(org.apache.calcite.rex.RexInputRef) RelOptTable(org.apache.calcite.plan.RelOptTable) LogicalProject(org.apache.calcite.rel.logical.LogicalProject) SqlNode(org.apache.calcite.sql.SqlNode) RexNode(org.apache.calcite.rex.RexNode)

Example 4 with SqlInsert

use of org.apache.calcite.sql.SqlInsert in project samza by apache.

the class SamzaSqlQueryParser method parseQuery.

public static QueryInfo parseQuery(String sql) {
    Planner planner = createPlanner();
    SqlNode sqlNode;
    // Having semi-colons at the end of sql statement is a valid syntax in standard sql but not for Calcite parser.
    // Hence, removing trailing semi-colon before passing sql statement to Calcite parser.
    sql = sql.replaceAll(TRAILING_SEMI_COLON_REGEX, "");
    try {
        sqlNode = planner.parse(sql);
    } catch (SqlParseException e) {
        String errorMsg = SamzaSqlValidator.formatErrorString(sql, e);
        LOG.error(errorMsg, e);
        throw new SamzaException(errorMsg, e);
    }
    String sink;
    String selectQuery;
    ArrayList<String> sources;
    if (sqlNode instanceof SqlInsert) {
        SqlInsert sqlInsert = (SqlInsert) sqlNode;
        sink = sqlInsert.getTargetTable().toString();
        if (sqlInsert.getSource() instanceof SqlSelect) {
            SqlSelect sqlSelect = (SqlSelect) sqlInsert.getSource();
            selectQuery = sqlSelect.toString();
            LOG.info("Parsed select query {} from sql {}", selectQuery, sql);
            sources = getSourcesFromSelectQuery(sqlSelect);
        } else {
            String msg = String.format("Sql query is not of the expected format. Select node expected, found %s", sqlInsert.getSource().getClass().toString());
            LOG.error(msg);
            throw new SamzaException(msg);
        }
    } else {
        String msg = String.format("Sql query is not of the expected format. Insert node expected, found %s", sqlNode.getClass().toString());
        LOG.error(msg);
        throw new SamzaException(msg);
    }
    return new QueryInfo(selectQuery, sources, sink, sql);
}
Also used : SqlSelect(org.apache.calcite.sql.SqlSelect) SqlParseException(org.apache.calcite.sql.parser.SqlParseException) Planner(org.apache.calcite.tools.Planner) SqlInsert(org.apache.calcite.sql.SqlInsert) SamzaException(org.apache.samza.SamzaException) SqlNode(org.apache.calcite.sql.SqlNode)

Example 5 with SqlInsert

use of org.apache.calcite.sql.SqlInsert 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)

Aggregations

SqlInsert (org.apache.calcite.sql.SqlInsert)8 SqlNode (org.apache.calcite.sql.SqlNode)7 SqlUpdate (org.apache.calcite.sql.SqlUpdate)7 SqlSelect (org.apache.calcite.sql.SqlSelect)6 SqlNodeList (org.apache.calcite.sql.SqlNodeList)5 SqlCall (org.apache.calcite.sql.SqlCall)4 SqlDelete (org.apache.calcite.sql.SqlDelete)3 RelDataType (org.apache.calcite.rel.type.RelDataType)2 JoinType (org.apache.calcite.sql.JoinType)2 SqlIdentifier (org.apache.calcite.sql.SqlIdentifier)2 SqlJoin (org.apache.calcite.sql.SqlJoin)2 SqlMerge (org.apache.calcite.sql.SqlMerge)2 BitString (org.apache.calcite.util.BitString)2 ArrayList (java.util.ArrayList)1 RelOptTable (org.apache.calcite.plan.RelOptTable)1 RelNode (org.apache.calcite.rel.RelNode)1 LogicalJoin (org.apache.calcite.rel.logical.LogicalJoin)1 LogicalProject (org.apache.calcite.rel.logical.LogicalProject)1 RelDataTypeField (org.apache.calcite.rel.type.RelDataTypeField)1 RexInputRef (org.apache.calcite.rex.RexInputRef)1