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);
}