tank_postgres/
prepared.rs1use crate::{PostgresTransaction, ValueHolder};
2use std::{
3 fmt::{self, Debug, Display},
4 mem,
5};
6use tank_core::{AsValue, Error, Prepared, Result, future::Either};
7use tokio_postgres::{Portal, Statement};
8
9pub struct PostgresPrepared {
10 pub(crate) statement: Statement,
11 pub(crate) index: u64,
12 pub(crate) value: Either<Vec<Option<ValueHolder>>, Portal>,
13}
14
15impl PostgresPrepared {
16 pub(crate) fn new(statement: Statement) -> Self {
17 Self {
18 statement,
19 index: Default::default(),
20 value: Either::Left(vec![]),
21 }
22 }
23 pub(crate) fn is_complete(&self) -> bool {
24 matches!(self.value, Either::Right(..))
25 }
26 pub(crate) async fn complete<'t>(
27 &mut self,
28 transaction: &mut PostgresTransaction<'t>,
29 ) -> Result<Portal> {
30 let Either::Left(params) = &mut self.value else {
31 return Err(Error::msg("The prepared statement is already complete"));
32 };
33 if let Some(i) = params
34 .iter()
35 .enumerate()
36 .find_map(|(i, v)| if v.is_none() { Some(i) } else { None })
37 {
38 return Err(Error::msg(format!("The parameter {} was not set", i)));
39 }
40 let portal = transaction
41 .0
42 .bind_raw(
43 &self.statement,
44 mem::take(params).into_iter().map(Option::unwrap),
45 )
46 .await?;
47 self.value = Either::Right(portal.clone());
48 Ok(portal)
49 }
50 pub(crate) fn get_portal(&self) -> Option<Portal> {
51 if let Either::Right(portal) = &self.value {
52 portal.clone().into()
53 } else {
54 None
55 }
56 }
57}
58
59impl Prepared for PostgresPrepared {
60 fn bind<V: AsValue>(&mut self, value: V) -> Result<&mut Self> {
61 self.bind_index(value, self.index)
62 }
63 fn bind_index<V: AsValue>(&mut self, value: V, index: u64) -> Result<&mut Self> {
64 let Either::Left(params) = &mut self.value else {
65 return Err(Error::msg("The prepared statement is already complete"));
66 };
67 params.reserve(self.statement.params().len());
68 params[index as usize] = Some(value.as_value().into());
69 Ok(self)
70 }
71}
72
73impl Display for PostgresPrepared {
74 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
75 self.statement.fmt(f)
76 }
77}