trailbase_sqlite/
rows.rs

1use rusqlite::{types, Statement};
2use std::fmt::Debug;
3use std::ops::Index;
4use std::str::FromStr;
5use std::sync::Arc;
6
7#[derive(Debug, Copy, Clone)]
8pub enum ValueType {
9  Integer = 1,
10  Real,
11  Text,
12  Blob,
13  Null,
14}
15
16impl FromStr for ValueType {
17  type Err = ();
18
19  fn from_str(s: &str) -> std::result::Result<ValueType, Self::Err> {
20    match s {
21      "TEXT" => Ok(ValueType::Text),
22      "INTEGER" => Ok(ValueType::Integer),
23      "BLOB" => Ok(ValueType::Blob),
24      "NULL" => Ok(ValueType::Null),
25      "REAL" => Ok(ValueType::Real),
26      _ => Err(()),
27    }
28  }
29}
30
31#[allow(unused)]
32#[derive(Debug)]
33pub struct Column {
34  name: String,
35  decl_type: Option<ValueType>,
36}
37
38#[derive(Debug)]
39pub struct Rows(pub(crate) Vec<Row>, pub(crate) Arc<Vec<Column>>);
40
41pub(crate) fn columns(stmt: &Statement<'_>) -> Vec<Column> {
42  return stmt
43    .columns()
44    .into_iter()
45    .map(|c| Column {
46      name: c.name().to_string(),
47      decl_type: c.decl_type().and_then(|s| ValueType::from_str(s).ok()),
48    })
49    .collect();
50}
51
52impl Rows {
53  pub fn from_rows(mut rows: rusqlite::Rows) -> rusqlite::Result<Self> {
54    let columns: Arc<Vec<Column>> = Arc::new(rows.as_ref().map_or(vec![], columns));
55
56    let mut result = vec![];
57    while let Some(row) = rows.next()? {
58      result.push(Row::from_row(row, Some(columns.clone()))?);
59    }
60
61    return Ok(Self(result, columns));
62  }
63
64  pub fn len(&self) -> usize {
65    return self.0.len();
66  }
67
68  pub fn is_empty(&self) -> bool {
69    return self.0.is_empty();
70  }
71
72  pub fn iter(&self) -> std::slice::Iter<'_, Row> {
73    return self.0.iter();
74  }
75
76  pub fn get(&self, idx: usize) -> Option<&Row> {
77    return self.0.get(idx);
78  }
79
80  pub fn last(&self) -> Option<&Row> {
81    return self.0.last();
82  }
83
84  pub fn column_count(&self) -> usize {
85    return self.1.len();
86  }
87
88  pub fn column_names(&self) -> Vec<&str> {
89    return self.1.iter().map(|s| s.name.as_str()).collect();
90  }
91
92  pub fn column_name(&self, idx: usize) -> Option<&str> {
93    return self.1.get(idx).map(|c| c.name.as_str());
94  }
95
96  pub fn column_type(&self, idx: usize) -> std::result::Result<ValueType, rusqlite::Error> {
97    if let Some(c) = self.1.get(idx) {
98      return c.decl_type.ok_or_else(|| {
99        rusqlite::Error::InvalidColumnType(
100          idx,
101          self.column_name(idx).unwrap_or("?").to_string(),
102          types::Type::Null,
103        )
104      });
105    }
106
107    return Err(rusqlite::Error::InvalidColumnType(
108      idx,
109      self.column_name(idx).unwrap_or("?").to_string(),
110      types::Type::Null,
111    ));
112  }
113}
114
115impl Index<usize> for Rows {
116  type Output = Row;
117
118  fn index(&self, idx: usize) -> &Self::Output {
119    return &self.0[idx];
120  }
121}
122
123#[derive(Debug)]
124pub struct Row(Vec<types::Value>, Arc<Vec<Column>>);
125
126impl Row {
127  pub fn from_row(row: &rusqlite::Row, cols: Option<Arc<Vec<Column>>>) -> rusqlite::Result<Self> {
128    let columns = cols.unwrap_or_else(|| Arc::new(columns(row.as_ref())));
129
130    let count = columns.len();
131    let mut values = Vec::<types::Value>::with_capacity(count);
132    for idx in 0..count {
133      values.push(row.get_ref(idx)?.into());
134    }
135
136    return Ok(Self(values, columns));
137  }
138
139  pub fn get<T>(&self, idx: usize) -> types::FromSqlResult<T>
140  where
141    T: types::FromSql,
142  {
143    let Some(value) = self.0.get(idx) else {
144      return Err(types::FromSqlError::OutOfRange(idx as i64));
145    };
146    return T::column_result(value.into());
147  }
148
149  pub fn get_value(&self, idx: usize) -> Option<&types::Value> {
150    return self.0.get(idx);
151  }
152
153  pub fn len(&self) -> usize {
154    assert_eq!(self.1.len(), self.0.len());
155    return self.0.len();
156  }
157
158  pub fn is_empty(&self) -> bool {
159    return self.0.is_empty();
160  }
161
162  pub fn column_count(&self) -> usize {
163    assert_eq!(self.1.len(), self.0.len());
164    return self.1.len();
165  }
166
167  pub fn column_names(&self) -> Vec<&str> {
168    return self.1.iter().map(|s| s.name.as_str()).collect();
169  }
170
171  pub fn column_name(&self, idx: usize) -> Option<&str> {
172    return self.1.get(idx).map(|c| c.name.as_str());
173  }
174}
175
176impl Index<usize> for Row {
177  type Output = types::Value;
178
179  fn index(&self, idx: usize) -> &Self::Output {
180    return &self.0[idx];
181  }
182}