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