surrealdb/api/method/
update.rs

1use crate::api::conn::Method;
2use crate::api::conn::Param;
3use crate::api::conn::Router;
4use crate::api::method::Content;
5use crate::api::method::Merge;
6use crate::api::method::Patch;
7use crate::api::opt::PatchOp;
8use crate::api::opt::Range;
9use crate::api::opt::Resource;
10use crate::api::Connection;
11use crate::api::Result;
12use crate::sql::Id;
13use crate::sql::Value;
14use serde::de::DeserializeOwned;
15use serde::Serialize;
16use std::future::Future;
17use std::future::IntoFuture;
18use std::marker::PhantomData;
19use std::pin::Pin;
20
21/// An update future
22#[derive(Debug)]
23#[must_use = "futures do nothing unless you `.await` or poll them"]
24pub struct Update<'r, C: Connection, R> {
25	pub(super) router: Result<&'r Router<C>>,
26	pub(super) resource: Result<Resource>,
27	pub(super) range: Option<Range<Id>>,
28	pub(super) response_type: PhantomData<R>,
29}
30
31macro_rules! into_future {
32	($method:ident) => {
33		fn into_future(self) -> Self::IntoFuture {
34			let Update {
35				router,
36				resource,
37				range,
38				..
39			} = self;
40			Box::pin(async move {
41				let param = match range {
42					Some(range) => resource?.with_range(range)?.into(),
43					None => resource?.into(),
44				};
45				let mut conn = Client::new(Method::Update);
46				conn.$method(router?, Param::new(vec![param])).await
47			})
48		}
49	};
50}
51
52impl<'r, Client> IntoFuture for Update<'r, Client, Value>
53where
54	Client: Connection,
55{
56	type Output = Result<Value>;
57	type IntoFuture = Pin<Box<dyn Future<Output = Self::Output> + Send + Sync + 'r>>;
58
59	into_future! {execute_value}
60}
61
62impl<'r, Client, R> IntoFuture for Update<'r, Client, Option<R>>
63where
64	Client: Connection,
65	R: DeserializeOwned,
66{
67	type Output = Result<Option<R>>;
68	type IntoFuture = Pin<Box<dyn Future<Output = Self::Output> + Send + Sync + 'r>>;
69
70	into_future! {execute_opt}
71}
72
73impl<'r, Client, R> IntoFuture for Update<'r, Client, Vec<R>>
74where
75	Client: Connection,
76	R: DeserializeOwned,
77{
78	type Output = Result<Vec<R>>;
79	type IntoFuture = Pin<Box<dyn Future<Output = Self::Output> + Send + Sync + 'r>>;
80
81	into_future! {execute_vec}
82}
83
84impl<C> Update<'_, C, Value>
85where
86	C: Connection,
87{
88	/// Restricts the records to update to those in the specified range
89	pub fn range(mut self, bounds: impl Into<Range<Id>>) -> Self {
90		self.range = Some(bounds.into());
91		self
92	}
93}
94
95impl<C, R> Update<'_, C, Vec<R>>
96where
97	C: Connection,
98{
99	/// Restricts the records to update to those in the specified range
100	pub fn range(mut self, bounds: impl Into<Range<Id>>) -> Self {
101		self.range = Some(bounds.into());
102		self
103	}
104}
105
106impl<'r, C, R> Update<'r, C, R>
107where
108	C: Connection,
109	R: DeserializeOwned,
110{
111	/// Replaces the current document / record data with the specified data
112	pub fn content<D>(self, data: D) -> Content<'r, C, D, R>
113	where
114		D: Serialize,
115	{
116		Content {
117			router: self.router,
118			method: Method::Update,
119			resource: self.resource,
120			range: self.range,
121			content: data,
122			response_type: PhantomData,
123		}
124	}
125
126	/// Merges the current document / record data with the specified data
127	pub fn merge<D>(self, data: D) -> Merge<'r, C, D, R>
128	where
129		D: Serialize,
130	{
131		Merge {
132			router: self.router,
133			resource: self.resource,
134			range: self.range,
135			content: data,
136			response_type: PhantomData,
137		}
138	}
139
140	/// Patches the current document / record data with the specified JSON Patch data
141	pub fn patch(self, PatchOp(patch): PatchOp) -> Patch<'r, C, R> {
142		Patch {
143			router: self.router,
144			resource: self.resource,
145			range: self.range,
146			patches: vec![patch],
147			response_type: PhantomData,
148		}
149	}
150}