Skip to main content

tank_core/query/
query.rs

1use crate::{AsValue, Driver, DynQuery, Prepared, Result, Row, RowsAffected, truncate_long};
2use anyhow::anyhow;
3use std::fmt::{self, Display};
4
5#[derive(Default, Clone, Debug)]
6pub struct RawQuery(pub String);
7
8impl Display for RawQuery {
9    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10        write!(f, "{}", truncate_long!(self.0))
11    }
12}
13
14/// Executable query: raw SQL or prepared statement.
15#[derive(Debug)]
16pub enum Query<D: Driver> {
17    /// Raw SQL text.
18    Raw(RawQuery),
19    /// Prepared statement.
20    Prepared(D::Prepared),
21}
22
23impl<D: Driver> Query<D> {
24    /// New raw query.
25    pub fn raw(value: String) -> Self {
26        Query::Raw(RawQuery(value))
27    }
28    /// New prepared query.
29    pub fn prepared(value: D::Prepared) -> Self {
30        Query::Prepared(value)
31    }
32    /// True if it is the prepared variant.
33    pub fn is_prepared(&self) -> bool {
34        matches!(self, Query::Prepared(..))
35    }
36    /// Clear bound values.
37    pub fn clear_bindings(&mut self) -> Result<&mut Self> {
38        if let Self::Prepared(prepared) = self {
39            prepared.clear_bindings()?;
40        };
41        Ok(self)
42    }
43    /// Bind value to next placeholder.
44    ///
45    /// Error if not prepared.
46    pub fn bind(&mut self, value: impl AsValue) -> Result<&mut Self> {
47        let Self::Prepared(prepared) = self else {
48            return Err(anyhow!("Cannot bind a raw query"));
49        };
50        prepared.bind(value)?;
51        Ok(self)
52    }
53    /// Bind value at index.
54    ///
55    /// Error if not prepared.
56    pub fn bind_index(&mut self, value: impl AsValue, index: u64) -> Result<&mut Self> {
57        let Self::Prepared(prepared) = self else {
58            return Err(anyhow!("Cannot bind index of a raw query"));
59        };
60        prepared.bind_index(value, index)?;
61        Ok(self)
62    }
63    pub fn into_dyn(self) -> DynQuery {
64        self.into()
65    }
66}
67
68impl<D: Driver> Default for Query<D> {
69    fn default() -> Self {
70        Self::raw(Default::default())
71    }
72}
73
74impl<D: Driver> From<&str> for Query<D> {
75    fn from(value: &str) -> Self {
76        Self::raw(value.into())
77    }
78}
79
80impl<D: Driver> From<String> for Query<D> {
81    fn from(value: String) -> Self {
82        Self::raw(value)
83    }
84}
85
86impl<D, P> From<P> for Query<D>
87where
88    D: Driver<Prepared = P>,
89    P: Prepared,
90{
91    fn from(value: P) -> Self {
92        Self::prepared(value)
93    }
94}
95
96impl<D: Driver> Display for Query<D> {
97    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
98        match self {
99            Query::Raw(v) => v.fmt(f),
100            Query::Prepared(query) => query.fmt(f),
101        }
102    }
103}
104
105impl<D: Driver> AsMut<Query<D>> for Query<D> {
106    fn as_mut(&mut self) -> &mut Query<D> {
107        self
108    }
109}
110
111/// Items from `Executor::run`: rows or effects.
112#[derive(Debug)]
113pub enum QueryResult {
114    /// A labeled row
115    Row(Row),
116    /// A modify effect aggregation
117    Affected(RowsAffected),
118}