Skip to content

Commit 4b58ebf

Browse files
authored
Add PatchDocument::condition and builder method for it (#2969)
Adds the ability to provide the `condition` for conditional patch operations. Related REST API docs here: - https://learn.microsoft.com/en-us/rest/api/cosmos-db/patch-a-document#conditional-patch-operation
1 parent 2cc1aec commit 4b58ebf

File tree

2 files changed

+51
-1
lines changed

2 files changed

+51
-1
lines changed

sdk/cosmos/azure_data_cosmos/examples/cosmos/patch.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,10 @@ impl PatchCommand {
4040
.iter()
4141
.map(|op| serde_json::from_str(op).expect("Invalid JSON patch operation"))
4242
.collect();
43-
let patch = PatchDocument { operations };
43+
let patch = PatchDocument {
44+
condition: None,
45+
operations,
46+
};
4447

4548
let response = container_client
4649
.patch_item(pk, &self.item_id, patch, None)

sdk/cosmos/azure_data_cosmos/src/models/patch_operations.rs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ use serde::{Deserialize, Serialize};
2323
/// .with_add("/color", "silver")?
2424
/// .with_move("/from", "/to")?;
2525
/// # assert_eq!(patch, PatchDocument {
26+
/// # condition: None,
2627
/// # operations: vec![
2728
/// # PatchOperation::Add {
2829
/// # path: "/color".into(),
@@ -39,10 +40,20 @@ use serde::{Deserialize, Serialize};
3940
/// ```
4041
#[derive(Default, Debug, Serialize, Deserialize, PartialEq, Eq)]
4142
pub struct PatchDocument {
43+
#[serde(skip_serializing_if = "Option::is_none")]
44+
pub condition: Option<Cow<'static, str>>,
4245
pub operations: Vec<PatchOperation>,
4346
}
4447

4548
impl PatchDocument {
49+
/// Adds a condition, which determines whether or not the patch should be applied.
50+
///
51+
/// The value is an SQL-like filter predicate as a string. For example, `from c where c.taskNum = 3`.
52+
pub fn with_condition(mut self, condition: impl Into<Cow<'static, str>>) -> Self {
53+
self.condition = Some(condition.into());
54+
self
55+
}
56+
4657
/// Adds a new "add" operation to the patch document.
4758
///
4859
/// See the [type documentation](PatchDocument) for more information on patch operations.
@@ -255,6 +266,18 @@ mod tests {
255266
Ok(())
256267
}
257268

269+
#[test]
270+
pub fn serialize_condition() -> Result<(), Box<dyn std::error::Error>> {
271+
let patch_document = PatchDocument::default().with_condition("from c where c.value = 0");
272+
273+
let serialized = serde_json::to_string(&patch_document).unwrap();
274+
assert_eq!(
275+
serialized,
276+
"{\"condition\":\"from c where c.value = 0\",\"operations\":[]}"
277+
);
278+
Ok(())
279+
}
280+
258281
#[test]
259282
pub fn serialize_add() -> Result<(), Box<dyn std::error::Error>> {
260283
let patch_document = PatchDocument::default().with_add(
@@ -380,6 +403,30 @@ mod tests {
380403
Ok(())
381404
}
382405

406+
#[test]
407+
pub fn cosmos_docs_conditional_patch_example() -> Result<(), Box<dyn std::error::Error>> {
408+
const TEST_DOC: &str = r#"{
409+
"condition": "from c where c.Address.ZipCode = '98101'",
410+
"operations": [
411+
{
412+
"op":"replace",
413+
"path":"/Address/ZipCode",
414+
"value":98107
415+
}
416+
]
417+
}"#;
418+
419+
let doc: PatchDocument = serde_json::from_str(TEST_DOC)?;
420+
421+
assert_eq!(
422+
doc,
423+
PatchDocument::default()
424+
.with_condition("from c where c.Address.ZipCode = '98101'")
425+
.with_replace("/Address/ZipCode", 98107)?
426+
);
427+
Ok(())
428+
}
429+
383430
#[test]
384431
pub fn to_json_number_f64() -> Result<(), Box<dyn std::error::Error>> {
385432
assert_eq!(

0 commit comments

Comments
 (0)