use sqlx_core::arguments::Arguments;
use sqlx_core::encode::{Encode, IsNull};
use sqlx_core::error::BoxDynError;
use sqlx_core::impl_into_arguments_for_arguments;
use sqlx_core::types::Type;
use spg_embedded::Value as EngineValue;
use crate::database::Spg;
use crate::type_info::SpgTypeInfo;
#[derive(Debug, Clone)]
pub struct SpgArgumentValue<'q> {
pub value: EngineValue,
pub type_info: Option<SpgTypeInfo>,
pub _phantom: core::marker::PhantomData<&'q ()>,
}
#[derive(Debug, Clone, Default)]
pub struct SpgArguments<'q> {
pub values: Vec<SpgArgumentValue<'q>>,
}
impl<'q> SpgArguments<'q> {
#[must_use]
pub fn into_engine_values(self) -> Vec<EngineValue> {
self.values.into_iter().map(|a| a.value).collect()
}
#[must_use]
pub fn count(&self) -> usize {
self.values.len()
}
}
impl<'q> Arguments<'q> for SpgArguments<'q> {
type Database = Spg;
fn reserve(&mut self, additional: usize, _size: usize) {
self.values.reserve(additional);
}
fn add<T>(&mut self, value: T) -> Result<(), BoxDynError>
where
T: 'q + Encode<'q, Self::Database> + Type<Self::Database>,
{
self.values.push(SpgArgumentValue {
value: EngineValue::Null,
type_info: Some(T::type_info()),
_phantom: core::marker::PhantomData,
});
let mut buf: Vec<SpgArgumentValue<'q>> = Vec::new();
let is_null = value.encode_by_ref(&mut buf)?;
if let Some(written) = buf.pop() {
let idx = self.values.len() - 1;
self.values[idx] = written;
}
if matches!(is_null, IsNull::Yes) {
let idx = self.values.len() - 1;
self.values[idx].value = EngineValue::Null;
}
Ok(())
}
fn len(&self) -> usize {
self.values.len()
}
}
impl_into_arguments_for_arguments!(SpgArguments<'q>);