Skip to main content

tank_core/query/
dyn_query.rs

1use crate::{Driver, Prepared, Query, QueryParam, RawQuery};
2use std::{
3    any::Any,
4    borrow::Cow,
5    fmt::{self, Display, Write},
6};
7
8/// Dyn compatible version of `Query`
9#[derive(Debug)]
10pub enum DynQuery {
11    Raw(RawQuery),
12    Prepared(Box<dyn Prepared>),
13}
14
15impl DynQuery {
16    pub fn new(value: String) -> Self {
17        Self::Raw(RawQuery::new(value))
18    }
19    pub fn with_capacity(capacity: usize) -> Self {
20        Self::new(String::with_capacity(capacity))
21    }
22    pub fn clear(&mut self) {
23        match self {
24            Self::Raw(raw) => raw.clear(),
25            Self::Prepared(..) => *self = Self::Raw(Default::default()),
26        }
27    }
28    pub fn buffer(&mut self) -> &mut String {
29        if !matches!(self, Self::Raw(..)) {
30            log::error!("DynQuery::buffer changed the query to raw, deleting the previous content");
31            *self = Self::Raw(Default::default())
32        }
33        let Self::Raw(RawQuery { sql, .. }) = self else {
34            unreachable!();
35        };
36        sql
37    }
38    /// Record the `begin..end` span of a parameter marker written to the buffer.
39    pub fn mark_param(&mut self, param: QueryParam) {
40        if let Self::Raw(RawQuery { params, .. }) = self {
41            params.push(param);
42        }
43    }
44    pub fn as_prepared<D: Driver>(&mut self) -> Option<&mut D::Prepared> {
45        if let Self::Prepared(prepared) = self {
46            return (&mut **prepared as &mut dyn Any).downcast_mut::<D::Prepared>();
47        }
48        None
49    }
50    pub fn as_str<'s>(&'s self) -> Cow<'s, str> {
51        match self {
52            Self::Raw(RawQuery { sql, .. }) => Cow::Borrowed(sql),
53            Self::Prepared(v) => Cow::Owned(format!("{:?}", *v)),
54        }
55    }
56    pub fn push_str(&mut self, s: &str) {
57        self.buffer().push_str(s);
58    }
59    pub fn push(&mut self, c: char) {
60        self.buffer().push(c);
61    }
62    pub fn len(&self) -> usize {
63        match self {
64            Self::Raw(RawQuery { sql, .. }) => sql.len(),
65            Self::Prepared(..) => 0,
66        }
67    }
68    pub fn is_empty(&self) -> bool {
69        match self {
70            Self::Raw(RawQuery { sql, .. }) => sql.is_empty(),
71            Self::Prepared(..) => true,
72        }
73    }
74
75    pub fn into_query<D: Driver>(self, _driver: D) -> Query<D> {
76        self.into()
77    }
78}
79
80impl Default for DynQuery {
81    fn default() -> Self {
82        Self::Raw(Default::default())
83    }
84}
85
86impl Write for DynQuery {
87    fn write_char(&mut self, c: char) -> fmt::Result {
88        self.push(c);
89        Ok(())
90    }
91    fn write_str(&mut self, s: &str) -> fmt::Result {
92        self.push_str(s);
93        Ok(())
94    }
95}
96
97impl<D: Driver> From<Query<D>> for DynQuery {
98    fn from(value: Query<D>) -> Self {
99        match value {
100            Query::Raw(v) => Self::Raw(v),
101            Query::Prepared(p) => Self::Prepared(Box::new(p)),
102        }
103    }
104}
105
106impl<D: Driver> From<DynQuery> for Query<D> {
107    fn from(value: DynQuery) -> Self {
108        match value {
109            DynQuery::Raw(r) => Self::Raw(r),
110            DynQuery::Prepared(p) => match p.as_any().downcast::<D::Prepared>() {
111                Ok(p) => Query::Prepared(*p),
112                Err(..) => Query::raw(Default::default()),
113            },
114        }
115    }
116}
117
118impl From<DynQuery> for String {
119    fn from(value: DynQuery) -> Self {
120        match value {
121            DynQuery::Raw(RawQuery { sql, .. }) => sql,
122            DynQuery::Prepared(value) => format!("{:?}", value),
123        }
124    }
125}
126
127impl Display for DynQuery {
128    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
129        match self {
130            DynQuery::Raw(v) => v.fmt(f),
131            DynQuery::Prepared(v) => v.fmt(f),
132        }
133    }
134}