This is an automated email from the ASF dual-hosted git repository.
nfsantos pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/jackrabbit-oak.git
The following commit(s) were added to refs/heads/trunk by this push:
new dde6148344 OAK-11764 - Query planner: when multiple indexes have same
cost, planner should choose index deterministically (#2349)
dde6148344 is described below
commit dde6148344c448c8cb77a7e870aed2c4f9adb630
Author: Nuno Santos <[email protected]>
AuthorDate: Wed Jun 25 10:29:54 2025 +0200
OAK-11764 - Query planner: when multiple indexes have same cost, planner
should choose index deterministically (#2349)
---
.../jackrabbit/oak/plugins/index/IndexName.java | 2 +-
.../org/apache/jackrabbit/oak/query/QueryImpl.java | 3 +-
.../index/lucene/LuceneIndexInfoProviderTest.java | 4 +--
.../index/lucene/LuceneIndexLookupTest.java | 8 ++---
.../index/lucene/LucenePropertyIndexTest.java | 34 ++++++++++++++++++++--
5 files changed, 40 insertions(+), 11 deletions(-)
diff --git
a/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexName.java
b/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexName.java
index 6ad2005a56..3597079d28 100644
---
a/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexName.java
+++
b/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexName.java
@@ -210,7 +210,7 @@ public class IndexName implements Comparable<IndexName> {
* @return the filtered list
*/
public static Collection<String> filterReplacedIndexes(Collection<String>
indexPaths, NodeState rootState, boolean checkIsActive) {
- HashMap<String, IndexName> latestVersions = new HashMap<String,
IndexName>();
+ HashMap<String, IndexName> latestVersions = new HashMap<>();
for (String p : indexPaths) {
IndexName indexName = IndexName.parse(p);
if (indexName.isVersioned && checkIsActive) {
diff --git
a/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryImpl.java
b/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryImpl.java
index 397e1c201b..35ada0ad68 100644
--- a/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryImpl.java
+++ b/oak-core/src/main/java/org/apache/jackrabbit/oak/query/QueryImpl.java
@@ -1132,7 +1132,8 @@ public class QueryImpl implements Query {
String msg = String.format("cost for [%s] of type (%s)
with plan [%s] is %1.2f", p.getPlanName(), indexName, plan, c);
logDebug(msg);
}
- if (c < bestCost) {
+ // In case of cost being the same, chose the index with
the lowest name by alphabetic order
+ if (c < bestCost || (c == bestCost && bestPlan != null &&
p.getPlanName().compareTo(bestPlan.getPlanName()) < 0 )) {
almostBestCost = bestCost;
almostBestIndex = bestIndex;
almostBestPlan = bestPlan;
diff --git
a/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexInfoProviderTest.java
b/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexInfoProviderTest.java
index 3dc6c61812..275be4b660 100644
---
a/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexInfoProviderTest.java
+++
b/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexInfoProviderTest.java
@@ -43,8 +43,8 @@ public class LuceneIndexInfoProviderTest {
@Rule
public final TemporaryFolder temporaryFolder = new TemporaryFolder(new
File("target"));
- private NodeStore store = new MemoryNodeStore();
- private AsyncIndexInfoService asyncService =
mock(AsyncIndexInfoService.class);
+ private final NodeStore store = new MemoryNodeStore();
+ private final AsyncIndexInfoService asyncService =
mock(AsyncIndexInfoService.class);
private LuceneIndexInfoProvider provider;
@Before
diff --git
a/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexLookupTest.java
b/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexLookupTest.java
index af486e9bba..e360a8d89e 100644
---
a/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexLookupTest.java
+++
b/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LuceneIndexLookupTest.java
@@ -35,12 +35,12 @@ import static
org.apache.jackrabbit.oak.InitialContentHelper.INITIAL_CONTENT;
import static org.junit.Assert.assertEquals;
public class LuceneIndexLookupTest {
- private NodeState root = INITIAL_CONTENT;
+ private final NodeState root = INITIAL_CONTENT;
- private NodeBuilder builder = root.builder();
+ private final NodeBuilder builder = root.builder();
@Test
- public void collectPathOnRootNode() throws Exception{
+ public void collectPathOnRootNode() {
NodeBuilder index = builder.child(INDEX_DEFINITIONS_NAME);
newLuceneIndexDefinition(index, "l1", Set.of(TYPENAME_STRING));
newLuceneIndexDefinition(index, "l2", Set.of(TYPENAME_STRING));
@@ -53,7 +53,7 @@ public class LuceneIndexLookupTest {
}
@Test
- public void collectPathOnSubNode() throws Exception{
+ public void collectPathOnSubNode() {
NodeBuilder index = builder.child(INDEX_DEFINITIONS_NAME);
newLuceneIndexDefinition(index, "l1", Set.of(TYPENAME_STRING));
diff --git
a/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LucenePropertyIndexTest.java
b/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LucenePropertyIndexTest.java
index bc7edbb592..53dd4e788c 100644
---
a/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LucenePropertyIndexTest.java
+++
b/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LucenePropertyIndexTest.java
@@ -317,7 +317,7 @@ public class LucenePropertyIndexTest extends
AbstractQueryTest {
public void declaringNodeTypeSameProp() throws Exception {
createIndex("test1", Set.of("propa"));
- Tree indexWithType = createIndex("test2", Set.of("propa"));
+ Tree indexWithType = createIndex("atest2", Set.of("propa"));
indexWithType.setProperty(PropertyStates
.createProperty(DECLARING_NODE_TYPES,
Set.of("nt:unstructured"),
Type.STRINGS));
@@ -339,7 +339,7 @@ public class LucenePropertyIndexTest extends
AbstractQueryTest {
root.commit();
String propabQuery = "select [jcr:path] from [nt:unstructured] where
[propa] = 'foo'";
- assertThat(explain(propabQuery), containsString("lucene:test2"));
+ assertThat(explain(propabQuery), containsString("lucene:atest2"));
assertQuery(propabQuery, List.of("/test/a", "/test/b"));
String propcdQuery = "select [jcr:path] from [nt:base] where [propa] =
'foo'";
@@ -347,6 +347,34 @@ public class LucenePropertyIndexTest extends
AbstractQueryTest {
assertQuery(propcdQuery, List.of("/test/a", "/test/b", "/test/c",
"/test/d"));
}
+
+ @Test
+ public void selectLowerAlphabeticOrderWhenSameCost() throws Exception {
+ createIndex("test3", Set.of("propa"));
+ createIndex("test1", Set.of("propa"));
+ createIndex("test2", Set.of("propa"));
+
+ Tree test = root.getTree("/").addChild("test");
+ test.setProperty("jcr:primaryType", "nt:unstructured", Type.NAME);
+ root.commit();
+
+ Tree a = test.addChild("a");
+ a.setProperty("jcr:primaryType", "nt:unstructured", Type.NAME);
+ a.setProperty("propa", "foo");
+ Tree b = test.addChild("b");
+ b.setProperty("jcr:primaryType", "nt:unstructured", Type.NAME);
+ b.setProperty("propa", "foo");
+
+ test.addChild("c").setProperty("propa", "foo");
+ test.addChild("d").setProperty("propa", "foo");
+
+ root.commit();
+
+ String propabQuery = "select [jcr:path] from [nt:unstructured] where
[propa] = 'foo'";
+ assertThat(explain(propabQuery), containsString("lucene:test1"));
+ assertQuery(propabQuery, List.of("/test/a", "/test/b"));
+ }
+
@Test
public void declaringNodeTypeSingleIndex() throws Exception {
Tree indexWithType = createIndex("test2", Set.of("propa", "propb"));
@@ -2064,7 +2092,7 @@ public class LucenePropertyIndexTest extends
AbstractQueryTest {
s.append("foo bar ").append(k).append(" ");
}
String text = s.toString();
- List<String> names = new LinkedList<String>();
+ List<String> names = new LinkedList<>();
for (int j = 0; j < 30; j++) {
Tree test = root.getTree("/").addChild("ex-test-" + j);
for (int i = 0; i < 100; i++) {