Skip to main content

tank_postgres/
prepared.rs

1use crate::ValueWrap;
2use std::{
3    borrow::Cow,
4    fmt::{self, Debug, Display},
5    mem,
6};
7use tank_core::{AsValue, Error, Prepared, Result, Value};
8use tokio_postgres::Statement;
9
10/// Prepared statement wrapper for Postgres.
11///
12/// Holds the `tokio_postgres::Statement` and collected parameter `Value`s for binding/execution through the `Executor` APIs.
13#[derive(Debug)]
14pub struct PostgresPrepared {
15    pub(crate) statement: Statement,
16    pub(crate) params: Vec<Value>,
17    pub(crate) index: u64,
18}
19
20impl PostgresPrepared {
21    pub(crate) fn new(statement: Statement) -> Self {
22        Self {
23            statement,
24            params: Vec::new(),
25            index: 0,
26        }
27    }
28
29    pub(crate) fn take_params(&mut self) -> Vec<ValueWrap<'static>> {
30        self.index = 0;
31        mem::take(&mut self.params)
32            .into_iter()
33            .map(|v| ValueWrap(Cow::Owned(v)))
34            .collect()
35    }
36}
37
38impl Prepared for PostgresPrepared {
39    fn as_any(self: Box<Self>) -> Box<dyn std::any::Any> {
40        self
41    }
42
43    fn clear_bindings(&mut self) -> Result<&mut Self> {
44        self.params.clear();
45        self.index = 0;
46        Ok(self)
47    }
48
49    fn bind(&mut self, value: impl AsValue) -> Result<&mut Self> {
50        self.bind_index(value, self.index)
51    }
52
53    fn bind_index(&mut self, value: impl AsValue, index: u64) -> Result<&mut Self> {
54        let len = self.statement.params().len();
55        self.params.resize_with(len, Default::default);
56        let target = self
57            .params
58            .get_mut(index as usize)
59            .ok_or(Error::msg(format!(
60                "Index {index} cannot be bound, the query has only {len} parameters",
61            )))?;
62        *target = value.as_value();
63        self.index = index + 1;
64        Ok(self)
65    }
66}
67
68impl Display for PostgresPrepared {
69    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
70        f.write_str("PostgresPrepared: ")?;
71        self.statement.fmt(f)
72    }
73}