use crate::*;
#[derive(Debug)]
pub struct Table {
inner: TableInner,
pub datatype: Arc<DataType>,
changed: bool,
}
#[derive(Debug, serde::Serialize, serde::Deserialize)]
pub struct TableInner {
next_id: u64,
store: Store,
}
impl TableInner {
pub fn to_bytes_id(&self, id: u64) -> LVec<u8> {
let mut result = LVec::new();
result.extend_from_slice( &id.to_le_bytes() );
postcard::to_io(self, &mut result).unwrap();
result
}
pub fn from_bytes_id(b: &[u8]) -> Self {
postcard::from_bytes(&b[8..]).unwrap()
}
}
impl Table {
pub fn new(datatype: Arc<DataType>, ps: &mut PageSet) -> Self {
let store = Store::new(ps);
Self {
inner : TableInner { next_id: 1, store },
datatype,
changed: true,
}
}
pub fn new_id(&mut self) -> i64 {
let result = self.inner.next_id;
self.inner.next_id += 1;
self.changed = true;
result as i64
}
pub fn reserve_id(&mut self, id: i64) {
if id as u64 >= self.inner.next_id
{
self.inner.next_id = ( id + 1) as u64;
self.changed = true;
}
}
pub fn insert(&mut self, v: &Value, ps: &mut PageSet) -> i64 {
let x = {
let m = &mut self.inner.store;
let mut spx = (m, &mut *ps);
self.datatype.value_to_bytes(v, &mut spx)
};
let id = v.list()[0].int() as u64;
let key = IdVKey { id };
self.inner.store.insert(&key, &x, ps);
id as i64
}
pub fn fetch(&self, id: i64, ps: &mut PageSet) -> Option<Value> {
let key = IdVKey { id: id as u64 };
let m = &self.inner.store;
if let Some(sd) = m.get(&key, ps) {
let mut spx = (m, &mut *ps);
let result = sd.decode(&self.datatype, &mut spx);
Some(result)
} else {
None
}
}
pub fn lazy_fetch<'a>(&'a self, id: i64, ps: &mut PageSet) -> Option<OwnedLazyRow<'a>> {
let key = IdVKey { id: id as u64 };
let m = &self.inner.store;
if let Some(sdata) = m.get(&key, ps) {
let items = sdata.lazy_row_items(&self.datatype);
Some(OwnedLazyRow {
sdata,
table: self,
items,
})
} else {
None
}
}
pub fn update(&mut self, id: i64, v: &Value, ps: &mut PageSet) {
let _ = self.remove(id, ps);
let m = &mut self.inner.store;
let x = {
let mut spx = (m, &mut *ps);
self.datatype.value_to_bytes(v, &mut spx)
};
let key = IdVKey { id: id as u64 };
self.inner.store.insert(&key, &x, ps);
}
pub fn remove(&mut self, id: i64, ps: &mut PageSet) -> Option<Value> {
let key = IdVKey { id: id as u64 };
let m = &mut self.inner.store;
if let Some(sd) = m.get(&key, ps) {
let result = {
let mut spx = (&mut *m, &mut *ps);
sd.decode_del(&self.datatype, &mut spx)
};
m.remove(&key, ps);
Some(result)
} else {
None
}
}
pub fn iter(&self, ps: &mut PageSet) -> TableIter<'_> {
let inner = self.inner.store.iter(ps);
TableIter { inner, table: self }
}
pub fn delete_all(&mut self, ps: &mut PageSet) {
self.inner.store.delete_all(ps);
}
pub fn select_value(&self, item: usize, buf: &[u8], ps: &mut PageSet) -> Value {
let mut spx = (&self.inner.store, &mut *ps);
self.datatype.select_value(item, buf, &mut spx)
}
pub fn lazy_row<'a>(&'a self, buf: &'a [u8]) -> LazyRow<'a> {
let mut ix = 0;
let items = self.datatype.lazy_row_items(buf, &mut ix);
LazyRow {
table: self,
buf,
items,
}
}
pub fn changed(&self) -> bool {
self.changed || self.inner.store.changed()
}
pub fn save(&mut self, id: i64, ps: &mut PageSet) {
println!("Table::Save id={} changed={}", id, self.changed() );
if self.changed()
{
let id = id as u64;
self.changed = false;
let ssc = ps.sys_store.clone();
let mut sys_store = ssc.borrow_mut();
let bytes = self.inner.to_bytes_id(id);
let key = IdVKey::new(id);
sys_store.remove(&key, ps); sys_store.insert(&key, &bytes, ps);
}
}
pub fn restore(id: i64, ps: &mut PageSet, datatype: Arc<DataType>) -> Self {
let ssc = ps.sys_store.clone();
let mut sys_store = ssc.borrow_mut();
let key = IdVKey::new(id as u64);
if let Some(sdata) = sys_store.get(&key, ps) {
println!("Table::restore decoding table id={}", id);
let inner = sdata.decode_table_inner();
Self{ inner, datatype, changed: false }
} else {
println!("Table::restore creating new table id={}", id);
let table = Table::new(datatype, ps);
let bytes = table.inner.to_bytes_id(id as u64);
sys_store.insert(&key, &bytes, ps);
table
}
}
}
pub struct OwnedLazyRow<'a> {
table: &'a Table,
sdata: SData,
items: LVec<LazyItem>,
}
impl<'a> OwnedLazyRow<'a> {
pub fn item(&mut self, item: usize, ps: &mut PageSet) -> Value {
let x = &mut self.items[item];
match x {
LazyItem::Value(v) => v.clone(),
LazyItem::Offset(off) => {
let mut spx = (&self.table.inner.store, ps);
let dt = &self.table.datatype.dt_struct(item);
let v = self.sdata.decode_at(dt, *off, &mut spx);
*x = LazyItem::Value(v.clone());
v
}
}
}
}
pub struct LazyRow<'a> {
table: &'a Table,
buf: &'a [u8],
items: LVec<LazyItem>,
}
impl<'a> LazyRow<'a> {
pub fn item(&mut self, item: usize, ps: &mut PageSet) -> Value {
let x = &mut self.items[item];
match x {
LazyItem::Value(v) => v.clone(),
LazyItem::Offset(off) => {
let b = &self.buf[*off..];
let mut spx = (&self.table.inner.store, ps);
let dt = &self.table.datatype.dt_struct(item);
let v = dt.bytes_to_value(b, &mut spx);
*x = LazyItem::Value(v.clone());
v
}
}
}
pub fn item_ref(&mut self, item: usize) -> &[u8] {
let x = &mut self.items[item];
match x {
LazyItem::Value(_v) => panic!(),
LazyItem::Offset(off) => &self.buf[*off..],
}
}
pub fn item_bytes(&mut self, item: usize) -> Option<&[u8]> {
let dt = &self.table.datatype.dt_struct(item);
match dt {
DataType::String(_) => {}
DataType::Binary(_) => (),
_ => panic!(),
}
let b = self.item_ref(item);
DataType::bytes(b)
}
}
pub struct TableIter<'a> {
inner: StoreIter<'a>,
table: &'a Table,
}
impl<'a> TableIter<'a> {
pub fn next_value(&mut self, ps: &mut PageSet) -> Option<Value> {
if let Some(data) = self.inner.next(ps) {
let mut spx = (&self.table.inner.store, &mut *ps);
let result = self.table.datatype.bytes_to_value(data, &mut spx);
Some(result)
} else {
None
}
}
pub fn next_ref(&mut self, ps: &mut PageSet) -> Option<&[u8]> {
self.inner.next(ps)
}
}
use std::hash::{Hash, Hasher};
#[derive(Debug)]
pub struct IndexKey<'a> {
val: &'a Value,
table: &'a Table,
col: usize,
}
impl<'a> IndexKey<'a> {
pub fn new(val: &'a Value, table: &'a Table, col: usize) -> Self {
Self { val, table, col }
}
fn lookup_key(&self, bytes: &[u8], ps: &mut PageSet) -> Value {
let ix_dt = DataType::IList(0);
let first_id = ix_dt.bytes_to_value0(bytes).ilist()[0];
let mut lz = self.table.lazy_fetch(first_id, ps).unwrap();
lz.item(self.col, ps)
}
}
impl<'a> VKey for IndexKey<'a> {
fn ok(&self, bytes: &[u8], ps: &mut PageSet) -> bool {
let v = self.lookup_key(bytes, ps);
&v == self.val
}
fn rehash<H: Hasher>(&self, bytes: &[u8], h: &mut H, ps: &mut PageSet) {
let tsv = self.lookup_key(bytes, ps);
tsv.hash(h);
}
}
impl<'a> Hash for IndexKey<'a> {
fn hash<H: Hasher>(&self, h: &mut H) {
self.val.hash(h);
}
}
pub fn index_insert(index: &mut Store, id: i64, key: &IndexKey, ps: &mut PageSet) {
use pstd::veca;
let ix_dt = DataType::IList(0);
let sdata = index.get(key, ps);
let ixv = Value::IList(if let Some(sdata) = sdata {
let v = sdata.decode0(&ix_dt);
let mut list = v.ilist().clone();
let mlist = LRc::make_mut(&mut list);
mlist.push(id);
index.remove(key, ps);
list
} else {
LRc::new(veca![id])
});
{
let enc = ix_dt.value_to_bytes0(&ixv);
index.insert(key, &enc, ps);
}
}