Skip to main content

tablestg/
sys.rs

1use crate::*;
2use pstd::veca;
3use std::hash::Hasher;
4
5// obj inner enum values
6const SCHEMA: usize = 0;
7const TABLE: usize = 1;
8
9// obj field numbers
10const OBJ_ID: usize = 0;
11const _OBJ_SCHEMA: usize = 1;
12const OBJ_NAME: usize = 2;
13const OBJ_INNER: usize = 3;
14
15/// DataType for sys object ( Schema, Table, Index, Function etc. )
16pub fn make_obj_dt() -> DataType {
17    use pstd::veca;
18
19    let objenum = DataType::Enum(veca![
20        (LString::from("Schema"), DataType::Empty),
21        (LString::from("Table"), DataType::TabInfo),
22    ]);
23
24    DataType::Struct(veca![
25        (LString::from("Id"), DataType::Int),
26        (LString::from("Schema"), DataType::Int),
27        (LString::from("Name"), DataType::String),
28        (LString::from("Inner"), objenum),
29    ])
30}
31
32/// Can be used for any record which has id as first elem of list.
33pub struct IdKey<'a> {
34    pub rid: i64,
35    pub dt: &'a DataType,
36}
37
38impl<'a> IdKey<'a> {
39    pub fn insert(&self, r: &Value, main: &mut BuckMapInfo, ps: &mut PageSet) {
40        // Store the record.
41        let addr = VarValAddr::new(self.dt, r, ps);
42
43        // Associate the id with the addr.
44        let mut bm = BuckMap::restore(*main, ps);
45        bm.insert(self, addr);
46        if bm.root_changed() {
47            *main = bm.save();
48        }
49    }
50}
51
52impl<'a> Hash for IdKey<'a> {
53    fn hash<H: Hasher>(&self, h: &mut H) {
54        self.rid.hash(h);
55    }
56}
57
58impl<'a> Key<VarValAddr> for IdKey<'a> {
59    fn ok(&self, addr: VarValAddr, ps: &mut PageSet) -> Option<(VarValAddr, Value)> {
60        let v = addr.get(self.dt, ps);
61        let rid = v.list()[0].int();
62        if rid == self.rid {
63            return Some((addr, v));
64        }
65        None
66    }
67}
68
69/// Get obj address and value from specified id.
70pub fn get_obj(rid: i64, ps: &mut PageSet) -> Option<(VarValAddr, Value)> {
71    let dt = ps.obj_dt.clone();
72    let key = IdKey { rid, dt: &dt };
73    BuckMap::restore(ps.obj_map, ps).get(&key)
74}
75
76#[derive(Hash)]
77pub struct ObjNameKey<'a> {
78    name: &'a str,
79}
80
81impl<'a> Key<i64> for ObjNameKey<'a> {
82    fn ok(&self, addr: i64, ps: &mut PageSet) -> Option<(i64, Value)> {
83        let (_, v) = get_obj(addr, ps).unwrap();
84        let name = v.list()[OBJ_NAME].string();
85        if self.name == name {
86            return Some((addr, v));
87        }
88        None
89    }
90}
91
92/// Print all objects ( debug ).
93pub fn list_obj_all(ps: &mut PageSet) {
94    let mut x = BuckMap::<VarValAddr>::restore(ps.obj_map, ps).all_addr();
95
96    x.sort();
97
98    let dt = ps.obj_dt.clone();
99
100    for addr in x {
101        let r = addr.get(&dt, ps);
102        println!("list_obj_all addr={:?} r={:?}", addr, r);
103    }
104}
105
106/// Save new object and save the address in primary object map.
107fn create_obj_inner(rid: i64, r: Value, ps: &mut PageSet) {
108    let dt = ps.obj_dt.clone();
109
110    let addr = VarValAddr::new(&dt, &r, ps);
111
112    let key = IdKey { rid, dt: &dt };
113
114    let mut bm = BuckMap::restore(ps.obj_map, ps);
115    bm.insert(&key, addr);
116    if bm.root_changed() {
117        ps.obj_map = bm.save();
118    }
119}
120
121/// Map the given object name to the object id.
122fn index_obj_by_name(id: i64, name: &str, ps: &mut PageSet) {
123    let key = ObjNameKey { name };
124    let mut bm = BuckMap::restore(ps.obj_by_name, ps);
125    bm.insert(&key, id);
126    if bm.root_changed() {
127        ps.obj_by_name = bm.save();
128    }
129}
130
131/// Create obj with specified id, name and inner value.
132pub fn create_obj(rid: i64, name: &str, inner: Value, ps: &mut PageSet) {
133    let r = Value::List(veca![
134        Value::Int(rid), // obj id
135        Value::Int(0),   // obj schema
136        Value::String(LString::from(name)),
137        inner
138    ]);
139
140    create_obj_inner(rid, r, ps);
141    index_obj_by_name(rid, name, ps);
142}
143
144/// Get the object id and Value for the supplied object name.
145pub fn get_obj_from_name(name: &str, ps: &mut PageSet) -> Option<(i64, Value)> {
146    let key = ObjNameKey { name };
147
148    let mut bm = BuckMap::restore(ps.obj_by_name, ps);
149    if let Some(x) = bm.get(&key) {
150        return Some(x);
151    }
152    None
153}
154
155/// Save ( update ) the Value associated with the given address.
156pub fn save_obj(addr: VarValAddr, obj: Value, ps: &mut PageSet) {
157    let dt = ps.obj_dt.clone();
158    let addr2 = addr.update(&dt, &obj, ps);
159    if addr2 != addr {
160        let rid = obj.list()[OBJ_ID].int();
161        let key = IdKey { rid, dt: &dt };
162
163        let mut bm = BuckMap::restore(ps.obj_map, ps);
164        bm.remove(&key);
165        bm.insert(&key, addr2);
166        if bm.root_changed() {
167            ps.obj_map = bm.save();
168        }
169    }
170}
171
172/// Create schema.
173pub fn create_schema(name: &str, ps: &mut PageSet) -> Option<(i64, Value)> {
174    // Check if obj already exists.
175    let obj = get_obj_from_name(name, ps);
176
177    if obj.is_some() {
178        obj
179    } else {
180        let rid = ps.next_obj_id;
181        ps.next_obj_id = rid + 1;
182        let inner = Value::Enum(SCHEMA, LBox::new(Value::Empty));
183        create_obj(rid, name, inner, ps);
184        None
185    }
186}
187
188fn set_table_datatype(rid: i64, tdt: DataType, ps: &mut PageSet) {
189    let dt = DataType::Tuple(veca![DataType::Int, DataType::DataType]);
190    let v = Value::List(veca![Value::Int(rid), Value::DataType(tdt)]);
191
192    let addr = VarValAddr::new(&dt, &v, ps);
193    let key = IdKey { rid, dt: &dt };
194    let mut bm = BuckMap::restore(ps.table_datatype_map, ps);
195    bm.insert(&key, addr);
196    if bm.root_changed() {
197        ps.table_datatype_map = bm.save();
198    }
199}
200
201/// Get table DataType given table id.
202pub fn get_table_datatype(rid: i64, ps: &mut PageSet) -> DataType {
203    let dt = DataType::Tuple(veca![DataType::Int, DataType::DataType]);
204    let key = IdKey { rid, dt: &dt };
205    let mut bm = BuckMap::restore(ps.table_datatype_map, ps);
206    let mut av = bm.get(&key).unwrap();
207    let dt = av.1.list_mut()[1].datatype_mut();
208    std::mem::take(dt)
209}
210
211/// Create a table. If it already exists, return id and value.
212pub fn create_table(
213    name: &str,
214    dt: DataType,
215    ix_count: usize,
216    ps: &mut PageSet,
217) -> Option<(i64, Value)> {
218    // Check if obj already exists.
219    let obj = get_obj_from_name(name, ps);
220
221    if obj.is_some() {
222        obj
223    } else {
224        let rid = ps.next_obj_id;
225        ps.next_obj_id = rid + 1;
226
227        let bm = BuckMap::<VarValAddr>::new(1, ps);
228        let main = bm.save();
229
230        let mut index = LVec::new();
231        for _ in 0..ix_count {
232            let bm = BuckMap::<VarValAddr>::new(1, ps);
233            index.push(bm.save());
234        }
235
236        let tableinfo = Value::TabInfo(TabInfo {
237            alloc: 0,
238            main,
239            index,
240        });
241
242        let inner = Value::Enum(TABLE, LBox::new(tableinfo));
243
244        create_obj(rid, name, inner, ps);
245
246        set_table_datatype(rid, dt, ps);
247
248        None
249    }
250}
251
252#[derive(
253    Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, serde::Serialize, serde::Deserialize,
254)]
255pub struct TabInfo {
256    alloc: i64,
257    pub main: BuckMapInfo,
258    pub index: LVec<BuckMapInfo>,
259}
260
261impl TabInfo {
262    pub fn id(&mut self) -> i64 {
263        let result = self.alloc;
264        self.alloc += 1;
265        result
266    }
267    pub fn to_bytes(&self) -> Vec<u8> {
268        postcard::to_stdvec(self).unwrap()
269    }
270    pub fn from_bytes(b: &[u8]) -> Self {
271        postcard::from_bytes(b).unwrap()
272    }
273}
274
275/// Get mut ref to TabInfo from Value.
276pub fn decode_table(obj: &mut Value) -> &mut TabInfo {
277    let (tag, inner) = obj.list_mut()[OBJ_INNER].en_mut();
278    assert!(*tag == TABLE);
279    inner.tabinfo_mut()
280}
281
282/// Update table data for the specified id.
283pub fn save_table(rid: i64, obj: Value, ps: &mut PageSet) {
284    let (addr, _) = get_obj(rid, ps).unwrap();
285    save_obj(addr, obj, ps);
286}