Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding FieldValue.increment() #4018

Merged
merged 3 commits into from
Mar 8, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,55 @@ FieldTransform toProto(FieldPath path) {
}
};

static class NumericIncrementFieldValue extends FieldValue {
final Number operand;

NumericIncrementFieldValue(Number operand) {
this.operand = operand;
}

@Override
boolean includeInDocumentMask() {
return false;
}

@Override
boolean includeInDocumentTransform() {
return true;
}

@Override
String getMethodName() {
return "FieldValue.increment()";
}

@Override
FieldTransform toProto(FieldPath path) {
FieldTransform.Builder fieldTransform = FieldTransform.newBuilder();
fieldTransform.setFieldPath(path.getEncodedPath());
fieldTransform.setIncrement(
UserDataConverter.encodeValue(path, operand, UserDataConverter.ARGUMENT));
return fieldTransform.build();
}

@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
NumericIncrementFieldValue that = (NumericIncrementFieldValue) o;
return Objects.equals(operand, that.operand);
}

@Override
public int hashCode() {
return Objects.hash(operand);
}
}

static class ArrayUnionFieldValue extends FieldValue {
final List<Object> elements;

Expand Down Expand Up @@ -205,11 +254,44 @@ public static FieldValue delete() {
}

/**
* Returns a special value that can be used with set() or update() that tells the server to union
* the given elements with any array value that already exists on the server. Each specified
* element that doesn't already exist in the array will be added to the end. If the field being
* modified is not already an array it will be overwritten with an array containing exactly the
* specified elements.
* Returns a special value that can be used with set(), create() or update() that tells the server
* to increment the field's current value by the given value.
*
* <p>If the current field value is an integer, possible integer overflows are resolved to
* Long.MAX_VALUE or Long.MIN_VALUE. If the current field value is a double, both values will be
* interpreted as doubles and the arithmetic will follow IEEE 754 semantics.
*
* <p>If the current field is not an integer or double, or if the field does not yet exist, the
* transformation will set the field to the given value.
*
* @return The FieldValue sentinel for use in a call to set(), create() or update().
*/
@Nonnull
public static FieldValue increment(long l) {
return new NumericIncrementFieldValue(l);
}

/**
* Returns a special value that can be used with set(), create() or update() that tells the server
* to increment the field's current value by the given value.
*
* <p>If the current value is an integer or a double, both the current and the given value will be
* interpreted as doubles and all arithmetic will follow IEEE 754 semantics. Otherwise, the
* transformation will set the field to the given value.
*
* @return The FieldValue sentinel for use in a call to set(), create() or update().
*/
@Nonnull
public static FieldValue increment(double d) {
return new NumericIncrementFieldValue(d);
}

/**
* Returns a special value that can be used with set(), create() or update() that tells the server
* to union the given elements with any array value that already exists on the server. Each
* specified element that doesn't already exist in the array will be added to the end. If the
* field being modified is not already an array it will be overwritten with an array containing
* exactly the specified elements.
*
* @param elements The elements to union into the array.
* @return The FieldValue sentinel for use in a call to set() or update().
Expand All @@ -221,10 +303,10 @@ public static FieldValue arrayUnion(@Nonnull Object... elements) {
}

/**
* Returns a special value that can be used with set() or update() that tells the server to remove
* the given elements from any array value that already exists on the server. All instances of
* each element specified will be removed from the array. If the field being modified is not
* already an array it will be overwritten with an empty array.
* Returns a special value that can be used with set(), create() or update() that tells the server
* to remove the given elements from any array value that already exists on the server. All
* instances of each element specified will be removed from the array. If the field being modified
* is not already an array it will be overwritten with an empty array.
*
* @param elements The elements to remove from the array.
* @return The FieldValue sentinel for use in a call to set() or update().
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ private UserDataConverter() {}
* @param path path THe field path of the object to encode.
* @param sanitizedObject An Object that has been sanitized by CustomClassMapper and only contains
* valid types.
* @param options Encoding opions to use for this value.
* @param options Encoding options to use for this value.
* @return The Value proto.
*/
@Nullable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
import static com.google.cloud.firestore.LocalFirestoreHelper.delete;
import static com.google.cloud.firestore.LocalFirestoreHelper.get;
import static com.google.cloud.firestore.LocalFirestoreHelper.getAllResponse;
import static com.google.cloud.firestore.LocalFirestoreHelper.increment;
import static com.google.cloud.firestore.LocalFirestoreHelper.map;
import static com.google.cloud.firestore.LocalFirestoreHelper.object;
import static com.google.cloud.firestore.LocalFirestoreHelper.serverTimestamp;
Expand Down Expand Up @@ -408,6 +409,30 @@ public void mergeWithServerTimestamps() throws Exception {
assertCommitEquals(set, commitRequests.get(1));
}

@Test
public void setWithIncrement() throws Exception {
doReturn(FIELD_TRANSFORM_COMMIT_RESPONSE)
.when(firestoreMock)
.sendRequest(
commitCapture.capture(), Matchers.<UnaryCallable<CommitRequest, CommitResponse>>any());

documentReference
.set(map("integer", FieldValue.increment(1), "double", FieldValue.increment(1.1)))
.get();

CommitRequest set =
commit(
set(Collections.<String, Value>emptyMap()),
transform(
"integer",
increment(Value.newBuilder().setIntegerValue(1).build()),
"double",
increment(Value.newBuilder().setDoubleValue(1.1).build())));

CommitRequest commitRequest = commitCapture.getValue();
assertCommitEquals(set, commitRequest);
}

@Test
public void setWithArrayUnion() throws Exception {
doReturn(FIELD_TRANSFORM_COMMIT_RESPONSE)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,4 +157,16 @@ public void arrayRemoveEquals() {
assertNotEquals(arrayRemove1, arrayRemove3);
assertNotEquals(arrayRemove1, arrayUnion);
}

@Test
public void incrementEquals() {
FieldValue increment1 = FieldValue.increment(42);
FieldValue increment2 = FieldValue.increment(42);
FieldValue increment3 = FieldValue.increment(42.0);
FieldValue increment4 = FieldValue.increment(42.0);
assertEquals(increment1, increment2);
assertEquals(increment3, increment4);
assertNotEquals(increment1, increment3);
assertNotEquals(increment2, increment4);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,10 @@ public static FieldTransform serverTimestamp() {
.build();
}

public static FieldTransform increment(Value value) {
return FieldTransform.newBuilder().setIncrement(value).build();
}

public static FieldTransform arrayUnion(Value... values) {
return FieldTransform.newBuilder()
.setAppendMissingElements(ArrayValue.newBuilder().addAllValues(Arrays.asList(values)))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@

public class ITSystemTest {

private static final double DOUBLE_EPSILON = 0.000001;

private final Map<String, Object> SINGLE_FIELD_MAP = LocalFirestoreHelper.SINGLE_FIELD_MAP;
private final Map<String, Object> ALL_SUPPORTED_TYPES_MAP =
LocalFirestoreHelper.ALL_SUPPORTED_TYPES_MAP;
Expand Down Expand Up @@ -977,4 +979,22 @@ public void arrayOperators() throws ExecutionException, InterruptedException {

assertTrue(containsQuery.get().get().isEmpty());
}

@Test
public void integerIncrement() throws ExecutionException, InterruptedException {
DocumentReference docRef = randomColl.document();
docRef.set(Collections.singletonMap("sum", (Object) 1L)).get();
docRef.update("sum", FieldValue.increment(2)).get();
DocumentSnapshot docSnap = docRef.get().get();
assertEquals(3L, docSnap.get("sum"));
}

@Test
public void floatIncrement() throws ExecutionException, InterruptedException {
DocumentReference docRef = randomColl.document();
docRef.set(Collections.singletonMap("sum", (Object) 1.1)).get();
docRef.update("sum", FieldValue.increment(2.2)).get();
DocumentSnapshot docSnap = docRef.get().get();
assertEquals(3.3, (Double) docSnap.get("sum"), DOUBLE_EPSILON);
}
}