Skip to content

Commit b30ef91

Browse files
DO NOT MERGE: Adding FieldValue.increment()
1 parent 5fa529e commit b30ef91

6 files changed

Lines changed: 145 additions & 6 deletions

File tree

google-cloud-clients/google-cloud-firestore/src/main/java/com/google/cloud/firestore/FieldValue.java

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,55 @@ FieldTransform toProto(FieldPath path) {
7777
}
7878
};
7979

80+
static class NumericIncrementFieldValue extends FieldValue {
81+
final Number operand;
82+
83+
NumericIncrementFieldValue(Number operand) {
84+
this.operand = operand;
85+
}
86+
87+
@Override
88+
boolean includeInDocumentMask() {
89+
return false;
90+
}
91+
92+
@Override
93+
boolean includeInDocumentTransform() {
94+
return true;
95+
}
96+
97+
@Override
98+
String getMethodName() {
99+
return "FieldValue.increment()";
100+
}
101+
102+
@Override
103+
FieldTransform toProto(FieldPath path) {
104+
FieldTransform.Builder fieldTransform = FieldTransform.newBuilder();
105+
fieldTransform.setFieldPath(path.getEncodedPath());
106+
fieldTransform.setNumericAdd(
107+
UserDataConverter.encodeValue(FieldPath.of(""), operand, UserDataConverter.ARGUMENT));
108+
return fieldTransform.build();
109+
}
110+
111+
@Override
112+
public boolean equals(Object o) {
113+
if (this == o) {
114+
return true;
115+
}
116+
if (o == null || getClass() != o.getClass()) {
117+
return false;
118+
}
119+
NumericIncrementFieldValue that = (NumericIncrementFieldValue) o;
120+
return Objects.equals(operand, that.operand);
121+
}
122+
123+
@Override
124+
public int hashCode() {
125+
return Objects.hash(operand);
126+
}
127+
}
128+
80129
static class ArrayUnionFieldValue extends FieldValue {
81130
final List<Object> elements;
82131

@@ -204,6 +253,39 @@ public static FieldValue delete() {
204253
return DELETE_SENTINEL;
205254
}
206255

256+
/**
257+
* Returns a special value that can be used with set(), create() or update() that tells the server
258+
* to increment the field's current value by the given value.
259+
*
260+
* <p>If the current field value is an integer, possible integer overflows are resolved to
261+
* Long.MAX_VALUE or Long.MIN_VALUE. If the current field value is a double, both values will be
262+
* interpreted as doubles and the arithmetic will follow IEEE 754 semantics.
263+
*
264+
* <p>If the current field is not an integer or double, or if the field does not yet exist, the
265+
* transformation will set the field to the given value.
266+
*
267+
* @return The FieldValue sentinel for use in a call to set(), create() or update().
268+
*/
269+
@Nonnull
270+
public static FieldValue increment(long l) {
271+
return new NumericIncrementFieldValue(l);
272+
}
273+
274+
/**
275+
* Returns a special value that can be used with set() or update() that tells the server to
276+
* increment the field's current value by the given value.
277+
*
278+
* <p>If the current value is an integer or a double, both the current and the given value will be
279+
* interpreted as doubles and all arithmetic will follow IEEE 754 semantics. Otherwise, the
280+
* transformation will set the field to the given value.
281+
*
282+
* @return The FieldValue sentinel for use in a call to set(), create() or update().
283+
*/
284+
@Nonnull
285+
public static FieldValue increment(double d) {
286+
return new NumericIncrementFieldValue(d);
287+
}
288+
207289
/**
208290
* Returns a special value that can be used with set() or update() that tells the server to union
209291
* the given elements with any array value that already exists on the server. Each specified

google-cloud-clients/google-cloud-firestore/src/main/java/com/google/cloud/firestore/UserDataConverter.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ private UserDataConverter() {}
9090
* @param path path THe field path of the object to encode.
9191
* @param sanitizedObject An Object that has been sanitized by CustomClassMapper and only contains
9292
* valid types.
93-
* @param options Encoding opions to use for this value.
93+
* @param options Encoding options to use for this value.
9494
* @return The Value proto.
9595
*/
9696
@Nullable

google-cloud-clients/google-cloud-firestore/src/test/java/com/google/cloud/firestore/DocumentReferenceTest.java

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
import static com.google.cloud.firestore.LocalFirestoreHelper.delete;
4545
import static com.google.cloud.firestore.LocalFirestoreHelper.get;
4646
import static com.google.cloud.firestore.LocalFirestoreHelper.getAllResponse;
47+
import static com.google.cloud.firestore.LocalFirestoreHelper.increment;
4748
import static com.google.cloud.firestore.LocalFirestoreHelper.map;
4849
import static com.google.cloud.firestore.LocalFirestoreHelper.object;
4950
import static com.google.cloud.firestore.LocalFirestoreHelper.serverTimestamp;
@@ -418,9 +419,7 @@ public void setWithArrayUnion() throws Exception {
418419
.sendRequest(
419420
commitCapture.capture(), Matchers.<UnaryCallable<CommitRequest, CommitResponse>>any());
420421

421-
documentReference
422-
.set(map("foo", FieldValue.arrayUnion("bar", map("foo", "baz"))))
423-
.get();
422+
documentReference.set(map("foo", FieldValue.arrayUnion("bar", map("foo", "baz")))).get();
424423

425424
CommitRequest set =
426425
commit(
@@ -432,16 +431,38 @@ public void setWithArrayUnion() throws Exception {
432431
}
433432

434433
@Test
435-
public void setWithArrayRemove() throws Exception {
434+
public void setWithIncrement() throws Exception {
436435
doReturn(FIELD_TRANSFORM_COMMIT_RESPONSE)
437436
.when(firestoreMock)
438437
.sendRequest(
439438
commitCapture.capture(), Matchers.<UnaryCallable<CommitRequest, CommitResponse>>any());
440439

441440
documentReference
442-
.set(map("foo", FieldValue.arrayRemove("bar", map("foo", "baz"))))
441+
.set(map("integer", FieldValue.increment(1), "double", FieldValue.increment(1.1)))
443442
.get();
444443

444+
CommitRequest set =
445+
commit(
446+
set(Collections.<String, Value>emptyMap()),
447+
transform(
448+
"integer",
449+
increment(Value.newBuilder().setIntegerValue(1).build()),
450+
"double",
451+
increment(Value.newBuilder().setDoubleValue(1.1).build())));
452+
453+
CommitRequest commitRequest = commitCapture.getValue();
454+
assertCommitEquals(set, commitRequest);
455+
}
456+
457+
@Test
458+
public void setWithArrayRemove() throws Exception {
459+
doReturn(FIELD_TRANSFORM_COMMIT_RESPONSE)
460+
.when(firestoreMock)
461+
.sendRequest(
462+
commitCapture.capture(), Matchers.<UnaryCallable<CommitRequest, CommitResponse>>any());
463+
464+
documentReference.set(map("foo", FieldValue.arrayRemove("bar", map("foo", "baz")))).get();
465+
445466
CommitRequest set =
446467
commit(
447468
set(Collections.<String, Value>emptyMap()),

google-cloud-clients/google-cloud-firestore/src/test/java/com/google/cloud/firestore/FirestoreTest.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,4 +141,16 @@ public void arrayRemoveEquals() {
141141
assertNotEquals(arrayRemove1, arrayRemove3);
142142
assertNotEquals(arrayRemove1, arrayUnion);
143143
}
144+
145+
@Test
146+
public void incrementEquals() {
147+
FieldValue increment1 = FieldValue.increment(42);
148+
FieldValue increment2 = FieldValue.increment(42);
149+
FieldValue increment3 = FieldValue.increment(42.0);
150+
FieldValue increment4 = FieldValue.increment(42.0);
151+
assertEquals(increment1, increment2);
152+
assertEquals(increment3, increment4);
153+
assertNotEquals(increment1, increment3);
154+
assertNotEquals(increment2, increment4);
155+
}
144156
}

google-cloud-clients/google-cloud-firestore/src/test/java/com/google/cloud/firestore/LocalFirestoreHelper.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,10 @@ public static FieldTransform serverTimestamp() {
272272
.build();
273273
}
274274

275+
public static FieldTransform increment(Value value) {
276+
return FieldTransform.newBuilder().setNumericAdd(value).build();
277+
}
278+
275279
public static FieldTransform arrayUnion(Value... values) {
276280
return FieldTransform.newBuilder()
277281
.setAppendMissingElements(ArrayValue.newBuilder().addAllValues(Arrays.asList(values)))

google-cloud-clients/google-cloud-firestore/src/test/java/com/google/cloud/firestore/it/ITSystemTest.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@
7070

7171
public class ITSystemTest {
7272

73+
private static final double DOUBLE_EPSILON = 0.000001;
74+
7375
private final Map<String, Object> SINGLE_FIELD_MAP = LocalFirestoreHelper.SINGLE_FIELD_MAP;
7476
private final Map<String, Object> ALL_SUPPORTED_TYPES_MAP =
7577
LocalFirestoreHelper.ALL_SUPPORTED_TYPES_MAP;
@@ -968,4 +970,22 @@ public void arrayOperators() throws ExecutionException, InterruptedException {
968970

969971
assertTrue(containsQuery.get().get().isEmpty());
970972
}
973+
974+
@Test
975+
public void integerIncrement() throws ExecutionException, InterruptedException {
976+
DocumentReference docRef = randomColl.document();
977+
docRef.set(Collections.singletonMap("sum", (Object) 1L)).get();
978+
docRef.update("sum", FieldValue.increment(2));
979+
DocumentSnapshot docSnap = docRef.get().get();
980+
assertEquals(3L, docSnap.get("sum"));
981+
}
982+
983+
@Test
984+
public void floatIncrement() throws ExecutionException, InterruptedException {
985+
DocumentReference docRef = randomColl.document();
986+
docRef.set(Collections.singletonMap("sum", (Object) 1.1)).get();
987+
docRef.update("sum", FieldValue.increment(2.2));
988+
DocumentSnapshot docSnap = docRef.get().get();
989+
assertEquals(3.3, (Double) docSnap.get("sum"), DOUBLE_EPSILON);
990+
}
971991
}

0 commit comments

Comments
 (0)