1use crate::{AsValue, Driver, Error, Prepared, Result, Value, truncate_long};
2use std::{
3 fmt::{self, Display},
4 sync::Arc,
5};
6
7#[derive(Debug)]
9pub enum Query<D: Driver> {
10 Raw(String),
12 Prepared(D::Prepared),
14}
15
16impl<D: Driver> Query<D> {
17 pub fn is_prepared(&self) -> bool {
19 matches!(self, Query::Prepared(..))
20 }
21 pub fn clear_bindings(&mut self) -> Result<&mut Self> {
23 if let Self::Prepared(prepared) = self {
24 prepared.clear_bindings()?;
25 };
26 Ok(self)
27 }
28 pub fn bind(&mut self, value: impl AsValue) -> Result<&mut Self> {
31 let Self::Prepared(prepared) = self else {
32 return Err(Error::msg("Cannot bind a raw query"));
33 };
34 prepared.bind(value)?;
35 Ok(self)
36 }
37 pub fn bind_index(&mut self, value: impl AsValue, index: u64) -> Result<&mut Self> {
40 let Self::Prepared(prepared) = self else {
41 return Err(Error::msg("Cannot bind index of a raw query"));
42 };
43 prepared.bind_index(value, index)?;
44 Ok(self)
45 }
46}
47
48pub trait AsQuery<D: Driver> {
49 type Output: AsMut<Query<D>> + Send;
50 fn as_query(self) -> Self::Output;
51}
52
53impl<D: Driver> AsQuery<D> for Query<D> {
54 type Output = Query<D>;
55 fn as_query(self) -> Self::Output {
56 self
57 }
58}
59
60impl<'q, D: Driver + 'q> AsQuery<D> for &'q mut Query<D> {
61 type Output = &'q mut Query<D>;
62 fn as_query(self) -> Self::Output {
63 self
64 }
65}
66
67impl<D: Driver> AsQuery<D> for String {
68 type Output = Query<D>;
69 fn as_query(self) -> Self::Output {
70 Query::Raw(self)
71 }
72}
73
74impl<D: Driver> AsQuery<D> for &str {
75 type Output = Query<D>;
76 fn as_query(self) -> Self::Output {
77 Query::Raw(self.to_owned())
78 }
79}
80
81impl<D: Driver> Default for Query<D> {
82 fn default() -> Self {
83 Self::Raw(Default::default())
84 }
85}
86
87impl<D: Driver> From<&str> for Query<D> {
88 fn from(value: &str) -> Self {
89 Query::Raw(value.into())
90 }
91}
92
93impl<D: Driver> From<String> for Query<D> {
94 fn from(value: String) -> Self {
95 Query::Raw(value.into())
96 }
97}
98
99impl<D, P> From<P> for Query<D>
100where
101 D: Driver<Prepared = P>,
102 P: Prepared,
103{
104 fn from(value: P) -> Self {
105 Query::Prepared(value)
106 }
107}
108
109impl<D: Driver> Display for Query<D> {
110 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
111 match self {
112 Query::Raw(query) => write!(f, "{}", truncate_long!(query)),
113 Query::Prepared(query) => query.fmt(f),
114 }
115 }
116}
117
118impl<D: Driver> AsMut<Query<D>> for Query<D> {
119 fn as_mut(&mut self) -> &mut Query<D> {
120 self
121 }
122}
123
124#[derive(Default, Debug, Clone, Copy)]
126pub struct RowsAffected {
127 pub rows_affected: Option<u64>,
130 pub last_affected_id: Option<i64>,
133}
134
135pub type RowNames = Arc<[String]>;
137pub type Row = Box<[Value]>;
139
140#[derive(Debug, Clone)]
142pub struct RowLabeled {
143 pub labels: RowNames,
145 pub values: Row,
147}
148
149impl RowLabeled {
150 pub fn new(names: RowNames, values: Row) -> Self {
151 Self {
152 labels: names,
153 values,
154 }
155 }
156 pub fn names(&self) -> &[String] {
158 &self.labels
159 }
160 pub fn values(&self) -> &[Value] {
162 &self.values
163 }
164 pub fn get_column(&self, name: &str) -> Option<&Value> {
166 self.labels
167 .iter()
168 .position(|v| v == name)
169 .map(|i| &self.values()[i])
170 }
171}
172
173#[derive(Debug)]
175pub enum QueryResult {
176 Row(RowLabeled),
178 Affected(RowsAffected),
180}
181
182impl Extend<RowsAffected> for RowsAffected {
183 fn extend<T: IntoIterator<Item = RowsAffected>>(&mut self, iter: T) {
184 for elem in iter {
185 if self.rows_affected.is_some() || elem.rows_affected.is_some() {
186 self.rows_affected = Some(
187 self.rows_affected.unwrap_or_default() + elem.rows_affected.unwrap_or_default(),
188 );
189 }
190 if elem.last_affected_id.is_some() {
191 self.last_affected_id = elem.last_affected_id;
192 }
193 }
194 }
195}
196
197impl From<RowLabeled> for Row {
198 fn from(value: RowLabeled) -> Self {
199 value.values
200 }
201}
202
203impl<'a> From<&'a RowLabeled> for &'a Row {
204 fn from(value: &'a RowLabeled) -> Self {
205 &value.values
206 }
207}
208
209impl From<RowLabeled> for QueryResult {
210 fn from(value: RowLabeled) -> Self {
211 QueryResult::Row(value)
212 }
213}
214
215impl From<RowsAffected> for QueryResult {
216 fn from(value: RowsAffected) -> Self {
217 QueryResult::Affected(value)
218 }
219}