aboutsummaryrefslogtreecommitdiffstats
path: root/lib/management/database.ml
diff options
context:
space:
mode:
authorMarcos Magueta <maguetamarcos@gmail.com>2026-03-07 02:40:26 -0300
committerMarcos Magueta <maguetamarcos@gmail.com>2026-03-07 02:40:26 -0300
commite9bc4aa3fa0e775acf1978722da1fde1ed8a469d (patch)
treeff78d21ba9a03acae20b15bb2fad2f27bcde75e1 /lib/management/database.ml
parentfcd8571577f2b98ffc8fa2b95781ed16982804a9 (diff)
downloadSakura-e9bc4aa3fa0e775acf1978722da1fde1ed8a469d.tar.gz
Sakura-e9bc4aa3fa0e775acf1978722da1fde1ed8a469d.zip
erlang port commands and generated tests
Diffstat (limited to 'lib/management/database.ml')
-rw-r--r--lib/management/database.ml104
1 files changed, 89 insertions, 15 deletions
diff --git a/lib/management/database.ml b/lib/management/database.ml
index 4fd43f1..1e68402 100644
--- a/lib/management/database.ml
+++ b/lib/management/database.ml
@@ -1,23 +1,97 @@
-module RelationMap = Map.Make (String)
+(** Database state management.
+
+ A database is a collection of relations with:
+ - A merkle tree of relation hashes (for integrity verification)
+ - A map of relation names to their actual Relation.t objects (integrated cache)
+ - A history of previous database hashes (for time-travel queries)
+
+ All mutations produce a new database state with a new hash.
+ The history chain allows reconstruction of any past state. *)
+
+module RelationMap = Map.Make(String)
type t = {
hash : Conventions.Hash.t;
name : Conventions.Name.t;
- tree : unit;
- relations : Relation.t RelationMap.t;
+ tree : Merkle.t;
+ relations : Relation.t RelationMap.t; (* Stores actual relations, not just hashes *)
+ history : Conventions.Hash.t list;
timestamp : float;
}
-let create_database (storage: Physical.Storage.t) ~name =
- let relations =
- RelationMap.of_list [("less_than", Prelude.Standard.less_than_natural)]
+let empty ~name = {
+ hash = "";
+ name;
+ tree = Merkle.empty;
+ relations = RelationMap.empty;
+ history = [];
+ timestamp = Unix.gettimeofday ();
+}
+
+(** Compute database hash from the merkle tree root *)
+let compute_hash db =
+ match Merkle.root_hash db.tree with
+ | Some root -> root
+ | None -> Conventions.Hash.hash_text db.name
+
+(** Update database with new relations map and tree *)
+let update_state db ~relations ~tree =
+ let new_hash =
+ match Merkle.root_hash tree with
+ | Some root -> root
+ | None -> Conventions.Hash.hash_text db.name
in
- let state =
- {
- hash = "";
- name;
- tree = ();
- relations = relations;
- timestamp = Unix.time ();
- }
- in Physical.Storage.write storage
+ let history = if db.hash = "" then db.history else db.hash :: db.history in
+ {
+ hash = new_hash;
+ name = db.name;
+ tree;
+ relations;
+ history;
+ timestamp = Unix.gettimeofday ();
+ }
+
+(** Get a relation by name *)
+let get_relation db name =
+ RelationMap.find_opt name db.relations
+
+(** Get a relation's hash by name *)
+let get_relation_hash db name =
+ match RelationMap.find_opt name db.relations with
+ | None -> None
+ | Some rel -> rel.Relation.hash
+
+let get_relation_names db =
+ RelationMap.fold (fun name _ acc -> name :: acc) db.relations []
+
+let has_relation db name =
+ RelationMap.mem name db.relations
+
+(** Add a relation to the database *)
+let add_relation db ~(relation : Relation.t) =
+ let relation_hash = Option.get relation.hash in
+ let tree = Merkle.insert relation_hash db.tree in
+ let relations = RelationMap.add relation.name relation db.relations in
+ update_state db ~relations ~tree
+
+(** Remove a relation from the database *)
+let remove_relation db ~name =
+ match RelationMap.find_opt name db.relations with
+ | None -> db
+ | Some relation ->
+ let relation_hash = Option.get relation.hash in
+ let tree = Merkle.delete relation_hash db.tree in
+ let relations = RelationMap.remove name db.relations in
+ update_state db ~relations ~tree
+
+(** Update a relation in the database (after tuple insert/delete) *)
+let update_relation db ~(relation : Relation.t) =
+ let name = relation.name in
+ match RelationMap.find_opt name db.relations with
+ | None -> db (* Relation doesn't exist, no-op *)
+ | Some old_relation ->
+ let old_hash = Option.get old_relation.hash in
+ let new_hash = Option.get relation.hash in
+ let tree = db.tree |> Merkle.delete old_hash |> Merkle.insert new_hash in
+ let relations = RelationMap.add name relation db.relations in
+ update_state db ~relations ~tree