implement ourdb in osis aside indexer

This commit is contained in:
timurgordon
2025-01-08 02:24:20 -05:00
parent df950143b4
commit 9a7a66192b
10 changed files with 53 additions and 514 deletions

View File

@@ -5,7 +5,6 @@ import db.sqlite
import db.pg
import freeflowuniverse.herolib.core.texttools
import freeflowuniverse.herolib.core.pathlib
import freeflowuniverse.herolib.clients.postgres
import orm
pub struct Indexer {
@@ -31,64 +30,29 @@ pub fn reset(path string) ! {
// new creates a new root object entry in the root_objects table,
// and the table belonging to the type of root object with columns for index fields
pub fn (mut backend Indexer) new(object RootObject) !u32 {
table_name := get_table_name(object)
// create table for root object if it doesn't exist
backend.create_root_object_table(object)!
indices, values := object.sql_indices_values()
insert_query := 'INSERT into ${table_name} (${indices.join(',')}) values (${values.join(',')})'
backend.db.exec(insert_query) or {
return error('Error inserting object ${object} into table ${table_name}\n${err}')
}
return 0
panic('implement')
}
// save the session to redis & mem
pub fn (mut backend Indexer) set(obj RootObject) ! {
table_name := get_table_name(obj)
indices, values := obj.sql_indices_values()
// todo: check table and entry exists
mut sql_stmts := []string{}
for i in 0 .. indices.len {
sql_stmts << '${indices[i]}=${values[i]}'
}
backend.db.exec("update ${table_name} set ${sql_stmts.join(' ')} where id=${obj.id}")!
panic('implement')
}
// save the session to redis & mem
pub fn (mut backend Indexer) delete(id string, obj RootObject) ! {
table_name := get_table_name(obj)
// todo: check table and entry exists
backend.db.exec('delete from ${table_name} where id=${id}')!
panic('implement')
}
pub fn (mut backend Indexer) get(id string, obj RootObject) !RootObject {
json_value := backend.get_json(id, obj)!
return root_object_from_json(json_value)
panic('implement')
}
pub fn (mut backend Indexer) get_json(id string, obj RootObject) !string {
table_name := get_table_name(obj)
// check root object and table exists
responses := backend.db.exec('select * from ${table_name} where id=${id}')!
if responses.len == 0 {
return error('Root object not found')
} else if responses.len > 1 {
panic('More than one result with same id found. This should never happen.')
}
return responses[0].vals[1]
panic('implement')
}
pub fn (mut backend Indexer) list(obj RootObject) ![]u32 {
table_name := get_table_name(obj)
responses := backend.db.exec('select * from ${table_name}') or { panic(err) }
ids := responses.map(it.vals[0].u32())
return ids
panic('implement')
}
// from and to for int f64 time etc.
@@ -102,43 +66,7 @@ pub struct FilterParams {
// filter lists root objects of type T that match provided index parameters and params.
pub fn (mut backend Indexer) filter(filter RootObject, params FilterParams) ![]string {
table_name := get_table_name(filter)
if !backend.table_exists(table_name)! {
return []string{}
}
table_indices := backend.get_table_indices(table_name) or { panic(err) }
for field in filter.fields {
if field.name !in table_indices {
return error('Index ${field.name} not found for root struct ${filter.name}')
}
}
mut select_stmt := 'select * from ${table_name}'
// $if D.fields.len > 0 {
select_stmt += ' where'
mut matchers := []string{}
for field in filter.fields {
if field.typ == .text {
matchers << "${field.name} == '${field.value}'"
} else if field.typ == .number {
matchers << "${field.name} == ${field.value}"
}
}
matchers_str := if params.matches_all {
matchers.join(' AND ')
} else {
matchers.join(' OR ')
}
select_stmt += ' ${matchers_str}'
println(select_stmt)
responses := backend.db.exec(select_stmt) or { panic(err) }
ids := responses.map(it.vals[0])
// objects := responses.map(json.decode(T, it.vals[1]) or { panic(err) })
return if params.limit == 0 { ids.map(it.str()) } else { ids.map(it.str())[..params.limit] }
panic('implement')
}
// create_root_struct_table creates a table for a root_struct with columns for each index field
@@ -148,31 +76,18 @@ fn (mut backend Indexer) create_root_object_table(object RootObject) ! {
// deletes an indexer table belonging to a root object
fn (mut backend Indexer) delete_table(object RootObject)! {
table_name := get_table_name(object)
delete_query := 'delete table ${table_name}'
backend.db.exec(delete_query)!
panic('implement')
}
fn (mut backend Indexer) get_table_indices(table_name string) ![]string {
table_info := backend.db.exec('pragma table_info(${table_name});')!
if table_info.len == 0 {
return error('table doesnt exist')
}
return table_info[1..].map(it.vals[1])
panic('implement')
}
fn (mut backend Indexer) table_exists(table_name string) !bool {
table_info := backend.db.exec('pragma table_info(${table_name});')!
println('debugzore ${table_info} ${table_name}')
if table_info.len == 0 {
return false
}
return true
panic('implement')
}
// get_table_name returns the name of the table belonging to a root struct
fn get_table_name(object RootObject) string {
mut table_name := texttools.name_fix(object.name)
table_name = table_name.replace('.', '_')
return table_name
panic('implement')
}

View File

@@ -1,68 +0,0 @@
module osis
import json
import db.sqlite
import db.pg
import freeflowuniverse.herolib.core.texttools
import freeflowuniverse.herolib.core.pathlib
import freeflowuniverse.herolib.clients.postgres
import orm
// new creates a new root object entry in the root_objects table,
// and the table belonging to the type of root object with columns for index fields
pub fn (mut indexer Indexer) generic_new[T](obj T) !u32 {
return indexer.new(root_object[T](obj))!
}
pub fn (mut indexer Indexer) generic_set[T](obj T) ! {
indexer.set(root_object[T](obj))!
}
pub fn (mut indexer Indexer) generic_delete[T](id u32) ! {
indexer.delete(id, root_object[T](T{}))
}
pub fn (mut indexer Indexer) generic_get[T](id u32) !T {
obj_json := indexer.get_json(id, root_object[T](T{}))!
return json.decode(T, obj_json)!
}
pub fn (mut indexer Indexer) generic_list[T]() ![]u32 {
return indexer.list(root_object[T](T{}))
}
// filter lists root objects of type T that match provided index parameters and params.
pub fn (mut indexer Indexer) generic_filter[T, D](filter D, params FilterParams) ![]string {
// TODO: make design decision for filter calls, below is a temporary hack
mut obj := root_object[D](filter)
obj.name = typeof[T]()
return indexer.filter(obj, params)
}
// create_root_struct_table creates a table for a root_struct with columns for each index field
fn (mut indexer Indexer) generic_create_root_object_table[T]() ! {
indexer.create_root_object_table(root_object[T](T{}))!
}
// deletes an indexer table belonging to a base object
fn (mut indexer Indexer) generic_delete_table[T]()! {
table_name := generic_get_table_name[T]()
delete_query := 'delete table ${table_name}'
indexer.db.exec(delete_query)!
}
// get_table_name returns the name of the table belonging to a root struct
fn generic_get_table_name[T]() string {
mut table_name := ''
$for attr in T.attributes {
if attr.name == 'table' && attr.arg.len > 0 {
table_name = attr.arg
}
}
if table_name == '' {
table_name = typeof[T]()
}
table_name = texttools.name_fix(table_name)
table_name = table_name.replace('.', '_')
return table_name
}

View File

@@ -1,132 +0,0 @@
module osis
import os
import freeflowuniverse.herolib.core.pathlib
import db.sqlite
import db.pg
const db_dir = '${os.dir(@FILE)}/testdata/db'
fn testsuite_begin() {
pathlib.get_dir(
path: db_dir
empty: true
)!
}
fn testsuite_end() {
mut dir := pathlib.get_dir(
path: db_dir
delete: true
)!
}
fn db_path(db_name string) string {
return '${db_dir}/${db_name}.db'
}
const pgconfig := pg.Config {
dbname: 'default'
user: 'admin'
password: 'test'
}
fn test_new_indexer() ! {
sqlite_db := sqlite.connect(db_path(@FN))!
sqlite_indexer := new_indexer(sqlite_db: sqlite_db)!
postgres_db := pg.connect(pgconfig)!
postgres_indexer := new_indexer(postgres_db: postgres_db)!
}
fn test_reset() ! {
reset(db_path(@FN))!
}
pub struct TestStruct {
text string @[index]
number int @[index]
}
fn test_indexer_new() ! {
// sqlite_db := sqlite.connect(db_path(@FN))!
// mut sqlite_indexer := new_indexer(sqlite_db: sqlite_db)!
// sqlite_indexer.generic_new(TestStruct{
// text: 'test_text'
// number: 41
// })!
// mut list := sqlite_indexer.generic_list[TestStruct]()!
// assert list.len == 1
// sqlite_indexer.generic_new(TestStruct{
// text: 'test_text2'
// number: 42
// })!
// list = sqlite_indexer.generic_list[TestStruct]()!
// assert list.len == 2
// postgres
postgres_db := pg.connect(pgconfig)!
mut postgres_indexer := new_indexer(postgres_db: postgres_db)!
postgres_indexer.generic_new(TestStruct{
text: 'test_text'
number: 41
})!
mut list := postgres_indexer.generic_list[TestStruct]()!
assert list.len == 1
postgres_indexer.generic_new(TestStruct{
text: 'test_text2'
number: 42
})!
list = postgres_indexer.generic_list[TestStruct]()!
assert list.len == 2
}
pub struct TestStructFilter {
text string
number int
}
fn test_indexer_filter() ! {
sqlite_db := sqlite.connect(db_path(@FN))!
mut sqlite_indexer := new_indexer(sqlite_db: sqlite_db)!
sqlite_indexer.generic_new(TestStruct{
text: 'test_text'
number: 41
})!
mut list := sqlite_indexer.generic_filter[TestStruct, TestStructFilter](
TestStructFilter {
text: 'test_tex'
}
)!
assert list.len == 0
list = sqlite_indexer.generic_filter[TestStruct, TestStructFilter](
TestStructFilter {
text: 'test_text'
}
)!
list = sqlite_indexer.generic_filter[TestStruct, TestStructFilter](
TestStructFilter {
number: 40
}
)!
assert list.len == 0
list = sqlite_indexer.generic_filter[TestStruct, TestStructFilter](
TestStructFilter {
number: 41
}
)!
assert list.len == 1
}

View File

@@ -1,29 +0,0 @@
module osis
import db.pg
struct BaseObject {
id int @[primary; sql: serial]
object string
}
pub fn (mut i Indexer) init() ! {
sql i.db {
create table BaseObject
}!
}
pub fn (mut i Indexer) new_id(object string) !u32 {
obj := BaseObject{object:object}
id := sql i.db {
insert obj into BaseObject
} or {return err}
return u32(id)
}
pub fn (i Indexer) get_id(id u32) !string {
obj := sql i.db {
select from BaseObject where id == id
}!
return obj[0].object
}

View File

@@ -1,107 +0,0 @@
module osis
import os
import freeflowuniverse.herolib.core.pathlib
import db.sqlite
import db.pg
const db_dir = '${os.dir(@FILE)}/testdata/db'
fn testsuite_begin() {
pathlib.get_dir(
path: db_dir
empty: true
)!
}
fn testsuite_end() {
mut dir := pathlib.get_dir(
path: db_dir
delete: true
)!
}
fn db_path(db_name string) string {
return '${db_dir}/${db_name}.db'
}
// fn test_new_indexer() ! {
// sqlite_db := sqlite.connect(db_path(@FN))!
// sqlite_indexer := new_indexer(sqlite_db: sqlite_db)!
// postgres_db := pg.connect(dbname: 'default')!
// postgres_indexer := new_indexer(postgres_db: postgres_db)!
// }
// fn test_reset() ! {
// reset(db_path(@FN))!
// }
// pub struct TestStruct {
// text string @[index]
// number int @[index]
// }
// fn test_indexer_new() ! {
// sqlite_db := sqlite.connect(db_path(@FN))!
// mut sqlite_indexer := new_indexer(sqlite_db: sqlite_db)!
// // mut postgres_indexer := new_indexer(new_db(@FN, PostgresConfig{})!)!
// sqlite_indexer.new(TestStruct{
// text: 'test_text'
// number: 41
// })!
// mut list := sqlite_indexer.list[TestStruct]()!
// assert list.len == 1
// sqlite_indexer.new(TestStruct{
// text: 'test_text2'
// number: 42
// })!
// list = sqlite_indexer.list[TestStruct]()!
// assert list.len == 2
// }
// pub struct TestStructFilter {
// text string
// number int
// }
// fn test_indexer_filter() ! {
// sqlite_db := sqlite.connect(db_path(@FN))!
// mut sqlite_indexer := new_indexer(sqlite_db: sqlite_db)!
// sqlite_indexer.new(TestStruct{
// text: 'test_text'
// number: 41
// })!
// mut list := sqlite_indexer.filter[TestStruct, TestStructFilter](
// TestStructFilter {
// text: 'test_tex'
// }
// )!
// assert list.len == 0
// list = sqlite_indexer.filter[TestStruct, TestStructFilter](
// TestStructFilter {
// text: 'test_text'
// }
// )!
// list = sqlite_indexer.filter[TestStruct, TestStructFilter](
// TestStructFilter {
// number: 40
// }
// )!
// assert list.len == 0
// list = sqlite_indexer.filter[TestStruct, TestStructFilter](
// TestStructFilter {
// number: 41
// }
// )!
// assert list.len == 1
// }

View File

@@ -20,7 +20,3 @@ pub:
secret string
reset bool
}
pub fn (mut backend OSIS) reset_all() ! {
panic('implement')
}

View File

@@ -12,10 +12,20 @@ pub fn (mut o OSIS) generic_new[T](obj T) !u32 {
return id
}
pub fn (mut o OSIS) new[T](obj T) !u32 {
id := o.indexer.generic_new[T](obj)!
o.storer.generic_new[T](obj)!
return id
}
pub fn (mut o OSIS) generic_get[T](id u32) !T {
return o.storer.generic_get[T](id)!
}
pub fn (mut o OSIS) get[T](id int) !T {
return o.storer.generic_get[T](u32(id))!
}
pub fn (mut o OSIS) generic_set[T](obj T) ! {
o.indexer.generic_set[T](obj) or { return error('Failed to set new indices:\n${err}') }
o.storer.generic_set[T](obj)!
@@ -26,6 +36,16 @@ pub fn (mut o OSIS) generic_delete[T](id u32) ! {
o.storer.generic_delete[T](id)!
}
pub fn (mut o OSIS) delete(id int) ! {
o.storer.delete(u32(id))!
}
pub fn (mut o OSIS) list[T]() ![]T {
panic('implement')
// ids := o.indexer.generic_list[T]()!
// return o.storer.generic_list[T](ids)!
}
pub fn (mut o OSIS) generic_list[T]() ![]T {
ids := o.indexer.generic_list[T]()!
return o.storer.generic_list[T](ids)!

View File

@@ -1,56 +1,15 @@
module osis
import freeflowuniverse.herolib.data.dbfs
import db.sqlite
import freeflowuniverse.herolib.data.ourdb {OurDB}
import os
pub struct Storer {
pub:
directory string
db_filesystem dbfs.DBCollection
db_sqlite sqlite.DB
pub mut:
db OurDB
}
@[params]
pub struct StorerConfig {
context_id u32
secret string
directory string = '${os.home_dir()}/hero/baobab/storer' // Directory of the storer
}
pub fn new_storer(config StorerConfig) !Storer {
pub fn new_storer() !Storer {
return Storer {
directory: config.directory
db_filesystem: dbfs.get(
dbpath: '${config.directory}/dbfs/${config.context_id}'
secret: config.secret
contextid: config.context_id
)!
db: ourdb.new()!
}
}
@[params]
pub struct StorageParams {
// database_type DatabaseType
encrypted bool
}
pub fn (mut storer Storer) new(object RootObject, params StorageParams) !u32 {
panic('implement')
}
pub fn (mut storer Storer) get(id u32, params StorageParams) !RootObject {
panic('implement')
}
pub fn (mut storer Storer) set(object RootObject, params StorageParams) ! {
panic('implement')
}
pub fn (mut storer Storer) delete(id u32, params StorageParams) ! {
panic('implement')
}
pub fn (mut storer Storer) list(ids []u32, params StorageParams) ![]RootObject {
panic('implement')
}

View File

@@ -1,45 +1,23 @@
module osis
import json
import db.sqlite
import db.pg
import freeflowuniverse.herolib.core.texttools
import freeflowuniverse.herolib.core.pathlib
import freeflowuniverse.herolib.clients.postgres
import orm
// new creates a new root object entry in the root_objects table,
// and the table belonging to the type of root object with columns for index fields
pub fn (mut storer Storer) generic_new[T](obj T) !u32 {
return storer.new(root_object[T](obj))!
}
pub fn (mut storer Storer) generic_set[T](obj T) ! {
storer.set(root_object[T](obj))!
}
pub fn (mut storer Storer) generic_delete[T](id u32) ! {
storer.delete(id, root_object[T](T{}))
data := json.encode(obj).bytes()
return storer.db.set(data: data)
}
pub fn (mut storer Storer) generic_get[T](id u32) !T {
root_object := storer.get(id)!
return root_object.to_generic[T]()
return json.decode(T, storer.db.get(id)!.bytestr())
}
pub fn (mut storer Storer) generic_list[T](ids []u32) ![]T {
root_objects := storer.list(ids)!
return root_objects.map(it.to_generic[T]())
pub fn (mut storer Storer) generic_set[T](obj T) ! {
data := json.encode(obj).bytes()
return storer.db.set(data: data)
}
// create_root_struct_table creates a table for a root_struct with columns for each index field
fn (mut storer Storer) generic_create_root_object_table[T]() ! {
storer.create_root_object_table(root_object[T](T{}))!
}
// deletes an storer table belonging to a base object
fn (mut storer Storer) generic_delete_table[T]()! {
table_name := generic_get_table_name[T]()
delete_query := 'delete table ${table_name}'
storer.db.exec(delete_query)!
pub fn (mut storer Storer) delete(id u32) ! {
storer.db.delete(id)!
}

View File

@@ -1,5 +1,7 @@
module stage
import freeflowuniverse.herolib.baobab.osis {OSIS}
@[heap]
pub interface IActor {
name string
@@ -10,10 +12,15 @@ mut:
pub struct Actor {
pub:
name string
mut:
osis OSIS
}
pub fn new_actor(name string) Actor {
return Actor{name}
pub fn new_actor(name string) !Actor {
return Actor{
osis: osis.new()!
name: name
}
}
pub fn (mut a IActor) handle(method string, data string) !string {