use std::sync::Arc;
use sqlx_core::HashMap;
use sqlx_core::column::ColumnIndex;
use sqlx_core::database::Database;
use sqlx_core::error::Error;
use sqlx_core::row::Row;
use spg_embedded::Value as EngineValue;
use crate::column::SpgColumn;
use crate::database::Spg;
use crate::value::SpgValueRef;
#[derive(Debug, Clone)]
pub struct SpgRow {
columns: Arc<Vec<SpgColumn>>,
by_name: Arc<HashMap<String, usize>>,
values: Vec<EngineValue>,
}
impl SpgRow {
#[must_use]
pub fn new(
columns: Arc<Vec<SpgColumn>>,
by_name: Arc<HashMap<String, usize>>,
values: Vec<EngineValue>,
) -> Self {
Self {
columns,
by_name,
values,
}
}
}
impl Row for SpgRow {
type Database = Spg;
fn columns(&self) -> &[SpgColumn] {
&self.columns
}
fn try_get_raw<I>(&self, index: I) -> Result<SpgValueRef<'_>, Error>
where
I: ColumnIndex<Self>,
{
use sqlx_core::column::Column as _;
let ord = index.index(self)?;
let col = self
.columns
.get(ord)
.ok_or_else(|| Error::ColumnIndexOutOfBounds {
index: ord,
len: self.columns.len(),
})?;
let val = self
.values
.get(ord)
.ok_or_else(|| Error::ColumnIndexOutOfBounds {
index: ord,
len: self.values.len(),
})?;
Ok(SpgValueRef::new(val, col.type_info().clone()))
}
}
impl ColumnIndex<SpgRow> for &str {
fn index(&self, row: &SpgRow) -> Result<usize, Error> {
row.by_name
.get(*self)
.copied()
.ok_or_else(|| Error::ColumnNotFound((*self).to_string()))
}
}
impl ColumnIndex<SpgRow> for usize {
fn index(&self, row: &SpgRow) -> Result<usize, Error> {
if *self >= row.columns.len() {
return Err(Error::ColumnIndexOutOfBounds {
index: *self,
len: row.columns.len(),
});
}
Ok(*self)
}
}
const _: fn() = || {
fn _ensure_column_trait<C: sqlx_core::column::Column>(c: &C)
where
C::Database: Database,
{
let _ = c.type_info();
}
};