1use std::pin::Pin;
16use std::task::Context;
17use std::task::Poll;
18
19use serde::Deserialize;
20use tokio_stream::{Stream, StreamExt};
21
22#[cfg(feature = "flight-sql")]
23use arrow::record_batch::RecordBatch;
24
25use crate::error::{Error, Result};
26use crate::schema::SchemaRef;
27use crate::value::Value;
28
29#[derive(Clone, Debug)]
30pub enum RowWithStats {
31 Row(Row),
32 Stats(ServerStats),
33}
34
35#[derive(Deserialize, Clone, Debug, Default)]
36pub struct ServerStats {
37 #[serde(default)]
38 pub total_rows: usize,
39 #[serde(default)]
40 pub total_bytes: usize,
41
42 #[serde(default)]
43 pub read_rows: usize,
44 #[serde(default)]
45 pub read_bytes: usize,
46
47 #[serde(default)]
48 pub write_rows: usize,
49 #[serde(default)]
50 pub write_bytes: usize,
51
52 #[serde(default)]
53 pub running_time_ms: f64,
54
55 #[serde(default)]
56 pub spill_file_nums: usize,
57
58 #[serde(default)]
59 pub spill_bytes: usize,
60}
61
62impl ServerStats {
63 pub fn normalize(&mut self) {
64 if self.total_rows == 0 {
65 self.total_rows = self.read_rows;
66 }
67 if self.total_bytes == 0 {
68 self.total_bytes = self.read_bytes;
69 }
70 }
71
72 pub fn merge(&mut self, other: &ServerStats) {
73 self.total_rows += other.total_rows;
74 self.total_bytes += other.total_bytes;
75 self.read_rows += other.read_rows;
76 self.read_bytes += other.read_bytes;
77 self.write_rows += other.write_rows;
78 self.write_bytes += other.write_bytes;
79 self.running_time_ms += other.running_time_ms;
80 self.spill_file_nums += other.spill_file_nums;
81 self.spill_bytes += other.spill_bytes;
82 }
83}
84
85impl From<databend_client::QueryStats> for ServerStats {
86 fn from(stats: databend_client::QueryStats) -> Self {
87 let mut p = Self {
88 total_rows: 0,
89 total_bytes: 0,
90 read_rows: stats.progresses.scan_progress.rows,
91 read_bytes: stats.progresses.scan_progress.bytes,
92 write_rows: stats.progresses.write_progress.rows,
93 write_bytes: stats.progresses.write_progress.bytes,
94 spill_file_nums: stats.progresses.spill_progress.file_nums,
95 spill_bytes: stats.progresses.spill_progress.bytes,
96 running_time_ms: stats.running_time_ms,
97 };
98 if let Some(total) = stats.progresses.total_scan {
99 p.total_rows = total.rows;
100 p.total_bytes = total.bytes;
101 }
102 p
103 }
104}
105
106#[derive(Clone, Debug, Default)]
107pub struct Row {
108 schema: SchemaRef,
109 values: Vec<Value>,
110}
111
112impl Row {
113 pub fn new(schema: SchemaRef, values: Vec<Value>) -> Self {
114 Self { schema, values }
115 }
116
117 pub fn len(&self) -> usize {
118 self.values.len()
119 }
120
121 pub fn is_empty(&self) -> bool {
122 self.values.is_empty()
123 }
124
125 pub fn values(&self) -> &[Value] {
126 &self.values
127 }
128
129 pub fn schema(&self) -> SchemaRef {
130 self.schema.clone()
131 }
132
133 pub fn from_vec(schema: SchemaRef, values: Vec<Value>) -> Self {
134 Self { schema, values }
135 }
136}
137
138impl TryFrom<(SchemaRef, Vec<Option<String>>)> for Row {
139 type Error = Error;
140
141 fn try_from((schema, data): (SchemaRef, Vec<Option<String>>)) -> Result<Self> {
142 let mut values: Vec<Value> = Vec::with_capacity(data.len());
143 for (field, val) in schema.fields().iter().zip(data.into_iter()) {
144 values.push(Value::try_from((&field.data_type, val))?);
145 }
146 Ok(Self::new(schema, values))
147 }
148}
149
150impl IntoIterator for Row {
151 type Item = Value;
152 type IntoIter = std::vec::IntoIter<Self::Item>;
153
154 fn into_iter(self) -> Self::IntoIter {
155 self.values.into_iter()
156 }
157}
158
159#[derive(Clone, Debug)]
160pub struct Rows {
161 rows: Vec<Row>,
162}
163
164impl Rows {
165 pub fn new(rows: Vec<Row>) -> Self {
166 Self { rows }
167 }
168
169 pub fn rows(&self) -> &[Row] {
174 &self.rows
175 }
176
177 pub fn len(&self) -> usize {
178 self.rows.len()
179 }
180
181 pub fn is_empty(&self) -> bool {
182 self.rows.is_empty()
183 }
184}
185
186#[cfg(feature = "flight-sql")]
187impl TryFrom<RecordBatch> for Rows {
188 type Error = Error;
189 fn try_from(batch: RecordBatch) -> Result<Self> {
190 let batch_schema = batch.schema();
191 let schema = SchemaRef::new(batch_schema.clone().try_into()?);
192 let mut rows: Vec<Row> = Vec::new();
193 for i in 0..batch.num_rows() {
194 let mut values: Vec<Value> = Vec::new();
195 for j in 0..batch_schema.fields().len() {
196 let v = batch.column(j);
197 let field = batch_schema.field(j);
198 let value = Value::try_from((field, v, i))?;
199 values.push(value);
200 }
201 rows.push(Row::new(schema.clone(), values));
202 }
203 Ok(Self::new(rows))
204 }
205}
206
207impl IntoIterator for Rows {
208 type Item = Row;
209 type IntoIter = std::vec::IntoIter<Self::Item>;
210
211 fn into_iter(self) -> Self::IntoIter {
212 self.rows.into_iter()
213 }
214}
215
216macro_rules! replace_expr {
217 ($_t:tt $sub:expr) => {
218 $sub
219 };
220}
221
222macro_rules! impl_tuple_from_row {
224 ( $($Ti:tt),+ ) => {
225 impl<$($Ti),+> TryFrom<Row> for ($($Ti,)+)
226 where
227 $($Ti: TryFrom<Value>),+
228 {
229 type Error = String;
230 fn try_from(row: Row) -> Result<Self, String> {
231 let expected_len = <[()]>::len(&[$(replace_expr!(($Ti) ())),*]);
235
236 if expected_len != row.len() {
237 return Err(format!("row size mismatch: expected {} columns, got {}", expected_len, row.len()));
238 }
239 let mut vals_iter = row.into_iter().enumerate();
240
241 Ok((
242 $(
243 {
244 let (col_ix, col_value) = vals_iter
245 .next()
246 .unwrap(); let t = col_value.get_type();
249 $Ti::try_from(col_value)
250 .map_err(|_| format!("failed converting column {} from type({:?}) to type({})", col_ix, t, std::any::type_name::<$Ti>()))?
251 }
252 ,)+
253 ))
254 }
255 }
256 }
257}
258
259impl_tuple_from_row!(T1);
261impl_tuple_from_row!(T1, T2);
262impl_tuple_from_row!(T1, T2, T3);
263impl_tuple_from_row!(T1, T2, T3, T4);
264impl_tuple_from_row!(T1, T2, T3, T4, T5);
265impl_tuple_from_row!(T1, T2, T3, T4, T5, T6);
266impl_tuple_from_row!(T1, T2, T3, T4, T5, T6, T7);
267impl_tuple_from_row!(T1, T2, T3, T4, T5, T6, T7, T8);
268impl_tuple_from_row!(T1, T2, T3, T4, T5, T6, T7, T8, T9);
269impl_tuple_from_row!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10);
270impl_tuple_from_row!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11);
271impl_tuple_from_row!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12);
272impl_tuple_from_row!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13);
273impl_tuple_from_row!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14);
274impl_tuple_from_row!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15);
275impl_tuple_from_row!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16);
276
277pub struct RowIterator {
278 schema: SchemaRef,
279 it: Pin<Box<dyn Stream<Item = Result<Row>> + Send>>,
280}
281
282impl RowIterator {
283 pub fn new(schema: SchemaRef, it: Pin<Box<dyn Stream<Item = Result<Row>> + Send>>) -> Self {
284 Self { schema, it }
285 }
286
287 pub fn schema(&self) -> SchemaRef {
288 self.schema.clone()
289 }
290
291 pub async fn try_collect<T>(mut self) -> Result<Vec<T>>
292 where
293 T: TryFrom<Row>,
294 T::Error: std::fmt::Display,
295 {
296 let mut ret = Vec::new();
297 while let Some(row) = self.it.next().await {
298 let v = T::try_from(row?).map_err(|e| Error::Parsing(e.to_string()))?;
299 ret.push(v)
300 }
301 Ok(ret)
302 }
303}
304
305impl Stream for RowIterator {
306 type Item = Result<Row>;
307
308 fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
309 Pin::new(&mut self.it).poll_next(cx)
310 }
311}
312
313pub struct RowStatsIterator {
314 schema: SchemaRef,
315 it: Pin<Box<dyn Stream<Item = Result<RowWithStats>> + Send>>,
316}
317
318impl RowStatsIterator {
319 pub fn new(
320 schema: SchemaRef,
321 it: Pin<Box<dyn Stream<Item = Result<RowWithStats>> + Send>>,
322 ) -> Self {
323 Self { schema, it }
324 }
325
326 pub fn schema(&self) -> SchemaRef {
327 self.schema.clone()
328 }
329
330 pub async fn filter_rows(self) -> RowIterator {
331 let it = self.it.filter_map(|r| match r {
332 Ok(RowWithStats::Row(r)) => Some(Ok(r)),
333 Ok(_) => None,
334 Err(err) => Some(Err(err)),
335 });
336 RowIterator::new(self.schema, Box::pin(it))
337 }
338}
339
340impl Stream for RowStatsIterator {
341 type Item = Result<RowWithStats>;
342
343 fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
344 Pin::new(&mut self.it).poll_next(cx)
345 }
346}