Search in sources :

Example 1 with QueryContext

use of org.apache.ignite.internal.processors.query.h2.opt.QueryContext in project ignite by apache.

the class GridMapQueryExecutor method onQueryRequest0.

/**
 * @param node Node authored request.
 * @param qryId Query ID.
 * @param reqId Request ID.
 * @param segmentId index segment ID.
 * @param schemaName Schema name.
 * @param qrys Queries to execute.
 * @param cacheIds Caches which will be affected by these queries.
 * @param topVer Topology version.
 * @param partsMap Partitions map for unstable topology.
 * @param parts Explicit partitions for current node.
 * @param pageSize Page size.
 * @param distributedJoins Query distributed join mode.
 * @param enforceJoinOrder Enforce join order H2 flag.
 * @param replicated Replicated only flag.
 * @param timeout Query timeout.
 * @param params Query parameters.
 * @param lazy Streaming flag.
 * @param mvccSnapshot MVCC snapshot.
 * @param dataPageScanEnabled If data page scan is enabled.
 */
private void onQueryRequest0(final ClusterNode node, final long qryId, final long reqId, final int segmentId, final String schemaName, final Collection<GridCacheSqlQuery> qrys, final List<Integer> cacheIds, final AffinityTopologyVersion topVer, final Map<UUID, int[]> partsMap, final int[] parts, final int pageSize, final boolean distributedJoins, final boolean enforceJoinOrder, final boolean replicated, final int timeout, final Object[] params, boolean lazy, @Nullable final MvccSnapshot mvccSnapshot, Boolean dataPageScanEnabled, boolean treatReplicatedAsPartitioned) {
    boolean performanceStatsEnabled = ctx.performanceStatistics().enabled();
    if (performanceStatsEnabled)
        IoStatisticsQueryHelper.startGatheringQueryStatistics();
    // Prepare to run queries.
    GridCacheContext<?, ?> mainCctx = mainCacheContext(cacheIds);
    MapNodeResults nodeRess = resultsForNode(node.id());
    MapQueryResults qryResults = null;
    PartitionReservation reserved = null;
    QueryContext qctx = null;
    // We don't use try with resources on purpose - the catch block must also be executed in the context of this span.
    TraceSurroundings trace = MTC.support(ctx.tracing().create(SQL_QRY_EXEC_REQ, MTC.span()).addTag(SQL_QRY_TEXT, () -> qrys.stream().map(GridCacheSqlQuery::query).collect(Collectors.joining("; "))));
    try {
        if (topVer != null) {
            // Reserve primary for topology version or explicit partitions.
            reserved = h2.partitionReservationManager().reservePartitions(cacheIds, topVer, parts, node.id(), reqId);
            if (reserved.failed()) {
                sendRetry(node, reqId, segmentId, reserved.error());
                return;
            }
        }
        // Prepare query context.
        DistributedJoinContext distributedJoinCtx = null;
        if (distributedJoins && !replicated) {
            distributedJoinCtx = new DistributedJoinContext(topVer, partsMap, node.id(), reqId, segmentId, pageSize);
        }
        qctx = new QueryContext(segmentId, h2.backupFilter(topVer, parts, treatReplicatedAsPartitioned), distributedJoinCtx, mvccSnapshot, reserved, true);
        qryResults = new MapQueryResults(h2, reqId, qrys.size(), mainCctx, lazy, qctx);
        // qctx is set, we have to release reservations inside of it.
        reserved = null;
        if (distributedJoinCtx != null)
            qryCtxRegistry.setShared(node.id(), reqId, qctx);
        if (nodeRess.put(reqId, segmentId, qryResults) != null)
            throw new IllegalStateException();
        if (nodeRess.cancelled(reqId)) {
            qryCtxRegistry.clearShared(node.id(), reqId);
            nodeRess.cancelRequest(reqId);
            throw new QueryCancelledException();
        }
        // Run queries.
        int qryIdx = 0;
        boolean evt = mainCctx != null && mainCctx.events().isRecordable(EVT_CACHE_QUERY_EXECUTED);
        for (GridCacheSqlQuery qry : qrys) {
            H2PooledConnection conn = h2.connections().connection(schemaName);
            H2Utils.setupConnection(conn, qctx, distributedJoins, enforceJoinOrder, lazy);
            MapQueryResult res = new MapQueryResult(h2, mainCctx, node.id(), qry, params, conn, log);
            qryResults.addResult(qryIdx, res);
            try {
                res.lock();
                // Ensure we are on the target node for this replicated query.
                if (qry.node() == null || (segmentId == 0 && qry.node().equals(ctx.localNodeId()))) {
                    String sql = qry.query();
                    Collection<Object> params0 = F.asList(qry.parameters(params));
                    PreparedStatement stmt = conn.prepareStatement(sql, H2StatementCache.queryFlags(distributedJoins, enforceJoinOrder));
                    H2Utils.bindParameters(stmt, params0);
                    MapH2QueryInfo qryInfo = new MapH2QueryInfo(stmt, qry.query(), node.id(), qryId, reqId, segmentId);
                    ResultSet rs = h2.executeSqlQueryWithTimer(stmt, conn, sql, timeout, qryResults.queryCancel(qryIdx), dataPageScanEnabled, qryInfo);
                    if (evt) {
                        ctx.event().record(new CacheQueryExecutedEvent<>(node, "SQL query executed.", EVT_CACHE_QUERY_EXECUTED, CacheQueryType.SQL.name(), mainCctx.name(), null, qry.query(), null, null, params, node.id(), null));
                    }
                    assert rs instanceof JdbcResultSet : rs.getClass();
                    if (qryResults.cancelled()) {
                        rs.close();
                        throw new QueryCancelledException();
                    }
                    res.openResult(rs, qryInfo);
                    final GridQueryNextPageResponse msg = prepareNextPage(nodeRess, node, qryResults, qryIdx, segmentId, pageSize, dataPageScanEnabled);
                    if (msg != null)
                        sendNextPage(node, msg);
                } else {
                    assert !qry.isPartitioned();
                    qryResults.closeResult(qryIdx);
                }
                qryIdx++;
            } finally {
                try {
                    res.unlockTables();
                } finally {
                    res.unlock();
                }
            }
        }
        if (!lazy)
            qryResults.releaseQueryContext();
    } catch (Throwable e) {
        if (qryResults != null) {
            nodeRess.remove(reqId, segmentId, qryResults);
            qryResults.close();
            // If a query is cancelled before execution is started partitions have to be released.
            if (!lazy || !qryResults.isAllClosed())
                qryResults.releaseQueryContext();
        } else
            releaseReservations(qctx);
        if (e instanceof QueryCancelledException)
            sendError(node, reqId, e);
        else {
            SQLException sqlEx = X.cause(e, SQLException.class);
            if (sqlEx != null && sqlEx.getErrorCode() == ErrorCode.STATEMENT_WAS_CANCELED)
                sendQueryCancel(node, reqId);
            else {
                GridH2RetryException retryErr = X.cause(e, GridH2RetryException.class);
                if (retryErr != null) {
                    final String retryCause = String.format("Failed to execute non-collocated query (will retry) [localNodeId=%s, rmtNodeId=%s, reqId=%s, " + "errMsg=%s]", ctx.localNodeId(), node.id(), reqId, retryErr.getMessage());
                    sendRetry(node, reqId, segmentId, retryCause);
                } else {
                    QueryRetryException qryRetryErr = X.cause(e, QueryRetryException.class);
                    if (qryRetryErr != null)
                        sendError(node, reqId, qryRetryErr);
                    else {
                        if (e instanceof Error) {
                            U.error(log, "Failed to execute local query.", e);
                            throw (Error) e;
                        }
                        U.warn(log, "Failed to execute local query.", e);
                        sendError(node, reqId, e);
                    }
                }
            }
        }
    } finally {
        if (reserved != null)
            reserved.release();
        if (trace != null)
            trace.close();
        if (performanceStatsEnabled) {
            IoStatisticsHolder stat = IoStatisticsQueryHelper.finishGatheringQueryStatistics();
            if (stat.logicalReads() > 0 || stat.physicalReads() > 0) {
                ctx.performanceStatistics().queryReads(GridCacheQueryType.SQL_FIELDS, node.id(), reqId, stat.logicalReads(), stat.physicalReads());
            }
        }
    }
}
Also used : QueryRetryException(org.apache.ignite.cache.query.QueryRetryException) SQLException(java.sql.SQLException) GridQueryNextPageResponse(org.apache.ignite.internal.processors.query.h2.twostep.messages.GridQueryNextPageResponse) TraceSurroundings(org.apache.ignite.internal.processors.tracing.MTC.TraceSurroundings) DistributedJoinContext(org.apache.ignite.internal.processors.query.h2.opt.join.DistributedJoinContext) ResultSet(java.sql.ResultSet) JdbcResultSet(org.h2.jdbc.JdbcResultSet) GridCacheSqlQuery(org.apache.ignite.internal.processors.cache.query.GridCacheSqlQuery) JdbcResultSet(org.h2.jdbc.JdbcResultSet) H2PooledConnection(org.apache.ignite.internal.processors.query.h2.H2PooledConnection) MapH2QueryInfo(org.apache.ignite.internal.processors.query.h2.MapH2QueryInfo) GridH2RetryException(org.apache.ignite.internal.processors.query.h2.opt.GridH2RetryException) PreparedStatement(java.sql.PreparedStatement) QueryContext(org.apache.ignite.internal.processors.query.h2.opt.QueryContext) IoStatisticsHolder(org.apache.ignite.internal.metric.IoStatisticsHolder) QueryCancelledException(org.apache.ignite.cache.query.QueryCancelledException)

Example 2 with QueryContext

use of org.apache.ignite.internal.processors.query.h2.opt.QueryContext in project ignite by apache.

the class ValidateIndexesClosure method mvccSession.

/**
 * Get session with MVCC snapshot and QueryContext.
 *
 * @param cctx Cache context.
 * @return Session with QueryContext and MVCC snapshot.
 * @throws IgniteCheckedException If failed.
 */
private Session mvccSession(GridCacheContext<?, ?> cctx) throws IgniteCheckedException {
    Session session = null;
    boolean mvccEnabled = cctx.mvccEnabled();
    if (mvccEnabled) {
        ConnectionManager connMgr = ((IgniteH2Indexing) ignite.context().query().getIndexing()).connections();
        JdbcConnection connection = (JdbcConnection) connMgr.connection().connection();
        session = (Session) connection.getSession();
        MvccQueryTracker tracker = MvccUtils.mvccTracker(cctx, true);
        MvccSnapshot mvccSnapshot = tracker.snapshot();
        final QueryContext qctx = new QueryContext(0, cacheName -> null, null, mvccSnapshot, null, true);
        session.setVariable(H2Utils.QCTX_VARIABLE_NAME, new H2Utils.ValueRuntimeSimpleObject<>(qctx));
    }
    return session;
}
Also used : H2Utils(org.apache.ignite.internal.processors.query.h2.H2Utils) MvccQueryTracker(org.apache.ignite.internal.processors.cache.mvcc.MvccQueryTracker) MvccSnapshot(org.apache.ignite.internal.processors.cache.mvcc.MvccSnapshot) ConnectionManager(org.apache.ignite.internal.processors.query.h2.ConnectionManager) JdbcConnection(org.h2.jdbc.JdbcConnection) QueryContext(org.apache.ignite.internal.processors.query.h2.opt.QueryContext) IgniteH2Indexing(org.apache.ignite.internal.processors.query.h2.IgniteH2Indexing) Session(org.h2.engine.Session)

Example 3 with QueryContext

use of org.apache.ignite.internal.processors.query.h2.opt.QueryContext 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)

Example 4 with QueryContext

use of org.apache.ignite.internal.processors.query.h2.opt.QueryContext in project ignite by apache.

the class H2PkHashIndex method find.

/**
 * {@inheritDoc}
 */
@Override
public Cursor find(Session ses, final SearchRow lower, final SearchRow upper) {
    IndexingQueryCacheFilter filter = null;
    MvccSnapshot mvccSnapshot = null;
    QueryContext qctx = H2Utils.context(ses);
    int seg = 0;
    if (qctx != null) {
        IndexingQueryFilter f = qctx.filter();
        filter = f != null ? f.forCache(getTable().cacheName()) : null;
        mvccSnapshot = qctx.mvccSnapshot();
        seg = qctx.segment();
    }
    assert !cctx.mvccEnabled() || mvccSnapshot != null;
    KeyCacheObject lowerObj = lower != null ? cctx.toCacheKeyObject(lower.getValue(0).getObject()) : null;
    KeyCacheObject upperObj = upper != null ? cctx.toCacheKeyObject(upper.getValue(0).getObject()) : null;
    try {
        CacheDataRowStore.setSkipVersion(true);
        Collection<GridCursor<? extends CacheDataRow>> cursors = new ArrayList<>();
        for (IgniteCacheOffheapManager.CacheDataStore store : cctx.offheap().cacheDataStores()) {
            int part = store.partId();
            if (segmentForPartition(part) != seg)
                continue;
            if (filter == null || filter.applyPartition(part))
                cursors.add(store.cursor(cctx.cacheId(), lowerObj, upperObj, null, mvccSnapshot));
        }
        return new H2PkHashIndexCursor(cursors.iterator());
    } catch (IgniteCheckedException e) {
        throw DbException.convert(e);
    } finally {
        CacheDataRowStore.setSkipVersion(false);
    }
}
Also used : CacheDataRow(org.apache.ignite.internal.processors.cache.persistence.CacheDataRow) MvccSnapshot(org.apache.ignite.internal.processors.cache.mvcc.MvccSnapshot) GridCursor(org.apache.ignite.internal.util.lang.GridCursor) IndexingQueryFilter(org.apache.ignite.spi.indexing.IndexingQueryFilter) ArrayList(java.util.ArrayList) QueryContext(org.apache.ignite.internal.processors.query.h2.opt.QueryContext) IgniteCheckedException(org.apache.ignite.IgniteCheckedException) IgniteCacheOffheapManager(org.apache.ignite.internal.processors.cache.IgniteCacheOffheapManager) IndexingQueryCacheFilter(org.apache.ignite.spi.indexing.IndexingQueryCacheFilter) KeyCacheObject(org.apache.ignite.internal.processors.cache.KeyCacheObject)

Example 5 with QueryContext

use of org.apache.ignite.internal.processors.query.h2.opt.QueryContext in project ignite by apache.

the class H2TreeIndex method onIndexRangeRequest.

/**
 * @param node Requesting node.
 * @param msg Request message.
 */
private void onIndexRangeRequest(final ClusterNode node, final GridH2IndexRangeRequest msg) {
    // We don't use try with resources on purpose - the catch block must also be executed in the context of this span.
    TraceSurroundings trace = MTC.support(ctx.tracing().create(SQL_IDX_RANGE_REQ, MTC.span()));
    Span span = MTC.span();
    try {
        span.addTag(SQL_IDX, () -> idxName);
        span.addTag(SQL_TABLE, () -> tblName);
        GridH2IndexRangeResponse res = new GridH2IndexRangeResponse();
        res.originNodeId(msg.originNodeId());
        res.queryId(msg.queryId());
        res.originSegmentId(msg.originSegmentId());
        res.segment(msg.segment());
        res.batchLookupId(msg.batchLookupId());
        QueryContext qctx = qryCtxRegistry.getShared(msg.originNodeId(), msg.queryId(), msg.originSegmentId());
        if (qctx == null)
            res.status(STATUS_NOT_FOUND);
        else {
            DistributedJoinContext joinCtx = qctx.distributedJoinContext();
            assert joinCtx != null;
            try {
                RangeSource src;
                if (msg.bounds() != null) {
                    // This is the first request containing all the search rows.
                    assert !msg.bounds().isEmpty() : "empty bounds";
                    src = new RangeSource(this, msg.bounds(), msg.segment(), idxQryContext(qctx));
                } else {
                    // This is request to fetch next portion of data.
                    src = joinCtx.getSource(node.id(), msg.segment(), msg.batchLookupId());
                    assert src != null;
                }
                List<GridH2RowRange> ranges = new ArrayList<>();
                int maxRows = joinCtx.pageSize();
                assert maxRows > 0 : maxRows;
                while (maxRows > 0) {
                    GridH2RowRange range = src.next(maxRows);
                    if (range == null)
                        break;
                    ranges.add(range);
                    if (range.rows() != null)
                        maxRows -= range.rows().size();
                }
                assert !ranges.isEmpty();
                if (src.hasMoreRows()) {
                    // Save source for future fetches.
                    if (msg.bounds() != null)
                        joinCtx.putSource(node.id(), msg.segment(), msg.batchLookupId(), src);
                } else if (msg.bounds() == null) {
                    // Drop saved source.
                    joinCtx.putSource(node.id(), msg.segment(), msg.batchLookupId(), null);
                }
                res.ranges(ranges);
                res.status(STATUS_OK);
                span.addTag(SQL_IDX_RANGE_ROWS, () -> Integer.toString(ranges.stream().mapToInt(GridH2RowRange::rowsSize).sum()));
            } catch (Throwable th) {
                span.addTag(ERROR, th::getMessage);
                U.error(log, "Failed to process request: " + msg, th);
                res.error(th.getClass() + ": " + th.getMessage());
                res.status(STATUS_ERROR);
            }
        }
        send(singletonList(node), res);
    } catch (Throwable th) {
        span.addTag(ERROR, th::getMessage);
        throw th;
    } finally {
        if (trace != null)
            trace.close();
    }
}
Also used : GridH2IndexRangeResponse(org.apache.ignite.internal.processors.query.h2.twostep.msg.GridH2IndexRangeResponse) DistributedJoinContext(org.apache.ignite.internal.processors.query.h2.opt.join.DistributedJoinContext) RangeSource(org.apache.ignite.internal.processors.query.h2.opt.join.RangeSource) ArrayList(java.util.ArrayList) GridH2RowRange(org.apache.ignite.internal.processors.query.h2.twostep.msg.GridH2RowRange) IndexQueryContext(org.apache.ignite.internal.cache.query.index.sorted.inline.IndexQueryContext) QueryContext(org.apache.ignite.internal.processors.query.h2.opt.QueryContext) Span(org.apache.ignite.internal.processors.tracing.Span) TraceSurroundings(org.apache.ignite.internal.processors.tracing.MTC.TraceSurroundings)

Aggregations

QueryContext (org.apache.ignite.internal.processors.query.h2.opt.QueryContext)14 IgniteCheckedException (org.apache.ignite.IgniteCheckedException)7 ArrayList (java.util.ArrayList)5 IndexQueryContext (org.apache.ignite.internal.cache.query.index.sorted.inline.IndexQueryContext)5 PreparedStatement (java.sql.PreparedStatement)4 MvccSnapshot (org.apache.ignite.internal.processors.cache.mvcc.MvccSnapshot)4 TraceSurroundings (org.apache.ignite.internal.processors.tracing.MTC.TraceSurroundings)4 ResultSet (java.sql.ResultSet)3 SQLException (java.sql.SQLException)3 QueryCancelledException (org.apache.ignite.cache.query.QueryCancelledException)3 Collections.singletonList (java.util.Collections.singletonList)2 List (java.util.List)2 CacheException (javax.cache.CacheException)2 IndexRow (org.apache.ignite.internal.cache.query.index.sorted.IndexRow)2 GridCacheContext (org.apache.ignite.internal.processors.cache.GridCacheContext)2 KeyCacheObject (org.apache.ignite.internal.processors.cache.KeyCacheObject)2 CacheDataRow (org.apache.ignite.internal.processors.cache.persistence.CacheDataRow)2 GridCacheSqlQuery (org.apache.ignite.internal.processors.cache.query.GridCacheSqlQuery)2 IgniteSQLException (org.apache.ignite.internal.processors.query.IgniteSQLException)2 H2Cursor (org.apache.ignite.internal.processors.query.h2.H2Cursor)2