use of org.apache.ignite.internal.processors.query.h2.sql.GridSqlOperationType.AND in project ignite by apache.
the class GridH2Table method checkIndexPresence.
/**
* Checks index presence, return {@link Index} if index with same name or same fields and search direction already
* exist or {@code null} othervise.
*
* @param curIdx Index to check.
* @return Index if equal or subset index exist.
* @throws IgniteCheckedException If failed.
*/
@Nullable
private Index checkIndexPresence(Index curIdx) throws IgniteCheckedException {
IndexColumn[] curColumns = curIdx.getIndexColumns();
Index registredIdx = null;
for (Index idx : idxs) {
if (!(idx instanceof H2TreeIndex))
continue;
if (F.eq(curIdx.getName(), idx.getName()))
throw new IgniteCheckedException("Index already exists: " + idx.getName());
IndexColumn[] idxColumns = idx.getIndexColumns();
for (int i = 0; i < Math.min(idxColumns.length, curColumns.length); ++i) {
IndexColumn idxCol = idxColumns[i];
IndexColumn curCol = curColumns[i];
// pk attach at the end of listed fields.
if (curCol.column.getColumnId() == 0 && registredIdx != null)
continue;
if (H2Utils.equals(idxCol, curCol) && idxCol.sortType == curCol.sortType)
registredIdx = idx;
else {
registredIdx = null;
break;
}
}
if (registredIdx != null)
return registredIdx;
}
return null;
}
use of org.apache.ignite.internal.processors.query.h2.sql.GridSqlOperationType.AND in project ignite by apache.
the class DmlUtils method doDelete.
/**
* Perform DELETE operation on top of results of SELECT.
*
* @param cctx Cache context.
* @param cursor SELECT results.
* @param pageSize Batch size for streaming, anything <= 0 for single page operations.
* @return Results of DELETE (number of items affected AND keys that failed to be updated).
*/
private static UpdateResult doDelete(GridCacheContext cctx, Iterable<List<?>> cursor, int pageSize) throws IgniteCheckedException {
DmlBatchSender sender = new DmlBatchSender(cctx, pageSize, 1);
for (List<?> row : cursor) {
if (row.size() != 2)
continue;
Object key = row.get(0);
ClusterNode node = sender.primaryNodeByKey(key);
IgniteInClosure<MutableEntry<Object, Object>> rmvC = DmlStatementsProcessor.getRemoveClosure(node, key);
sender.add(key, new DmlStatementsProcessor.ModifyingEntryProcessor(row.get(1), rmvC), 0);
}
sender.flush();
SQLException resEx = sender.error();
if (resEx != null) {
if (!F.isEmpty(sender.failedKeys())) {
// Don't go for a re-run if processing of some keys yielded exceptions and report keys that
// had been modified concurrently right away.
String msg = "Failed to DELETE some keys because they had been modified concurrently " + "[keys=" + sender.failedKeys() + ']';
SQLException conEx = createJdbcSqlException(msg, IgniteQueryErrorCode.CONCURRENT_UPDATE);
conEx.setNextException(resEx);
resEx = conEx;
}
throw new IgniteSQLException(resEx);
}
return new UpdateResult(sender.updateCount(), sender.failedKeys().toArray(), cursor instanceof QueryCursorImpl ? ((QueryCursorImpl) cursor).partitionResult() : null);
}
use of org.apache.ignite.internal.processors.query.h2.sql.GridSqlOperationType.AND in project ignite by apache.
the class DistributedLookupBatch method addSearchRows.
/**
* {@inheritDoc}
*/
@SuppressWarnings({ "ForLoopReplaceableByForEach", "IfMayBeConditional" })
@Override
public boolean addSearchRows(SearchRow firstRow, SearchRow lastRow) {
if (joinCtx == null || findCalled) {
if (joinCtx == null) {
// It is the first call after query begin (may be after reuse),
// reinitialize query context and result.
QueryContext qctx = QueryContext.threadLocal();
res = new ArrayList<>();
assert qctx != null;
assert !findCalled;
joinCtx = qctx.distributedJoinContext();
} else {
// Cleanup after the previous lookup phase.
assert batchLookupId != 0;
findCalled = false;
joinCtx.putStreams(batchLookupId, null);
res.clear();
}
// Reinitialize for the next lookup phase.
batchLookupId = joinCtx.nextBatchLookupId();
rangeStreams = new HashMap<>();
}
Object affKey = getAffinityKey(firstRow, lastRow);
List<SegmentKey> segmentKeys;
if (affKey != null) {
// Affinity key is provided.
if (// Affinity key is explicit null, we will not find anything.
affKey == EXPLICIT_NULL)
return false;
segmentKeys = F.asList(rangeSegment(affKey));
} else {
// Affinity key is not provided or is not the same in upper and lower bounds, we have to broadcast.
if (broadcastSegments == null)
broadcastSegments = broadcastSegments();
segmentKeys = broadcastSegments;
}
assert !F.isEmpty(segmentKeys) : segmentKeys;
final int rangeId = res.size();
// Create messages.
GridH2RowMessage first = idx.toSearchRowMessage(firstRow);
GridH2RowMessage last = idx.toSearchRowMessage(lastRow);
// Range containing upper and lower bounds.
GridH2RowRangeBounds rangeBounds = rangeBounds(rangeId, first, last);
// Add range to every message of every participating node.
for (int i = 0; i < segmentKeys.size(); i++) {
SegmentKey segmentKey = segmentKeys.get(i);
assert segmentKey != null;
RangeStream stream = rangeStreams.get(segmentKey);
List<GridH2RowRangeBounds> bounds;
if (stream == null) {
stream = new RangeStream(cctx.kernalContext(), idx, joinCtx, segmentKey.node());
stream.request(createRequest(joinCtx, batchLookupId, segmentKey.segmentId()));
stream.request().bounds(bounds = new ArrayList<>());
rangeStreams.put(segmentKey, stream);
} else
bounds = stream.request().bounds();
bounds.add(rangeBounds);
// If at least one node will have a full batch then we are ok.
if (bounds.size() >= joinCtx.pageSize())
batchFull = true;
}
Cursor cur;
if (segmentKeys.size() == 1)
cur = new UnicastCursor(rangeId, rangeStreams.get(F.first(segmentKeys)));
else
cur = new BroadcastCursor(idx, rangeId, segmentKeys, rangeStreams);
res.add(new DoneFuture<>(cur));
return true;
}
use of org.apache.ignite.internal.processors.query.h2.sql.GridSqlOperationType.AND in project ignite by apache.
the class ValidateIndexesClosure method checkSizes.
/**
* Checking size of records in cache and indexes with a record into
* {@code checkSizeRes} if they are not equal.
*
* @param cacheSizesFutures Futures calculating size of records in caches.
* @param idxSizeFutures Futures calculating size of indexes of caches.
* @param checkSizeRes Result of size check.
*/
private void checkSizes(List<T3<CacheGroupContext, GridDhtLocalPartition, Future<CacheSize>>> cacheSizesFutures, List<T3<GridCacheContext, Index, Future<T2<Throwable, Long>>>> idxSizeFutures, Map<String, ValidateIndexesCheckSizeResult> checkSizeRes) throws ExecutionException, InterruptedException {
if (!checkSizes)
return;
Map<Integer, CacheSize> cacheSizeTotal = new HashMap<>();
for (T3<CacheGroupContext, GridDhtLocalPartition, Future<CacheSize>> cacheSizeFut : cacheSizesFutures) {
CacheGroupContext cacheGrpCtx = cacheSizeFut.get1();
CacheSize cacheSize = cacheSizeFut.get3().get();
Throwable cacheSizeErr = cacheSize.err;
int grpId = cacheGrpCtx.groupId();
if (failCalcCacheSizeGrpIds.contains(grpId) && nonNull(cacheSizeErr)) {
checkSizeRes.computeIfAbsent(cacheGrpInfo(cacheGrpCtx), s -> new ValidateIndexesCheckSizeResult(0, new ArrayList<>())).issues().add(new ValidateIndexesCheckSizeIssue(null, 0, cacheSizeErr));
} else {
cacheSizeTotal.computeIfAbsent(grpId, i -> new CacheSize(null, new HashMap<>())).merge(cacheSize.cacheSizePerTbl);
}
}
for (T3<GridCacheContext, Index, Future<T2<Throwable, Long>>> idxSizeFut : idxSizeFutures) {
GridCacheContext cacheCtx = idxSizeFut.get1();
int grpId = cacheCtx.groupId();
if (failCalcCacheSizeGrpIds.contains(grpId))
continue;
Index idx = idxSizeFut.get2();
String tblName = idx.getTable().getName();
AtomicLong cacheSizeObj = cacheSizeTotal.get(grpId).cacheSizePerTbl.getOrDefault(cacheCtx.cacheId(), emptyMap()).get(tblName);
long cacheSizeByTbl = isNull(cacheSizeObj) ? 0L : cacheSizeObj.get();
T2<Throwable, Long> idxSizeRes = idxSizeFut.get3().get();
Throwable err = idxSizeRes.get1();
long idxSize = idxSizeRes.get2();
if (isNull(err) && idxSize != cacheSizeByTbl)
err = new IgniteException("Cache and index size not same.");
if (nonNull(err)) {
checkSizeRes.computeIfAbsent("[" + cacheGrpInfo(cacheCtx.group()) + ", " + cacheInfo(cacheCtx) + ", tableName=" + tblName + "]", s -> new ValidateIndexesCheckSizeResult(cacheSizeByTbl, new ArrayList<>())).issues().add(new ValidateIndexesCheckSizeIssue(idx.getName(), idxSize, err));
}
}
}
use of org.apache.ignite.internal.processors.query.h2.sql.GridSqlOperationType.AND in project ignite by apache.
the class ValidateIndexesClosure method call0.
/**
*/
private VisorValidateIndexesJobResult call0() {
if (validateCtx.isCancelled())
throw new IgniteException(CANCELLED_MSG);
Set<Integer> grpIds = collectGroupIds();
/**
* Update counters per partition per group.
*/
final Map<Integer, Map<Integer, PartitionUpdateCounter>> partsWithCntrsPerGrp = getUpdateCountersSnapshot(ignite, grpIds);
IdleVerifyUtility.IdleChecker idleChecker = new IdleVerifyUtility.IdleChecker(ignite, partsWithCntrsPerGrp);
List<T2<CacheGroupContext, GridDhtLocalPartition>> partArgs = new ArrayList<>();
List<T2<GridCacheContext, Index>> idxArgs = new ArrayList<>();
totalCacheGrps = grpIds.size();
Map<Integer, IndexIntegrityCheckIssue> integrityCheckResults = integrityCheckIndexesPartitions(grpIds, idleChecker);
GridQueryProcessor qryProcessor = ignite.context().query();
IgniteH2Indexing h2Indexing = (IgniteH2Indexing) qryProcessor.getIndexing();
for (Integer grpId : grpIds) {
CacheGroupContext grpCtx = ignite.context().cache().cacheGroup(grpId);
if (isNull(grpCtx) || integrityCheckResults.containsKey(grpId))
continue;
for (GridDhtLocalPartition part : grpCtx.topology().localPartitions()) partArgs.add(new T2<>(grpCtx, part));
for (GridCacheContext ctx : grpCtx.caches()) {
String cacheName = ctx.name();
if (cacheNames == null || cacheNames.contains(cacheName)) {
Collection<GridQueryTypeDescriptor> types = qryProcessor.types(cacheName);
if (F.isEmpty(types))
continue;
for (GridQueryTypeDescriptor type : types) {
GridH2Table gridH2Tbl = h2Indexing.schemaManager().dataTable(cacheName, type.tableName());
if (isNull(gridH2Tbl))
continue;
for (Index idx : gridH2Tbl.getIndexes()) {
if (idx instanceof H2TreeIndexBase)
idxArgs.add(new T2<>(ctx, idx));
}
}
}
}
}
// To decrease contention on same indexes.
shuffle(partArgs);
shuffle(idxArgs);
totalPartitions = partArgs.size();
totalIndexes = idxArgs.size();
List<Future<Map<PartitionKey, ValidateIndexesPartitionResult>>> procPartFutures = new ArrayList<>(partArgs.size());
List<Future<Map<String, ValidateIndexesPartitionResult>>> procIdxFutures = new ArrayList<>(idxArgs.size());
List<T3<CacheGroupContext, GridDhtLocalPartition, Future<CacheSize>>> cacheSizeFutures = new ArrayList<>(partArgs.size());
List<T3<GridCacheContext, Index, Future<T2<Throwable, Long>>>> idxSizeFutures = new ArrayList<>(idxArgs.size());
partArgs.forEach(k -> procPartFutures.add(processPartitionAsync(k.get1(), k.get2())));
idxArgs.forEach(k -> procIdxFutures.add(processIndexAsync(k, idleChecker)));
if (checkSizes) {
for (T2<CacheGroupContext, GridDhtLocalPartition> partArg : partArgs) {
CacheGroupContext cacheGrpCtx = partArg.get1();
GridDhtLocalPartition locPart = partArg.get2();
cacheSizeFutures.add(new T3<>(cacheGrpCtx, locPart, calcCacheSizeAsync(cacheGrpCtx, locPart)));
}
for (T2<GridCacheContext, Index> idxArg : idxArgs) {
GridCacheContext cacheCtx = idxArg.get1();
Index idx = idxArg.get2();
idxSizeFutures.add(new T3<>(cacheCtx, idx, calcIndexSizeAsync(cacheCtx, idx, idleChecker)));
}
}
Map<PartitionKey, ValidateIndexesPartitionResult> partResults = new HashMap<>();
Map<String, ValidateIndexesPartitionResult> idxResults = new HashMap<>();
Map<String, ValidateIndexesCheckSizeResult> checkSizeResults = new HashMap<>();
int curPart = 0;
int curIdx = 0;
int curCacheSize = 0;
int curIdxSize = 0;
try {
for (; curPart < procPartFutures.size(); curPart++) {
Future<Map<PartitionKey, ValidateIndexesPartitionResult>> fut = procPartFutures.get(curPart);
Map<PartitionKey, ValidateIndexesPartitionResult> partRes = fut.get();
if (!partRes.isEmpty() && partRes.entrySet().stream().anyMatch(e -> !e.getValue().issues().isEmpty()))
partResults.putAll(partRes);
}
for (; curIdx < procIdxFutures.size(); curIdx++) {
Future<Map<String, ValidateIndexesPartitionResult>> fut = procIdxFutures.get(curIdx);
Map<String, ValidateIndexesPartitionResult> idxRes = fut.get();
if (!idxRes.isEmpty() && idxRes.entrySet().stream().anyMatch(e -> !e.getValue().issues().isEmpty()))
idxResults.putAll(idxRes);
}
if (checkSizes) {
for (; curCacheSize < cacheSizeFutures.size(); curCacheSize++) cacheSizeFutures.get(curCacheSize).get3().get();
for (; curIdxSize < idxSizeFutures.size(); curIdxSize++) idxSizeFutures.get(curIdxSize).get3().get();
checkSizes(cacheSizeFutures, idxSizeFutures, checkSizeResults);
Map<Integer, Map<Integer, PartitionUpdateCounter>> partsWithCntrsPerGrpAfterChecks = getUpdateCountersSnapshot(ignite, grpIds);
List<Integer> diff = compareUpdateCounters(ignite, partsWithCntrsPerGrp, partsWithCntrsPerGrpAfterChecks);
if (!F.isEmpty(diff)) {
String res = formatUpdateCountersDiff(ignite, diff);
if (!res.isEmpty())
throw new GridNotIdleException(GRID_NOT_IDLE_MSG + "[" + res + "]");
}
}
log.warning("ValidateIndexesClosure finished: processed " + totalPartitions + " partitions and " + totalIndexes + " indexes.");
} catch (InterruptedException | ExecutionException e) {
for (int j = curPart; j < procPartFutures.size(); j++) procPartFutures.get(j).cancel(false);
for (int j = curIdx; j < procIdxFutures.size(); j++) procIdxFutures.get(j).cancel(false);
for (int j = curCacheSize; j < cacheSizeFutures.size(); j++) cacheSizeFutures.get(j).get3().cancel(false);
for (int j = curIdxSize; j < idxSizeFutures.size(); j++) idxSizeFutures.get(j).get3().cancel(false);
throw unwrapFutureException(e);
}
if (validateCtx.isCancelled())
throw new IgniteException(CANCELLED_MSG);
return new VisorValidateIndexesJobResult(partResults, idxResults, integrityCheckResults.values(), checkSizeResults);
}
Aggregations