Skip to main content

tank_core/query/
query.rs

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