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}