trailbase_sqlite/
rows.rs

1use base64::prelude::*;
2use rusqlite::{Statement, types};
3use std::fmt::Debug;
4use std::ops::Index;
5use std::str::FromStr;
6use std::sync::Arc;
7use thiserror::Error;
8
9#[derive(Debug, Copy, Clone)]
10pub enum ValueType {
11  Integer = 1,
12  Real,
13  Text,
14  Blob,
15  Null,
16}
17
18impl FromStr for ValueType {
19  type Err = ();
20
21  fn from_str(s: &str) -> std::result::Result<ValueType, Self::Err> {
22    match s {
23      "TEXT" => Ok(ValueType::Text),
24      "INTEGER" => Ok(ValueType::Integer),
25      "BLOB" => Ok(ValueType::Blob),
26      "NULL" => Ok(ValueType::Null),
27      "REAL" => Ok(ValueType::Real),
28      _ => Err(()),
29    }
30  }
31}
32
33#[derive(Debug, Clone)]
34pub struct Column {
35  name: String,
36  decl_type: Option<ValueType>,
37}
38
39#[derive(Debug)]
40pub struct Rows(pub(crate) Vec<Row>, pub(crate) Arc<Vec<Column>>);
41
42pub(crate) fn columns(stmt: &Statement<'_>) -> Vec<Column> {
43  return stmt
44    .columns()
45    .into_iter()
46    .map(|c| Column {
47      name: c.name().to_string(),
48      decl_type: c.decl_type().and_then(|s| ValueType::from_str(s).ok()),
49    })
50    .collect();
51}
52
53impl Rows {
54  pub fn from_rows(mut rows: rusqlite::Rows) -> rusqlite::Result<Self> {
55    let columns: Arc<Vec<Column>> = Arc::new(rows.as_ref().map_or(vec![], columns));
56
57    let mut result = vec![];
58    while let Some(row) = rows.next()? {
59      result.push(Row::from_row(row, Some(columns.clone()))?);
60    }
61
62    return Ok(Self(result, columns));
63  }
64
65  pub fn len(&self) -> usize {
66    return self.0.len();
67  }
68
69  pub fn is_empty(&self) -> bool {
70    return self.0.is_empty();
71  }
72
73  pub fn iter(&self) -> std::slice::Iter<'_, Row> {
74    return self.0.iter();
75  }
76
77  pub fn get(&self, idx: usize) -> Option<&Row> {
78    return self.0.get(idx);
79  }
80
81  pub fn last(&self) -> Option<&Row> {
82    return self.0.last();
83  }
84
85  pub fn column_count(&self) -> usize {
86    return self.1.len();
87  }
88
89  pub fn column_names(&self) -> Vec<&str> {
90    return self.1.iter().map(|s| s.name.as_str()).collect();
91  }
92
93  pub fn column_name(&self, idx: usize) -> Option<&str> {
94    return self.1.get(idx).map(|c| c.name.as_str());
95  }
96
97  pub fn column_type(&self, idx: usize) -> std::result::Result<ValueType, rusqlite::Error> {
98    if let Some(c) = self.1.get(idx) {
99      return c.decl_type.ok_or_else(|| {
100        rusqlite::Error::InvalidColumnType(
101          idx,
102          self.column_name(idx).unwrap_or("?").to_string(),
103          types::Type::Null,
104        )
105      });
106    }
107
108    return Err(rusqlite::Error::InvalidColumnType(
109      idx,
110      self.column_name(idx).unwrap_or("?").to_string(),
111      types::Type::Null,
112    ));
113  }
114}
115
116impl Index<usize> for Rows {
117  type Output = Row;
118
119  fn index(&self, idx: usize) -> &Self::Output {
120    return &self.0[idx];
121  }
122}
123
124impl IntoIterator for Rows {
125  type Item = Row;
126  type IntoIter = std::vec::IntoIter<Self::Item>;
127
128  fn into_iter(self) -> Self::IntoIter {
129    return self.0.into_iter();
130  }
131}
132
133#[derive(Debug)]
134pub struct Row(Vec<types::Value>, Arc<Vec<Column>>);
135
136impl Row {
137  pub fn from_row(row: &rusqlite::Row, cols: Option<Arc<Vec<Column>>>) -> rusqlite::Result<Self> {
138    let columns = cols.unwrap_or_else(|| Arc::new(columns(row.as_ref())));
139
140    let values = (0..columns.len())
141      .map(|idx| Ok(row.get_ref(idx)?.into()))
142      .collect::<Result<Vec<types::Value>, rusqlite::Error>>()?;
143
144    return Ok(Self(values, columns));
145  }
146
147  pub fn split_off(&mut self, at: usize) -> Row {
148    let split_values = self.0.split_off(at);
149    let mut columns = (*self.1).clone();
150    let split_columns = columns.split_off(at);
151    self.1 = Arc::new(columns);
152    return Row(split_values, Arc::new(split_columns));
153  }
154
155  pub fn get<T>(&self, idx: usize) -> types::FromSqlResult<T>
156  where
157    T: types::FromSql,
158  {
159    let Some(value) = self.0.get(idx) else {
160      return Err(types::FromSqlError::OutOfRange(idx as i64));
161    };
162    return T::column_result(value.into());
163  }
164
165  pub fn get_value(&self, idx: usize) -> Option<&types::Value> {
166    return self.0.get(idx);
167  }
168
169  pub fn len(&self) -> usize {
170    assert_eq!(self.1.len(), self.0.len());
171    return self.0.len();
172  }
173
174  pub fn is_empty(&self) -> bool {
175    return self.0.is_empty();
176  }
177
178  pub fn last(&self) -> Option<&types::Value> {
179    return self.0.last();
180  }
181
182  pub fn column_count(&self) -> usize {
183    assert_eq!(self.1.len(), self.0.len());
184    return self.1.len();
185  }
186
187  pub fn column_names(&self) -> Vec<&str> {
188    return self.1.iter().map(|s| s.name.as_str()).collect();
189  }
190
191  pub fn column_name(&self, idx: usize) -> Option<&str> {
192    return self.1.get(idx).map(|c| c.name.as_str());
193  }
194}
195
196impl Index<usize> for Row {
197  type Output = types::Value;
198
199  fn index(&self, idx: usize) -> &Self::Output {
200    return &self.0[idx];
201  }
202}
203
204#[derive(Debug, Error)]
205pub enum JsonError {
206  #[error("Float not finite")]
207  Finite,
208  #[error("Value not found")]
209  ValueNotFound,
210}
211
212pub fn value_to_json(value: &types::Value) -> Result<serde_json::Value, JsonError> {
213  return Ok(match value {
214    types::Value::Null => serde_json::Value::Null,
215    types::Value::Real(real) => {
216      let Some(number) = serde_json::Number::from_f64(*real) else {
217        return Err(JsonError::Finite);
218      };
219      serde_json::Value::Number(number)
220    }
221    types::Value::Integer(integer) => serde_json::Value::Number(serde_json::Number::from(*integer)),
222    types::Value::Blob(blob) => serde_json::Value::String(BASE64_URL_SAFE.encode(blob)),
223    types::Value::Text(text) => serde_json::Value::String(text.clone()),
224  });
225}
226
227pub fn row_to_json_array(row: &Row) -> Result<Vec<serde_json::Value>, JsonError> {
228  let cols = row.column_count();
229  let mut json_row = Vec::<serde_json::Value>::with_capacity(cols);
230
231  for i in 0..cols {
232    let value = row.get_value(i).ok_or(JsonError::ValueNotFound)?;
233    json_row.push(value_to_json(value)?);
234  }
235
236  return Ok(json_row);
237}
238
239pub fn rows_to_json_arrays(rows: &Rows) -> Result<Vec<Vec<serde_json::Value>>, JsonError> {
240  return rows.iter().map(row_to_json_array).collect();
241}