1use std::sync::Arc;
6
7use sqlx_core::column::ColumnIndex;
8use sqlx_core::database::Database;
9use sqlx_core::error::Error;
10use sqlx_core::row::Row;
11use sqlx_core::HashMap;
12
13use spg_embedded::Value as EngineValue;
14
15use crate::column::SpgColumn;
16use crate::database::Spg;
17use crate::value::SpgValueRef;
18
19#[derive(Debug, Clone)]
21pub struct SpgRow {
22 columns: Arc<Vec<SpgColumn>>,
26 by_name: Arc<HashMap<String, usize>>,
28 values: Vec<EngineValue>,
30}
31
32impl SpgRow {
33 #[must_use]
36 pub fn new(
37 columns: Arc<Vec<SpgColumn>>,
38 by_name: Arc<HashMap<String, usize>>,
39 values: Vec<EngineValue>,
40 ) -> Self {
41 Self {
42 columns,
43 by_name,
44 values,
45 }
46 }
47}
48
49impl Row for SpgRow {
50 type Database = Spg;
51
52 fn columns(&self) -> &[SpgColumn] {
53 &self.columns
54 }
55
56 fn try_get_raw<I>(&self, index: I) -> Result<SpgValueRef<'_>, Error>
57 where
58 I: ColumnIndex<Self>,
59 {
60 use sqlx_core::column::Column as _;
61 let ord = index.index(self)?;
62 let col = self.columns.get(ord).ok_or_else(|| Error::ColumnIndexOutOfBounds {
63 index: ord,
64 len: self.columns.len(),
65 })?;
66 let val = self.values.get(ord).ok_or_else(|| Error::ColumnIndexOutOfBounds {
67 index: ord,
68 len: self.values.len(),
69 })?;
70 Ok(SpgValueRef::new(val, col.type_info().clone()))
71 }
72}
73
74impl ColumnIndex<SpgRow> for &str {
75 fn index(&self, row: &SpgRow) -> Result<usize, Error> {
76 row.by_name
77 .get(*self)
78 .copied()
79 .ok_or_else(|| Error::ColumnNotFound((*self).to_string()))
80 }
81}
82
83impl ColumnIndex<SpgRow> for usize {
84 fn index(&self, row: &SpgRow) -> Result<usize, Error> {
85 if *self >= row.columns.len() {
86 return Err(Error::ColumnIndexOutOfBounds {
87 index: *self,
88 len: row.columns.len(),
89 });
90 }
91 Ok(*self)
92 }
93}
94
95const _: fn() = || {
101 fn _ensure_column_trait<C: sqlx_core::column::Column>(c: &C)
102 where
103 C::Database: Database,
104 {
105 let _ = c.type_info();
106 }
107};