mirror of
https://github.com/aljazceru/turso.git
synced 2025-12-25 12:04:21 +01:00
This is just the bare minimum that I needed to convince myself that this approach will work. The only views that we support are slices of the main table: no aggregations, no joins, no projections. drop view is implemented. view population is implemented. deletes, inserts and updates are implemented. much like indexes before, a flag must be passed to enable views.
102 lines
3.1 KiB
Rust
102 lines
3.1 KiB
Rust
use crate::incremental::view::IncrementalView;
|
|
use crate::{Connection, LimboError, Value, VirtualTable};
|
|
use std::sync::{Arc, Mutex};
|
|
|
|
/// Create a virtual table wrapper for a view
|
|
pub fn create_view_virtual_table(
|
|
view_name: &str,
|
|
view: Arc<Mutex<IncrementalView>>,
|
|
) -> crate::Result<Arc<VirtualTable>> {
|
|
// Use the VirtualTable::view method we added
|
|
let view_locked = view.lock().map_err(|_| {
|
|
LimboError::InternalError("Failed to lock view for virtual table creation".to_string())
|
|
})?;
|
|
let columns = view_locked.columns.clone();
|
|
drop(view_locked); // Release the lock before passing the Arc
|
|
VirtualTable::view(view_name, columns, view)
|
|
}
|
|
|
|
/// Virtual table wrapper for incremental views
|
|
#[derive(Clone, Debug)]
|
|
pub struct ViewVirtualTable {
|
|
pub view: Arc<Mutex<IncrementalView>>,
|
|
}
|
|
|
|
impl ViewVirtualTable {
|
|
pub fn best_index(&self) -> Result<turso_ext::IndexInfo, turso_ext::ResultCode> {
|
|
// Views don't use indexes - return a simple index info
|
|
Ok(turso_ext::IndexInfo {
|
|
idx_num: 0,
|
|
idx_str: None,
|
|
order_by_consumed: false,
|
|
estimated_cost: 1000000.0,
|
|
estimated_rows: 1000,
|
|
constraint_usages: Vec::new(),
|
|
})
|
|
}
|
|
|
|
pub fn open(&self, conn: Arc<Connection>) -> crate::Result<ViewVirtualTableCursor> {
|
|
// Views are now populated during schema parsing (in parse_schema_rows)
|
|
// so we just get the current data from the view.
|
|
|
|
let view = self.view.lock().map_err(|_| {
|
|
LimboError::InternalError("Failed to lock view for reading".to_string())
|
|
})?;
|
|
|
|
let tx_states = conn.view_transaction_states.borrow();
|
|
let tx_state = tx_states.get(view.name());
|
|
|
|
let data: Vec<(i64, Vec<Value>)> = view.current_data(tx_state);
|
|
Ok(ViewVirtualTableCursor {
|
|
data,
|
|
current_pos: 0,
|
|
})
|
|
}
|
|
}
|
|
|
|
/// Cursor for iterating over view data
|
|
pub struct ViewVirtualTableCursor {
|
|
data: Vec<(i64, Vec<Value>)>,
|
|
current_pos: usize,
|
|
}
|
|
|
|
impl ViewVirtualTableCursor {
|
|
pub fn next(&mut self) -> crate::Result<bool> {
|
|
if self.current_pos < self.data.len() {
|
|
self.current_pos += 1;
|
|
Ok(self.current_pos < self.data.len())
|
|
} else {
|
|
Ok(false)
|
|
}
|
|
}
|
|
|
|
pub fn rowid(&self) -> i64 {
|
|
if self.current_pos < self.data.len() {
|
|
self.data[self.current_pos].0
|
|
} else {
|
|
-1
|
|
}
|
|
}
|
|
|
|
pub fn column(&self, column: usize) -> crate::Result<Value> {
|
|
if self.current_pos >= self.data.len() {
|
|
return Ok(Value::Null);
|
|
}
|
|
|
|
let (_row_key, values) = &self.data[self.current_pos];
|
|
|
|
// Return the value at the requested column index
|
|
if let Some(value) = values.get(column) {
|
|
Ok(value.clone())
|
|
} else {
|
|
Ok(Value::Null)
|
|
}
|
|
}
|
|
|
|
pub fn filter(&mut self, _args: Vec<Value>) -> crate::Result<bool> {
|
|
// Reset to beginning for new filter
|
|
self.current_pos = 0;
|
|
Ok(!self.data.is_empty())
|
|
}
|
|
}
|