nextsql_backend_rust_runtime/
lib.rs1use std::future::Future;
2
3#[derive(Debug, Clone, PartialEq)]
7pub enum UpdateField<T> {
8 Unchanged,
9 Set(T),
10}
11
12impl<T> UpdateField<T> {
13 pub fn is_set(&self) -> bool {
14 matches!(self, UpdateField::Set(_))
15 }
16
17 pub fn is_unchanged(&self) -> bool {
18 matches!(self, UpdateField::Unchanged)
19 }
20}
21
22impl<T> Default for UpdateField<T> {
23 fn default() -> Self {
24 UpdateField::Unchanged
25 }
26}
27
28pub trait ToSqlParam: Send + Sync {
30 fn as_any(&self) -> &(dyn std::any::Any + Send + Sync);
33}
34
35pub trait Row: Send {
37 fn get_i16(&self, idx: usize) -> i16;
38 fn get_i32(&self, idx: usize) -> i32;
39 fn get_i64(&self, idx: usize) -> i64;
40 fn get_f32(&self, idx: usize) -> f32;
41 fn get_f64(&self, idx: usize) -> f64;
42 fn get_string(&self, idx: usize) -> String;
43 fn get_bool(&self, idx: usize) -> bool;
44 fn get_uuid(&self, idx: usize) -> uuid::Uuid;
45 fn get_timestamp(&self, idx: usize) -> chrono::NaiveDateTime;
46 fn get_timestamptz(&self, idx: usize) -> chrono::DateTime<chrono::Utc>;
47 fn get_date(&self, idx: usize) -> chrono::NaiveDate;
48 fn get_decimal(&self, idx: usize) -> rust_decimal::Decimal;
49 fn get_json(&self, idx: usize) -> serde_json::Value;
50
51 fn get_opt_i16(&self, idx: usize) -> Option<i16>;
53 fn get_opt_i32(&self, idx: usize) -> Option<i32>;
54 fn get_opt_i64(&self, idx: usize) -> Option<i64>;
55 fn get_opt_f32(&self, idx: usize) -> Option<f32>;
56 fn get_opt_f64(&self, idx: usize) -> Option<f64>;
57 fn get_opt_string(&self, idx: usize) -> Option<String>;
58 fn get_opt_bool(&self, idx: usize) -> Option<bool>;
59 fn get_opt_uuid(&self, idx: usize) -> Option<uuid::Uuid>;
60 fn get_opt_timestamp(&self, idx: usize) -> Option<chrono::NaiveDateTime>;
61 fn get_opt_timestamptz(&self, idx: usize) -> Option<chrono::DateTime<chrono::Utc>>;
62 fn get_opt_date(&self, idx: usize) -> Option<chrono::NaiveDate>;
63 fn get_opt_decimal(&self, idx: usize) -> Option<rust_decimal::Decimal>;
64 fn get_opt_json(&self, idx: usize) -> Option<serde_json::Value>;
65
66 fn get_vec_i16(&self, idx: usize) -> Vec<i16>;
68 fn get_vec_i32(&self, idx: usize) -> Vec<i32>;
69 fn get_vec_i64(&self, idx: usize) -> Vec<i64>;
70 fn get_vec_f32(&self, idx: usize) -> Vec<f32>;
71 fn get_vec_f64(&self, idx: usize) -> Vec<f64>;
72 fn get_vec_string(&self, idx: usize) -> Vec<String>;
73 fn get_vec_bool(&self, idx: usize) -> Vec<bool>;
74 fn get_vec_uuid(&self, idx: usize) -> Vec<uuid::Uuid>;
75}
76
77pub trait QueryExecutor: Send + Sync {
82 type Error: std::error::Error + Send + Sync + 'static;
83 type Row: Row;
84
85 fn query(
87 &self,
88 sql: &str,
89 params: &[&dyn ToSqlParam],
90 ) -> impl Future<Output = Result<Vec<Self::Row>, Self::Error>> + Send;
91
92 fn execute(
94 &self,
95 sql: &str,
96 params: &[&dyn ToSqlParam],
97 ) -> impl Future<Output = Result<u64, Self::Error>> + Send;
98}
99
100pub trait Client: QueryExecutor {
106 type Transaction<'a>: Transaction<Error = Self::Error, Row = Self::Row> + 'a where Self: 'a;
107
108 fn transaction(&mut self) -> impl Future<Output = Result<Self::Transaction<'_>, Self::Error>> + Send;
110}
111
112pub trait Transaction: QueryExecutor {
116 type Nested<'a>: Transaction<Error = Self::Error, Row = Self::Row> + 'a where Self: 'a;
117
118 fn transaction(&mut self) -> impl Future<Output = Result<Self::Nested<'_>, Self::Error>> + Send;
120
121 fn commit(self) -> impl Future<Output = Result<(), Self::Error>> + Send;
123
124 fn rollback(self) -> impl Future<Output = Result<(), Self::Error>> + Send;
126}
127
128macro_rules! impl_to_sql_param {
131 ($($ty:ty),*) => {
132 $(
133 impl ToSqlParam for $ty {
134 fn as_any(&self) -> &(dyn std::any::Any + Send + Sync) {
135 self
136 }
137 }
138 )*
139 };
140}
141
142impl_to_sql_param!(
143 i16, i32, i64, f32, f64, bool, String,
144 uuid::Uuid, chrono::NaiveDateTime, chrono::NaiveDate,
145 rust_decimal::Decimal
146);
147
148impl ToSqlParam for chrono::DateTime<chrono::Utc> {
149 fn as_any(&self) -> &(dyn std::any::Any + Send + Sync) {
150 self
151 }
152}
153
154impl ToSqlParam for serde_json::Value {
155 fn as_any(&self) -> &(dyn std::any::Any + Send + Sync) {
156 self
157 }
158}
159
160impl ToSqlParam for &'static str {
161 fn as_any(&self) -> &(dyn std::any::Any + Send + Sync) {
162 self
163 }
164}
165
166impl<T: ToSqlParam + 'static> ToSqlParam for Option<T> {
167 fn as_any(&self) -> &(dyn std::any::Any + Send + Sync) {
168 self
169 }
170}
171
172impl<T: ToSqlParam + 'static> ToSqlParam for Vec<T> {
173 fn as_any(&self) -> &(dyn std::any::Any + Send + Sync) {
174 self
175 }
176}
177
178impl<T: ToSqlParam + 'static> ToSqlParam for UpdateField<T> {
179 fn as_any(&self) -> &(dyn std::any::Any + Send + Sync) {
180 match self {
181 UpdateField::Set(v) => v.as_any(),
182 UpdateField::Unchanged => panic!("Unchanged fields should not be passed as SQL params"),
183 }
184 }
185}
186
187#[cfg(feature = "backend-tokio-postgres")]
188pub mod tokio_postgres_impl;