Skip to main content

tank_core/
row.rs

1use crate::{QueryResult, Value};
2use std::{
3    iter::{self},
4    slice,
5    sync::Arc,
6};
7
8/// Result of a modifying operation (INSERT/UPDATE/DELETE).
9#[derive(Default, Clone, Copy, Debug)]
10pub struct RowsAffected {
11    /// Number of rows modified (if supported by backend).
12    pub rows_affected: Option<u64>,
13    /// Last inserted ID (driver-dependent).
14    pub last_affected_id: Option<i64>,
15}
16
17/// Shared column names.
18pub type RowNames = Arc<[String]>;
19/// Row values matching `RowNames`.
20pub type Row = Box<[Value]>;
21
22/// Row with column labels.
23#[derive(Default, Clone, Debug)]
24pub struct RowLabeled {
25    /// Column names.
26    pub labels: RowNames,
27    /// Column values.
28    pub values: Row,
29}
30
31impl RowLabeled {
32    pub fn new(names: RowNames, values: Row) -> Self {
33        Self {
34            labels: names,
35            values,
36        }
37    }
38    /// Column labels.
39    pub fn names(&self) -> &[String] {
40        &self.labels
41    }
42    /// Row values.
43    pub fn values(&self) -> &[Value] {
44        &self.values
45    }
46    /// Get value by column name.
47    pub fn get_column(&self, name: &str) -> Option<&Value> {
48        self.labels
49            .iter()
50            .position(|v| v == name)
51            .map(|i| &self.values()[i])
52    }
53    /// Column count.
54    pub fn len(&self) -> usize {
55        self.values.len()
56    }
57}
58
59impl<'s> IntoIterator for &'s RowLabeled {
60    type Item = (&'s String, &'s Value);
61    type IntoIter = iter::Zip<slice::Iter<'s, String>, slice::Iter<'s, Value>>;
62    fn into_iter(self) -> Self::IntoIter {
63        iter::zip(self.labels.iter(), self.values.iter())
64    }
65}
66
67impl<'s> IntoIterator for &'s mut RowLabeled {
68    type Item = (&'s String, &'s mut Value);
69    type IntoIter = iter::Zip<slice::Iter<'s, String>, slice::IterMut<'s, Value>>;
70    fn into_iter(self) -> Self::IntoIter {
71        iter::zip(self.labels.iter(), self.values.iter_mut())
72    }
73}
74
75impl Extend<RowsAffected> for RowsAffected {
76    fn extend<T: IntoIterator<Item = RowsAffected>>(&mut self, iter: T) {
77        for elem in iter {
78            if self.rows_affected.is_some() || elem.rows_affected.is_some() {
79                self.rows_affected = Some(
80                    self.rows_affected.unwrap_or_default() + elem.rows_affected.unwrap_or_default(),
81                );
82            }
83            if elem.last_affected_id.is_some() {
84                self.last_affected_id = elem.last_affected_id;
85            }
86        }
87    }
88}
89
90impl From<RowLabeled> for Row {
91    fn from(value: RowLabeled) -> Self {
92        value.values
93    }
94}
95
96impl<'a> From<&'a RowLabeled> for &'a Row {
97    fn from(value: &'a RowLabeled) -> Self {
98        &value.values
99    }
100}
101
102impl From<RowLabeled> for QueryResult {
103    fn from(value: RowLabeled) -> Self {
104        QueryResult::Row(value)
105    }
106}
107
108impl From<RowsAffected> for QueryResult {
109    fn from(value: RowsAffected) -> Self {
110        QueryResult::Affected(value)
111    }
112}