use super::row::CustomDbRow;
use crate::types::RowValues;
type ColumnCacheMap = std::sync::LazyLock<
std::sync::Mutex<
std::collections::HashMap<usize, std::sync::Arc<std::collections::HashMap<String, usize>>>,
>,
>;
#[derive(Debug, Clone, Default)]
pub struct ResultSet {
pub results: Vec<CustomDbRow>,
pub rows_affected: usize,
column_names: Option<std::sync::Arc<Vec<String>>>,
}
impl ResultSet {
#[must_use]
pub fn with_capacity(capacity: usize) -> ResultSet {
ResultSet {
results: Vec::with_capacity(capacity),
rows_affected: 0,
column_names: None,
}
}
pub fn set_column_names(&mut self, column_names: std::sync::Arc<Vec<String>>) {
self.column_names = Some(column_names);
}
#[must_use]
pub fn get_column_names(&self) -> Option<&std::sync::Arc<Vec<String>>> {
self.column_names.as_ref()
}
pub fn add_row_values(&mut self, row_values: Vec<RowValues>) {
if let Some(column_names) = &self.column_names {
static CACHE_MAP: ColumnCacheMap =
std::sync::LazyLock::new(
|| std::sync::Mutex::new(std::collections::HashMap::new()),
);
let ptr = column_names.as_ref().as_ptr() as usize;
let cache = {
let mut cache_map = match CACHE_MAP.lock() {
Ok(guard) => guard,
Err(poisoned) => {
poisoned.into_inner()
}
};
let cache_entry = cache_map.entry(ptr).or_insert_with(|| {
std::sync::Arc::new(
column_names
.iter()
.enumerate()
.map(|(i, name)| (name.clone(), i))
.collect::<std::collections::HashMap<_, _>>(),
)
});
cache_entry.clone()
};
let row = CustomDbRow {
column_names: column_names.clone(),
rows: row_values,
column_index_cache: cache,
};
self.results.push(row);
self.rows_affected += 1;
}
}
pub fn add_row(&mut self, row: CustomDbRow) {
if self.column_names.is_none() {
self.column_names = Some(row.column_names.clone());
}
self.results.push(row);
self.rows_affected += 1;
}
}