use of org.apache.ignite.internal.sql.optimizer.affinity.PartitionResult in project ignite by apache.
the class JdbcThinPartitionAwarenessSelfTest method verifyPartitionResultIsNull.
/**
* Utility method that executes given query and verifies that expected number of records was returned.
* Besides that given method verified that partition result for corresponding query is null.
*
* @param sqlQry Sql query.
* @param expRowsCnt Expected rows count.
* @throws SQLException If failed.
*/
protected void verifyPartitionResultIsNull(String sqlQry, int expRowsCnt) throws SQLException {
ResultSet rs = stmt.executeQuery(sqlQry);
assert rs != null;
int rowCntr = 0;
while (rs.next()) rowCntr++;
assertEquals("Rows counter doesn't match expected value.", expRowsCnt, rowCntr);
AffinityCache affinityCache = GridTestUtils.getFieldValue(conn, "affinityCache");
PartitionResult gotPartRes = affinityCache.partitionResult(new QualifiedSQLQuery("default", sqlQry)).partitionResult();
assertNull("Partition result descriptor is not null.", gotPartRes);
}
use of org.apache.ignite.internal.sql.optimizer.affinity.PartitionResult in project ignite by apache.
the class PartitionExtractor method mergeMapQueries.
/**
* Merge partition info from multiple queries.
*
* @param qrys Queries.
* @return Partition result or {@code null} if nothing is resolved.
*/
@SuppressWarnings("IfMayBeConditional")
public PartitionResult mergeMapQueries(List<GridCacheSqlQuery> qrys) {
// Check if merge is possible.
PartitionTableAffinityDescriptor aff = null;
for (GridCacheSqlQuery qry : qrys) {
PartitionResult qryRes = (PartitionResult) qry.derivedPartitions();
// Failed to get results for one query -> broadcast.
if (qryRes == null)
return null;
// This only possible if query is resolved to "NONE". Will be skipped later during map request prepare.
if (qryRes.affinity() == null)
continue;
if (aff == null)
aff = qryRes.affinity();
else if (!aff.isCompatible(qryRes.affinity()))
// Queries refer to incompatible affinity groups, cannot merge -> broadcast.
return null;
}
// Merge.
PartitionNode tree = null;
AffinityTopologyVersion affinityTopVer = null;
for (GridCacheSqlQuery qry : qrys) {
PartitionResult qryRes = (PartitionResult) qry.derivedPartitions();
if (tree == null)
tree = qryRes.tree();
else
tree = new PartitionCompositeNode(tree, qryRes.tree(), PartitionCompositeNodeOperator.OR);
if (affinityTopVer == null)
affinityTopVer = qryRes.topologyVersion();
else
assert affinityTopVer.equals(qryRes.topologyVersion());
}
// Optimize.
assert tree != null;
tree = tree.optimize();
if (tree instanceof PartitionAllNode)
return null;
// If there is no affinity, then we assume "NONE" result.
assert aff != null || tree == PartitionNoneNode.INSTANCE;
// TODO: during PartitionResult construction/application.
assert affinityTopVer != null;
return new PartitionResult(tree, aff, affinityTopVer);
}
use of org.apache.ignite.internal.sql.optimizer.affinity.PartitionResult in project ignite by apache.
the class IgniteH2Indexing method executeUpdate.
/**
* Execute DML statement, possibly with few re-attempts in case of concurrent data modifications.
*
* @param qryId Query id.
* @param qryDesc Query descriptor.
* @param qryParams Query parameters.
* @param dml DML command.
* @param loc Query locality flag.
* @param filters Cache name and key filter.
* @param cancel Cancel.
* @return Update result (modified items count and failed keys).
* @throws IgniteCheckedException if failed.
*/
@SuppressWarnings("IfMayBeConditional")
private UpdateResult executeUpdate(long qryId, QueryDescriptor qryDesc, QueryParameters qryParams, QueryParserResultDml dml, boolean loc, IndexingQueryFilter filters, GridQueryCancel cancel) throws IgniteCheckedException {
Object[] errKeys = null;
long items = 0;
PartitionResult partRes = null;
GridCacheContext<?, ?> cctx = dml.plan().cacheContext();
boolean transactional = cctx != null && cctx.mvccEnabled();
int maxRetryCnt = transactional ? 1 : DFLT_UPDATE_RERUN_ATTEMPTS;
for (int i = 0; i < maxRetryCnt; i++) {
CacheOperationContext opCtx = cctx != null ? DmlUtils.setKeepBinaryContext(cctx) : null;
UpdateResult r;
try {
if (transactional)
r = executeUpdateTransactional(qryId, qryDesc, qryParams, dml, loc, cancel);
else
r = executeUpdateNonTransactional(qryId, qryDesc, qryParams, dml, loc, filters, cancel);
} finally {
if (opCtx != null)
DmlUtils.restoreKeepBinaryContext(cctx, opCtx);
}
items += r.counter();
errKeys = r.errorKeys();
partRes = r.partitionResult();
if (F.isEmpty(errKeys))
break;
}
if (F.isEmpty(errKeys) && partRes == null) {
if (items == 1L)
return UpdateResult.ONE;
else if (items == 0L)
return UpdateResult.ZERO;
}
return new UpdateResult(items, errKeys, partRes);
}
use of org.apache.ignite.internal.sql.optimizer.affinity.PartitionResult in project ignite by apache.
the class IgniteH2Indexing method executeSelectDistributed.
/**
* Run distributed query on detected set of partitions.
*
* @param qryId Query id.
* @param qryDesc Query descriptor.
* @param qryParams Query parameters.
* @param twoStepQry Two-step query.
* @param keepBinary Keep binary flag.
* @param mvccTracker Query tracker.
* @param cancel Cancel handler.
* @param timeout Timeout.
* @return Cursor representing distributed query result.
*/
@SuppressWarnings("IfMayBeConditional")
private Iterable<List<?>> executeSelectDistributed(final long qryId, final QueryDescriptor qryDesc, final QueryParameters qryParams, final GridCacheTwoStepQuery twoStepQry, final boolean keepBinary, MvccQueryTracker mvccTracker, final GridQueryCancel cancel, int timeout) {
// When explicit partitions are set, there must be an owning cache they should be applied to.
PartitionResult derivedParts = twoStepQry.derivedPartitions();
final int[] parts = PartitionResult.calculatePartitions(qryParams.partitions(), derivedParts, qryParams.arguments());
Iterable<List<?>> iter;
if (parts != null && parts.length == 0) {
iter = new Iterable<List<?>>() {
@Override
public Iterator<List<?>> iterator() {
return new Iterator<List<?>>() {
@Override
public boolean hasNext() {
return false;
}
@SuppressWarnings("IteratorNextCanNotThrowNoSuchElementException")
@Override
public List<?> next() {
return null;
}
};
}
};
} else {
assert !twoStepQry.mvccEnabled() || !F.isEmpty(twoStepQry.cacheIds());
assert twoStepQry.mvccEnabled() == (mvccTracker != null);
iter = new Iterable<List<?>>() {
@Override
public Iterator<List<?>> iterator() {
try (TraceSurroundings ignored = MTC.support(ctx.tracing().create(SQL_ITER_OPEN, MTC.span()))) {
return IgniteH2Indexing.this.rdcQryExec.query(qryId, qryDesc.schemaName(), twoStepQry, keepBinary, qryDesc.enforceJoinOrder(), timeout, cancel, qryParams.arguments(), parts, qryParams.lazy(), mvccTracker, qryParams.dataPageScanEnabled(), qryParams.pageSize());
} catch (Throwable e) {
if (mvccTracker != null)
mvccTracker.onDone();
throw e;
}
}
};
}
return iter;
}
use of org.apache.ignite.internal.sql.optimizer.affinity.PartitionResult in project ignite by apache.
the class JdbcRequestHandler method executeQuery.
/**
* {@link JdbcQueryExecuteRequest} command handler.
*
* @param req Execute query request.
* @return Response.
*/
@SuppressWarnings("unchecked")
private JdbcResponse executeQuery(JdbcQueryExecuteRequest req) {
GridQueryCancel cancel = null;
boolean unregisterReq = false;
if (isCancellationSupported()) {
synchronized (reqMux) {
JdbcQueryDescriptor desc = reqRegister.get(req.requestId());
// Query was already cancelled and unregistered.
if (desc == null)
return null;
cancel = desc.cancelHook();
desc.incrementUsageCount();
}
}
try {
int cursorCnt = jdbcCursors.size();
if (maxCursors > 0 && cursorCnt >= maxCursors)
return new JdbcResponse(IgniteQueryErrorCode.UNKNOWN, "Too many open cursors (either close other " + "open cursors or increase the limit through " + "ClientConnectorConfiguration.maxOpenCursorsPerConnection) [maximum=" + maxCursors + ", current=" + cursorCnt + ']');
assert !cliCtx.isStream();
String sql = req.sqlQuery();
SqlFieldsQueryEx qry;
switch(req.expectedStatementType()) {
case ANY_STATEMENT_TYPE:
qry = new SqlFieldsQueryEx(sql, null);
break;
case SELECT_STATEMENT_TYPE:
qry = new SqlFieldsQueryEx(sql, true);
break;
default:
assert req.expectedStatementType() == JdbcStatementType.UPDATE_STMT_TYPE;
qry = new SqlFieldsQueryEx(sql, false);
if (cliCtx.isSkipReducerOnUpdate())
((SqlFieldsQueryEx) qry).setSkipReducerOnUpdate(true);
}
setupQuery(qry, prepareSchemaName(req.schemaName()));
qry.setArgs(req.arguments());
qry.setAutoCommit(req.autoCommit());
if (req.explicitTimeout()) {
// Timeout is handled on a client side, do not handle it on a server side.
qry.setTimeout(0, TimeUnit.MILLISECONDS);
}
if (req.pageSize() <= 0)
return new JdbcResponse(IgniteQueryErrorCode.UNKNOWN, "Invalid fetch size: " + req.pageSize());
qry.setPageSize(req.pageSize());
String schemaName = req.schemaName();
if (F.isEmpty(schemaName))
schemaName = QueryUtils.DFLT_SCHEMA;
qry.setSchema(schemaName);
List<FieldsQueryCursor<List<?>>> results = connCtx.kernalContext().query().querySqlFields(null, qry, cliCtx, true, protocolVer.compareTo(VER_2_3_0) < 0, cancel);
FieldsQueryCursor<List<?>> fieldsCur = results.get(0);
if (fieldsCur instanceof BulkLoadContextCursor) {
BulkLoadContextCursor blCur = (BulkLoadContextCursor) fieldsCur;
BulkLoadProcessor blProcessor = blCur.bulkLoadProcessor();
BulkLoadAckClientParameters clientParams = blCur.clientParams();
JdbcBulkLoadProcessor processor = new JdbcBulkLoadProcessor(blProcessor, req.requestId());
jdbcCursors.put(processor.cursorId(), processor);
// responses for the same query on the client side
return resultToResonse(new JdbcBulkLoadAckResult(processor.cursorId(), clientParams));
}
if (results.size() == 1) {
JdbcQueryCursor cur = new JdbcQueryCursor(req.pageSize(), req.maxRows(), (QueryCursorImpl) fieldsCur, req.requestId());
jdbcCursors.put(cur.cursorId(), cur);
cur.openIterator();
JdbcQueryExecuteResult res;
PartitionResult partRes = ((QueryCursorImpl<List<?>>) fieldsCur).partitionResult();
if (cur.isQuery())
res = new JdbcQueryExecuteResult(cur.cursorId(), cur.fetchRows(), !cur.hasNext(), isClientPartitionAwarenessApplicable(req.partitionResponseRequest(), partRes) ? partRes : null);
else {
List<List<Object>> items = cur.fetchRows();
assert items != null && items.size() == 1 && items.get(0).size() == 1 && items.get(0).get(0) instanceof Long : "Invalid result set for not-SELECT query. [qry=" + sql + ", res=" + S.toString(List.class, items) + ']';
res = new JdbcQueryExecuteResult(cur.cursorId(), (Long) items.get(0).get(0), isClientPartitionAwarenessApplicable(req.partitionResponseRequest(), partRes) ? partRes : null);
}
if (res.last() && (!res.isQuery() || autoCloseCursors)) {
jdbcCursors.remove(cur.cursorId());
unregisterReq = true;
cur.close();
}
return resultToResonse(res);
} else {
List<JdbcResultInfo> jdbcResults = new ArrayList<>(results.size());
List<List<Object>> items = null;
boolean last = true;
for (FieldsQueryCursor<List<?>> c : results) {
QueryCursorImpl qryCur = (QueryCursorImpl) c;
JdbcResultInfo jdbcRes;
if (qryCur.isQuery()) {
JdbcQueryCursor cur = new JdbcQueryCursor(req.pageSize(), req.maxRows(), qryCur, req.requestId());
jdbcCursors.put(cur.cursorId(), cur);
jdbcRes = new JdbcResultInfo(true, -1, cur.cursorId());
cur.openIterator();
if (items == null) {
items = cur.fetchRows();
last = cur.hasNext();
}
} else
jdbcRes = new JdbcResultInfo(false, (Long) ((List<?>) qryCur.getAll().get(0)).get(0), -1);
jdbcResults.add(jdbcRes);
}
return resultToResonse(new JdbcQueryExecuteMultipleStatementsResult(jdbcResults, items, last));
}
} catch (Exception e) {
// Trying to close all cursors of current request.
clearCursors(req.requestId());
unregisterReq = true;
U.error(log, "Failed to execute SQL query [reqId=" + req.requestId() + ", req=" + req + ']', e);
if (X.cause(e, QueryCancelledException.class) != null)
return exceptionToResult(new QueryCancelledException());
else
return exceptionToResult(e);
} finally {
cleanupQueryCancellationMeta(unregisterReq, req.requestId());
}
}
Aggregations