Skip to main content

tank_core/query/
dyn_query.rs

1use crate::{Driver, Prepared, Query, RawQuery};
2use std::{
3    any::Any,
4    borrow::Cow,
5    fmt::{self, 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(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(RawQuery(value)) => value.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(value)) = self else {
34            unreachable!();
35        };
36        value
37    }
38    pub fn as_prepared<D: Driver>(&mut self) -> Option<&mut D::Prepared> {
39        if let Self::Prepared(prepared) = self {
40            return (&mut **prepared as &mut dyn Any).downcast_mut::<D::Prepared>();
41        }
42        None
43    }
44    pub fn as_str<'s>(&'s self) -> Cow<'s, str> {
45        match self {
46            Self::Raw(RawQuery(sql)) => Cow::Borrowed(sql),
47            Self::Prepared(v) => Cow::Owned(format!("{:?}", *v)),
48        }
49    }
50    pub fn push_str(&mut self, s: &str) {
51        self.buffer().push_str(s);
52    }
53    pub fn push(&mut self, c: char) {
54        self.buffer().push(c);
55    }
56    pub fn len(&self) -> usize {
57        match self {
58            Self::Raw(RawQuery(sql)) => sql.len(),
59            Self::Prepared(..) => 0,
60        }
61    }
62    pub fn is_empty(&self) -> bool {
63        match self {
64            Self::Raw(RawQuery(sql)) => sql.is_empty(),
65            Self::Prepared(..) => true,
66        }
67    }
68
69    pub fn into_query<D: Driver>(self, _driver: D) -> Query<D> {
70        self.into()
71    }
72}
73
74impl Default for DynQuery {
75    fn default() -> Self {
76        Self::Raw(Default::default())
77    }
78}
79
80impl Write for DynQuery {
81    fn write_char(&mut self, c: char) -> fmt::Result {
82        self.push(c);
83        Ok(())
84    }
85    fn write_str(&mut self, s: &str) -> fmt::Result {
86        self.push_str(s);
87        Ok(())
88    }
89}
90
91impl<D: Driver> From<Query<D>> for DynQuery {
92    fn from(value: Query<D>) -> Self {
93        match value {
94            Query::Raw(v) => Self::Raw(v),
95            Query::Prepared(p) => Self::Prepared(Box::new(p)),
96        }
97    }
98}
99
100impl<D: Driver> From<DynQuery> for Query<D> {
101    fn from(value: DynQuery) -> Self {
102        match value {
103            DynQuery::Raw(r) => Self::Raw(r),
104            DynQuery::Prepared(p) => match p.as_any().downcast::<D::Prepared>() {
105                Ok(p) => Query::Prepared(*p),
106                Err(..) => Query::raw(Default::default()),
107            },
108        }
109    }
110}
111
112impl From<DynQuery> for String {
113    fn from(value: DynQuery) -> Self {
114        match value {
115            DynQuery::Raw(RawQuery(value)) => value,
116            DynQuery::Prepared(value) => format!("{:?}", value),
117        }
118    }
119}