tank_core/
row.rs

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