Skip to main content

clt_database/turso/src/
rows.rs

1use crate::turso::{assert_send_sync, Column, Error, Result, Statement, Value};
2use std::fmt::Debug;
3use std::future::Future;
4
5/// Results of a prepared statement query.
6pub struct Rows {
7    inner: Statement,
8}
9
10impl Rows {
11    pub(crate) fn new(inner: Statement) -> Self {
12        Self { inner }
13    }
14
15    /// Returns the number of columns in the result set.
16    pub fn column_count(&self) -> usize {
17        self.inner.column_count()
18    }
19
20    /// Returns the name of the column at the given index.
21    pub fn column_name(&self, idx: usize) -> Result<String> {
22        self.inner.column_name(idx)
23    }
24
25    /// Returns the names of all columns in the result set.
26    pub fn column_names(&self) -> Vec<String> {
27        self.inner.column_names()
28    }
29
30    /// Returns the index of the column with the given name.
31    pub fn column_index(&self, name: &str) -> Result<usize> {
32        self.inner.column_index(name)
33    }
34
35    /// Returns columns of the result set.
36    pub fn columns(&self) -> Vec<Column> {
37        self.inner.columns()
38    }
39
40    /// Fetch the next row of this result set.
41    pub async fn next(&mut self) -> Result<Option<Row>> {
42        struct Next {
43            columns: usize,
44            stmt: Statement,
45        }
46
47        impl Future for Next {
48            type Output = Result<Option<Row>>;
49
50            fn poll(
51                self: std::pin::Pin<&mut Self>,
52                cx: &mut std::task::Context<'_>,
53            ) -> std::task::Poll<Self::Output> {
54                self.stmt.step(Some(self.columns), cx)
55            }
56        }
57
58        assert_send_sync!(Next);
59
60        let next = Next {
61            columns: self.inner.inner.lock().unwrap().column_count(),
62            stmt: self.inner.clone(),
63        };
64
65        next.await
66    }
67}
68
69/// Query result row.
70#[derive(Debug, PartialEq)]
71pub struct Row {
72    pub(crate) values: Vec<crate::turso_sdk_kit::rsapi::Value>,
73}
74
75impl Row {
76    pub fn get_value(&self, idx: usize) -> Result<Value> {
77        let val = self.values.get(idx).ok_or_else(|| {
78            Error::Misuse(format!(
79                "column index {idx} out of bounds (row has {} columns)",
80                self.values.len()
81            ))
82        })?;
83        match val {
84            crate::turso_sdk_kit::rsapi::Value::Numeric(crate::turso_sdk_kit::rsapi::Numeric::Integer(i)) => {
85                Ok(Value::Integer(*i))
86            }
87            crate::turso_sdk_kit::rsapi::Value::Numeric(crate::turso_sdk_kit::rsapi::Numeric::Float(f)) => {
88                Ok(Value::Real(f64::from(*f)))
89            }
90            crate::turso_sdk_kit::rsapi::Value::Null => Ok(Value::Null),
91            crate::turso_sdk_kit::rsapi::Value::Text(text) => {
92                Ok(Value::Text(text.value.clone().into_owned()))
93            }
94            crate::turso_sdk_kit::rsapi::Value::Blob(items) => Ok(Value::Blob(items.to_vec())),
95        }
96    }
97
98    pub fn get<T>(&self, idx: usize) -> Result<T>
99    where
100        T: crate::turso_sdk_kit::rsapi::FromValue,
101    {
102        let val = self.values.get(idx).ok_or_else(|| {
103            Error::Misuse(format!(
104                "column index {idx} out of bounds (row has {} columns)",
105                self.values.len()
106            ))
107        })?;
108        T::from_sql(val.clone()).map_err(|err| Error::ConversionFailure(err.to_string()))
109    }
110
111    pub fn column_count(&self) -> usize {
112        self.values.len()
113    }
114}