zero_mysql/
handler.rs

1use crate::error::Result;
2use crate::protocol::command::ColumnDefinition;
3use crate::protocol::response::{OkPayload, OkPayloadBytes};
4use crate::protocol::r#trait::{BinaryResultSetHandler, TextResultSetHandler};
5use crate::protocol::{BinaryRowPayload, TextRowPayload};
6use crate::raw::FromRawRow;
7use smart_default::SmartDefault;
8
9/// A handler that ignores all result set data but captures affected_rows and last_insert_id
10///
11/// Useful for `exec_drop()` and `query_drop()` methods that discard results but need metadata.
12#[derive(Default)]
13pub struct DropHandler {
14    affected_rows: u64,
15    last_insert_id: u64,
16}
17
18impl DropHandler {
19    /// Get the number of affected rows from the last operation
20    pub fn affected_rows(&self) -> u64 {
21        self.affected_rows
22    }
23
24    /// Get the last insert ID from the last operation
25    pub fn last_insert_id(&self) -> u64 {
26        self.last_insert_id
27    }
28}
29
30impl BinaryResultSetHandler for DropHandler {
31    fn no_result_set(&mut self, ok: OkPayloadBytes) -> Result<()> {
32        let payload = OkPayload::try_from(ok)?;
33        self.affected_rows = payload.affected_rows;
34        self.last_insert_id = payload.last_insert_id;
35        Ok(())
36    }
37
38    fn resultset_start(&mut self, _: &[ColumnDefinition<'_>]) -> Result<()> {
39        Ok(())
40    }
41
42    fn row(&mut self, _: &[ColumnDefinition<'_>], _: BinaryRowPayload<'_>) -> Result<()> {
43        Ok(())
44    }
45
46    fn resultset_end(&mut self, eof: OkPayloadBytes) -> Result<()> {
47        let payload = OkPayload::try_from(eof)?;
48        self.affected_rows = payload.affected_rows;
49        self.last_insert_id = payload.last_insert_id;
50        Ok(())
51    }
52}
53
54impl TextResultSetHandler for DropHandler {
55    fn no_result_set(&mut self, ok: OkPayloadBytes) -> Result<()> {
56        let payload = OkPayload::try_from(ok)?;
57        self.affected_rows = payload.affected_rows;
58        self.last_insert_id = payload.last_insert_id;
59        Ok(())
60    }
61
62    fn resultset_start(&mut self, _: &[ColumnDefinition<'_>]) -> Result<()> {
63        Ok(())
64    }
65
66    fn row(&mut self, _: &[ColumnDefinition<'_>], _: TextRowPayload<'_>) -> Result<()> {
67        Ok(())
68    }
69
70    fn resultset_end(&mut self, eof: OkPayloadBytes) -> Result<()> {
71        let payload = OkPayload::try_from(eof)?;
72        self.affected_rows = payload.affected_rows;
73        self.last_insert_id = payload.last_insert_id;
74        Ok(())
75    }
76}
77
78/// A handler that stores only the first row.
79///
80/// Useful for `exec_first()` methods that return `Option<Row>`.
81#[derive(SmartDefault)]
82pub struct FirstHandler<Row> {
83    row: Option<Row>,
84}
85
86impl<Row> FirstHandler<Row> {
87    /// Take the stored row, if any.
88    pub fn take(&mut self) -> Option<Row> {
89        self.row.take()
90    }
91}
92
93impl<Row: for<'buf> FromRawRow<'buf>> BinaryResultSetHandler for FirstHandler<Row> {
94    fn no_result_set(&mut self, _ok: OkPayloadBytes) -> Result<()> {
95        Ok(())
96    }
97
98    fn resultset_start(&mut self, _cols: &[ColumnDefinition<'_>]) -> Result<()> {
99        Ok(())
100    }
101
102    fn row(&mut self, cols: &[ColumnDefinition<'_>], row: BinaryRowPayload<'_>) -> Result<()> {
103        if self.row.is_none() {
104            self.row = Some(Row::from_raw_row(cols, row)?);
105        }
106        Ok(())
107    }
108
109    fn resultset_end(&mut self, _eof: OkPayloadBytes) -> Result<()> {
110        Ok(())
111    }
112}
113
114/// A handler that collects all rows into a Vec<Row>
115///
116/// Useful for `exec()` methods that need to return all rows as a collection.
117#[derive(SmartDefault)]
118pub struct CollectHandler<Row> {
119    rows: Vec<Row>,
120    affected_rows: u64,
121    last_insert_id: u64,
122}
123
124impl<Row> CollectHandler<Row> {
125    pub fn take_rows(&mut self) -> Vec<Row> {
126        std::mem::take(&mut self.rows)
127    }
128    pub fn into_rows(self) -> Vec<Row> {
129        self.rows
130    }
131    pub fn affected_rows(&self) -> u64 {
132        self.affected_rows
133    }
134    pub fn last_insert_id(&self) -> u64 {
135        self.last_insert_id
136    }
137}
138
139impl<Row: for<'buf> FromRawRow<'buf>> BinaryResultSetHandler for CollectHandler<Row> {
140    fn no_result_set(&mut self, ok: OkPayloadBytes) -> Result<()> {
141        let payload = OkPayload::try_from(ok)?;
142        self.affected_rows = payload.affected_rows;
143        self.last_insert_id = payload.last_insert_id;
144        Ok(())
145    }
146
147    fn resultset_start(&mut self, _cols: &[ColumnDefinition<'_>]) -> Result<()> {
148        Ok(())
149    }
150
151    fn row(&mut self, cols: &[ColumnDefinition], row: BinaryRowPayload) -> Result<()> {
152        self.rows.push(Row::from_raw_row(cols, row)?);
153        Ok(())
154    }
155
156    fn resultset_end(&mut self, eof: OkPayloadBytes) -> Result<()> {
157        let payload = OkPayload::try_from(eof)?;
158        self.affected_rows = payload.affected_rows;
159        self.last_insert_id = payload.last_insert_id;
160        Ok(())
161    }
162}
163
164/// A handler that calls a closure for each row.
165///
166/// Useful for `exec_foreach()` methods that process rows without collecting.
167pub struct ForEachHandler<Row, F> {
168    f: F,
169    _marker: std::marker::PhantomData<Row>,
170}
171
172impl<Row, F> ForEachHandler<Row, F> {
173    pub fn new(f: F) -> Self {
174        Self {
175            f,
176            _marker: std::marker::PhantomData,
177        }
178    }
179}
180
181impl<Row, F> BinaryResultSetHandler for ForEachHandler<Row, F>
182where
183    Row: for<'buf> FromRawRow<'buf>,
184    F: FnMut(Row) -> Result<()>,
185{
186    fn no_result_set(&mut self, _ok: OkPayloadBytes) -> Result<()> {
187        Ok(())
188    }
189
190    fn resultset_start(&mut self, _cols: &[ColumnDefinition<'_>]) -> Result<()> {
191        Ok(())
192    }
193
194    fn row(&mut self, cols: &[ColumnDefinition], row: BinaryRowPayload) -> Result<()> {
195        let parsed = Row::from_raw_row(cols, row)?;
196        (self.f)(parsed)
197    }
198
199    fn resultset_end(&mut self, _eof: OkPayloadBytes) -> Result<()> {
200        Ok(())
201    }
202}