supabase_client_query/
update.rs1use std::marker::PhantomData;
2
3use serde::de::DeserializeOwned;
4
5use supabase_client_core::SupabaseResponse;
6
7use crate::backend::QueryBackend;
8use crate::filter::Filterable;
9use crate::modifier::Modifiable;
10use crate::sql::{FilterCondition, ParamStore, SqlParts};
11
12pub struct UpdateBuilder<T> {
15 pub(crate) backend: QueryBackend,
16 pub(crate) parts: SqlParts,
17 pub(crate) params: ParamStore,
18 pub(crate) _marker: PhantomData<T>,
19}
20
21impl<T> Filterable for UpdateBuilder<T> {
22 fn filters_mut(&mut self) -> &mut Vec<FilterCondition> {
23 &mut self.parts.filters
24 }
25 fn params_mut(&mut self) -> &mut ParamStore {
26 &mut self.params
27 }
28}
29
30impl<T> Modifiable for UpdateBuilder<T> {
31 fn parts_mut(&mut self) -> &mut SqlParts {
32 &mut self.parts
33 }
34}
35
36impl<T> UpdateBuilder<T> {
37 pub fn schema(mut self, schema: &str) -> Self {
41 self.parts.schema_override = Some(schema.to_string());
42 self
43 }
44
45 pub fn select(mut self) -> Self {
47 self.parts.returning = Some("*".to_string());
48 self
49 }
50
51 pub fn select_columns(mut self, columns: &str) -> Self {
53 if columns == "*" || columns.is_empty() {
54 self.parts.returning = Some("*".to_string());
55 } else {
56 let quoted = columns
57 .split(',')
58 .map(|c| {
59 let c = c.trim();
60 if c.contains('(') || c.contains('*') || c.contains('"') {
61 c.to_string()
62 } else {
63 format!("\"{}\"", c)
64 }
65 })
66 .collect::<Vec<_>>()
67 .join(", ");
68 self.parts.returning = Some(quoted);
69 }
70 self
71 }
72}
73
74#[cfg(not(feature = "direct-sql"))]
76impl<T> UpdateBuilder<T>
77where
78 T: DeserializeOwned + Send,
79{
80 pub async fn execute(self) -> SupabaseResponse<T> {
82 let QueryBackend::Rest { ref http, ref base_url, ref api_key, ref schema } = self.backend;
83 let (url, headers, body) = match crate::postgrest::build_postgrest_update(
84 base_url, &self.parts, &self.params,
85 ) {
86 Ok(r) => r,
87 Err(e) => return SupabaseResponse::error(
88 supabase_client_core::SupabaseError::QueryBuilder(e),
89 ),
90 };
91 crate::postgrest_execute::execute_rest(
92 http, reqwest::Method::PATCH, &url, headers, Some(body), api_key, schema, &self.parts,
93 ).await
94 }
95}
96
97#[cfg(feature = "direct-sql")]
99impl<T> UpdateBuilder<T>
100where
101 T: DeserializeOwned + Send + Unpin + for<'r> sqlx::FromRow<'r, sqlx::postgres::PgRow>,
102{
103 pub async fn execute(self) -> SupabaseResponse<T> {
105 match &self.backend {
106 QueryBackend::Rest { http, base_url, api_key, schema } => {
107 let (url, headers, body) = match crate::postgrest::build_postgrest_update(
108 base_url, &self.parts, &self.params,
109 ) {
110 Ok(r) => r,
111 Err(e) => return SupabaseResponse::error(
112 supabase_client_core::SupabaseError::QueryBuilder(e),
113 ),
114 };
115 crate::postgrest_execute::execute_rest(
116 http, reqwest::Method::PATCH, &url, headers, Some(body), api_key, schema, &self.parts,
117 ).await
118 }
119 QueryBackend::DirectSql { pool } => {
120 crate::execute::execute_typed::<T>(pool, &self.parts, &self.params).await
121 }
122 }
123 }
124}