This is an automated email from the ASF dual-hosted git repository.

thomasm pushed a commit to branch OAK-11534
in repository https://gitbox.apache.org/repos/asf/jackrabbit-oak.git

commit c30991d45d31d3964c144c75aecd2c3db7c4455e
Author: Thomas Mueller <thom...@apache.org>
AuthorDate: Fri Feb 28 15:38:55 2025 +0100

    OAK-11534 Auto-merge indexes if string matches single-value array
---
 .../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},

Reply via email to