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