This is an automated email from the ASF dual-hosted git repository.
thomasm 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 9c78ef283b OAK-11534 Auto-merge indexes if string matches single-value
array (#2124)
9c78ef283b is described below
commit 9c78ef283bf895bddf2187b646a5432276cb1e71
Author: Thomas Mueller <[email protected]>
AuthorDate: Fri Feb 28 17:44:31 2025 +0100
OAK-11534 Auto-merge indexes if string matches single-value array (#2124)
---
.../oak/index/merge/IndexDefMergerUtils.java | 37 ++++++++++++++++++++++
.../oak/index/merge/IndexDefMergerTest.java | 28 +++++++++++++++-
.../apache/jackrabbit/oak/index/merge/merge.txt | 7 ++++
3 files changed, 71 insertions(+), 1 deletion(-)
diff --git
a/oak-run/src/main/java/org/apache/jackrabbit/oak/index/merge/IndexDefMergerUtils.java
b/oak-run/src/main/java/org/apache/jackrabbit/oak/index/merge/IndexDefMergerUtils.java
index 3736e3c7ea..aade3856e3 100644
---
a/oak-run/src/main/java/org/apache/jackrabbit/oak/index/merge/IndexDefMergerUtils.java
+++
b/oak-run/src/main/java/org/apache/jackrabbit/oak/index/merge/IndexDefMergerUtils.java
@@ -31,6 +31,8 @@ import java.util.stream.Collectors;
import org.apache.jackrabbit.oak.commons.json.JsonObject;
import org.apache.jackrabbit.oak.commons.json.JsopBuilder;
+import org.apache.jackrabbit.oak.commons.json.JsopReader;
+import org.apache.jackrabbit.oak.commons.json.JsopTokenizer;
import org.apache.jackrabbit.oak.plugins.index.IndexName;
/**
@@ -148,6 +150,8 @@ public class IndexDefMergerUtils {
return cp;
} else if (Objects.equals(ap, cp)) {
return pp;
+ } else if (equalStringValues(ap, cp)) {
+ return pp;
} else {
conflicts.add("Could not merge value; path=" + path + " property="
+ property + "; ancestor=" + ap + "; custom=" + cp
+ "; product=" + pp);
@@ -155,6 +159,39 @@ public class IndexDefMergerUtils {
}
}
+ public static boolean equalStringValues(String a, String b) {
+ String aa = getStringOrStringFromSingleValueArray(a);
+ String bb = getStringOrStringFromSingleValueArray(b);
+ if (aa == null || bb == null) {
+ // a or b are not strings or single-valued array of strings
+ return false;
+ }
+ return Objects.equals(aa, bb);
+ }
+
+ public static String getStringOrStringFromSingleValueArray(String value) {
+ if (value == null) {
+ return null;
+ }
+ JsopTokenizer tokenizer = new JsopTokenizer(value);
+ if (tokenizer.matches(JsopReader.STRING)) {
+ return tokenizer.getEscapedToken();
+ }
+ if (!tokenizer.matches('[')) {
+ return null;
+ }
+ if (!tokenizer.matches(JsopReader.STRING)) {
+ // not a string
+ return null;
+ }
+ String jsonString = tokenizer.getEscapedToken();
+ if (!tokenizer.matches(']')) {
+ // not a single-element array
+ return null;
+ }
+ return jsonString;
+ }
+
private static JsonObject mergeChild(String path, String child, int level,
JsonObject ancestor, JsonObject custom, JsonObject product,
ArrayList<String> conflicts) {
JsonObject a = ancestor.getChildren().get(child);
diff --git
a/oak-run/src/test/java/org/apache/jackrabbit/oak/index/merge/IndexDefMergerTest.java
b/oak-run/src/test/java/org/apache/jackrabbit/oak/index/merge/IndexDefMergerTest.java
index 952cca3042..7a71b1f65e 100644
---
a/oak-run/src/test/java/org/apache/jackrabbit/oak/index/merge/IndexDefMergerTest.java
+++
b/oak-run/src/test/java/org/apache/jackrabbit/oak/index/merge/IndexDefMergerTest.java
@@ -19,6 +19,8 @@
package org.apache.jackrabbit.oak.index.merge;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
import java.io.IOException;
import java.io.InputStreamReader;
@@ -35,11 +37,35 @@ import org.junit.Test;
*/
public class IndexDefMergerTest {
+ @Test
+ public void compareStringAndSingleValueArray() {
+ assertEquals(null,
IndexDefMergerUtils.getStringOrStringFromSingleValueArray(null));
+ assertEquals(null,
IndexDefMergerUtils.getStringOrStringFromSingleValueArray("1"));
+ assertEquals(null,
IndexDefMergerUtils.getStringOrStringFromSingleValueArray("[\"a\",2]"));
+ assertEquals(null,
IndexDefMergerUtils.getStringOrStringFromSingleValueArray("[\"a\",null]"));
+ assertEquals(null,
IndexDefMergerUtils.getStringOrStringFromSingleValueArray("[1]"));
+ assertEquals("",
IndexDefMergerUtils.getStringOrStringFromSingleValueArray("\"\""));
+ assertEquals("a",
IndexDefMergerUtils.getStringOrStringFromSingleValueArray("\"a\""));
+ assertEquals("a",
IndexDefMergerUtils.getStringOrStringFromSingleValueArray("[\"a\"]"));
+ assertTrue(IndexDefMergerUtils.equalStringValues("[\"a\"]",
"[\"a\"]"));
+ assertTrue(IndexDefMergerUtils.equalStringValues("[\"a\"]", "\"a\""));
+ assertTrue(IndexDefMergerUtils.equalStringValues("\"a\"", "[\"a\"]"));
+ assertTrue(IndexDefMergerUtils.equalStringValues("\"a\"", "\"a\""));
+ assertFalse(IndexDefMergerUtils.equalStringValues("\"a\"", "\"b\""));
+ assertFalse(IndexDefMergerUtils.equalStringValues("1", "1"));
+ assertFalse(IndexDefMergerUtils.equalStringValues("1", "2"));
+ assertFalse(IndexDefMergerUtils.equalStringValues(null, null));
+ assertFalse(IndexDefMergerUtils.equalStringValues("1", null));
+ assertFalse(IndexDefMergerUtils.equalStringValues(null, "1"));
+ assertFalse(IndexDefMergerUtils.equalStringValues("\"1\"", "1"));
+ assertFalse(IndexDefMergerUtils.equalStringValues("1", "\"1\""));
+ }
+
@Test
public void merge() throws IOException, CommitFailedException {
String s = readFromResource("merge.txt");
JsonObject json = JsonObject.fromJson(s, true);
- for(JsonObject e : array(json.getProperties().get("tests"))) {
+ for (JsonObject e : array(json.getProperties().get("tests"))) {
merge(e);
}
}
diff --git
a/oak-run/src/test/resources/org/apache/jackrabbit/oak/index/merge/merge.txt
b/oak-run/src/test/resources/org/apache/jackrabbit/oak/index/merge/merge.txt
index a6dc62ac44..b767cdeb20 100644
--- a/oak-run/src/test/resources/org/apache/jackrabbit/oak/index/merge/merge.txt
+++ b/oak-run/src/test/resources/org/apache/jackrabbit/oak/index/merge/merge.txt
@@ -1,5 +1,12 @@
{"tests":
[
+{
+ "ancestor": {"includedPaths": ["/content/a"]},
+ "custom": {"includedPaths": "/content/a"},
+ "product": {"includedPaths": ["/content/a", "/content/b"]},
+ "expected": {"includedPaths": ["/content/a", "/content/b"], "merges":
["/oak:index/test-2", "/oak:index/test-1-custom-1"]
+ }
+},
{
"ancestor": {"value": 1, "a-old": 0},
"custom": {"value": 2, "b-new": 3},