Skip to main content

tank_postgres/
prepared.rs

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