Skip to main content

tank_core/query/
query.rs

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