surrealdb/api/method/
merge.rs1use std::borrow::Cow;
2use std::future::IntoFuture;
3use std::marker::PhantomData;
4
5use serde::Serialize;
6use serde::de::DeserializeOwned;
7use uuid::Uuid;
8
9use super::validate_data;
10use crate::Surreal;
11use crate::api::conn::Command;
12use crate::api::method::BoxFuture;
13use crate::api::opt::Resource;
14use crate::api::{Connection, Result};
15use crate::method::OnceLockExt;
16use crate::value::Value;
17
18#[derive(Debug)]
20#[must_use = "futures do nothing unless you `.await` or poll them"]
21pub struct Merge<'r, C: Connection, D, R> {
22 pub(super) txn: Option<Uuid>,
23 pub(super) client: Cow<'r, Surreal<C>>,
24 pub(super) resource: Result<Resource>,
25 pub(super) content: D,
26 pub(super) upsert: bool,
27 pub(super) response_type: PhantomData<R>,
28}
29
30impl<C, D, R> Merge<'_, C, D, R>
31where
32 C: Connection,
33{
34 pub fn into_owned(self) -> Merge<'static, C, D, R> {
37 Merge {
38 client: Cow::Owned(self.client.into_owned()),
39 ..self
40 }
41 }
42}
43
44macro_rules! into_future {
45 () => {
46 fn into_future(self) -> Self::IntoFuture {
47 let Merge {
48 txn,
49 client,
50 resource,
51 content,
52 upsert,
53 ..
54 } = self;
55 let content = crate::api::value::to_core_value(content);
56 Box::pin(async move {
57 let content = match content? {
58 crate::core::val::Value::None | surrealdb_core::val::Value::Null => None,
59 data => {
60 validate_data(
61 &data,
62 "Tried to merge non-object-like data, only structs and objects are supported",
63 )?;
64 Some(data)
65 }
66 };
67
68 let router = client.inner.router.extract()?;
69 let cmd = Command::Merge {
70 upsert,
71 txn,
72 what: resource?,
73 data: content,
74 };
75 router.execute_query(cmd).await?.take(0)
76 })
77 }
78 };
79}
80
81impl<'r, Client, D> IntoFuture for Merge<'r, Client, D, Value>
82where
83 Client: Connection,
84 D: Serialize + 'static,
85{
86 type Output = Result<Value>;
87 type IntoFuture = BoxFuture<'r, Self::Output>;
88
89 into_future! {}
90}
91
92impl<'r, Client, D, R> IntoFuture for Merge<'r, Client, D, Option<R>>
93where
94 Client: Connection,
95 D: Serialize + 'static,
96 R: DeserializeOwned,
97{
98 type Output = Result<Option<R>>;
99 type IntoFuture = BoxFuture<'r, Self::Output>;
100
101 into_future! {}
102}
103
104impl<'r, Client, D, R> IntoFuture for Merge<'r, Client, D, Vec<R>>
105where
106 Client: Connection,
107 D: Serialize + 'static,
108 R: DeserializeOwned,
109{
110 type Output = Result<Vec<R>>;
111 type IntoFuture = BoxFuture<'r, Self::Output>;
112
113 into_future! {}
114}