use crate::prelude::*;
use crate::{
OwnedParam, ParamBind, SQL, SQLChunk, ToSQL,
prepared::{PreparedStatement, bind_values_internal},
traits::SQLParam,
};
use compact_str::CompactString;
use core::fmt;
use smallvec::SmallVec;
#[derive(Debug, Clone)]
pub struct OwnedPreparedStatement<V: SQLParam> {
pub text_segments: Box<[CompactString]>,
pub params: Box<[OwnedParam<V>]>,
pub sql: CompactString,
}
impl<V: SQLParam> core::fmt::Display for OwnedPreparedStatement<V> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.sql())
}
}
impl<'a, V: SQLParam> From<PreparedStatement<'a, V>> for OwnedPreparedStatement<V> {
fn from(prepared: PreparedStatement<'a, V>) -> Self {
OwnedPreparedStatement {
text_segments: prepared.text_segments,
params: prepared.params.into_iter().map(|p| p.into()).collect(),
sql: prepared.sql,
}
}
}
impl<V: SQLParam> OwnedPreparedStatement<V> {
pub fn bind<'a, T: SQLParam + Into<V>>(
&self,
param_binds: impl IntoIterator<Item = ParamBind<'a, T>>,
) -> (&str, impl Iterator<Item = V>) {
let bound_params = bind_values_internal(
&self.params,
param_binds,
|p| p.placeholder.name,
|p| p.value.as_ref(), );
(self.sql.as_str(), bound_params)
}
pub fn sql(&self) -> &str {
self.sql.as_str()
}
}
impl<'a, V: SQLParam> ToSQL<'a, V> for OwnedPreparedStatement<V> {
fn to_sql(&self) -> SQL<'a, V> {
let capacity = self.text_segments.len() + self.params.len();
let mut chunks = SmallVec::with_capacity(capacity);
let mut param_iter = self.params.iter();
for text_segment in &self.text_segments {
chunks.push(SQLChunk::Raw(Cow::Owned(text_segment.to_string())));
if let Some(param) = param_iter.next() {
chunks.push(SQLChunk::Param(param.clone().into()));
}
}
SQL { chunks }
}
}