Search in sources :

Example 1 with GridSqlQueryParser

use of org.apache.ignite.internal.processors.query.h2.sql.GridSqlQueryParser in project ignite by apache.

the class DdlStatementsProcessor method runDdlStatement.

/**
     * Execute DDL statement.
     *
     * @param sql SQL.
     * @param stmt H2 statement to parse and execute.
     */
@SuppressWarnings("unchecked")
public FieldsQueryCursor<List<?>> runDdlStatement(String sql, PreparedStatement stmt) throws IgniteCheckedException {
    assert stmt instanceof JdbcPreparedStatement;
    IgniteInternalFuture fut = null;
    try {
        GridSqlStatement stmt0 = new GridSqlQueryParser(false).parse(GridSqlQueryParser.prepared(stmt));
        if (stmt0 instanceof GridSqlCreateIndex) {
            GridSqlCreateIndex cmd = (GridSqlCreateIndex) stmt0;
            GridH2Table tbl = idx.dataTable(cmd.schemaName(), cmd.tableName());
            if (tbl == null)
                throw new SchemaOperationException(SchemaOperationException.CODE_TABLE_NOT_FOUND, cmd.tableName());
            assert tbl.rowDescriptor() != null;
            QueryIndex newIdx = new QueryIndex();
            newIdx.setName(cmd.index().getName());
            newIdx.setIndexType(cmd.index().getIndexType());
            LinkedHashMap<String, Boolean> flds = new LinkedHashMap<>();
            // Let's replace H2's table and property names by those operated by GridQueryProcessor.
            GridQueryTypeDescriptor typeDesc = tbl.rowDescriptor().type();
            for (Map.Entry<String, Boolean> e : cmd.index().getFields().entrySet()) {
                GridQueryProperty prop = typeDesc.property(e.getKey());
                if (prop == null)
                    throw new SchemaOperationException(SchemaOperationException.CODE_COLUMN_NOT_FOUND, e.getKey());
                flds.put(prop.name(), e.getValue());
            }
            newIdx.setFields(flds);
            fut = ctx.query().dynamicIndexCreate(tbl.cacheName(), cmd.schemaName(), typeDesc.tableName(), newIdx, cmd.ifNotExists());
        } else if (stmt0 instanceof GridSqlDropIndex) {
            GridSqlDropIndex cmd = (GridSqlDropIndex) stmt0;
            GridH2Table tbl = idx.dataTableForIndex(cmd.schemaName(), cmd.indexName());
            if (tbl != null) {
                fut = ctx.query().dynamicIndexDrop(tbl.cacheName(), cmd.schemaName(), cmd.indexName(), cmd.ifExists());
            } else {
                if (cmd.ifExists())
                    fut = new GridFinishedFuture();
                else
                    throw new SchemaOperationException(SchemaOperationException.CODE_INDEX_NOT_FOUND, cmd.indexName());
            }
        } else if (stmt0 instanceof GridSqlCreateTable) {
            GridSqlCreateTable cmd = (GridSqlCreateTable) stmt0;
            if (!F.eq(QueryUtils.DFLT_SCHEMA, cmd.schemaName()))
                throw new SchemaOperationException("CREATE TABLE can only be executed on " + QueryUtils.DFLT_SCHEMA + " schema.");
            GridH2Table tbl = idx.dataTable(cmd.schemaName(), cmd.tableName());
            if (tbl != null) {
                if (!cmd.ifNotExists())
                    throw new SchemaOperationException(SchemaOperationException.CODE_TABLE_EXISTS, cmd.tableName());
            } else {
                ctx.query().dynamicTableCreate(cmd.schemaName(), toQueryEntity(cmd), cmd.templateName(), cmd.atomicityMode(), cmd.backups(), cmd.ifNotExists());
            }
        } else if (stmt0 instanceof GridSqlDropTable) {
            GridSqlDropTable cmd = (GridSqlDropTable) stmt0;
            if (!F.eq(QueryUtils.DFLT_SCHEMA, cmd.schemaName()))
                throw new SchemaOperationException("DROP TABLE can only be executed on " + QueryUtils.DFLT_SCHEMA + " schema.");
            GridH2Table tbl = idx.dataTable(cmd.schemaName(), cmd.tableName());
            if (tbl == null) {
                if (!cmd.ifExists())
                    throw new SchemaOperationException(SchemaOperationException.CODE_TABLE_NOT_FOUND, cmd.tableName());
            } else
                ctx.query().dynamicTableDrop(tbl.cacheName(), cmd.tableName(), cmd.ifExists());
        } else
            throw new IgniteSQLException("Unsupported DDL operation: " + sql, IgniteQueryErrorCode.UNSUPPORTED_OPERATION);
        if (fut != null)
            fut.get();
        QueryCursorImpl<List<?>> resCur = (QueryCursorImpl<List<?>>) new QueryCursorImpl(Collections.singletonList(Collections.singletonList(0L)), null, false);
        resCur.fieldsMeta(UPDATE_RESULT_META);
        return resCur;
    } catch (SchemaOperationException e) {
        throw convert(e);
    } catch (IgniteSQLException e) {
        throw e;
    } catch (Exception e) {
        throw new IgniteSQLException("Unexpected DLL operation failure: " + e.getMessage(), e);
    }
}
Also used : GridSqlStatement(org.apache.ignite.internal.processors.query.h2.sql.GridSqlStatement) IgniteInternalFuture(org.apache.ignite.internal.IgniteInternalFuture) GridSqlDropIndex(org.apache.ignite.internal.processors.query.h2.sql.GridSqlDropIndex) LinkedHashMap(java.util.LinkedHashMap) GridQueryTypeDescriptor(org.apache.ignite.internal.processors.query.GridQueryTypeDescriptor) GridFinishedFuture(org.apache.ignite.internal.util.future.GridFinishedFuture) GridSqlCreateIndex(org.apache.ignite.internal.processors.query.h2.sql.GridSqlCreateIndex) GridH2Table(org.apache.ignite.internal.processors.query.h2.opt.GridH2Table) QueryIndex(org.apache.ignite.cache.QueryIndex) List(java.util.List) JdbcPreparedStatement(org.h2.jdbc.JdbcPreparedStatement) SchemaOperationException(org.apache.ignite.internal.processors.query.schema.SchemaOperationException) GridSqlCreateTable(org.apache.ignite.internal.processors.query.h2.sql.GridSqlCreateTable) QueryCursorImpl(org.apache.ignite.internal.processors.cache.QueryCursorImpl) IgniteCheckedException(org.apache.ignite.IgniteCheckedException) IgniteSQLException(org.apache.ignite.internal.processors.query.IgniteSQLException) SchemaOperationException(org.apache.ignite.internal.processors.query.schema.SchemaOperationException) GridQueryProperty(org.apache.ignite.internal.processors.query.GridQueryProperty) GridSqlQueryParser(org.apache.ignite.internal.processors.query.h2.sql.GridSqlQueryParser) IgniteSQLException(org.apache.ignite.internal.processors.query.IgniteSQLException) LinkedHashMap(java.util.LinkedHashMap) Map(java.util.Map) GridSqlDropTable(org.apache.ignite.internal.processors.query.h2.sql.GridSqlDropTable)

Example 2 with GridSqlQueryParser

use of org.apache.ignite.internal.processors.query.h2.sql.GridSqlQueryParser in project ignite by apache.

the class IgniteH2Indexing method parseAndSplit.

/**
 * Parse and split query if needed, cache either two-step query or statement.
 * @param schemaName Schema name.
 * @param qry Query.
 * @param firstArg Position of the first argument of the following {@code Prepared}.
 * @return Result: prepared statement, H2 command, two-step query (if needed),
 *     metadata for two-step query (if needed), evaluated query local execution flag.
 */
private ParsingResult parseAndSplit(String schemaName, SqlFieldsQuery qry, int firstArg) {
    Connection c = connectionForSchema(schemaName);
    // For queries that are explicitly local, we rely on the flag specified in the query
    // because this parsing result will be cached and used for queries directly.
    // For other queries, we enforce join order at this stage to avoid premature optimizations
    // (and therefore longer parsing) as long as there'll be more parsing at split stage.
    boolean enforceJoinOrderOnParsing = (!qry.isLocal() || qry.isEnforceJoinOrder());
    H2Utils.setupConnection(c, /*distributedJoins*/
    false, /*enforceJoinOrder*/
    enforceJoinOrderOnParsing);
    boolean loc = qry.isLocal();
    PreparedStatement stmt = prepareStatementAndCaches(c, qry.getSql());
    if (loc && GridSqlQueryParser.checkMultipleStatements(stmt))
        throw new IgniteSQLException("Multiple statements queries are not supported for local queries");
    GridSqlQueryParser.PreparedWithRemaining prep = GridSqlQueryParser.preparedWithRemaining(stmt);
    Prepared prepared = prep.prepared();
    checkQueryType(qry, prepared.isQuery());
    String remainingSql = prep.remainingSql();
    int paramsCnt = prepared.getParameters().size();
    Object[] argsOrig = qry.getArgs();
    Object[] args = null;
    if (!DmlUtils.isBatched(qry) && paramsCnt > 0) {
        if (argsOrig == null || argsOrig.length < firstArg + paramsCnt) {
            throw new IgniteException("Invalid number of query parameters. " + "Cannot find " + (argsOrig != null ? argsOrig.length + 1 - firstArg : 1) + " parameter.");
        }
        args = Arrays.copyOfRange(argsOrig, firstArg, firstArg + paramsCnt);
    }
    if (prepared.isQuery()) {
        try {
            bindParameters(stmt, F.asList(args));
        } catch (IgniteCheckedException e) {
            U.closeQuiet(stmt);
            throw new IgniteSQLException("Failed to bind parameters: [qry=" + prepared.getSQL() + ", params=" + Arrays.deepToString(args) + "]", IgniteQueryErrorCode.PARSING, e);
        }
        GridSqlQueryParser parser = null;
        if (!loc) {
            parser = new GridSqlQueryParser(false);
            GridSqlStatement parsedStmt = parser.parse(prepared);
            // Legit assertion - we have H2 query flag above.
            assert parsedStmt instanceof GridSqlQuery;
            loc = parser.isLocalQuery(qry.isReplicatedOnly());
        }
        if (loc) {
            if (parser == null) {
                parser = new GridSqlQueryParser(false);
                parser.parse(prepared);
            }
            GridCacheContext cctx = parser.getFirstPartitionedCache();
            if (cctx != null && cctx.config().getQueryParallelism() > 1) {
                loc = false;
                qry.setDistributedJoins(true);
            }
        }
    }
    SqlFieldsQuery newQry = cloneFieldsQuery(qry).setSql(prepared.getSQL()).setArgs(args);
    boolean hasTwoStep = !loc && prepared.isQuery();
    // Let's not cache multiple statements and distributed queries as whole two step query will be cached later on.
    if (remainingSql != null || hasTwoStep)
        getStatementsCacheForCurrentThread().remove(schemaName, qry.getSql());
    if (!hasTwoStep)
        return new ParsingResult(prepared, newQry, remainingSql, null, null, null);
    final UUID locNodeId = ctx.localNodeId();
    // Now we're sure to have a distributed query. Let's try to get a two-step plan from the cache, or perform the
    // split if needed.
    H2TwoStepCachedQueryKey cachedQryKey = new H2TwoStepCachedQueryKey(schemaName, qry.getSql(), qry.isCollocated(), qry.isDistributedJoins(), qry.isEnforceJoinOrder(), qry.isLocal());
    H2TwoStepCachedQuery cachedQry;
    if ((cachedQry = twoStepCache.get(cachedQryKey)) != null) {
        checkQueryType(qry, true);
        GridCacheTwoStepQuery twoStepQry = cachedQry.query().copy();
        List<GridQueryFieldMetadata> meta = cachedQry.meta();
        return new ParsingResult(prepared, newQry, remainingSql, twoStepQry, cachedQryKey, meta);
    }
    try {
        GridH2QueryContext.set(new GridH2QueryContext(locNodeId, locNodeId, 0, PREPARE).distributedJoinMode(distributedJoinMode(qry.isLocal(), qry.isDistributedJoins())));
        try {
            return new ParsingResult(prepared, newQry, remainingSql, split(prepared, newQry), cachedQryKey, H2Utils.meta(stmt.getMetaData()));
        } catch (IgniteCheckedException e) {
            throw new IgniteSQLException("Failed to bind parameters: [qry=" + newQry.getSql() + ", params=" + Arrays.deepToString(newQry.getArgs()) + "]", IgniteQueryErrorCode.PARSING, e);
        } catch (SQLException e) {
            throw new IgniteSQLException(e);
        } finally {
            U.close(stmt, log);
        }
    } finally {
        GridH2QueryContext.clearThreadLocal();
    }
}
Also used : SQLException(java.sql.SQLException) IgniteSQLException(org.apache.ignite.internal.processors.query.IgniteSQLException) GridSqlStatement(org.apache.ignite.internal.processors.query.h2.sql.GridSqlStatement) Prepared(org.h2.command.Prepared) GridCacheTwoStepQuery(org.apache.ignite.internal.processors.cache.query.GridCacheTwoStepQuery) GridQueryFieldMetadata(org.apache.ignite.internal.processors.query.GridQueryFieldMetadata) IgniteSystemProperties.getString(org.apache.ignite.IgniteSystemProperties.getString) IgniteCheckedException(org.apache.ignite.IgniteCheckedException) IgniteException(org.apache.ignite.IgniteException) UUID(java.util.UUID) GridH2QueryContext(org.apache.ignite.internal.processors.query.h2.opt.GridH2QueryContext) GridCacheContext(org.apache.ignite.internal.processors.cache.GridCacheContext) Connection(java.sql.Connection) PreparedStatement(java.sql.PreparedStatement) SqlFieldsQuery(org.apache.ignite.cache.query.SqlFieldsQuery) GridSqlQuery(org.apache.ignite.internal.processors.query.h2.sql.GridSqlQuery) GridSqlQueryParser(org.apache.ignite.internal.processors.query.h2.sql.GridSqlQueryParser) IgniteSQLException(org.apache.ignite.internal.processors.query.IgniteSQLException)

Example 3 with GridSqlQueryParser

use of org.apache.ignite.internal.processors.query.h2.sql.GridSqlQueryParser in project ignite by apache.

the class SqlFieldsQuerySelfTest method testQueryCaching.

/**
 * @throws Exception If error.
 */
public void testQueryCaching() throws Exception {
    startGrid(0);
    PreparedStatement stmt = null;
    for (int i = 0; i < 2; i++) {
        createAndFillCache();
        PreparedStatement stmt0 = grid(0).context().query().prepareNativeStatement("person", INSERT);
        // Statement should either be parsed initially or in response to schema change...
        assertTrue(stmt != stmt0);
        stmt = stmt0;
        // ...and be properly compiled considering schema changes to be properly parsed
        new GridSqlQueryParser(false).parse(GridSqlQueryParser.prepared(stmt));
        destroyCache();
    }
    stmt = null;
    createAndFillCache();
    // Now let's do the same without restarting the cache.
    for (int i = 0; i < 2; i++) {
        PreparedStatement stmt0 = grid(0).context().query().prepareNativeStatement("person", INSERT);
        // Statement should either be parsed or taken from cache as no schema changes occurred...
        assertTrue(stmt == null || stmt == stmt0);
        stmt = stmt0;
        // ...and be properly compiled considering schema changes to be properly parsed
        new GridSqlQueryParser(false).parse(GridSqlQueryParser.prepared(stmt));
    }
    destroyCache();
}
Also used : GridSqlQueryParser(org.apache.ignite.internal.processors.query.h2.sql.GridSqlQueryParser) PreparedStatement(java.sql.PreparedStatement)

Example 4 with GridSqlQueryParser

use of org.apache.ignite.internal.processors.query.h2.sql.GridSqlQueryParser in project ignite by apache.

the class QueryParser method prepareDmlStatement.

/**
 * Prepare DML statement.
 *
 * @param planKey Plan key.
 * @param prepared Prepared.
 * @return Statement.
 */
private QueryParserResultDml prepareDmlStatement(QueryDescriptor planKey, Prepared prepared) {
    if (F.eq(QueryUtils.SCHEMA_SYS, planKey.schemaName()))
        throw new IgniteSQLException("DML statements are not supported on " + planKey.schemaName() + " schema", IgniteQueryErrorCode.UNSUPPORTED_OPERATION);
    // Prepare AST.
    GridSqlQueryParser parser = new GridSqlQueryParser(false, log);
    GridSqlStatement stmt = parser.parse(prepared);
    List<GridH2Table> tbls = parser.tablesForDml();
    // available on local node.
    for (GridH2Table h2tbl : tbls) H2Utils.checkAndStartNotStartedCache(idx.kernalContext(), h2tbl);
    // Check MVCC mode.
    GridCacheContextInfo ctx = null;
    boolean mvccEnabled = false;
    for (GridH2Table h2tbl : tbls) {
        GridCacheContextInfo curCtx = h2tbl.cacheInfo();
        boolean curMvccEnabled = curCtx.config().getAtomicityMode() == CacheAtomicityMode.TRANSACTIONAL_SNAPSHOT;
        if (ctx == null) {
            ctx = curCtx;
            mvccEnabled = curMvccEnabled;
        } else if (curMvccEnabled != mvccEnabled)
            MvccUtils.throwAtomicityModesMismatchException(ctx.config(), curCtx.config());
    }
    // Get streamer info.
    GridH2Table streamTbl = null;
    if (GridSqlQueryParser.isStreamableInsertStatement(prepared)) {
        GridSqlInsert insert = (GridSqlInsert) stmt;
        streamTbl = DmlAstUtils.gridTableForElement(insert.into()).dataTable();
    }
    // Create update plan.
    UpdatePlan plan;
    try {
        plan = UpdatePlanBuilder.planForStatement(planKey, stmt, mvccEnabled, idx, log, forceFillAbsentPKsWithDefaults);
    } catch (Exception e) {
        if (e instanceof IgniteSQLException)
            throw (IgniteSQLException) e;
        else
            throw new IgniteSQLException("Failed to prepare update plan.", e);
    }
    return new QueryParserResultDml(stmt, mvccEnabled, streamTbl, plan);
}
Also used : GridSqlQueryParser(org.apache.ignite.internal.processors.query.h2.sql.GridSqlQueryParser) GridSqlStatement(org.apache.ignite.internal.processors.query.h2.sql.GridSqlStatement) GridH2Table(org.apache.ignite.internal.processors.query.h2.opt.GridH2Table) IgniteSQLException(org.apache.ignite.internal.processors.query.IgniteSQLException) GridCacheContextInfo(org.apache.ignite.internal.processors.cache.GridCacheContextInfo) GridSqlInsert(org.apache.ignite.internal.processors.query.h2.sql.GridSqlInsert) UpdatePlan(org.apache.ignite.internal.processors.query.h2.dml.UpdatePlan) SqlStrictParseException(org.apache.ignite.internal.sql.SqlStrictParseException) IgniteCheckedException(org.apache.ignite.IgniteCheckedException) SqlParseException(org.apache.ignite.internal.sql.SqlParseException) SQLException(java.sql.SQLException) IgniteSQLException(org.apache.ignite.internal.processors.query.IgniteSQLException)

Example 5 with GridSqlQueryParser

use of org.apache.ignite.internal.processors.query.h2.sql.GridSqlQueryParser in project ignite by apache.

the class QueryParser method parseH2.

/**
 * Parse and split query if needed, cache either two-step query or statement.
 *
 * @param schemaName Schema name.
 * @param qry Query.
 * @param batched Batched flag.
 * @param remainingAllowed Whether multiple statements are allowed.
 * @return Parsing result.
 */
@SuppressWarnings("IfMayBeConditional")
private QueryParserResult parseH2(String schemaName, SqlFieldsQuery qry, boolean batched, boolean remainingAllowed) {
    try (H2PooledConnection c = connMgr.connection(schemaName)) {
        // For queries that are explicitly local, we rely on the flag specified in the query
        // because this parsing result will be cached and used for queries directly.
        // For other queries, we enforce join order at this stage to avoid premature optimizations
        // (and therefore longer parsing) as long as there'll be more parsing at split stage.
        boolean enforceJoinOrderOnParsing = (!qry.isLocal() || qry.isEnforceJoinOrder());
        QueryContext qctx = QueryContext.parseContext(idx.backupFilter(null, null), qry.isLocal());
        H2Utils.setupConnection(c, qctx, false, enforceJoinOrderOnParsing, false);
        PreparedStatement stmt = null;
        try {
            stmt = c.prepareStatementNoCache(qry.getSql());
            if (qry.isLocal() && GridSqlQueryParser.checkMultipleStatements(stmt))
                throw new IgniteSQLException("Multiple statements queries are not supported for local queries.", IgniteQueryErrorCode.UNSUPPORTED_OPERATION);
            GridSqlQueryParser.PreparedWithRemaining prep = GridSqlQueryParser.preparedWithRemaining(stmt);
            Prepared prepared = prep.prepared();
            if (GridSqlQueryParser.isExplainUpdate(prepared))
                throw new IgniteSQLException("Explains of update queries are not supported.", IgniteQueryErrorCode.UNSUPPORTED_OPERATION);
            // Get remaining query and check if it is allowed.
            SqlFieldsQuery remainingQry = null;
            if (!F.isEmpty(prep.remainingSql())) {
                checkRemainingAllowed(remainingAllowed);
                remainingQry = cloneFieldsQuery(qry).setSql(prep.remainingSql());
            }
            // Prepare new query.
            SqlFieldsQuery newQry = cloneFieldsQuery(qry).setSql(prepared.getSQL());
            final int paramsCnt = prepared.getParameters().size();
            Object[] argsOrig = qry.getArgs();
            Object[] args = null;
            Object[] remainingArgs = null;
            if (!batched && paramsCnt > 0) {
                if (argsOrig == null || argsOrig.length < paramsCnt)
                    // Not enough parameters, but we will handle this later on execution phase.
                    args = argsOrig;
                else {
                    args = Arrays.copyOfRange(argsOrig, 0, paramsCnt);
                    if (paramsCnt != argsOrig.length)
                        remainingArgs = Arrays.copyOfRange(argsOrig, paramsCnt, argsOrig.length);
                }
            } else
                remainingArgs = argsOrig;
            newQry.setArgs(args);
            QueryDescriptor newQryDesc = queryDescriptor(schemaName, newQry);
            if (remainingQry != null)
                remainingQry.setArgs(remainingArgs);
            final List<JdbcParameterMeta> paramsMeta;
            try {
                paramsMeta = H2Utils.parametersMeta(stmt.getParameterMetaData());
                assert prepared.getParameters().size() == paramsMeta.size();
            } catch (IgniteCheckedException | SQLException e) {
                throw new IgniteSQLException("Failed to get parameters metadata", IgniteQueryErrorCode.UNKNOWN, e);
            }
            // Do actual parsing.
            if (CommandProcessor.isCommand(prepared)) {
                GridSqlStatement cmdH2 = new GridSqlQueryParser(false, log).parse(prepared);
                QueryParserResultCommand cmd = new QueryParserResultCommand(null, cmdH2, false);
                return new QueryParserResult(newQryDesc, queryParameters(newQry), remainingQry, paramsMeta, null, null, cmd);
            } else if (CommandProcessor.isCommandNoOp(prepared)) {
                QueryParserResultCommand cmd = new QueryParserResultCommand(null, null, true);
                return new QueryParserResult(newQryDesc, queryParameters(newQry), remainingQry, paramsMeta, null, null, cmd);
            } else if (GridSqlQueryParser.isDml(prepared)) {
                QueryParserResultDml dml = prepareDmlStatement(newQryDesc, prepared);
                return new QueryParserResult(newQryDesc, queryParameters(newQry), remainingQry, paramsMeta, null, dml, null);
            } else if (!prepared.isQuery()) {
                throw new IgniteSQLException("Unsupported statement: " + newQry.getSql(), IgniteQueryErrorCode.UNSUPPORTED_OPERATION);
            }
            // Parse SELECT.
            GridSqlQueryParser parser = new GridSqlQueryParser(false, log);
            GridSqlQuery selectStmt = (GridSqlQuery) parser.parse(prepared);
            List<Integer> cacheIds = parser.cacheIds();
            Integer mvccCacheId = mvccCacheIdForSelect(parser.objectsMap());
            // Calculate if query is in fact can be executed locally.
            boolean loc = qry.isLocal();
            if (!loc) {
                if (parser.isLocalQuery())
                    loc = true;
            }
            // If this is a local query, check if it must be split.
            boolean locSplit = false;
            if (loc) {
                GridCacheContext cctx = parser.getFirstPartitionedCache();
                if (cctx != null && cctx.config().getQueryParallelism() > 1)
                    locSplit = true;
            }
            // Split is required either if query is distributed, or when it is local, but executed
            // over segmented PARTITIONED case. In this case multiple map queries will be executed against local
            // node stripes in parallel and then merged through reduce process.
            boolean splitNeeded = !loc || locSplit;
            String forUpdateQryOutTx = null;
            String forUpdateQryTx = null;
            GridCacheTwoStepQuery forUpdateTwoStepQry = null;
            boolean forUpdate = GridSqlQueryParser.isForUpdateQuery(prepared);
            // column to be able to lock selected rows further.
            if (forUpdate) {
                // We have checked above that it's not an UNION query, so it's got to be SELECT.
                assert selectStmt instanceof GridSqlSelect;
                // Check FOR UPDATE invariants: only one table, MVCC is there.
                if (cacheIds.size() != 1)
                    throw new IgniteSQLException("SELECT FOR UPDATE is supported only for queries " + "that involve single transactional cache.");
                if (mvccCacheId == null)
                    throw new IgniteSQLException("SELECT FOR UPDATE query requires transactional cache " + "with MVCC enabled.", IgniteQueryErrorCode.UNSUPPORTED_OPERATION);
                // We need a copy because we are going to modify AST a bit. We do not want to modify original select.
                GridSqlSelect selForUpdate = ((GridSqlSelect) selectStmt).copySelectForUpdate();
                // Clear forUpdate flag to run it as a plain query.
                selForUpdate.forUpdate(false);
                ((GridSqlSelect) selectStmt).forUpdate(false);
                // Remember sql string without FOR UPDATE clause.
                forUpdateQryOutTx = selForUpdate.getSQL();
                GridSqlAlias keyCol = keyColumn(selForUpdate);
                selForUpdate.addColumn(keyCol, true);
                // Remember sql string without FOR UPDATE clause and with _key column.
                forUpdateQryTx = selForUpdate.getSQL();
                // Prepare additional two-step query for FOR UPDATE case.
                if (splitNeeded) {
                    c.schema(newQry.getSchema());
                    forUpdateTwoStepQry = GridSqlQuerySplitter.split(c, selForUpdate, forUpdateQryTx, newQry.isCollocated(), newQry.isDistributedJoins(), newQry.isEnforceJoinOrder(), locSplit, idx, paramsCnt, log);
                }
            }
            GridCacheTwoStepQuery twoStepQry = null;
            if (splitNeeded) {
                GridSubqueryJoinOptimizer.pullOutSubQueries(selectStmt);
                c.schema(newQry.getSchema());
                twoStepQry = GridSqlQuerySplitter.split(c, selectStmt, newQry.getSql(), newQry.isCollocated(), newQry.isDistributedJoins(), newQry.isEnforceJoinOrder(), locSplit, idx, paramsCnt, log);
            }
            List<GridQueryFieldMetadata> meta = H2Utils.meta(stmt.getMetaData());
            QueryParserResultSelect select = new QueryParserResultSelect(selectStmt, twoStepQry, forUpdateTwoStepQry, meta, cacheIds, mvccCacheId, forUpdateQryOutTx, forUpdateQryTx);
            return new QueryParserResult(newQryDesc, queryParameters(newQry), remainingQry, paramsMeta, select, null, null);
        } catch (IgniteCheckedException | SQLException e) {
            throw new IgniteSQLException("Failed to parse query. " + e.getMessage(), IgniteQueryErrorCode.PARSING, e);
        } finally {
            U.close(stmt, log);
        }
    }
}
Also used : GridSqlAlias(org.apache.ignite.internal.processors.query.h2.sql.GridSqlAlias) SQLException(java.sql.SQLException) IgniteSQLException(org.apache.ignite.internal.processors.query.IgniteSQLException) GridSqlStatement(org.apache.ignite.internal.processors.query.h2.sql.GridSqlStatement) Prepared(org.h2.command.Prepared) GridCacheTwoStepQuery(org.apache.ignite.internal.processors.cache.query.GridCacheTwoStepQuery) GridQueryFieldMetadata(org.apache.ignite.internal.processors.query.GridQueryFieldMetadata) IgniteCheckedException(org.apache.ignite.IgniteCheckedException) GridCacheContext(org.apache.ignite.internal.processors.cache.GridCacheContext) JdbcParameterMeta(org.apache.ignite.internal.processors.odbc.jdbc.JdbcParameterMeta) PreparedStatement(java.sql.PreparedStatement) QueryContext(org.apache.ignite.internal.processors.query.h2.opt.QueryContext) GridSqlSelect(org.apache.ignite.internal.processors.query.h2.sql.GridSqlSelect) SqlFieldsQuery(org.apache.ignite.cache.query.SqlFieldsQuery) GridSqlQuery(org.apache.ignite.internal.processors.query.h2.sql.GridSqlQuery) GridSqlQueryParser(org.apache.ignite.internal.processors.query.h2.sql.GridSqlQueryParser) IgniteSQLException(org.apache.ignite.internal.processors.query.IgniteSQLException)

Aggregations

GridSqlQueryParser (org.apache.ignite.internal.processors.query.h2.sql.GridSqlQueryParser)7 IgniteCheckedException (org.apache.ignite.IgniteCheckedException)6 IgniteSQLException (org.apache.ignite.internal.processors.query.IgniteSQLException)6 GridSqlStatement (org.apache.ignite.internal.processors.query.h2.sql.GridSqlStatement)5 PreparedStatement (java.sql.PreparedStatement)4 SQLException (java.sql.SQLException)4 GridCacheTwoStepQuery (org.apache.ignite.internal.processors.cache.query.GridCacheTwoStepQuery)3 GridH2Table (org.apache.ignite.internal.processors.query.h2.opt.GridH2Table)3 GridSqlQuery (org.apache.ignite.internal.processors.query.h2.sql.GridSqlQuery)3 Prepared (org.h2.command.Prepared)3 LinkedHashMap (java.util.LinkedHashMap)2 List (java.util.List)2 Map (java.util.Map)2 QueryIndex (org.apache.ignite.cache.QueryIndex)2 SqlFieldsQuery (org.apache.ignite.cache.query.SqlFieldsQuery)2 IgniteInternalFuture (org.apache.ignite.internal.IgniteInternalFuture)2 GridCacheContext (org.apache.ignite.internal.processors.cache.GridCacheContext)2 QueryCursorImpl (org.apache.ignite.internal.processors.cache.QueryCursorImpl)2 GridQueryFieldMetadata (org.apache.ignite.internal.processors.query.GridQueryFieldMetadata)2 GridQueryProperty (org.apache.ignite.internal.processors.query.GridQueryProperty)2