Skip to main content

kstone_client/
update.rs

1/// Remote update operations
2use crate::convert::*;
3use crate::error::Result;
4use kstone_core::Item;
5use kstone_proto::{self as proto, keystone_db_client::KeystoneDbClient};
6use tonic::transport::Channel;
7use std::collections::HashMap;
8
9/// Remote update request builder
10pub struct RemoteUpdate {
11    partition_key: Vec<u8>,
12    sort_key: Option<Vec<u8>>,
13    update_expression: String,
14    condition_expression: Option<String>,
15    expression_values: HashMap<String, kstone_core::Value>,
16}
17
18impl RemoteUpdate {
19    /// Create a new update operation
20    pub fn new(pk: &[u8]) -> Self {
21        Self {
22            partition_key: pk.to_vec(),
23            sort_key: None,
24            update_expression: String::new(),
25            condition_expression: None,
26            expression_values: HashMap::new(),
27        }
28    }
29
30    /// Create update with sort key
31    pub fn with_sk(pk: &[u8], sk: &[u8]) -> Self {
32        Self {
33            partition_key: pk.to_vec(),
34            sort_key: Some(sk.to_vec()),
35            update_expression: String::new(),
36            condition_expression: None,
37            expression_values: HashMap::new(),
38        }
39    }
40
41    /// Set the update expression
42    pub fn expression(mut self, expr: impl Into<String>) -> Self {
43        self.update_expression = expr.into();
44        self
45    }
46
47    /// Set a condition expression
48    pub fn condition(mut self, condition: impl Into<String>) -> Self {
49        self.condition_expression = Some(condition.into());
50        self
51    }
52
53    /// Add an expression attribute value
54    pub fn value(mut self, placeholder: impl Into<String>, value: kstone_core::Value) -> Self {
55        self.expression_values.insert(placeholder.into(), value);
56        self
57    }
58
59    /// Execute the update operation
60    pub async fn execute(self, client: &mut KeystoneDbClient<Channel>) -> Result<RemoteUpdateResponse> {
61        // Convert expression values to protobuf
62        let proto_values: HashMap<String, proto::Value> = self
63            .expression_values
64            .iter()
65            .map(|(k, v)| (k.clone(), ks_value_to_proto(v)))
66            .collect();
67
68        let request = proto::UpdateRequest {
69            partition_key: self.partition_key,
70            sort_key: self.sort_key,
71            update_expression: self.update_expression,
72            condition_expression: self.condition_expression,
73            expression_values: proto_values,
74        };
75
76        let response = client
77            .update(request)
78            .await?
79            .into_inner();
80
81        let item = proto_item_to_ks(
82            response.item.expect("Server should return updated item")
83        )?;
84
85        Ok(RemoteUpdateResponse { item })
86    }
87}
88
89/// Update response
90pub struct RemoteUpdateResponse {
91    /// The updated item
92    pub item: Item,
93}