use of org.apache.ignite.internal.cache.query.index.sorted.keys.IndexKey in project ignite by apache.
the class InlineObjectBytesDetector method apply.
/**
* {@inheritDoc}
*/
@Override
public boolean apply(BPlusTree<IndexRow, IndexRow> tree, BPlusIO<IndexRow> io, long pageAddr, int idx) throws IgniteCheckedException {
IndexRow r = tree.getRow(io, pageAddr, idx);
int off = io.offset(idx);
int fieldOff = 0;
boolean varLenPresents = false;
IndexKeyTypeSettings keyTypeSettings = new IndexKeyTypeSettings();
Iterator<IndexKeyDefinition> it = keyDefs.iterator();
for (int i = 0; i < keyDefs.size(); ++i) {
IndexKeyDefinition keyDef = it.next();
if (fieldOff >= inlineSize)
return false;
if (keyDef.idxType() != IndexKeyTypes.JAVA_OBJECT) {
InlineIndexKeyType keyType = InlineIndexKeyTypeRegistry.get(keyDef.idxType(), keyTypeSettings);
if (keyType.inlineSize() < 0)
varLenPresents = true;
fieldOff += keyType.inlineSize(pageAddr, off + fieldOff);
continue;
}
IndexKey key = r.key(i);
if (key == NullIndexKey.INSTANCE)
return false;
int type = PageUtils.getByte(pageAddr, off + fieldOff);
// We can have garbage in memory and need to compare data.
if (type == IndexKeyTypes.JAVA_OBJECT) {
int len = PageUtils.getShort(pageAddr, off + fieldOff + 1);
len &= 0x7FFF;
byte[] originalObjBytes = ((JavaObjectIndexKey) key).bytesNoCopy();
// Read size more then available space or more then origin length.
if (len > inlineSize - fieldOff - 3 || len > originalObjBytes.length) {
inlineObjectSupportedDecision(false, "length is big " + len);
return true;
}
// Try compare byte by byte for fully or partial inlined object.
byte[] inlineBytes = PageUtils.getBytes(pageAddr, off + fieldOff + 3, len);
if (!Arrays.equals(inlineBytes, originalObjBytes)) {
inlineObjectSupportedDecision(false, "byte compare");
return true;
}
inlineObjectSupportedDecision(true, len + " bytes compared");
return true;
}
if (type == IndexKeyTypes.UNKNOWN && varLenPresents) {
// 2: short string, inlined java object
return false;
}
inlineObjectSupportedDecision(false, "inline type " + type);
return true;
}
inlineObjectSupportedDecision(true, "no java objects for inlining");
return true;
}
use of org.apache.ignite.internal.cache.query.index.sorted.keys.IndexKey in project ignite by apache.
the class NullableInlineIndexKeyType method get.
/**
* Restores value from inline, if possible.
*
* @param pageAddr Address of the page.
* @param off Offset on the page.
* @param maxSize Max size to read.
*
* @return Restored value or {@code null} if value can't be restored.
*/
@Override
public IndexKey get(long pageAddr, int off, int maxSize) {
if (keySize > 0 && keySize + 1 > maxSize)
return null;
if (maxSize < 1)
return null;
int type = PageUtils.getByte(pageAddr, off);
if (type == IndexKeyTypes.UNKNOWN)
return null;
if (type == IndexKeyTypes.NULL)
return NullIndexKey.INSTANCE;
ensureKeyType(type);
IndexKey o = get0(pageAddr, off);
if (o == null)
return NullIndexKey.INSTANCE;
return o;
}
use of org.apache.ignite.internal.cache.query.index.sorted.keys.IndexKey in project ignite by apache.
the class InlineIndexColumnTest method testPutGet.
/**
*/
private void testPutGet(Value v1, Value v2, Value v3) throws Exception {
DataRegionConfiguration plcCfg = new DataRegionConfiguration().setInitialSize(1024 * MB).setMaxSize(1024 * MB);
PageMemory pageMem = new PageMemoryNoStoreImpl(log, new UnsafeMemoryProvider(log), null, PAGE_SIZE, plcCfg, new DataRegionMetricsImpl(plcCfg, new GridTestKernalContext(log())), false);
pageMem.start();
long pageId = 0L;
long page = 0L;
try {
pageId = pageMem.allocatePage(CACHE_ID, 1, PageIdAllocator.FLAG_DATA);
page = pageMem.acquirePage(CACHE_ID, pageId);
long pageAddr = pageMem.readLock(CACHE_ID, pageId, page);
int off = 0;
int max = 255;
IndexKeyTypeSettings keyTypeSettings = new IndexKeyTypeSettings().inlineObjHash(false).stringOptimizedCompare(false);
InlineIndexKeyType keyType = InlineIndexKeyTypeRegistry.get(v1.getType(), keyTypeSettings);
off += keyType.put(pageAddr, off, idxKey(v1), max - off);
off += keyType.put(pageAddr, off, idxKey(v2), max - off);
off += keyType.put(pageAddr, off, idxKey(v3), max - off);
IndexKey v11 = keyType.get(pageAddr, 0, max);
IndexKey v22 = keyType.get(pageAddr, keyType.inlineSize(pageAddr, 0), max);
assertEquals(v1.getObject(), v11.key());
assertEquals(v2.getObject(), v22.key());
assertEquals(0, keyType.compare(pageAddr, 0, max, idxKey(v1)));
} finally {
if (page != 0L)
pageMem.releasePage(CACHE_ID, pageId, page);
pageMem.stop(true);
}
}
use of org.apache.ignite.internal.cache.query.index.sorted.keys.IndexKey in project ignite by apache.
the class IndexQueryProcessor method mergeIndexQueryCriteria.
/**
* Merges multiple criteria for the same field into single criterion.
*/
private Map<String, RangeIndexQueryCriterion> mergeIndexQueryCriteria(InlineIndexImpl idx, SortedIndexDefinition idxDef, IndexQueryDesc idxQryDesc) throws IgniteCheckedException {
Map<String, RangeIndexQueryCriterion> mergedCriteria = new HashMap<>();
Map<String, IndexKeyDefinition> idxFlds = idxDef.indexKeyDefinitions();
IndexKeyTypeSettings keyTypeSettings = idx.segment(0).rowHandler().indexKeyTypeSettings();
CacheObjectContext coctx = idx.segment(0).cacheGroupContext().cacheObjectContext();
IndexRowComparator keyCmp = idxDef.rowComparator();
for (IndexQueryCriterion c : idxQryDesc.criteria()) {
RangeIndexQueryCriterion crit = (RangeIndexQueryCriterion) c;
String fldName = idxFlds.containsKey(crit.field()) ? crit.field() : QueryUtils.normalizeObjectName(crit.field(), false);
IndexKeyDefinition keyDef = idxFlds.get(fldName);
if (keyDef == null)
throw failIndexQuery("Index doesn't match criteria", idxDef, idxQryDesc);
IndexKey l = key(crit.lower(), crit.lowerNull(), keyDef, keyTypeSettings, coctx);
IndexKey u = key(crit.upper(), crit.upperNull(), keyDef, keyTypeSettings, coctx);
if (l != null && u != null && keyCmp.compareKey(l, u) > 0) {
throw failIndexQuery("Illegal criterion: lower boundary is greater than the upper boundary: " + rangeDesc(crit, fldName, null, null), idxDef, idxQryDesc);
}
boolean lowIncl = crit.lowerIncl();
boolean upIncl = crit.upperIncl();
boolean lowNull = crit.lowerNull();
boolean upNull = crit.upperNull();
if (mergedCriteria.containsKey(fldName)) {
RangeIndexQueryCriterion prev = mergedCriteria.get(fldName);
IndexKey prevLower = (IndexKey) prev.lower();
IndexKey prevUpper = (IndexKey) prev.upper();
// Validate merged criteria.
if (!checkBoundaries(l, prevUpper, crit.lowerIncl(), prev.upperIncl(), keyCmp) || !checkBoundaries(prevLower, u, prev.lowerIncl(), crit.upperIncl(), keyCmp)) {
String prevDesc = rangeDesc(prev, null, prevLower == null ? null : prevLower.key(), prevUpper == null ? null : prevUpper.key());
throw failIndexQuery("Failed to merge criterion " + rangeDesc(crit, fldName, null, null) + " with previous criteria range " + prevDesc, idxDef, idxQryDesc);
}
int lowCmp = 0;
// Use previous lower boudary, as it's greater than the current.
if (l == null || (prevLower != null && (lowCmp = keyCmp.compareKey(prevLower, l)) >= 0)) {
l = prevLower;
lowIncl = lowCmp != 0 ? prev.lowerIncl() : prev.lowerIncl() ? lowIncl : prev.lowerIncl();
lowNull = prev.lowerNull();
}
int upCmp = 0;
// Use previous upper boudary, as it's less than the current.
if (u == null || (prevUpper != null && (upCmp = keyCmp.compareKey(prevUpper, u)) <= 0)) {
u = prevUpper;
upIncl = upCmp != 0 ? prev.upperIncl() : prev.upperIncl() ? upIncl : prev.upperIncl();
upNull = prev.upperNull();
}
}
RangeIndexQueryCriterion idxKeyCrit = new RangeIndexQueryCriterion(fldName, l, u);
idxKeyCrit.lowerIncl(lowIncl);
idxKeyCrit.upperIncl(upIncl);
idxKeyCrit.lowerNull(lowNull);
idxKeyCrit.upperNull(upNull);
mergedCriteria.put(fldName, idxKeyCrit);
}
return mergedCriteria;
}
use of org.apache.ignite.internal.cache.query.index.sorted.keys.IndexKey in project ignite by apache.
the class IndexQueryProcessor method alignCriteriaWithIndex.
/**
* Checks that specified index matches index query criteria.
*/
private IndexRangeQuery alignCriteriaWithIndex(InlineIndexImpl idx, Map<String, RangeIndexQueryCriterion> criteria, IndexDefinition idxDef) {
// Size of bounds array has to be equal to count of indexed fields.
IndexKey[] lowerBounds = new IndexKey[idxDef.indexKeyDefinitions().size()];
IndexKey[] upperBounds = new IndexKey[idxDef.indexKeyDefinitions().size()];
boolean lowerAllNulls = true;
boolean upperAllNulls = true;
IndexRangeQuery qry = new IndexRangeQuery(criteria.size());
// Checks that users criteria matches a prefix subset of index fields.
int i = 0;
for (Map.Entry<String, IndexKeyDefinition> keyDef : idxDef.indexKeyDefinitions().entrySet()) {
RangeIndexQueryCriterion criterion = criteria.remove(keyDef.getKey());
if (keyDef.getValue().order().sortOrder() == DESC)
criterion = criterion.swap();
qry.criteria[i] = criterion;
IndexKey l = (IndexKey) criterion.lower();
IndexKey u = (IndexKey) criterion.upper();
if (l != null)
lowerAllNulls = false;
if (u != null)
upperAllNulls = false;
lowerBounds[i] = l;
upperBounds[i++] = u;
if (criteria.isEmpty())
break;
}
InlineIndexRowHandler hnd = idx.segment(0).rowHandler();
qry.lower = lowerAllNulls ? null : new IndexSearchRowImpl(lowerBounds, hnd);
qry.upper = upperAllNulls ? null : new IndexSearchRowImpl(upperBounds, hnd);
return qry;
}
Aggregations