Skip to main content

surrealdb/api/method/
merge.rs

1use 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/// A merge future
19#[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	/// Converts to an owned type which can easily be moved to a different
35	/// thread
36	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}