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