rbdc_sqlite/
row.rs

1#![allow(clippy::rc_buffer)]
2
3use crate::decode::Decode;
4use crate::statement::StatementHandle;
5use crate::{SqliteColumn, SqliteValue, SqliteValueRef};
6use rbdc::db::{MetaData, Row};
7use rbdc::error::Error;
8use rbdc::ext::ustr::UStr;
9use rbs::Value;
10use std::collections::HashMap;
11use std::fmt::Debug;
12use std::sync::Arc;
13
14/// Implementation of [`Row`] for SQLite.
15#[derive(Debug)]
16pub struct SqliteRow {
17    pub(crate) values: Vec<SqliteValue>,
18    pub(crate) columns: Arc<Vec<SqliteColumn>>,
19    pub(crate) column_names: Arc<HashMap<UStr, usize>>,
20}
21
22// Accessing values from the statement object is
23// safe across threads as long as we don't call [sqlite3_step]
24
25// we block ourselves from doing that by only exposing
26// a set interface on [StatementHandle]
27
28unsafe impl Send for SqliteRow {}
29
30unsafe impl Sync for SqliteRow {}
31
32impl SqliteRow {
33    pub(crate) fn current(
34        statement: &StatementHandle,
35        columns: &Arc<Vec<SqliteColumn>>,
36        column_names: &Arc<HashMap<UStr, usize>>,
37    ) -> Self {
38        let size = statement.column_count();
39        let mut values = Vec::with_capacity(size);
40
41        for i in 0..columns.len() {
42            values.push(unsafe {
43                let raw = statement.column_value(i);
44                SqliteValue::new(raw, columns[i].type_info.clone())
45            });
46        }
47
48        Self {
49            values: values,
50            columns: Arc::clone(columns),
51            column_names: Arc::clone(column_names),
52        }
53    }
54}
55
56#[derive(Debug)]
57pub struct SqliteMetaData {
58    pub columns: Arc<Vec<SqliteColumn>>,
59}
60
61impl MetaData for SqliteMetaData {
62    fn column_len(&self) -> usize {
63        self.columns.len()
64    }
65
66    fn column_name(&self, i: usize) -> String {
67        self.columns[i].name.to_string()
68    }
69
70    fn column_type(&self, i: usize) -> String {
71        self.columns[i].type_info.to_string()
72    }
73}
74
75impl Row for SqliteRow {
76    fn meta_data(&self) -> Box<dyn MetaData> {
77        Box::new(SqliteMetaData {
78            columns: self.columns.clone(),
79        })
80    }
81
82    fn get(&mut self, i: usize) -> Result<Value, Error> {
83        match self.try_take(i) {
84            Err(e) => Err(Error::from(format!("get error index:{},error:{}", i, e))),
85            Ok(v) => Value::decode(v),
86        }
87    }
88}
89
90impl SqliteRow {
91    fn columns(&self) -> &[SqliteColumn] {
92        &self.columns
93    }
94
95    fn try_get_raw(&self, index: usize) -> Result<SqliteValueRef<'_>, Error> {
96        Ok(SqliteValueRef::value(&self.values[index]))
97    }
98
99    fn try_take(&mut self, index: usize) -> Result<SqliteValue, Error> {
100        if (index + 1) > self.values.len() {
101            return Err(Error::from("try_take out of range!"));
102        }
103        Ok(self.values.remove(index))
104    }
105}