use crate::mvcc::clock::LogicalClock; use crate::mvcc::database::{MvStore, Result, Row, RowID}; use std::fmt::Debug; use std::rc::Rc; #[derive(Debug)] pub struct ScanCursor { pub db: Rc>, pub row_ids: Vec, pub index: usize, tx_id: u64, } impl ScanCursor { pub fn new(db: Rc>, tx_id: u64, table_id: u64) -> Result> { let row_ids = db.scan_row_ids_for_table(table_id)?; Ok(Self { db, tx_id, row_ids, index: 0, }) } pub fn insert(&self, row: Row) -> Result<()> { self.db.insert(self.tx_id, row) } pub fn current_row_id(&self) -> Option { if self.index >= self.row_ids.len() { return None; } Some(self.row_ids[self.index]) } pub fn current_row(&self) -> Result> { if self.index >= self.row_ids.len() { return Ok(None); } let id = self.row_ids[self.index]; self.db.read(self.tx_id, id) } pub fn close(self) -> Result<()> { Ok(()) } pub fn forward(&mut self) -> bool { self.index += 1; self.index < self.row_ids.len() } pub fn is_empty(&self) -> bool { self.index >= self.row_ids.len() } } #[derive(Debug)] pub struct LazyScanCursor { pub db: Rc>, pub current_pos: Option, pub prev_pos: Option, table_id: u64, tx_id: u64, } impl LazyScanCursor { pub fn new(db: Rc>, tx_id: u64, table_id: u64) -> Result> { let current_pos = db.get_next_row_id_for_table(table_id, 0); Ok(Self { db, tx_id, current_pos, prev_pos: None, table_id, }) } pub fn insert(&self, row: Row) -> Result<()> { self.db.insert(self.tx_id, row) } pub fn current_row_id(&self) -> Option { self.current_pos } pub fn current_row(&self) -> Result> { if let Some(id) = self.current_pos { self.db.read(self.tx_id, id) } else { Ok(None) } } pub fn close(self) -> Result<()> { Ok(()) } pub fn forward(&mut self) -> bool { self.prev_pos = self.current_pos; if let Some(row_id) = self.prev_pos { let next_id = row_id.row_id + 1; self.current_pos = self.db.get_next_row_id_for_table(self.table_id, next_id); println!("{:?}", self.current_pos); self.current_pos.is_some() } else { false } } pub fn is_empty(&self) -> bool { self.current_pos.is_none() } } #[derive(Debug)] pub struct BucketScanCursor { pub db: Rc>, pub bucket: Vec, bucket_size: u64, table_id: u64, tx_id: u64, index: usize, } impl BucketScanCursor { pub fn new( db: Rc>, tx_id: u64, table_id: u64, size: u64, ) -> Result> { let mut bucket = Vec::with_capacity(size as usize); db.get_row_id_range(table_id, 0, &mut bucket, size)?; Ok(Self { db, tx_id, bucket, bucket_size: size, table_id, index: 0, }) } pub fn insert(&self, row: Row) -> Result<()> { self.db.insert(self.tx_id, row) } pub fn current_row_id(&self) -> Option { if self.index >= self.bucket.len() { return None; } Some(self.bucket[self.index]) } pub fn current_row(&self) -> Result> { if self.index >= self.bucket.len() { return Ok(None); } let id = self.bucket[self.index]; self.db.read(self.tx_id, id) } pub fn close(self) -> Result<()> { Ok(()) } pub fn forward(&mut self) -> bool { self.index += 1; if self.index < self.bucket.len() { true } else { self.next_bucket().unwrap_or_default() } } pub fn is_empty(&self) -> bool { self.index >= self.bucket.len() } fn next_bucket(&mut self) -> Result { let last_id = if !self.bucket.is_empty() { Some(self.bucket[self.bucket.len() - 1].row_id + 1) } else { None }; self.bucket.clear(); if let Some(next_id) = last_id { self.db .get_row_id_range(self.table_id, next_id, &mut self.bucket, self.bucket_size)?; self.index = 0; Ok(!self.bucket.is_empty()) } else { Ok(false) } } }