use std::borrow::Cow;
use drizzle_core::{
OwnedParam, Param,
prepared::{
OwnedPreparedStatement as CoreOwnedPreparedStatement,
PreparedStatement as CorePreparedStatement,
},
};
use crate::values::{OwnedPostgresValue, PostgresValue};
#[derive(Debug, Clone)]
pub struct PreparedStatement<'a> {
pub inner: CorePreparedStatement<'a, PostgresValue<'a>>,
}
impl<'a> PreparedStatement<'a> {
pub fn into_owned(&self) -> OwnedPreparedStatement {
let owned_params = self.inner.params.iter().map(|p| OwnedParam {
placeholder: p.placeholder,
value: p
.value
.clone()
.map(|v| OwnedPostgresValue::from(v.into_owned())),
});
let inner = CoreOwnedPreparedStatement {
text_segments: self.inner.text_segments.clone(),
params: owned_params.collect::<Box<[_]>>(),
sql: self.inner.sql.clone(),
};
OwnedPreparedStatement { inner }
}
}
#[derive(Debug, Clone)]
pub struct OwnedPreparedStatement {
pub inner: CoreOwnedPreparedStatement<crate::values::OwnedPostgresValue>,
}
impl<'a> From<PreparedStatement<'a>> for OwnedPreparedStatement {
fn from(value: PreparedStatement<'a>) -> Self {
let owned_params = value.inner.params.iter().map(|p| OwnedParam {
placeholder: p.placeholder,
value: p
.value
.clone()
.map(|v| OwnedPostgresValue::from(v.into_owned())),
});
let inner = CoreOwnedPreparedStatement {
text_segments: value.inner.text_segments,
params: owned_params.collect::<Box<[_]>>(),
sql: value.inner.sql,
};
Self { inner }
}
}
impl From<OwnedPreparedStatement> for PreparedStatement<'_> {
fn from(value: OwnedPreparedStatement) -> Self {
let postgresvalue = value.inner.params.iter().map(|v| {
Param::new(
v.placeholder,
v.value.clone().map(|v| Cow::Owned(PostgresValue::from(v))),
)
});
let inner = CorePreparedStatement {
text_segments: value.inner.text_segments,
params: postgresvalue.collect::<Box<[_]>>(),
sql: value.inner.sql,
};
PreparedStatement { inner }
}
}
impl OwnedPreparedStatement {}
impl<'a> std::fmt::Display for PreparedStatement<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.inner)
}
}
impl std::fmt::Display for OwnedPreparedStatement {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.inner)
}
}
#[cfg(test)]
mod tests {
use super::*;
use drizzle_core::{SQL, prepared::prepare_render};
#[test]
fn test_prepare_render_basic() {
let sql: SQL<'_, PostgresValue<'_>> = SQL::raw("SELECT * FROM users WHERE id = ")
.append(SQL::placeholder("user_id"))
.append(SQL::raw(" AND name = "))
.append(SQL::placeholder("user_name"));
let prepared = prepare_render(sql);
assert_eq!(prepared.text_segments.len(), 3);
assert_eq!(prepared.params.len(), 2);
assert!(prepared.text_segments[0].contains("SELECT * FROM users WHERE id"));
assert!(prepared.text_segments[1].contains("AND name"));
}
#[test]
fn test_prepare_with_no_parameters() {
let sql: SQL<'_, PostgresValue<'_>> = SQL::raw("SELECT COUNT(*) FROM users");
let prepared = prepare_render(sql);
assert_eq!(prepared.text_segments.len(), 1);
assert_eq!(prepared.params.len(), 0);
assert_eq!(prepared.text_segments[0], "SELECT COUNT(*) FROM users");
}
#[test]
fn test_prepared_statement_display() {
let sql: SQL<'_, PostgresValue<'_>> = SQL::raw("SELECT * FROM users")
.append(SQL::raw(" WHERE id = "))
.append(SQL::placeholder("id"));
let prepared = prepare_render(sql);
let display = format!("{}", prepared);
assert!(display.contains("SELECT * FROM users"));
assert!(display.contains("WHERE id"));
}
#[test]
fn test_owned_conversion_roundtrip() {
let sql: SQL<'_, PostgresValue<'_>> =
SQL::raw("SELECT name FROM users WHERE id = ").append(SQL::placeholder("id"));
let prepared = prepare_render(sql);
let core_prepared = PreparedStatement { inner: prepared };
let owned = core_prepared.into_owned();
let borrowed: PreparedStatement<'_> = owned.into();
assert_eq!(borrowed.inner.text_segments.len(), 2);
assert_eq!(borrowed.inner.params.len(), 1);
}
}