1use std::sync::Arc;
6
7use sqlx_core::HashMap;
8use sqlx_core::column::ColumnIndex;
9use sqlx_core::database::Database;
10use sqlx_core::error::Error;
11use sqlx_core::row::Row;
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
63 .columns
64 .get(ord)
65 .ok_or_else(|| Error::ColumnIndexOutOfBounds {
66 index: ord,
67 len: self.columns.len(),
68 })?;
69 let val = self
70 .values
71 .get(ord)
72 .ok_or_else(|| Error::ColumnIndexOutOfBounds {
73 index: ord,
74 len: self.values.len(),
75 })?;
76 Ok(SpgValueRef::new(val, col.type_info().clone()))
77 }
78}
79
80impl ColumnIndex<SpgRow> for &str {
81 fn index(&self, row: &SpgRow) -> Result<usize, Error> {
82 row.by_name
83 .get(*self)
84 .copied()
85 .ok_or_else(|| Error::ColumnNotFound((*self).to_string()))
86 }
87}
88
89impl ColumnIndex<SpgRow> for usize {
90 fn index(&self, row: &SpgRow) -> Result<usize, Error> {
91 if *self >= row.columns.len() {
92 return Err(Error::ColumnIndexOutOfBounds {
93 index: *self,
94 len: row.columns.len(),
95 });
96 }
97 Ok(*self)
98 }
99}
100
101const _: fn() = || {
107 fn _ensure_column_trait<C: sqlx_core::column::Column>(c: &C)
108 where
109 C::Database: Database,
110 {
111 let _ = c.type_info();
112 }
113};