diff --git a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/models/CosmosPatchOperations.java b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/models/CosmosPatchOperations.java index 431512211d7d4..ca8d7ccca319a 100644 --- a/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/models/CosmosPatchOperations.java +++ b/sdk/cosmos/azure-cosmos/src/main/java/com/azure/cosmos/models/CosmosPatchOperations.java @@ -86,8 +86,6 @@ public static CosmosPatchOperations create() { * @return same instance of {@link CosmosPatchOperations} */ public CosmosPatchOperations add(String path, T value) { - - checkNotNull(value, "expected non-null value"); checkArgument(StringUtils.isNotEmpty(path), "path empty %s", path); this.patchOperations.add( @@ -182,7 +180,6 @@ public CosmosPatchOperations replace(String path, T value) { */ public CosmosPatchOperations set(String path, T value) { - checkNotNull(value, "expected non-null value"); checkArgument(StringUtils.isNotEmpty(path), "path empty %s", path); this.patchOperations.add( diff --git a/sdk/cosmos/azure-cosmos/src/test/java/com/azure/cosmos/PatchAsyncTest.java b/sdk/cosmos/azure-cosmos/src/test/java/com/azure/cosmos/PatchAsyncTest.java index f1264248ed4c5..526ee88cef858 100644 --- a/sdk/cosmos/azure-cosmos/src/test/java/com/azure/cosmos/PatchAsyncTest.java +++ b/sdk/cosmos/azure-cosmos/src/test/java/com/azure/cosmos/PatchAsyncTest.java @@ -3,6 +3,7 @@ package com.azure.cosmos; +import com.azure.cosmos.implementation.Utils; import com.azure.cosmos.models.CosmosBatch; import com.azure.cosmos.models.CosmosBatchPatchItemRequestOptions; import com.azure.cosmos.models.CosmosBatchResponse; @@ -12,7 +13,9 @@ import com.azure.cosmos.models.CosmosBulkPatchItemRequestOptions; import com.azure.cosmos.models.CosmosItemOperation; import com.azure.cosmos.models.CosmosItemResponse; +import com.azure.cosmos.models.CosmosPatchOperations; import com.azure.cosmos.models.PartitionKey; +import com.fasterxml.jackson.databind.node.ObjectNode; import io.netty.handler.codec.http.HttpResponseStatus; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; @@ -22,6 +25,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.UUID; import static org.assertj.core.api.Assertions.assertThat; @@ -251,4 +255,35 @@ public void patchInBulk() { testDocForPatch.setDescription("xx"); this.verifyByRead(container, testDocForPatch); } + + @Test(groups = { "emulator" }, timeOut = TIMEOUT) + public void itemPatchSuccessForNullValue() { + // Null value should be allowed for add, set, and replace + + ObjectNode objectNode = Utils.getSimpleObjectMapper().createObjectNode(); + String id = UUID.randomUUID().toString(); + String pkValue = "mypk"; + + String stringColumnName = "stringColumn"; + String stringColumnName2 = "stringColumn2"; + String newStringColumnName = "newStringColumn"; + + objectNode.put("id", id); + objectNode.put("mypk", pkValue); + objectNode.put(stringColumnName, UUID.randomUUID().toString()); + objectNode.put(stringColumnName2, UUID.randomUUID().toString()); + + this.container.createItem(objectNode).block(); + + CosmosPatchOperations patchOperations = CosmosPatchOperations.create(); + patchOperations.add("/" + newStringColumnName, null); + patchOperations.replace("/" + stringColumnName, null); + patchOperations.set("/" + stringColumnName2, null); + + ObjectNode patchedItem = this.container.patchItem(id, new PartitionKey(pkValue), patchOperations, ObjectNode.class).block().getItem(); + assertThat(patchedItem).isNotNull(); + assert(patchedItem.get(newStringColumnName)).isNull(); + assert(patchedItem.get(stringColumnName)).isNull(); + assert(patchedItem.get(stringColumnName2)).isNull(); + } } diff --git a/sdk/cosmos/azure-cosmos/src/test/java/com/azure/cosmos/PatchTest.java b/sdk/cosmos/azure-cosmos/src/test/java/com/azure/cosmos/PatchTest.java index f63525d6acfa5..f8a00b405c990 100644 --- a/sdk/cosmos/azure-cosmos/src/test/java/com/azure/cosmos/PatchTest.java +++ b/sdk/cosmos/azure-cosmos/src/test/java/com/azure/cosmos/PatchTest.java @@ -3,12 +3,15 @@ package com.azure.cosmos; +import com.azure.cosmos.implementation.Utils; import com.azure.cosmos.models.CosmosItemRequestOptions; import com.azure.cosmos.models.CosmosItemResponse; import com.azure.cosmos.models.CosmosPatchItemRequestOptions; +import com.azure.cosmos.models.CosmosPatchOperations; import com.azure.cosmos.models.PartitionKey; import com.azure.cosmos.rx.TestSuiteBase; import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.node.ObjectNode; import io.netty.handler.codec.http.HttpResponseStatus; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; @@ -55,7 +58,7 @@ public void itemConditionalPatchSuccess() { assertThat(testItem.children[1].status).isNull(); - com.azure.cosmos.models.CosmosPatchOperations cosmosPatchOperations = com.azure.cosmos.models.CosmosPatchOperations.create(); + CosmosPatchOperations cosmosPatchOperations = CosmosPatchOperations.create(); cosmosPatchOperations.add("/children/1/CamelCase", "patched"); cosmosPatchOperations.remove("/description"); cosmosPatchOperations.replace("/taskNum", newTaskNum); @@ -166,7 +169,7 @@ public void itemPatchContentResponseOnWriteEnabled() { assertThat(testItem.children[1].status).isNull(); - com.azure.cosmos.models.CosmosPatchOperations cosmosPatchOperations = com.azure.cosmos.models.CosmosPatchOperations.create(); + CosmosPatchOperations cosmosPatchOperations = CosmosPatchOperations.create(); cosmosPatchOperations.add("/children/1/CamelCase", "alpha"); cosmosPatchOperations.remove("/description"); cosmosPatchOperations.replace("/taskNum", newTaskNum); @@ -186,7 +189,7 @@ public void itemPatchContentResponseOnWriteEnabled() { assertThat(response.getItem()).isNull(); // skip content is true // Right now - com.azure.cosmos.models.CosmosPatchOperations cosmosPatchOperations2 = com.azure.cosmos.models.CosmosPatchOperations.create(); + CosmosPatchOperations cosmosPatchOperations2 = CosmosPatchOperations.create(); cosmosPatchOperations2.set("/valid", false); CosmosItemResponse response2 = this.container.patchItem( @@ -220,7 +223,7 @@ public void itemPatchContentResponseOnWriteEnabled() { public void itemPatchFailure() { // Create an item ToDoActivity testItem = ToDoActivity.createRandomItem(this.container); - com.azure.cosmos.models.CosmosPatchOperations cosmosPatchOperations = com.azure.cosmos.models.CosmosPatchOperations.create(); + CosmosPatchOperations cosmosPatchOperations = CosmosPatchOperations.create(); cosmosPatchOperations.add("/nonExistentParent/child", "bar"); cosmosPatchOperations.remove("/cost"); @@ -271,6 +274,37 @@ public void itemPatchFailure() { } } + @Test(groups = { "emulator" }, timeOut = TIMEOUT * 100) + public void itemPatchSuccessForNullValue() { + // Null value should be allowed for add, set, and replace + + ObjectNode objectNode = Utils.getSimpleObjectMapper().createObjectNode(); + String id = UUID.randomUUID().toString(); + String pkValue = "mypk"; + + String stringColumnName = "stringColumn"; + String stringColumnName2 = "stringColumn2"; + String newStringColumnName = "newStringColumn"; + + objectNode.put("id", id); + objectNode.put("mypk", pkValue); + objectNode.put(stringColumnName, UUID.randomUUID().toString()); + objectNode.put(stringColumnName2, UUID.randomUUID().toString()); + + this.container.createItem(objectNode); + + CosmosPatchOperations patchOperations = CosmosPatchOperations.create(); + patchOperations.add("/" + newStringColumnName, null); + patchOperations.replace("/" + stringColumnName, null); + patchOperations.set("/" + stringColumnName2, null); + + ObjectNode patchedItem = this.container.patchItem(id, new PartitionKey(pkValue), patchOperations, ObjectNode.class).getItem(); + assertThat(patchedItem).isNotNull(); + assert(patchedItem.get(newStringColumnName)).isNull(); + assert(patchedItem.get(stringColumnName)).isNull(); + assert(patchedItem.get(stringColumnName2)).isNull(); + } + public static class ToDoActivity { public String id;