diff --git a/firestore/google/cloud/firestore_v1/_helpers.py b/firestore/google/cloud/firestore_v1/_helpers.py index 7f47e74bcf18..09f5d7f41c0e 100644 --- a/firestore/google/cloud/firestore_v1/_helpers.py +++ b/firestore/google/cloud/firestore_v1/_helpers.py @@ -836,10 +836,6 @@ def _get_update_mask(self, allow_empty_mask=False): for field_path in self.top_level_paths: if field_path not in self.transform_paths: mask_paths.append(field_path.to_api_repr()) - else: - prefix = FieldPath(*field_path.parts[:-1]) - if prefix.parts: - mask_paths.append(prefix.to_api_repr()) return common_pb2.DocumentMask(field_paths=mask_paths) diff --git a/firestore/google/cloud/firestore_v1beta1/_helpers.py b/firestore/google/cloud/firestore_v1beta1/_helpers.py index 9f9e4337eee2..11dcefc98fad 100644 --- a/firestore/google/cloud/firestore_v1beta1/_helpers.py +++ b/firestore/google/cloud/firestore_v1beta1/_helpers.py @@ -785,10 +785,6 @@ def _get_update_mask(self, allow_empty_mask=False): for field_path in self.top_level_paths: if field_path not in self.transform_paths: mask_paths.append(field_path.to_api_repr()) - else: - prefix = FieldPath(*field_path.parts[:-1]) - if prefix.parts: - mask_paths.append(prefix.to_api_repr()) return common_pb2.DocumentMask(field_paths=mask_paths) diff --git a/firestore/tests/unit/v1/test__helpers.py b/firestore/tests/unit/v1/test__helpers.py index e33a2c9d0855..e804d9bfcb6f 100644 --- a/firestore/tests/unit/v1/test__helpers.py +++ b/firestore/tests/unit/v1/test__helpers.py @@ -2110,10 +2110,7 @@ def _helper(self, option=None, do_transform=False, **write_kwargs): map_pb = document_pb2.MapValue(fields={"yum": _value_pb(bytes_value=value)}) - if do_transform: - field_paths = [field_path1, "blog"] - else: - field_paths = [field_path1] + field_paths = [field_path1] expected_update_pb = write_pb2.Write( update=document_pb2.Document( diff --git a/firestore/tests/unit/v1/testdata/update-nested-transform-and-nested-value.json b/firestore/tests/unit/v1/testdata/update-nested-transform-and-nested-value.json new file mode 100644 index 000000000000..ff7bfc6ee944 --- /dev/null +++ b/firestore/tests/unit/v1/testdata/update-nested-transform-and-nested-value.json @@ -0,0 +1,52 @@ +{ + "tests": [ + { + "description": "update: Nested transforms should not affect the field mask, even\nwhen there are other values that do. Transforms should only affect the\nDocumentTransform_FieldTransform list.", + "comment": "For updates, top-level paths in json-like map inputs\nare split on the dot. That is, an input {\"a.b.c\": 7} results in an update to\nfield c of object b of object a with value 7. In order to specify this behavior,\nthe update must use a fieldmask \"a.b.c\". However, fieldmasks are only used for\nconcrete values - transforms are separately encoded in a\nDocumentTransform_FieldTransform array.\n\nThis test exercises a bug found in python (https://github.com/googleapis/google-cloud-python/issues/7215)\nin which nested transforms ({\"a.c\": \"ServerTimestamp\"}) next to nested values\n({\"a.b\": 7}) incorrectly caused the fieldmask \"a\" to be set, which has the\neffect of wiping out all data in \"a\" other than what was specified in the\njson-like input.\n\nInstead, as this test specifies, transforms should not affect the fieldmask.", + "update": { + "docRefPath": "projects/projectID/databases/(default)/documents/C/d", + "jsonData": "{\"a.b\": 7, \"a.c\": \"ServerTimestamp\"}", + "request": { + "database": "projects/projectID/databases/(default)", + "writes": [ + { + "update": { + "name": "projects/projectID/databases/(default)/documents/C/d", + "fields": { + "a": { + "mapValue": { + "fields": { + "b": { + "integerValue": "7" + } + } + } + } + } + }, + "updateMask": { + "fieldPaths": [ + "a.b" + ] + }, + "currentDocument": { + "exists": true + } + }, + { + "transform": { + "document": "projects/projectID/databases/(default)/documents/C/d", + "fieldTransforms": [ + { + "fieldPath": "a.c", + "setToServerValue": "REQUEST_TIME" + } + ] + } + } + ] + } + } + } + ] +} diff --git a/firestore/tests/unit/v1beta1/test__helpers.py b/firestore/tests/unit/v1beta1/test__helpers.py index 5175e19332e2..c4b3828e8cd8 100644 --- a/firestore/tests/unit/v1beta1/test__helpers.py +++ b/firestore/tests/unit/v1beta1/test__helpers.py @@ -1801,10 +1801,7 @@ def _helper(self, option=None, do_transform=False, **write_kwargs): map_pb = document_pb2.MapValue(fields={"yum": _value_pb(bytes_value=value)}) - if do_transform: - field_paths = [field_path1, "blog"] - else: - field_paths = [field_path1] + field_paths = [field_path1] expected_update_pb = write_pb2.Write( update=document_pb2.Document( diff --git a/firestore/tests/unit/v1beta1/testdata/update-nested-transform-and-nested-value.textproto b/firestore/tests/unit/v1beta1/testdata/update-nested-transform-and-nested-value.textproto new file mode 100644 index 000000000000..d2cee270d531 --- /dev/null +++ b/firestore/tests/unit/v1beta1/testdata/update-nested-transform-and-nested-value.textproto @@ -0,0 +1,58 @@ +# DO NOT MODIFY. This file was generated by +# github.com/GoogleCloudPlatform/google-cloud-common/testing/firestore/cmd/generate-firestore-tests/generate-firestore-tests.go. + +# For updates, top-level paths in json-like map inputs are split on the dot. That +# is, an input {"a.b.c": 7} results in an update to field c of object b of object +# a with value 7. In order to specify this behavior, the update must use a +# fieldmask "a.b.c". However, fieldmasks are only used for concrete values - +# transforms are separately encoded in a DocumentTransform_FieldTransform array. + +# This test exercises a bug found in python +# (https://github.com/googleapis/google-cloud-python/issues/7215) in which nested +# transforms ({"a.c": "ServerTimestamp"}) next to nested values ({"a.b": 7}) +# incorrectly caused the fieldmask "a" to be set, which has the effect of wiping +# out all data in "a" other than what was specified in the json-like input. + +# Instead, as this test specifies, transforms should not affect the fieldmask. + +description: "update: Nested transforms should not affect the field mask, even\nwhen there are other values that do. Transforms should only affect the\nDocumentTransform_FieldTransform list." +update: < + doc_ref_path: "projects/projectID/databases/(default)/documents/C/d" + json_data: "{\"a.b\": 7, \"a.c\": \"ServerTimestamp\"}" + request: < + database: "projects/projectID/databases/(default)" + writes: < + update: < + name: "projects/projectID/databases/(default)/documents/C/d" + fields: < + key: "a" + value: < + map_value: < + fields: < + key: "b" + value: < + integer_value: 7 + > + > + > + > + > + > + update_mask: < + field_paths: "a.b" + > + current_document: < + exists: true + > + > + writes: < + transform: < + document: "projects/projectID/databases/(default)/documents/C/d" + field_transforms: < + field_path: "a.c" + set_to_server_value: REQUEST_TIME + > + > + > + > +>