Skip to content

Commit

Permalink
Fix usage of indexes with CONTAINSTEXT in SQL
Browse files Browse the repository at this point in the history
Resolves: #8693
  • Loading branch information
luigidellaquila committed Apr 10, 2019
1 parent 937b9eb commit 7d3fc99
Show file tree
Hide file tree
Showing 3 changed files with 113 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,8 @@ private void init(OCollection fromKey, boolean fromKeyIncluded, OCollection toKe

} else if (additionalRangeCondition == null && allEqualities((OAndBlock) condition)) {
cursor = index.iterateEntries(toIndexKey(indexDef, secondValue), isOrderAsc());
} else if (isFullTextIndex(index)) {
cursor = index.iterateEntries(toIndexKey(indexDef, secondValue), isOrderAsc());
} else {
throw new UnsupportedOperationException("Cannot evaluate " + this.condition + " on index " + index);
}
Expand All @@ -408,6 +410,10 @@ private void init(OCollection fromKey, boolean fromKeyIncluded, OCollection toKe
}
}

private boolean isFullTextIndex(OIndex index) {
return index.getType().equalsIgnoreCase("FULLTEXT") && !index.getAlgorithm().equalsIgnoreCase("LUCENE");
}

private OIndexCursor getCursorForNullKey() {
Object result = index.get(null);

Expand All @@ -432,7 +438,7 @@ public OIdentifiable next() {

@Override
public Map.Entry<Object, OIdentifiable> nextEntry() {
if(!iter.hasNext()){
if (!iter.hasNext()) {
return null;
}
Object val = iter.next();
Expand Down Expand Up @@ -727,6 +733,13 @@ private OCollection indexKeyFrom(OAndBlock keyCondition, OBinaryCondition additi
throw new UnsupportedOperationException("Cannot execute index query with " + exp);
}

}else if (exp instanceof OContainsTextCondition) {
if (((OContainsTextCondition) exp).getRight() != null) {
result.add(((OContainsTextCondition) exp).getRight());
} else {
throw new UnsupportedOperationException("Cannot execute index query with " + exp);
}

} else {
throw new UnsupportedOperationException("Cannot execute index query with " + exp);
}
Expand Down Expand Up @@ -767,6 +780,8 @@ private OCollection indexKeyTo(OAndBlock keyCondition, OBinaryCondition addition
throw new UnsupportedOperationException("Cannot execute index query with " + exp);
}

} else if (exp instanceof OContainsTextCondition) {
result.add(((OContainsTextCondition) exp).getRight());
} else {
throw new UnsupportedOperationException("Cannot execute index query with " + exp);
}
Expand Down Expand Up @@ -796,6 +811,8 @@ private boolean indexKeyFromIncluded(OAndBlock keyCondition, OBinaryCondition ad
} else {
return false;
}
} else if (exp instanceof OContainsTextCondition){
return true;
} else {
throw new UnsupportedOperationException("Cannot execute index query with " + exp);
}
Expand Down Expand Up @@ -844,7 +861,9 @@ private boolean indexKeyToIncluded(OAndBlock keyCondition, OBinaryCondition addi
} else {
return false;
}
} else {
} else if(exp instanceof OContainsTextCondition){
return true;
}else {
throw new UnsupportedOperationException("Cannot execute index query with " + exp);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2157,6 +2157,15 @@ private IndexSearchDescriptor findBestIndexFor(OCommandContext ctx, Set<OIndex<?
.map(index -> buildIndexSearchDescriptor(ctx, index, block, clazz)).filter(Objects::nonNull)
.filter(x -> x.keyCondition != null).filter(x -> x.keyCondition.getSubBlocks().size() > 0).collect(Collectors.toList());

List<IndexSearchDescriptor> fullTextIndexDescriptors = indexes.stream()
.filter(idx->idx.getType().equalsIgnoreCase("FULLTEXT"))
.filter(idx->!idx.getAlgorithm().equalsIgnoreCase("LUCENE"))
.map(idx -> buildIndexSearchDescriptorForFulltext(ctx, idx, block, clazz)).filter(Objects::nonNull)
.filter(x -> x.keyCondition != null).filter(x -> x.keyCondition.getSubBlocks().size() > 0).collect(Collectors.toList());

descriptors.addAll(fullTextIndexDescriptors);


//remove the redundant descriptors (eg. if I have one on [a] and one on [a, b], the first one is redundant, just discard it)
descriptors = removePrefixIndexes(descriptors);

Expand Down Expand Up @@ -2418,6 +2427,73 @@ && isMap(clazz, indexField) && isIndexByValue(index, indexField)) {
return null;
}


/**
* given a full text index and a flat AND block, returns a descriptor on how to process it with an index (index, index key and additional
* filters to apply after index fetch
*
* @param ctx
* @param index
* @param block
* @param clazz
*
* @return
*/
private IndexSearchDescriptor buildIndexSearchDescriptorForFulltext(OCommandContext ctx, OIndex<?> index, OAndBlock block, OClass clazz) {
List<String> indexFields = index.getDefinition().getFields();
OBinaryCondition keyCondition = new OBinaryCondition(-1);
OIdentifier key = new OIdentifier("key");
keyCondition.setLeft(new OExpression(key));
boolean found = false;

OAndBlock blockCopy = block.copy();
Iterator<OBooleanExpression> blockIterator;

OAndBlock indexKeyValue = new OAndBlock(-1);
IndexSearchDescriptor result = new IndexSearchDescriptor();
result.idx = index;
result.keyCondition = indexKeyValue;
for (String indexField : indexFields) {
blockIterator = blockCopy.getSubBlocks().iterator();
boolean breakHere = false;
boolean indexFieldFound = false;
while (blockIterator.hasNext()) {
OBooleanExpression singleExp = blockIterator.next();
if (singleExp instanceof OContainsTextCondition) {
OExpression left = ((OContainsTextCondition) singleExp).getLeft();
if (left.isBaseIdentifier()) {
String fieldName = left.getDefaultAlias().getStringValue();
if (indexField.equals(fieldName)) {
found = true;
indexFieldFound = true;
OContainsTextCondition condition = new OContainsTextCondition(-1);
condition.setLeft(left);
condition.setRight(((OContainsTextCondition) singleExp).getRight().copy());
indexKeyValue.getSubBlocks().add(condition);
blockIterator.remove();
break;
}
}
}
}
if (breakHere || !indexFieldFound) {
break;
}
}

if (result.keyCondition.getSubBlocks().size() < index.getDefinition().getFields().size() && !index
.supportsOrderedIterations()) {
//hash indexes do not support partial key match
return null;
}

if (found) {
result.remainingCondition = blockCopy;
return result;
}
return null;
}

private boolean isIndexByKey(OIndex<?> index, String field) {
OIndexDefinition def = index.getDefinition();
for (String o : def.getFieldsToIndex()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -174,5 +174,21 @@ public boolean isCacheable() {
}
return true;
}

public void setLeft(OExpression left) {
this.left = left;
}

public void setRight(OExpression right) {
this.right = right;
}

public OExpression getLeft() {
return left;
}

public OExpression getRight() {
return right;
}
}
/* JavaCC - OriginalChecksum=b588492ba2cbd0f932055f1f64bbbecd (do not edit this line) */

0 comments on commit 7d3fc99

Please sign in to comment.