libsql/local/
rows.rs

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/// Query result rows.
14#[derive(Debug, Clone)]
15pub struct Rows {
16    stmt: Statement,
17    err: RefCell<Option<(i32, i32, String)>>,
18}
19
20unsafe impl Send for Rows {} // TODO: is this safe?
21unsafe impl Sync for Rows {} // TODO: is this safe?
22
23impl 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    /// Colname, decl_type
189    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}