Skip to main content

sofie_db/
rows.rs

1use sofie_core::{ColumnReader, ColumnSpec, Result, SqlType, SqlValue};
2
3use crate::{Driver, RowSink};
4
5pub struct Decoding<T, F> {
6    expects: Vec<Option<SqlType>>,
7    decode: F,
8    decoded: Vec<T>,
9}
10
11impl<T, F> Decoding<T, F>
12where
13    T: Send,
14    F: FnMut(&mut dyn ColumnReader) -> Result<T> + Send,
15{
16    pub fn new(expects: Vec<Option<SqlType>>, decode: F) -> Self {
17        Self {
18            expects,
19            decode,
20            decoded: Vec::new(),
21        }
22    }
23
24    pub(crate) fn reserve(&mut self, rows: usize) {
25        self.decoded.reserve(rows);
26    }
27
28    pub fn into_decoded(self) -> Vec<T> {
29        self.decoded
30    }
31}
32
33impl<T, F> RowSink for Decoding<T, F>
34where
35    T: Send,
36    F: FnMut(&mut dyn ColumnReader) -> Result<T> + Send,
37{
38    fn expects(&self) -> &[Option<SqlType>] {
39        &self.expects
40    }
41
42    fn row(&mut self, row: &mut dyn ColumnReader) -> Result<()> {
43        self.decoded.push((self.decode)(row)?);
44        Ok(())
45    }
46}
47
48pub async fn query_decoded<T: Send>(
49    driver: &dyn Driver,
50    sql: &str,
51    params: &[SqlValue],
52    expects: Vec<Option<SqlType>>,
53    decode: impl FnMut(&mut dyn ColumnReader) -> Result<T> + Send,
54) -> Result<Vec<T>> {
55    let mut rows = Decoding::new(expects, decode);
56    driver.query(sql, params, &mut rows).await?;
57    Ok(rows.into_decoded())
58}
59
60/// Each row as owned values, for the few reads that have no type to decode into.
61pub async fn query_values(
62    driver: &dyn Driver,
63    sql: &str,
64    params: &[SqlValue],
65) -> Result<Vec<Vec<SqlValue>>> {
66    query_decoded(driver, sql, params, Vec::new(), row_values).await
67}
68
69pub fn row_values(row: &mut dyn ColumnReader) -> Result<Vec<SqlValue>> {
70    (0..row.remaining()).map(|_| row.value()).collect()
71}
72
73#[must_use]
74pub fn column_types(fields: &[&[ColumnSpec]]) -> Vec<Option<SqlType>> {
75    fields
76        .iter()
77        .flat_map(|columns| columns.iter().map(|column| Some(column.ty)))
78        .collect()
79}