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>, ) -> crate::Result> { // 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>, } impl ViewVirtualTable { pub fn best_index(&self) -> Result { // 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) -> crate::Result { // 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)> = view.current_data(tx_state); Ok(ViewVirtualTableCursor { data, current_pos: 0, }) } } /// Cursor for iterating over view data pub struct ViewVirtualTableCursor { data: Vec<(i64, Vec)>, current_pos: usize, } impl ViewVirtualTableCursor { pub fn next(&mut self) -> crate::Result { 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 { 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) -> crate::Result { // Reset to beginning for new filter self.current_pos = 0; Ok(!self.data.is_empty()) } }