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