1use crate::local::{Connection, Statement};
2use crate::params::Params;
3use crate::rows::{ColumnsInner, RowInner, RowsInner};
4use crate::{errors, Error, Result};
5use crate::{Value, ValueRef};
6use libsql_sys::ValueType;
7
8use std::cell::RefCell;
9use std::collections::VecDeque;
10use std::ffi::c_char;
11use std::fmt;
12use std::sync::Arc;
13#[derive(Debug, Clone)]
15pub struct Rows {
16 stmt: Statement,
17 err: RefCell<Option<(i32, i32, String)>>,
18}
19
20unsafe impl Send for Rows {} unsafe impl Sync for Rows {} impl Rows {
24 pub fn new(stmt: Statement) -> Rows {
25 Rows {
26 stmt,
27 err: RefCell::new(None),
28 }
29 }
30
31 pub fn new2(stmt: Statement, err: RefCell<Option<(i32, i32, String)>>) -> Rows {
32 Rows { stmt, err }
33 }
34
35 pub fn next(&self) -> Result<Option<Row>> {
36 let err;
37 let err_code;
38 let err_msg;
39 if let Some((e, code, msg)) = self.err.take() {
40 err = e;
41 err_code = code;
42 err_msg = msg;
43 } else {
44 err = self.stmt.inner.step();
45 err_code = errors::extended_error_code(self.stmt.conn.raw);
46 err_msg = errors::error_from_handle(self.stmt.conn.raw);
47 }
48 match err {
49 libsql_sys::ffi::SQLITE_OK => Ok(None),
50 libsql_sys::ffi::SQLITE_DONE => Ok(None),
51 libsql_sys::ffi::SQLITE_ROW => Ok(Some(Row {
52 stmt: self.stmt.clone(),
53 })),
54 _ => Err(Error::SqliteFailure(err_code, err_msg)),
55 }
56 }
57
58 pub fn column_count(&self) -> i32 {
59 self.stmt.inner.column_count()
60 }
61
62 pub fn column_name(&self, idx: i32) -> Option<&str> {
63 self.stmt.inner.column_name(idx)
64 }
65
66 pub fn column_type(&self, idx: i32) -> Result<ValueType> {
67 let val = self.stmt.inner.column_type(idx);
68 match val {
69 libsql_sys::ffi::SQLITE_INTEGER => Ok(ValueType::Integer),
70 libsql_sys::ffi::SQLITE_FLOAT => Ok(ValueType::Real),
71 libsql_sys::ffi::SQLITE_BLOB => Ok(ValueType::Blob),
72 libsql_sys::ffi::SQLITE_TEXT => Ok(ValueType::Text),
73 libsql_sys::ffi::SQLITE_NULL => Ok(ValueType::Null),
74 _ => unreachable!("unknown column type {} at index {}", val, idx),
75 }
76 }
77}
78
79impl AsRef<Statement> for Rows {
80 fn as_ref(&self) -> &Statement {
81 &self.stmt
82 }
83}
84
85pub struct RowsFuture {
86 pub(crate) conn: Connection,
87 pub(crate) sql: String,
88 pub(crate) params: Params,
89}
90
91impl RowsFuture {
92 pub fn wait(&mut self) -> Result<Option<Rows>> {
93 futures::executor::block_on(self)
94 }
95}
96
97impl futures::Future for RowsFuture {
98 type Output = Result<Option<Rows>>;
99
100 fn poll(
101 self: std::pin::Pin<&mut Self>,
102 _cx: &mut std::task::Context<'_>,
103 ) -> std::task::Poll<Self::Output> {
104 let stmt = self.conn.prepare(&self.sql)?;
105 let ret = stmt.query(&self.params)?;
106 std::task::Poll::Ready(Ok(Some(ret)))
107 }
108}
109
110pub struct Row {
111 pub(crate) stmt: Statement,
112}
113
114impl AsRef<Statement> for Row {
115 fn as_ref(&self) -> &Statement {
116 &self.stmt
117 }
118}
119
120impl Row {
121 pub fn get<T>(&self, idx: i32) -> Result<T>
122 where
123 T: FromValue,
124 {
125 let val = self.stmt.inner.column_value(idx);
126 T::from_sql(val)
127 }
128
129 pub fn get_value(&self, idx: i32) -> Result<Value> {
130 let val = self.stmt.inner.column_value(idx);
131 <crate::Value as FromValue>::from_sql(val)
132 }
133
134 pub fn column_type(&self, idx: i32) -> Result<ValueType> {
135 let val = self.stmt.inner.column_type(idx);
136 match val {
137 libsql_sys::ffi::SQLITE_INTEGER => Ok(ValueType::Integer),
138 libsql_sys::ffi::SQLITE_FLOAT => Ok(ValueType::Real),
139 libsql_sys::ffi::SQLITE_BLOB => Ok(ValueType::Blob),
140 libsql_sys::ffi::SQLITE_TEXT => Ok(ValueType::Text),
141 libsql_sys::ffi::SQLITE_NULL => Ok(ValueType::Null),
142 _ => unreachable!("unknown column type: {} at index {}", val, idx),
143 }
144 }
145
146 pub fn column_name(&self, idx: i32) -> Option<&str> {
147 self.stmt.inner.column_name(idx)
148 }
149
150 pub fn get_ref(&self, idx: i32) -> Result<ValueRef<'_>> {
151 Ok(crate::local::Statement::value_ref(
152 &self.stmt.inner,
153 idx as usize,
154 ))
155 }
156}
157
158impl fmt::Debug for Row {
159 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::result::Result<(), fmt::Error> {
160 let mut dbg_map = f.debug_map();
161 for column in 0..self.stmt.column_count() {
162 dbg_map.key(&self.stmt.column_name(column));
163 let value = self.get_ref(column as i32);
164 match value {
165 Ok(value_ref) => {
166 let value_type = value_ref.data_type();
167 match value_ref {
168 ValueRef::Null => dbg_map.value(&(value_type, ())),
169 ValueRef::Integer(i) => dbg_map.value(&(value_type, i)),
170 ValueRef::Real(f) => dbg_map.value(&(value_type, f)),
171 ValueRef::Text(s) => {
172 dbg_map.value(&(value_type, String::from_utf8_lossy(s)))
173 }
174 ValueRef::Blob(b) => dbg_map.value(&(value_type, b.len())),
175 };
176 }
177 Err(_) => {
178 dbg_map.value(&value);
179 }
180 }
181 }
182 dbg_map.finish()
183 }
184}
185
186#[derive(Debug)]
187pub(crate) struct BatchedRows {
188 cols: Arc<Vec<(String, crate::value::ValueType)>>,
190 rows: VecDeque<Vec<Value>>,
191}
192
193impl BatchedRows {
194 pub fn new(cols: Vec<(String, crate::value::ValueType)>, rows: Vec<Vec<Value>>) -> Self {
195 Self {
196 cols: Arc::new(cols),
197 rows: rows.into(),
198 }
199 }
200}
201
202#[async_trait::async_trait]
203impl RowsInner for BatchedRows {
204 async fn next(&mut self) -> Result<Option<crate::Row>> {
205 let cols = self.cols.clone();
206 let row = self.rows.pop_front();
207
208 if let Some(row) = row {
209 Ok(Some(crate::Row {
210 inner: Box::new(BatchedRow { cols, row }),
211 }))
212 } else {
213 Ok(None)
214 }
215 }
216}
217
218impl ColumnsInner for BatchedRows {
219 fn column_count(&self) -> i32 {
220 self.cols.len() as i32
221 }
222
223 fn column_name(&self, idx: i32) -> Option<&str> {
224 self.cols.get(idx as usize).map(|s| s.0.as_str())
225 }
226
227 fn column_type(&self, idx: i32) -> Result<crate::value::ValueType> {
228 self.cols
229 .get(idx as usize)
230 .ok_or(Error::InvalidColumnIndex)
231 .map(|(_, vt)| vt.clone())
232 }
233}
234
235#[derive(Debug)]
236pub(crate) struct BatchedRow {
237 cols: Arc<Vec<(String, crate::value::ValueType)>>,
238 row: Vec<Value>,
239}
240
241impl RowInner for BatchedRow {
242 fn column_value(&self, idx: i32) -> Result<Value> {
243 self.row
244 .get(idx as usize)
245 .cloned()
246 .ok_or(Error::InvalidColumnIndex)
247 }
248
249 fn column_str(&self, idx: i32) -> Result<&str> {
250 self.row
251 .get(idx as usize)
252 .ok_or(Error::InvalidColumnIndex)
253 .and_then(|v| {
254 v.as_text()
255 .map(String::as_str)
256 .ok_or(Error::InvalidColumnType)
257 })
258 }
259}
260
261impl ColumnsInner for BatchedRow {
262 fn column_name(&self, idx: i32) -> Option<&str> {
263 self.cols.get(idx as usize).map(|c| c.0.as_str())
264 }
265
266 fn column_count(&self) -> i32 {
267 self.cols.len() as i32
268 }
269
270 fn column_type(&self, idx: i32) -> Result<crate::value::ValueType> {
271 self.cols
272 .get(idx as usize)
273 .ok_or(Error::InvalidColumnIndex)
274 .map(|(_, vt)| vt.clone())
275 }
276}
277
278pub trait FromValue {
279 fn from_sql(val: libsql_sys::Value) -> Result<Self>
280 where
281 Self: Sized;
282}
283
284impl FromValue for crate::Value {
285 fn from_sql(val: libsql_sys::Value) -> Result<Self> {
286 Ok(val.into())
287 }
288}
289
290impl FromValue for i32 {
291 fn from_sql(val: libsql_sys::Value) -> Result<Self> {
292 let ret = val.int();
293 Ok(ret)
294 }
295}
296
297impl FromValue for u32 {
298 fn from_sql(val: libsql_sys::Value) -> Result<Self> {
299 let ret = val.int() as u32;
300 Ok(ret)
301 }
302}
303
304impl FromValue for i64 {
305 fn from_sql(val: libsql_sys::Value) -> Result<Self> {
306 let ret = val.int64();
307 Ok(ret)
308 }
309}
310
311impl FromValue for u64 {
312 fn from_sql(val: libsql_sys::Value) -> Result<Self> {
313 let ret = val.int64() as u64;
314 Ok(ret)
315 }
316}
317
318impl FromValue for f64 {
319 fn from_sql(val: libsql_sys::Value) -> Result<Self> {
320 let ret = val.double();
321 Ok(ret)
322 }
323}
324
325impl FromValue for Vec<u8> {
326 fn from_sql(val: libsql_sys::Value) -> Result<Self> {
327 let ret = val.blob();
328 if ret.is_null() {
329 return Err(Error::NullValue);
330 }
331 let ret = unsafe { std::slice::from_raw_parts(ret as *const u8, val.bytes() as usize) };
332 Ok(ret.to_vec())
333 }
334}
335
336impl FromValue for String {
337 fn from_sql(val: libsql_sys::Value) -> Result<Self> {
338 let ret = val.text();
339 if ret.is_null() {
340 return Err(Error::NullValue);
341 }
342 let ret = unsafe { std::ffi::CStr::from_ptr(ret as *const c_char) };
343 let ret = ret.to_str().unwrap();
344 Ok(ret.to_string())
345 }
346}
347
348impl FromValue for &[u8] {
349 fn from_sql(val: libsql_sys::Value) -> Result<Self> {
350 let ret = val.blob();
351 if ret.is_null() {
352 return Err(Error::NullValue);
353 }
354 let ret = unsafe { std::slice::from_raw_parts(ret as *const u8, val.bytes() as usize) };
355 Ok(ret)
356 }
357}
358
359impl FromValue for &str {
360 fn from_sql(val: libsql_sys::Value) -> Result<Self> {
361 let ret = val.text();
362 if ret.is_null() {
363 return Err(Error::NullValue);
364 }
365 let ret = unsafe { std::ffi::CStr::from_ptr(ret as *const c_char) };
366 let ret = ret.to_str().unwrap();
367 Ok(ret)
368 }
369}
370
371pub struct MappedRows<F> {
372 rows: Rows,
373 map: F,
374}
375
376impl<F> MappedRows<F> {
377 pub fn new(rows: Rows, map: F) -> Self {
378 Self { rows, map }
379 }
380}
381
382impl<F, T> Iterator for MappedRows<F>
383where
384 F: FnMut(Row) -> Result<T>,
385{
386 type Item = Result<T>;
387
388 #[inline]
389 fn next(&mut self) -> Option<Self::Item> {
390 let map = &mut self.map;
391 self.rows
392 .next()
393 .transpose()
394 .map(|row_result| row_result.and_then(map))
395 }
396}