Skip to content

Commit 283773f

Browse files
author
Brian Chen
committed
add update_transforms
1 parent 715e434 commit 283773f

File tree

20 files changed

+591
-475
lines changed

20 files changed

+591
-475
lines changed

firebase-firestore/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33
This more closely aligns the SDK with the Firestore backend, which has always
44
accepted null and NaN for all operators, even though this isn't necessarily
55
useful.
6+
- [changed] A write to a document that contains FieldValue transforms is no
7+
longer split up into two separate operations. This reduces the number of
8+
writes the backend performs and allows each WriteBatch to hold 500 writes
9+
regardless of how many FieldValue transformations are attached.
610

711
# (22.0.0)
812
- [changed] Removed the deprecated `timestampsInSnapshotsEnabled` setting.

firebase-firestore/src/main/java/com/google/firebase/firestore/DocumentReference.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
import com.google.firebase.firestore.util.Assert;
4343
import com.google.firebase.firestore.util.Executors;
4444
import com.google.firebase.firestore.util.Util;
45+
import java.util.Collections;
4546
import java.util.Map;
4647
import java.util.concurrent.ExecutionException;
4748
import java.util.concurrent.Executor;
@@ -166,7 +167,7 @@ public Task<Void> set(@NonNull Object data, @NonNull SetOptions options) {
166167
: firestore.getUserDataReader().parseSetData(data);
167168
return firestore
168169
.getClient()
169-
.write(parsed.toMutationList(key, Precondition.NONE))
170+
.write(Collections.singletonList(parsed.toMutation(key, Precondition.NONE)))
170171
.continueWith(Executors.DIRECT_EXECUTOR, voidErrorTransformer());
171172
}
172173

@@ -230,7 +231,7 @@ public Task<Void> update(
230231
private Task<Void> update(@NonNull ParsedUpdateData parsedData) {
231232
return firestore
232233
.getClient()
233-
.write(parsedData.toMutationList(key, Precondition.exists(true)))
234+
.write(Collections.singletonList(parsedData.toMutation(key, Precondition.exists(true))))
234235
.continueWith(Executors.DIRECT_EXECUTOR, voidErrorTransformer());
235236
}
236237

firebase-firestore/src/main/java/com/google/firebase/firestore/UserDataReader.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ public Value parseQueryValue(Object input, boolean allowArrays) {
208208
}
209209

210210
/** Converts a POJO to native types and then parses it into model types. */
211-
private Value convertAndParseFieldData(Object input, ParseContext context) {
211+
public Value convertAndParseFieldData(Object input, ParseContext context) {
212212
Object converted = CustomClassMapper.convertToPlainJavaTypes(input);
213213
return parseData(converted, context);
214214
}

firebase-firestore/src/main/java/com/google/firebase/firestore/WriteBatch.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ public WriteBatch set(
8888
options.isMerge()
8989
? firestore.getUserDataReader().parseMergeData(data, options.getFieldMask())
9090
: firestore.getUserDataReader().parseSetData(data);
91-
mutations.addAll(parsed.toMutationList(documentRef.getKey(), Precondition.NONE));
91+
mutations.add(parsed.toMutation(documentRef.getKey(), Precondition.NONE));
9292
return this;
9393
}
9494

@@ -163,7 +163,7 @@ private WriteBatch update(
163163
@NonNull DocumentReference documentRef, @NonNull ParsedUpdateData updateData) {
164164
firestore.validateReference(documentRef);
165165
verifyNotCommitted();
166-
mutations.addAll(updateData.toMutationList(documentRef.getKey(), Precondition.exists(true)));
166+
mutations.add(updateData.toMutation(documentRef.getKey(), Precondition.exists(true)));
167167
return this;
168168
}
169169

firebase-firestore/src/main/java/com/google/firebase/firestore/core/Transaction.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ public Task<List<MaybeDocument>> lookup(List<DocumentKey> keys) {
103103

104104
/** Stores a set mutation for the given key and value, to be committed when commit() is called. */
105105
public void set(DocumentKey key, ParsedSetData data) {
106-
write(data.toMutationList(key, precondition(key)));
106+
write(Collections.singletonList(data.toMutation(key, precondition(key))));
107107
writtenDocs.add(key);
108108
}
109109

@@ -113,7 +113,7 @@ public void set(DocumentKey key, ParsedSetData data) {
113113
*/
114114
public void update(DocumentKey key, ParsedUpdateData data) {
115115
try {
116-
write(data.toMutationList(key, preconditionForUpdate(key)));
116+
write(Collections.singletonList(data.toMutation(key, preconditionForUpdate(key))));
117117
} catch (FirebaseFirestoreException e) {
118118
lastWriteError = e;
119119
}

firebase-firestore/src/main/java/com/google/firebase/firestore/core/UserData.java

Lines changed: 27 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626
import com.google.firebase.firestore.model.mutation.PatchMutation;
2727
import com.google.firebase.firestore.model.mutation.Precondition;
2828
import com.google.firebase.firestore.model.mutation.SetMutation;
29-
import com.google.firebase.firestore.model.mutation.TransformMutation;
3029
import com.google.firebase.firestore.model.mutation.TransformOperation;
3130
import com.google.firebase.firestore.util.Assert;
3231
import java.util.ArrayList;
@@ -335,23 +334,32 @@ public static class ParsedSetData {
335334
this.fieldTransforms = fieldTransforms;
336335
}
337336

338-
public List<Mutation> toMutationList(DocumentKey key, Precondition precondition) {
339-
ArrayList<Mutation> mutations = new ArrayList<>();
337+
public ObjectValue getData() {
338+
return data;
339+
}
340+
341+
@Nullable
342+
public FieldMask getFieldMask() {
343+
return fieldMask;
344+
}
345+
346+
public List<FieldTransform> getFieldTransforms() {
347+
return fieldTransforms;
348+
}
349+
350+
public Mutation toMutation(DocumentKey key, Precondition precondition) {
340351
if (fieldMask != null) {
341-
mutations.add(new PatchMutation(key, data, fieldMask, precondition));
352+
return new PatchMutation(key, data, fieldMask, precondition, fieldTransforms);
342353
} else {
343-
mutations.add(new SetMutation(key, data, precondition));
344-
}
345-
if (!fieldTransforms.isEmpty()) {
346-
mutations.add(new TransformMutation(key, fieldTransforms));
354+
return new SetMutation(key, data, precondition, fieldTransforms);
347355
}
348-
return mutations;
349356
}
350357
}
351358

352359
/** The result of parsing "update" data (i.e. for an updateData call). */
353360
public static class ParsedUpdateData {
354361
private final ObjectValue data;
362+
// The fieldMask does not include document transforms.
355363
private final FieldMask fieldMask;
356364
private final List<FieldTransform> fieldTransforms;
357365

@@ -361,17 +369,20 @@ public static class ParsedUpdateData {
361369
this.fieldTransforms = fieldTransforms;
362370
}
363371

372+
public ObjectValue getData() {
373+
return data;
374+
}
375+
376+
public FieldMask getFieldMask() {
377+
return fieldMask;
378+
}
379+
364380
public List<FieldTransform> getFieldTransforms() {
365381
return fieldTransforms;
366382
}
367383

368-
public List<Mutation> toMutationList(DocumentKey key, Precondition precondition) {
369-
ArrayList<Mutation> mutations = new ArrayList<>();
370-
mutations.add(new PatchMutation(key, data, fieldMask, precondition));
371-
if (!fieldTransforms.isEmpty()) {
372-
mutations.add(new TransformMutation(key, fieldTransforms));
373-
}
374-
return mutations;
384+
public Mutation toMutation(DocumentKey key, Precondition precondition) {
385+
return new PatchMutation(key, data, fieldMask, precondition, fieldTransforms);
375386
}
376387
}
377388
}

firebase-firestore/src/main/java/com/google/firebase/firestore/local/LocalSerializer.java

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@
2929
import com.google.firebase.firestore.model.mutation.Mutation;
3030
import com.google.firebase.firestore.model.mutation.MutationBatch;
3131
import com.google.firebase.firestore.remote.RemoteSerializer;
32+
import com.google.firestore.v1.DocumentTransform.FieldTransform;
33+
import com.google.firestore.v1.Write;
34+
import com.google.firestore.v1.Write.Builder;
3235
import com.google.protobuf.ByteString;
3336
import java.util.ArrayList;
3437
import java.util.List;
@@ -171,6 +174,35 @@ MutationBatch decodeMutationBatch(com.google.firebase.firestore.proto.WriteBatch
171174
for (int i = 0; i < baseMutationsCount; i++) {
172175
baseMutations.add(rpcSerializer.decodeMutation(batch.getBaseWrites(i)));
173176
}
177+
178+
// Squash old transform mutations into existing patch or set mutations. The replacement of
179+
// representing `transforms` with `update_transforms` on the SDK means that old `transform`
180+
// mutations stored in IndexedDB need to be updated to `update_transforms`.
181+
// TODO(b/174608374): Remove this code once we perform a schema migration.
182+
for (int i = batch.getWritesCount() - 1; i >= 0; --i) {
183+
Write mutation = batch.getWrites(i);
184+
if (mutation.getTransform().getFieldTransformsCount() != 0) {
185+
hardAssert(
186+
i >= 1
187+
&& batch.getWrites(i - 1).getTransform().getFieldTransformsCount() == 0
188+
&& batch.getWrites(i - 1).getUpdate().getFieldsCount() != 0,
189+
"TransformMutation should be preceded by a patch or set mutation");
190+
Write mutationToJoin = batch.getWrites(i - 1);
191+
Builder newMutationBuilder = Write.newBuilder(mutationToJoin);
192+
for (FieldTransform fieldTransform : mutation.getTransform().getFieldTransformsList()) {
193+
newMutationBuilder.addUpdateTransforms(fieldTransform);
194+
}
195+
196+
batch =
197+
com.google.firebase.firestore.proto.WriteBatch.newBuilder(batch)
198+
.removeWrites(i)
199+
.removeWrites(i - 1)
200+
.addWrites(i - 1, newMutationBuilder.build())
201+
.build();
202+
--i;
203+
}
204+
}
205+
174206
int mutationsCount = batch.getWritesCount();
175207
List<Mutation> mutations = new ArrayList<>(mutationsCount);
176208
for (int i = 0; i < mutationsCount; i++) {

firebase-firestore/src/main/java/com/google/firebase/firestore/model/ServerTimestamps.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,8 @@
2828
* `__previous_value__` and `__local_write_time__` fields respectively.
2929
*
3030
* <p>Notes:
31-
* <li>ServerTimestamp Values are created as the result of applying a TransformMutation (see
32-
* TransformMutation.applyTo()). They can only exist in the local view of a document. Therefore
33-
* they do not need to be parsed or serialized.
31+
* <li>ServerTimestamp Values are created as the result of applying a transform. They can only exist
32+
* in the local view of a document. Therefore they do not need to be parsed or serialized.
3433
* <li>When evaluated locally (e.g. via DocumentSnapshot data), they evaluate to null.
3534
* <li>They sort after all Timestamp Values. With respect to other ServerTimestamp Values, they sort
3635
* by their localWriteTime.

0 commit comments

Comments
 (0)