private QueryParserResult parseH2()

in modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/QueryParser.java [313:535]


    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);

                GridSqlQueryParser.failIfSelectForUpdateQuery(prepared);

                // 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();

                // 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;

                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,
                    meta,
                    cacheIds
                );

                return new QueryParserResult(
                    newQryDesc,
                    queryParameters(newQry),
                    remainingQry,
                    paramsMeta,
                    select,
                    null,
                    null
                );
            }
            catch (SQLException e) {
                if (e.getErrorCode() == ErrorCode.DATABASE_IS_CLOSED) {
                    idx.kernalContext().failure().process(new FailureContext(CRITICAL_ERROR, e));

                    throw new IgniteSQLException("Critical database error. " + e.getMessage(),
                        IgniteQueryErrorCode.DB_UNRECOVERABLE_ERROR, e);
                }
                else
                    throw new IgniteSQLException("Failed to parse query. " + e.getMessage(), IgniteQueryErrorCode.PARSING, e);
            }
            catch (IgniteCheckedException e) {
                throw new IgniteSQLException("Failed to parse query. " + e.getMessage(), IgniteQueryErrorCode.PARSING, e);
            }
            finally {
                U.close(stmt, log);
            }
        }
    }