1use libsql::params::IntoParams;
2
3use crate::error::{Error, Result};
4
5use super::from_row::FromRow;
6
7pub trait ConnExt: Sync {
13 fn query_raw(
15 &self,
16 sql: &str,
17 params: impl IntoParams + Send,
18 ) -> impl std::future::Future<Output = std::result::Result<libsql::Rows, libsql::Error>> + Send;
19
20 fn execute_raw(
22 &self,
23 sql: &str,
24 params: impl IntoParams + Send,
25 ) -> impl std::future::Future<Output = std::result::Result<u64, libsql::Error>> + Send;
26
27 fn select<'a>(&'a self, sql: &str) -> super::select::SelectBuilder<'a, Self>
29 where
30 Self: Sized,
31 {
32 super::select::SelectBuilder::new(self, sql)
33 }
34}
35
36impl ConnExt for libsql::Connection {
37 fn query_raw(
38 &self,
39 sql: &str,
40 params: impl IntoParams + Send,
41 ) -> impl std::future::Future<Output = std::result::Result<libsql::Rows, libsql::Error>> + Send
42 {
43 self.query(sql, params)
44 }
45
46 fn execute_raw(
47 &self,
48 sql: &str,
49 params: impl IntoParams + Send,
50 ) -> impl std::future::Future<Output = std::result::Result<u64, libsql::Error>> + Send {
51 self.execute(sql, params)
52 }
53}
54
55impl ConnExt for libsql::Transaction {
56 fn query_raw(
57 &self,
58 sql: &str,
59 params: impl IntoParams + Send,
60 ) -> impl std::future::Future<Output = std::result::Result<libsql::Rows, libsql::Error>> + Send
61 {
62 self.query(sql, params)
63 }
64
65 fn execute_raw(
66 &self,
67 sql: &str,
68 params: impl IntoParams + Send,
69 ) -> impl std::future::Future<Output = std::result::Result<u64, libsql::Error>> + Send {
70 self.execute(sql, params)
71 }
72}
73
74pub trait ConnQueryExt: ConnExt {
79 fn query_one<T: FromRow + Send>(
85 &self,
86 sql: &str,
87 params: impl IntoParams + Send,
88 ) -> impl std::future::Future<Output = Result<T>> + Send {
89 async move {
90 let mut rows = self.query_raw(sql, params).await.map_err(Error::from)?;
91 let row = rows
92 .next()
93 .await
94 .map_err(Error::from)?
95 .ok_or_else(|| Error::not_found("record not found"))?;
96 T::from_row(&row)
97 }
98 }
99
100 fn query_optional<T: FromRow + Send>(
106 &self,
107 sql: &str,
108 params: impl IntoParams + Send,
109 ) -> impl std::future::Future<Output = Result<Option<T>>> + Send {
110 async move {
111 let mut rows = self.query_raw(sql, params).await.map_err(Error::from)?;
112 match rows.next().await.map_err(Error::from)? {
113 Some(row) => Ok(Some(T::from_row(&row)?)),
114 None => Ok(None),
115 }
116 }
117 }
118
119 fn query_all<T: FromRow + Send>(
125 &self,
126 sql: &str,
127 params: impl IntoParams + Send,
128 ) -> impl std::future::Future<Output = Result<Vec<T>>> + Send {
129 async move {
130 let mut rows = self.query_raw(sql, params).await.map_err(Error::from)?;
131 let mut result = Vec::new();
132 while let Some(row) = rows.next().await.map_err(Error::from)? {
133 result.push(T::from_row(&row)?);
134 }
135 Ok(result)
136 }
137 }
138
139 fn query_one_map<T: Send, F>(
145 &self,
146 sql: &str,
147 params: impl IntoParams + Send,
148 f: F,
149 ) -> impl std::future::Future<Output = Result<T>> + Send
150 where
151 F: Fn(&libsql::Row) -> Result<T> + Send,
152 {
153 async move {
154 let mut rows = self.query_raw(sql, params).await.map_err(Error::from)?;
155 let row = rows
156 .next()
157 .await
158 .map_err(Error::from)?
159 .ok_or_else(|| Error::not_found("record not found"))?;
160 f(&row)
161 }
162 }
163
164 fn query_optional_map<T: Send, F>(
170 &self,
171 sql: &str,
172 params: impl IntoParams + Send,
173 f: F,
174 ) -> impl std::future::Future<Output = Result<Option<T>>> + Send
175 where
176 F: Fn(&libsql::Row) -> Result<T> + Send,
177 {
178 async move {
179 let mut rows = self.query_raw(sql, params).await.map_err(Error::from)?;
180 match rows.next().await.map_err(Error::from)? {
181 Some(row) => Ok(Some(f(&row)?)),
182 None => Ok(None),
183 }
184 }
185 }
186
187 fn query_all_map<T: Send, F>(
193 &self,
194 sql: &str,
195 params: impl IntoParams + Send,
196 f: F,
197 ) -> impl std::future::Future<Output = Result<Vec<T>>> + Send
198 where
199 F: Fn(&libsql::Row) -> Result<T> + Send,
200 {
201 async move {
202 let mut rows = self.query_raw(sql, params).await.map_err(Error::from)?;
203 let mut result = Vec::new();
204 while let Some(row) = rows.next().await.map_err(Error::from)? {
205 result.push(f(&row)?);
206 }
207 Ok(result)
208 }
209 }
210}
211
212impl<T: ConnExt> ConnQueryExt for T {}