You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by re...@apache.org on 2015/10/27 12:39:38 UTC

svn commit: r1710789 - in /jackrabbit/oak/trunk/oak-core/src: main/java/org/apache/jackrabbit/oak/plugins/document/ main/java/org/apache/jackrabbit/oak/plugins/document/mongo/ test/java/org/apache/jackrabbit/oak/plugins/document/

Author: reschke
Date: Tue Oct 27 11:39:38 2015
New Revision: 1710789

URL: http://svn.apache.org/viewvc?rev=1710789&view=rev
Log:
OAK-3489: introduce "notEquals" condition in UpdateOp

Modified:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/UpdateOp.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/UpdateUtils.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/mongo/MongoDocumentStore.java
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/BasicDocumentStoreTest.java
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/UpdateOpTest.java
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/UpdateUtilsTest.java

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/UpdateOp.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/UpdateOp.java?rev=1710789&r1=1710788&r2=1710789&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/UpdateOp.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/UpdateOp.java Tue Oct 27 11:39:38 2015
@@ -245,16 +245,26 @@ public final class UpdateOp {
     }
 
     /**
+     * Checks if the property is equal to the given value.
+     *
+     * @param property the name of the property or map.
+     * @param value the value to compare to ({@code null} checks both for non-existence and the value being null)
+     */
+    void equals(@Nonnull String property, @Nullable Object value) {
+        equals(property, null, value);
+    }
+
+    /**
      * Checks if the property or map entry is equal to the given value.
      *
      * @param property the name of the property or map.
      * @param revision the revision within the map or {@code null} if this check
      *                 is for a property.
-     * @param value the value to compare to.
+     * @param value the value to compare to ({@code null} checks both for non-existence and the value being null)
      */
     void equals(@Nonnull String property,
                 @Nullable Revision revision,
-                @Nonnull Object value) {
+                @Nullable Object value) {
         if (isNew) {
             throw new IllegalStateException("Cannot perform equals check on new document");
         }
@@ -263,6 +273,34 @@ public final class UpdateOp {
     }
 
     /**
+     * Checks if the property does not exist or is not equal to the given value.
+     *
+     * @param property the name of the property or map.
+     * @param value the value to compare to.
+     */
+    void notEquals(@Nonnull String property, @Nullable Object value) {
+        notEquals(property, null, value);
+    }
+
+    /**
+     * Checks if the property or map entry does not exist or is not equal to the given value.
+     *
+     * @param property the name of the property or map.
+     * @param revision the revision within the map or {@code null} if this check
+     *                 is for a property.
+     * @param value the value to compare to.
+     */
+    void notEquals(@Nonnull String property,
+                   @Nullable Revision revision,
+                   @Nullable Object value) {
+        if (isNew) {
+            throw new IllegalStateException("Cannot perform notEquals check on new document");
+        }
+        getOrCreateConditions().put(new Key(property, revision),
+                Condition.newNotEqualsCondition(value));
+    }
+
+    /**
      * Increment the value.
      *
      * @param property the key
@@ -415,8 +453,12 @@ public final class UpdateOp {
             /**
              * Checks if a map entry equals a given value.
              */
-            EQUALS
+            EQUALS,
 
+            /**
+             * Checks if a map entry does not equal a given value.
+             */
+            NOTEQUALS
         }
 
         /**
@@ -440,8 +482,18 @@ public final class UpdateOp {
          * @param value the value to compare to.
          * @return the equals condition.
          */
-        public static Condition newEqualsCondition(@Nonnull Object value) {
-            return new Condition(Type.EQUALS, checkNotNull(value));
+        public static Condition newEqualsCondition(@Nullable Object value) {
+            return new Condition(Type.EQUALS, value);
+        }
+
+        /**
+         * Creates a new notEquals condition with the given value.
+         *
+         * @param value the value to compare to.
+         * @return the notEquals condition.
+         */
+        public static Condition newNotEqualsCondition(@Nullable Object value) {
+            return new Condition(Type.NOTEQUALS, value);
         }
 
         @Override

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/UpdateUtils.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/UpdateUtils.java?rev=1710789&r1=1710788&r2=1710789&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/UpdateUtils.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/UpdateUtils.java Tue Oct 27 11:39:38 2015
@@ -134,7 +134,7 @@ public class UpdateUtils {
                         return false;
                     }
                 }
-            } else if (c.type == Condition.Type.EQUALS) {
+            } else if (c.type == Condition.Type.EQUALS || c.type == Condition.Type.NOTEQUALS) {
                 if (r != null) {
                     if (value instanceof Map) {
                         value = ((Map) value).get(r);
@@ -142,7 +142,10 @@ public class UpdateUtils {
                         value = null;
                     }
                 }
-                if (!Objects.equal(value, c.value)) {
+                boolean equal = Objects.equal(value, c.value);
+                if (c.type == Condition.Type.EQUALS && !equal) {
+                    return false;
+                } else if (c.type == Condition.Type.NOTEQUALS && equal) {
                     return false;
                 }
             } else {

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/mongo/MongoDocumentStore.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/mongo/MongoDocumentStore.java?rev=1710789&r1=1710788&r2=1710789&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/mongo/MongoDocumentStore.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/mongo/MongoDocumentStore.java Tue Oct 27 11:39:38 2015
@@ -1272,6 +1272,9 @@ public class MongoDocumentStore implemen
                 case EQUALS:
                     query.and(k.toString()).is(c.value);
                     break;
+                case NOTEQUALS:
+                    query.and(k.toString()).notEquals(c.value);
+                    break;
             }
         }
 

Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/BasicDocumentStoreTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/BasicDocumentStoreTest.java?rev=1710789&r1=1710788&r2=1710789&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/BasicDocumentStoreTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/BasicDocumentStoreTest.java Tue Oct 27 11:39:38 2015
@@ -68,6 +68,119 @@ public class BasicDocumentStoreTest exte
     }
 
     @Test
+    public void testConditionalUpdate() {
+        String id = this.getClass().getName() + ".testConditionalUpdate";
+
+        // remove if present
+        NodeDocument nd = super.ds.find(Collection.NODES, id);
+        if (nd != null) {
+            super.ds.remove(Collection.NODES, id);
+        }
+
+        String existingProp = "_recoverylock";
+        String existingRevisionProp = "recoverylock";
+        String nonExistingProp = "_qux";
+        String nonExistingRevisionProp = "qux";
+        Revision r = new Revision(1, 1, 1);
+
+        // add
+        UpdateOp up = new UpdateOp(id, true);
+        up.set("_id", id);
+        up.set(existingProp, "lock");
+        up.setMapEntry(existingRevisionProp, r, "lock");
+        assertTrue(super.ds.create(Collection.NODES, Collections.singletonList(up)));
+
+        // updates
+        up = new UpdateOp(id, false);
+        up.set("_id", id);
+        up.notEquals(nonExistingProp, "none");
+        NodeDocument result = super.ds.findAndUpdate(Collection.NODES, up);
+        assertNotNull(result);
+
+        up = new UpdateOp(id, false);
+        up.set("_id", id);
+        up.equals(nonExistingProp, null);
+        result = super.ds.findAndUpdate(Collection.NODES, up);
+        assertNotNull(result);
+
+        up = new UpdateOp(id, false);
+        up.set("_id", id);
+        up.notEquals(nonExistingRevisionProp, r, "none");
+        result = super.ds.findAndUpdate(Collection.NODES, up);
+        assertNotNull(result);
+
+        up = new UpdateOp(id, false);
+        up.set("_id", id);
+        up.equals(nonExistingRevisionProp, r, null);
+        result = super.ds.findAndUpdate(Collection.NODES, up);
+        assertNotNull(result);
+
+        up = new UpdateOp(id, false);
+        up.set("_id", id);
+        up.equals(existingProp, "none");
+        result = super.ds.findAndUpdate(Collection.NODES, up);
+        assertNull(result);
+
+        up = new UpdateOp(id, false);
+        up.set("_id", id);
+        up.equals(existingProp, null);
+        result = super.ds.findAndUpdate(Collection.NODES, up);
+        assertNull(result);
+
+        up = new UpdateOp(id, false);
+        up.set("_id", id);
+        up.equals(existingRevisionProp, r, "none");
+        result = super.ds.findAndUpdate(Collection.NODES, up);
+        assertNull(result);
+
+        up = new UpdateOp(id, false);
+        up.set("_id", id);
+        up.equals(existingRevisionProp, r, null);
+        result = super.ds.findAndUpdate(Collection.NODES, up);
+        assertNull(result);
+
+        up = new UpdateOp(id, false);
+        up.set("_id", id);
+        up.notEquals(existingProp, "lock");
+        result = super.ds.findAndUpdate(Collection.NODES, up);
+        assertNull(result);
+
+        up = new UpdateOp(id, false);
+        up.set("_id", id);
+        up.equals(existingProp, null);
+        result = super.ds.findAndUpdate(Collection.NODES, up);
+        assertNull(result);
+
+        up = new UpdateOp(id, false);
+        up.set("_id", id);
+        up.notEquals(existingRevisionProp, r, "lock");
+        result = super.ds.findAndUpdate(Collection.NODES, up);
+        assertNull(result);
+
+        up = new UpdateOp(id, false);
+        up.set("_id", id);
+        up.equals(existingRevisionProp, r, null);
+        result = super.ds.findAndUpdate(Collection.NODES, up);
+        assertNull(result);
+
+        up = new UpdateOp(id, false);
+        up.set("_id", id);
+        up.equals(existingProp, "lock");
+        up.set(existingProp, "none");
+        result = super.ds.findAndUpdate(Collection.NODES, up);
+        assertNotNull(result);
+
+        up = new UpdateOp(id, false);
+        up.set("_id", id);
+        up.equals(existingRevisionProp, r, "lock");
+        up.setMapEntry(existingRevisionProp, r, "none");
+        result = super.ds.findAndUpdate(Collection.NODES, up);
+        assertNotNull(result);
+
+        removeMe.add(id);
+    }
+
+    @Test
     public void testMaxIdAscii() {
         int result = testMaxId(true);
         assertTrue("needs to support keys of 512 bytes length, but only supports " + result, result >= 512);

Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/UpdateOpTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/UpdateOpTest.java?rev=1710789&r1=1710788&r2=1710789&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/UpdateOpTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/UpdateOpTest.java Tue Oct 27 11:39:38 2015
@@ -16,8 +16,6 @@
  */
 package org.apache.jackrabbit.oak.plugins.document;
 
-import com.google.common.collect.Lists;
-
 import org.junit.Test;
 
 import static com.google.common.collect.Lists.newArrayList;
@@ -44,15 +42,15 @@ public class UpdateOpTest {
         UpdateOp.Key k3 = new UpdateOp.Key("foo", null);
         assertTrue(k1.equals(k3));
         assertTrue(k3.equals(k1));
-        
+
         UpdateOp.Key k4 = new UpdateOp.Key("foo", r1);
         assertFalse(k4.equals(k3));
         assertFalse(k3.equals(k4));
-        
+
         UpdateOp.Key k5 = new UpdateOp.Key("foo", r2);
         assertFalse(k5.equals(k4));
         assertFalse(k4.equals(k5));
-        
+
         UpdateOp.Key k6 = new UpdateOp.Key("foo", r1);
         assertTrue(k6.equals(k4));
         assertTrue(k4.equals(k6));
@@ -144,6 +142,37 @@ public class UpdateOpTest {
     }
 
     @Test
+    public void notEqualsTest() {
+        Revision r = Revision.newRevision(1);
+        UpdateOp op = new UpdateOp("id", true);
+        try {
+            op.notEquals("p", r, "v");
+            fail("expected " + IllegalStateException.class.getName());
+        } catch (IllegalStateException e) {
+            // expected
+        }
+        op = new UpdateOp("id", false);
+        op.notEquals("p", r, "v");
+        assertEquals(1, op.getConditions().size());
+        UpdateOp.Key key = op.getConditions().keySet().iterator().next();
+        assertEquals(r, key.getRevision());
+        assertEquals("p", key.getName());
+        UpdateOp.Condition c = op.getConditions().get(key);
+        assertEquals(UpdateOp.Condition.Type.NOTEQUALS, c.type);
+        assertEquals("v", c.value);
+
+        op = new UpdateOp("id", false);
+        op.notEquals("p", r, null);
+        assertEquals(1, op.getConditions().size());
+        key = op.getConditions().keySet().iterator().next();
+        assertEquals(r, key.getRevision());
+        assertEquals("p", key.getName());
+        c = op.getConditions().get(key);
+        assertEquals(UpdateOp.Condition.Type.NOTEQUALS, c.type);
+        assertEquals(null, c.value);
+    }
+
+    @Test
     public void getChanges() {
         UpdateOp op = new UpdateOp("id", false);
         assertEquals(0, op.getChanges().size());

Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/UpdateUtilsTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/UpdateUtilsTest.java?rev=1710789&r1=1710788&r2=1710789&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/UpdateUtilsTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/UpdateUtilsTest.java Tue Oct 27 11:39:38 2015
@@ -111,32 +111,84 @@ public class UpdateUtilsTest {
         assertTrue(UpdateUtils.checkConditions(d, op.getConditions()));
 
         op = newUpdateOp(id);
+        op.notEquals("t", r, "value");
+        assertFalse(UpdateUtils.checkConditions(d, op.getConditions()));
+
+        op = newUpdateOp(id);
         op.equals("t", r, "foo");
         assertFalse(UpdateUtils.checkConditions(d, op.getConditions()));
 
         op = newUpdateOp(id);
+        op.notEquals("t", r, "foo");
+        assertTrue(UpdateUtils.checkConditions(d, op.getConditions()));
+
+        op = newUpdateOp(id);
         op.equals("t", Revision.newRevision(1), "value");
         assertFalse(UpdateUtils.checkConditions(d, op.getConditions()));
 
         op = newUpdateOp(id);
-        op.equals("t", null, "value");
+        op.notEquals("t", Revision.newRevision(1), "value");
+        assertTrue(UpdateUtils.checkConditions(d, op.getConditions()));
+
+        op = newUpdateOp(id);
+        op.equals("t", "value");
         assertFalse(UpdateUtils.checkConditions(d, op.getConditions()));
 
         op = newUpdateOp(id);
+        op.notEquals("t", "value");
+        assertTrue(UpdateUtils.checkConditions(d, op.getConditions()));
+
+        op = newUpdateOp(id);
         op.equals("p", r, 42L);
         assertFalse(UpdateUtils.checkConditions(d, op.getConditions()));
 
         op = newUpdateOp(id);
-        op.equals("p", null, 42L);
+        op.notEquals("p", r, 42L);
+        assertTrue(UpdateUtils.checkConditions(d, op.getConditions()));
+
+        op = newUpdateOp(id);
+        op.equals("p", 42L);
+        assertTrue(UpdateUtils.checkConditions(d, op.getConditions()));
+
+        op = newUpdateOp(id);
+        op.notEquals("p", 42L);
+        assertFalse(UpdateUtils.checkConditions(d, op.getConditions()));
+
+        op = newUpdateOp(id);
+        op.equals("p", 7L);
+        assertFalse(UpdateUtils.checkConditions(d, op.getConditions()));
+
+        op = newUpdateOp(id);
+        op.notEquals("p", 7L);
         assertTrue(UpdateUtils.checkConditions(d, op.getConditions()));
 
+        // check on non-existing property
         op = newUpdateOp(id);
-        op.equals("p", null, 7L);
+        op.notEquals("other", 7L);
+        assertTrue(UpdateUtils.checkConditions(d, op.getConditions()));
+
+        op = newUpdateOp(id);
+        op.notEquals("other", r, 7L);
+        assertTrue(UpdateUtils.checkConditions(d, op.getConditions()));
+
+        op = newUpdateOp(id);
+        op.notEquals("other", r, null);
         assertFalse(UpdateUtils.checkConditions(d, op.getConditions()));
 
+        op = newUpdateOp(id);
+        op.equals("other", r, null);
+        assertTrue(UpdateUtils.checkConditions(d, op.getConditions()));
 
+        // check null
+        op = newUpdateOp(id);
+        op.notEquals("p", null);
+        assertTrue(UpdateUtils.checkConditions(d, op.getConditions()));
+
+        op = newUpdateOp(id);
+        op.notEquals("other", r, null);
+        assertFalse(UpdateUtils.checkConditions(d, op.getConditions()));
     }
-    
+
     private static UpdateOp newUpdateOp(String id) {
         return new UpdateOp(id, false);
     }