use crate::*;
pub fn create_schema(db: &DB, name: &str) {
if let Some(_id) = get_schema(db, name) {
panic!("schema '{}' already exists", name);
}
let t = &db.sys_schema;
let mut row = t.row();
row.id = t.alloc_id(db);
row.values[0] = Value::String(Rc::new(name.to_string()));
t.insert(db, &mut row);
}
pub fn create_table(db: &DB, info: &ColInfo) {
if let Some(_t) = get_table(db, &info.name) {
panic!("table {} already exists", info.name.str());
}
let tid = {
let schema = &info.name.schema;
if let Some(schema_id) = get_schema(db, schema) {
let root = db.alloc_page();
let t = &db.sys_table;
let mut row = t.row();
row.id = t.alloc_id(db);
row.values[0] = Value::Int(root as i64);
row.values[1] = Value::Int(schema_id);
row.values[2] = Value::String(Rc::new(info.name.name.clone()));
row.values[3] = Value::Int(1);
t.insert(db, &mut row);
row.id
} else {
panic!("schema not found [{}]", &schema);
}
};
{
let cnames = &info.colnames;
let t = &db.sys_column;
let mut row = t.row();
row.values[0] = Value::Int(tid);
for (num, typ) in info.typ.iter().enumerate() {
row.id = t.alloc_id(db);
row.values[1] = Value::String(Rc::new(cnames[num].to_string()));
row.values[2] = Value::Int(*typ as i64);
t.insert(db, &mut row);
}
}
}
pub fn create_index(db: &DB, info: &IndexInfo) {
if let Some(table) = db.get_table(&info.tname) {
let root = db.alloc_page();
let index_id = {
let t = &db.sys_index;
let mut row = t.row();
row.id = t.alloc_id(db);
row.values[0] = Value::Int(root as i64);
row.values[1] = Value::Int(table.id);
row.values[2] = Value::String(Rc::new(info.iname.clone()));
t.insert(db, &mut row);
row.id
};
{
let t = &db.sys_index_col;
let mut row = t.row();
for cnum in &info.cols {
row.id = t.alloc_id(db);
row.values[0] = Value::Int(index_id);
row.values[1] = Value::Int(*cnum as i64);
t.insert(db, &mut row);
}
}
if root > SYS_ROOT_LAST {
table.add_index(root, info.cols.clone(), index_id);
table.init_index(db);
}
} else {
panic!("table not found: {}", &info.tname.str());
}
}
pub fn create_function(db: &DB, name: &ObjRef, source: Rc<String>, alter: bool) {
if let Some(schema_id) = get_schema(db, &name.schema) {
let t = &db.sys_function;
if alter {
let keys = vec![
Value::Int(schema_id),
Value::String(Rc::new(name.name.to_string())),
];
if let Some((pp, off)) = t.ix_get(db, keys, 0) {
let p = &mut *pp.borrow_mut();
let off = off + t.info.off[2];
let (val, oldcode) = Value::load(db, BIGSTR, &p.data, off);
if val.str() != source {
db.delcode(oldcode);
let val = Value::String(source);
let newcode = db.encode(&val, data_size(BIGSTR));
val.save(BIGSTR, &mut p.data, off, newcode);
t.file.set_dirty(p, &pp);
db.function_reset.set(true);
}
return;
}
panic!("function {} not found", &name.str());
} else {
if get_function_id(db, name).is_some() {
panic!("function already exists");
}
let mut row = t.row();
row.id = t.alloc_id(db);
row.values[0] = Value::Int(schema_id);
row.values[1] = Value::String(Rc::new(name.name.clone()));
row.values[2] = Value::String(source);
t.insert(db, &mut row);
}
} else {
panic!("schema [{}] not found", &name.schema);
}
}
pub fn get_schema(db: &DB, sname: &str) -> Option<i64> {
if let Some(&id) = db.schemas.borrow().get(sname) {
return Some(id);
}
let t = &db.sys_schema;
let keys = vec![Value::String(Rc::new(sname.to_string()))];
if let Some((pp, off)) = t.ix_get(db, keys, 0) {
let p = &pp.borrow();
let a = t.access(p, off);
debug_assert!(a.str(db, 0) == sname);
let id = a.id() as i64;
db.schemas.borrow_mut().insert(sname.to_string(), id);
return Some(id);
}
None
}
fn get_table0(db: &DB, name: &ObjRef) -> Option<(i64, i64, i64)> {
if let Some(schema_id) = get_schema(db, &name.schema) {
let t = &db.sys_table;
let keys = vec![
Value::Int(schema_id),
Value::String(Rc::new(name.name.to_string())),
];
if let Some((pp, off)) = t.ix_get(db, keys, 0) {
let p = &pp.borrow();
let a = t.access(p, off);
return Some((a.id() as i64, a.int(0), a.int(3)));
}
}
None
}
pub fn get_index(db: &DB, tname: &ObjRef, iname: &str) -> (Rc<Table>, usize, u64) {
if let Some(t) = get_table(db, tname) {
let ixt = &db.sys_index;
let key = Value::Int(t.id);
for (ix, (pp, off)) in ixt.scan_key(db, key, 0).enumerate() {
let p = &pp.borrow();
let a = ixt.access(p, off);
if a.str(db, 2) == iname {
let id = a.id();
return (t, ix, id);
}
}
panic!("index {} not found", iname);
} else {
panic!("table {} not found", tname.str());
}
}
pub fn get_table(db: &DB, name: &ObjRef) -> Option<Rc<Table>> {
if let Some((table_id, root, id_gen)) = get_table0(db, name) {
let mut info = ColInfo::empty(name.clone());
let t = &db.sys_column;
let key = Value::Int(table_id);
for (pp, off) in t.scan_key(db, key, 0) {
let p = &pp.borrow();
let a = t.access(p, off);
debug_assert!(a.int(0) == table_id);
let cname = a.str(db, 1);
let ctype = a.int(2) as DataType;
info.add(cname, ctype);
}
let table = Table::new(table_id, root as u64, id_gen, Rc::new(info));
let t = &db.sys_index;
let key = Value::Int(table_id);
for (pp, off) in t.scan_key(db, key, 0) {
let p = &pp.borrow();
let a = t.access(p, off);
debug_assert!(a.int(1) == table_id);
let index_id = a.id() as i64;
let root = a.int(0) as u64;
let mut cols = Vec::new();
let t = &db.sys_index_col;
let key = Value::Int(index_id);
for (pp, off) in t.scan_key(db, key, 0) {
let p = &pp.borrow();
let a = t.access(p, off);
debug_assert!(a.int(0) == index_id);
let cnum = a.int(1) as usize;
cols.push(cnum);
}
table.add_index(root, cols, index_id);
}
db.publish_table(table.clone());
Some(table)
} else {
None
}
}
pub fn get_function(db: &DB, name: &ObjRef) -> Option<Rc<Function>> {
if let Some(schema_id) = get_schema(db, &name.schema) {
let t = &db.sys_function;
let keys = vec![
Value::Int(schema_id),
Value::String(Rc::new(name.name.to_string())),
];
if let Some((pp, off)) = t.ix_get(db, keys, 0) {
let p = &pp.borrow();
let a = t.access(p, off);
let source = Rc::new(a.str(db, 2));
let function = parse_function(db, source);
db.functions
.borrow_mut()
.insert(name.clone(), function.clone());
return Some(function);
}
}
None
}
pub fn get_function_id(db: &DB, name: &ObjRef) -> Option<i64> {
if let Some(schema_id) = get_schema(db, &name.schema) {
let t = &db.sys_function;
let keys = vec![
Value::Int(schema_id),
Value::String(Rc::new(name.name.to_string())),
];
if let Some((pp, off)) = t.ix_get(db, keys, 0) {
let p = &pp.borrow();
let a = t.access(p, off);
return Some(a.id() as i64);
}
}
None
}
fn parse_function(db: &DB, source: Rc<String>) -> Rc<Function> {
let mut p = Parser::new(&source, db);
p.b.parse_only = true;
p.parse_function();
Rc::new(Function {
compiled: Cell::new(false),
ilist: RefCell::new(Vec::new()),
local_typ: p.b.local_typ,
return_type: p.b.return_type,
param_count: p.b.param_count,
source,
})
}
pub fn get_id_gen(db: &DB, id: u64) -> i64 {
let t = &db.sys_table;
let (pp, off) = t.id_get(db, id).unwrap();
let p = &pp.borrow();
let a = t.access(p, off);
debug_assert!(a.id() == id);
a.int(3)
}
pub fn save_id_gen(db: &DB, id: u64, val: i64) {
let t = &db.sys_table;
let (pp, off) = t.id_get(db, id).unwrap();
let p = &mut pp.borrow_mut();
let mut wa = t.write_access(p, off);
debug_assert!(wa.id() == id);
wa.set_int(3, val);
t.file.set_dirty(p, &pp);
}
pub fn set_root(db: &DB, id: i64, new_root: u64) {
let id = id as u64;
let t = &db.sys_table;
let (pp, off) = t.id_get(db, id).unwrap();
let p = &mut pp.borrow_mut();
let mut wa = t.write_access(p, off);
debug_assert!(wa.id() == id);
wa.set_int(0, new_root as i64);
t.file.set_dirty(p, &pp);
}
#[cfg(feature = "renumber")]
pub fn set_ix_root(db: &DB, id: i64, new_root: u64) {
let id = id as u64;
let t = &db.sys_index;
let (pp, off) = t.id_get(db, id).unwrap();
let p = &mut pp.borrow_mut();
let mut wa = t.write_access(p, off);
debug_assert!(wa.id() == id);
wa.set_int(0, new_root as i64);
t.file.set_dirty(p, &pp);
}