Skip to content

Commit

Permalink
fix: use everytime the most specific index when multiple are found
Browse files Browse the repository at this point in the history
  • Loading branch information
tglman committed Jul 3, 2023
1 parent 4d5eced commit 04a7577
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -980,4 +980,8 @@ public void close() {
ViewManager viewManager = sharedContext.getViewManager();
viewManager.endUsingViewIndex(indexName);
}

public String getIndexName() {
return indexName;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2689,6 +2689,8 @@ private IndexSearchDescriptor findBestIndexFor(

descriptors.addAll(fullTextIndexDescriptors);

descriptors = removeGenericIndexes(descriptors, clazz);

// 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 @@ -2721,6 +2723,47 @@ private IndexSearchDescriptor findBestIndexFor(
return descriptors.isEmpty() ? null : descriptors.get(descriptors.size() - 1);
}

/**
* If between the index candidates there are for the same property target class index and super
* class index prefer the target class.
*/
private List<IndexSearchDescriptor> removeGenericIndexes(
List<IndexSearchDescriptor> descriptors, OClass clazz) {
List<IndexSearchDescriptor> results = new ArrayList<>();
for (IndexSearchDescriptor desc : descriptors) {
IndexSearchDescriptor matching = null;
for (IndexSearchDescriptor result : results) {
if (isSameCondition(desc, result)) {
matching = result;
break;
}
}
if (matching != null) {
if (clazz.getName().equals(desc.getIndex().getDefinition().getClassName())) {
results.remove(matching);
results.add(desc);
}
} else {
results.add(desc);
}
}
return results;
}

private boolean isSameCondition(IndexSearchDescriptor item, IndexSearchDescriptor desc) {
List<OBooleanExpression> left = item.getKeyCondition().getSubBlocks();
List<OBooleanExpression> right = desc.getKeyCondition().getSubBlocks();
if (left.size() != right.size()) {
return false;
}
for (int i = 0; i < left.size(); i++) {
if (!left.get(i).equals(right.get(i))) {
return false;
}
}
return true;
}

private List<IndexSearchDescriptor> removePrefixIndexes(List<IndexSearchDescriptor> descriptors) {
List<IndexSearchDescriptor> result = new ArrayList<>();
for (IndexSearchDescriptor desc : descriptors) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1156,6 +1156,50 @@ public void testFetchFromIndex() {
OGlobalConfiguration.INDEX_ALLOW_MANUAL_INDEXES.setValue(oldAllowManual);
}

@Test
public void testFetchFromIndexHierarchy() {
String className = "testFetchFromIndexHierarchy";
OClass clazz = db.getMetadata().getSchema().createClass(className);
clazz.createProperty("name", OType.STRING);
clazz.createIndex(className + ".name", OClass.INDEX_TYPE.NOTUNIQUE, "name");

String classNameExt = "testFetchFromIndexHierarchyExt";
OClass clazzExt = db.getMetadata().getSchema().createClass(classNameExt, clazz);
clazzExt.createIndex(classNameExt + ".name", OClass.INDEX_TYPE.NOTUNIQUE, "name");

for (int i = 0; i < 5; i++) {
ODocument doc = db.newInstance(className);
doc.setProperty("name", "name" + i);
doc.save();
}

for (int i = 5; i < 10; i++) {
ODocument doc = db.newInstance(classNameExt);
doc.setProperty("name", "name" + i);
doc.save();
}

OResultSet result = db.query("select from " + classNameExt + " where name = 'name6'");
printExecutionPlan(result);

Assert.assertTrue(result.hasNext());
OResult next = result.next();
Assert.assertNotNull(next);

Assert.assertFalse(result.hasNext());

Optional<OExecutionPlan> p = result.getExecutionPlan();
Assert.assertTrue(p.isPresent());
OExecutionPlan p2 = p.get();
Assert.assertTrue(p2 instanceof OSelectExecutionPlan);
OSelectExecutionPlan plan = (OSelectExecutionPlan) p2;
Assert.assertEquals(FetchFromIndexStep.class, plan.getSteps().get(0).getClass());

Assert.assertEquals(
((FetchFromIndexStep) plan.getSteps().get(0)).getIndexName(), classNameExt + ".name");
result.close();
}

@Test
public void testFetchFromClassWithIndexes() {
String className = "testFetchFromClassWithIndexes";
Expand Down

0 comments on commit 04a7577

Please sign in to comment.