123 lines
3.9 KiB
Rust
123 lines
3.9 KiB
Rust
//! Модуль управления индексами
|
||
|
||
use std::collections::{HashMap, HashSet};
|
||
use crate::parser::sql::Value;
|
||
use std::sync::atomic::{AtomicU64, Ordering};
|
||
use atomic_refcell::AtomicRefCell;
|
||
|
||
/// Индекс для быстрого поиска с поддержкой MVCC
|
||
#[derive(Debug)]
|
||
pub struct Index {
|
||
name: String,
|
||
data: AtomicRefCell<HashMap<Value, HashSet<u64>>>,
|
||
version: AtomicU64,
|
||
}
|
||
|
||
impl Clone for Index {
|
||
fn clone(&self) -> Self {
|
||
let data = self.data.borrow();
|
||
Self {
|
||
name: self.name.clone(),
|
||
data: AtomicRefCell::new(data.clone()),
|
||
version: AtomicU64::new(self.version.load(Ordering::Relaxed)),
|
||
}
|
||
}
|
||
}
|
||
|
||
impl Index {
|
||
/// Создание нового индекса
|
||
pub fn new(name: &str) -> Self {
|
||
Self {
|
||
name: name.to_string(),
|
||
data: AtomicRefCell::new(HashMap::new()),
|
||
version: AtomicU64::new(1),
|
||
}
|
||
}
|
||
|
||
/// Вставка значения в индекс (wait-free)
|
||
pub fn insert(&self, value: Value, record_id: u64) {
|
||
let mut data = self.data.borrow_mut();
|
||
data.entry(value)
|
||
.or_insert_with(HashSet::new)
|
||
.insert(record_id);
|
||
self.version.fetch_add(1, Ordering::SeqCst);
|
||
}
|
||
|
||
/// Поиск по значению (wait-free чтение)
|
||
pub fn search(&self, value: &Value) -> Option<HashSet<u64>> {
|
||
let data = self.data.borrow();
|
||
data.get(value).cloned()
|
||
}
|
||
|
||
/// Удаление значения из индекса
|
||
pub fn remove(&self, value: &Value, record_id: u64) {
|
||
let mut data = self.data.borrow_mut();
|
||
if let Some(set) = data.get_mut(value) {
|
||
set.remove(&record_id);
|
||
if set.is_empty() {
|
||
data.remove(value);
|
||
}
|
||
self.version.fetch_add(1, Ordering::SeqCst);
|
||
}
|
||
}
|
||
|
||
/// Получение всех значений индекса (wait-free)
|
||
pub fn get_all(&self) -> Vec<Value> {
|
||
let data = self.data.borrow();
|
||
data.keys().cloned().collect()
|
||
}
|
||
|
||
/// Очистка индекса
|
||
pub fn clear(&mut self) {
|
||
let mut data = self.data.borrow_mut();
|
||
data.clear();
|
||
self.version.fetch_add(1, Ordering::SeqCst);
|
||
}
|
||
|
||
/// Получение имени индекса
|
||
pub fn name(&self) -> &str {
|
||
&self.name
|
||
}
|
||
|
||
/// Получение версии индекса
|
||
pub fn version(&self) -> u64 {
|
||
self.version.load(Ordering::Relaxed)
|
||
}
|
||
|
||
/// Массовая вставка записей (оптимизированная)
|
||
pub fn bulk_insert(&self, values: Vec<(Value, u64)>) {
|
||
let mut data = self.data.borrow_mut();
|
||
for (value, record_id) in values {
|
||
data.entry(value)
|
||
.or_insert_with(HashSet::new)
|
||
.insert(record_id);
|
||
}
|
||
self.version.fetch_add(1, Ordering::SeqCst);
|
||
}
|
||
|
||
/// Поиск по диапазону (для упорядоченных типов)
|
||
pub fn range_search(&self, start: &Value, end: &Value) -> HashSet<u64> {
|
||
let data = self.data.borrow();
|
||
let mut result = HashSet::new();
|
||
|
||
for (key, record_ids) in data.iter() {
|
||
// Упрощенная реализация - только для сравнимых типов
|
||
match (key, start, end) {
|
||
(Value::Integer(k), Value::Integer(s), Value::Integer(e)) => {
|
||
if k >= s && k <= e {
|
||
result.extend(record_ids);
|
||
}
|
||
}
|
||
(Value::Text(k), Value::Text(s), Value::Text(e)) => {
|
||
if k >= s && k <= e {
|
||
result.extend(record_ids);
|
||
}
|
||
}
|
||
_ => {}
|
||
}
|
||
}
|
||
|
||
result
|
||
}
|
||
}
|