1#![allow(clippy::rc_buffer)]
2
3use std::sync::Arc;
4
5use sqlx_core::column::ColumnIndex;
6use sqlx_core::error::Error;
7use sqlx_core::ext::ustr::UStr;
8use sqlx_core::row::Row;
9use sqlx_core::HashMap;
10
11use crate::statement::StatementHandle;
12use crate::{Sqlite, SqliteColumn, SqliteValue, SqliteValueRef};
13
14pub struct SqliteRow {
16 pub(crate) values: Box<[SqliteValue]>,
17 pub(crate) columns: Arc<Vec<SqliteColumn>>,
18 pub(crate) column_names: Arc<HashMap<UStr, usize>>,
19}
20
21unsafe impl Send for SqliteRow {}
28unsafe impl Sync for SqliteRow {}
29
30impl SqliteRow {
31 pub(crate) fn current(
32 statement: &StatementHandle,
33 columns: &Arc<Vec<SqliteColumn>>,
34 column_names: &Arc<HashMap<UStr, usize>>,
35 ) -> Self {
36 let size = statement.column_count();
37 let mut values = Vec::with_capacity(size);
38
39 for i in 0..size {
40 values.push(unsafe {
41 let raw = statement.column_value(i);
42
43 SqliteValue::new(raw, columns[i].type_info.clone())
44 });
45 }
46
47 Self {
48 values: values.into_boxed_slice(),
49 columns: Arc::clone(columns),
50 column_names: Arc::clone(column_names),
51 }
52 }
53}
54
55impl Row for SqliteRow {
56 type Database = Sqlite;
57
58 fn columns(&self) -> &[SqliteColumn] {
59 &self.columns
60 }
61
62 fn try_get_raw<I>(&self, index: I) -> Result<SqliteValueRef<'_>, Error>
63 where
64 I: ColumnIndex<Self>,
65 {
66 let index = index.index(self)?;
67 Ok(SqliteValueRef::value(&self.values[index]))
68 }
69}
70
71impl ColumnIndex<SqliteRow> for &'_ str {
72 fn index(&self, row: &SqliteRow) -> Result<usize, Error> {
73 row.column_names
74 .get(*self)
75 .ok_or_else(|| Error::ColumnNotFound((*self).into()))
76 .copied()
77 }
78}
79
80