use crate::*;
use pstd::veca;
use std::hash::Hasher;
const SCHEMA: usize = 0;
const TABLE: usize = 1;
const OBJ_ID: usize = 0;
const _OBJ_SCHEMA: usize = 1;
const OBJ_NAME: usize = 2;
const OBJ_INNER: usize = 3;
pub fn make_obj_dt() -> DataType {
use pstd::veca;
let objenum = DataType::Enum(veca![
(LString::from("Schema"), DataType::Empty),
(LString::from("Table"), DataType::TabInfo),
]);
DataType::Struct(veca![
(LString::from("Id"), DataType::Int),
(LString::from("Schema"), DataType::Int),
(LString::from("Name"), DataType::String),
(LString::from("Inner"), objenum),
])
}
pub struct IdKey<'a> {
pub rid: i64,
pub dt: &'a DataType,
}
impl<'a> IdKey<'a> {
pub fn insert(&self, r: &Value, main: &mut BuckMapInfo, ps: &mut PageSet) {
let addr = VarValAddr::new(self.dt, r, ps);
let mut bm = BuckMap::restore(*main, ps);
bm.insert(self, addr);
if bm.root_changed() {
*main = bm.save();
}
}
}
impl<'a> Hash for IdKey<'a> {
fn hash<H: Hasher>(&self, h: &mut H) {
self.rid.hash(h);
}
}
impl<'a> Key<VarValAddr> for IdKey<'a> {
fn ok(&self, addr: VarValAddr, ps: &mut PageSet) -> Option<(VarValAddr, Value)> {
let v = addr.get(self.dt, ps);
let rid = v.list()[0].int();
if rid == self.rid {
return Some((addr, v));
}
None
}
}
pub fn get_obj(rid: i64, ps: &mut PageSet) -> Option<(VarValAddr, Value)> {
let dt = ps.obj_dt.clone();
let key = IdKey { rid, dt: &dt };
BuckMap::restore(ps.obj_map, ps).get(&key)
}
#[derive(Hash)]
pub struct ObjNameKey<'a> {
name: &'a str,
}
impl<'a> Key<i64> for ObjNameKey<'a> {
fn ok(&self, addr: i64, ps: &mut PageSet) -> Option<(i64, Value)> {
let (_, v) = get_obj(addr, ps).unwrap();
let name = v.list()[OBJ_NAME].string();
if self.name == name {
return Some((addr, v));
}
None
}
}
pub fn list_obj_all(ps: &mut PageSet) {
let mut x = BuckMap::<VarValAddr>::restore(ps.obj_map, ps).all_addr();
x.sort();
let dt = ps.obj_dt.clone();
for addr in x {
let r = addr.get(&dt, ps);
println!("list_obj_all addr={:?} r={:?}", addr, r);
}
}
fn create_obj_inner(rid: i64, r: Value, ps: &mut PageSet) {
let dt = ps.obj_dt.clone();
let addr = VarValAddr::new(&dt, &r, ps);
let key = IdKey { rid, dt: &dt };
let mut bm = BuckMap::restore(ps.obj_map, ps);
bm.insert(&key, addr);
if bm.root_changed() {
ps.obj_map = bm.save();
}
}
fn index_obj_by_name(id: i64, name: &str, ps: &mut PageSet) {
let key = ObjNameKey { name };
let mut bm = BuckMap::restore(ps.obj_by_name, ps);
bm.insert(&key, id);
if bm.root_changed() {
ps.obj_by_name = bm.save();
}
}
pub fn create_obj(rid: i64, name: &str, inner: Value, ps: &mut PageSet) {
let r = Value::List(veca![
Value::Int(rid), Value::Int(0), Value::String(LString::from(name)),
inner
]);
create_obj_inner(rid, r, ps);
index_obj_by_name(rid, name, ps);
}
pub fn get_obj_from_name(name: &str, ps: &mut PageSet) -> Option<(i64, Value)> {
let key = ObjNameKey { name };
let mut bm = BuckMap::restore(ps.obj_by_name, ps);
if let Some(x) = bm.get(&key) {
return Some(x);
}
None
}
pub fn save_obj(addr: VarValAddr, obj: Value, ps: &mut PageSet) {
let dt = ps.obj_dt.clone();
let addr2 = addr.update(&dt, &obj, ps);
if addr2 != addr {
let rid = obj.list()[OBJ_ID].int();
let key = IdKey { rid, dt: &dt };
let mut bm = BuckMap::restore(ps.obj_map, ps);
bm.remove(&key);
bm.insert(&key, addr2);
if bm.root_changed() {
ps.obj_map = bm.save();
}
}
}
pub fn create_schema(name: &str, ps: &mut PageSet) -> Option<(i64, Value)> {
let obj = get_obj_from_name(name, ps);
if obj.is_some() {
obj
} else {
let rid = ps.next_obj_id;
ps.next_obj_id = rid + 1;
let inner = Value::Enum(SCHEMA, LBox::new(Value::Empty));
create_obj(rid, name, inner, ps);
None
}
}
fn set_table_datatype(rid: i64, tdt: DataType, ps: &mut PageSet) {
let dt = DataType::Tuple(veca![DataType::Int, DataType::DataType]);
let v = Value::List(veca![Value::Int(rid), Value::DataType(tdt)]);
let addr = VarValAddr::new(&dt, &v, ps);
let key = IdKey { rid, dt: &dt };
let mut bm = BuckMap::restore(ps.table_datatype_map, ps);
bm.insert(&key, addr);
if bm.root_changed() {
ps.table_datatype_map = bm.save();
}
}
pub fn get_table_datatype(rid: i64, ps: &mut PageSet) -> DataType {
let dt = DataType::Tuple(veca![DataType::Int, DataType::DataType]);
let key = IdKey { rid, dt: &dt };
let mut bm = BuckMap::restore(ps.table_datatype_map, ps);
let mut av = bm.get(&key).unwrap();
let dt = av.1.list_mut()[1].datatype_mut();
std::mem::take(dt)
}
pub fn create_table(
name: &str,
dt: DataType,
ix_count: usize,
ps: &mut PageSet,
) -> Option<(i64, Value)> {
let obj = get_obj_from_name(name, ps);
if obj.is_some() {
obj
} else {
let rid = ps.next_obj_id;
ps.next_obj_id = rid + 1;
let bm = BuckMap::<VarValAddr>::new(1, ps);
let main = bm.save();
let mut index = LVec::new();
for _ in 0..ix_count {
let bm = BuckMap::<VarValAddr>::new(1, ps);
index.push(bm.save());
}
let tableinfo = Value::TabInfo(TabInfo {
alloc: 0,
main,
index,
});
let inner = Value::Enum(TABLE, LBox::new(tableinfo));
create_obj(rid, name, inner, ps);
set_table_datatype(rid, dt, ps);
None
}
}
#[derive(
Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, serde::Serialize, serde::Deserialize,
)]
pub struct TabInfo {
alloc: i64,
pub main: BuckMapInfo,
pub index: LVec<BuckMapInfo>,
}
impl TabInfo {
pub fn id(&mut self) -> i64 {
let result = self.alloc;
self.alloc += 1;
result
}
pub fn to_bytes(&self) -> Vec<u8> {
postcard::to_stdvec(self).unwrap()
}
pub fn from_bytes(b: &[u8]) -> Self {
postcard::from_bytes(b).unwrap()
}
}
pub fn decode_table(obj: &mut Value) -> &mut TabInfo {
let (tag, inner) = obj.list_mut()[OBJ_INNER].en_mut();
assert!(*tag == TABLE);
inner.tabinfo_mut()
}
pub fn save_table(rid: i64, obj: Value, ps: &mut PageSet) {
let (addr, _) = get_obj(rid, ps).unwrap();
save_obj(addr, obj, ps);
}