sql_middleware/results/row.rs
1use crate::types::RowValues;
2
3/// A row from a database query result
4///
5/// This struct represents a single row from a database query result,
6/// with access to both the column names and the values.
7#[derive(Debug, Clone)]
8pub struct CustomDbRow {
9 /// The column names for this row (shared across all rows in a result set)
10 pub column_names: std::sync::Arc<Vec<String>>,
11 /// The values for this row
12 pub rows: Vec<RowValues>,
13 // Internal cache for faster column lookups (to avoid repeated string comparisons)
14 #[doc(hidden)]
15 pub(crate) column_index_cache: std::sync::Arc<std::collections::HashMap<String, usize>>,
16}
17
18impl CustomDbRow {
19 /// Create a new database row
20 ///
21 /// # Arguments
22 ///
23 /// * `column_names` - The column names
24 /// * `rows` - The values for this row
25 ///
26 /// # Returns
27 ///
28 /// A new `CustomDbRow` instance
29 #[must_use]
30 pub fn new(column_names: std::sync::Arc<Vec<String>>, rows: Vec<RowValues>) -> Self {
31 // Build a cache of column name to index for faster lookups
32 let cache = std::sync::Arc::new(
33 column_names
34 .iter()
35 .enumerate()
36 .map(|(i, name)| (name.clone(), i))
37 .collect::<std::collections::HashMap<_, _>>(),
38 );
39
40 Self {
41 column_names,
42 rows,
43 column_index_cache: cache,
44 }
45 }
46
47 /// Get the index of a column by name
48 ///
49 /// # Arguments
50 ///
51 /// * `column_name` - The name of the column
52 ///
53 /// # Returns
54 ///
55 /// The index of the column, or None if not found
56 #[must_use]
57 pub fn get_column_index(&self, column_name: &str) -> Option<usize> {
58 // First check the cache
59 if let Some(&idx) = self.column_index_cache.get(column_name) {
60 return Some(idx);
61 }
62
63 // Fall back to linear search
64 self.column_names.iter().position(|col| col == column_name)
65 }
66
67 /// Get a value from the row by column name
68 ///
69 /// # Arguments
70 ///
71 /// * `column_name` - The name of the column
72 ///
73 /// # Returns
74 ///
75 /// The value at the column, or None if the column wasn't found
76 #[must_use]
77 pub fn get(&self, column_name: &str) -> Option<&RowValues> {
78 let index_opt = self.get_column_index(column_name);
79 if let Some(idx) = index_opt {
80 self.rows.get(idx)
81 } else {
82 None
83 }
84 }
85
86 /// Get a value from the row by column index
87 ///
88 /// # Arguments
89 ///
90 /// * `index` - The index of the column
91 ///
92 /// # Returns
93 ///
94 /// The value at the index, or None if the index is out of bounds
95 #[must_use]
96 pub fn get_by_index(&self, index: usize) -> Option<&RowValues> {
97 self.rows.get(index)
98 }
99}