From cf0fffed43d0ca7618cd0013411151e057b7a32a Mon Sep 17 00:00:00 2001 From: Marcos Magueta Date: Mon, 18 May 2026 12:35:26 -0300 Subject: RNT interface Co-authored-by: Estevan Castilho --- lib/storable.ml | 38 ++++++++++++++++++++++++++++---------- 1 file changed, 28 insertions(+), 10 deletions(-) (limited to 'lib/storable.ml') diff --git a/lib/storable.ml b/lib/storable.ml index 5d87846..5527044 100644 --- a/lib/storable.ml +++ b/lib/storable.ml @@ -63,11 +63,17 @@ module Tuple = struct end module Relation = struct - type t = { name : string; schema : (string * string) list } + type t = { + name : string; + schema : (string * string) list; + (** Hex Merkle root of the relation's tuple set. Empty string = empty relation. *) + tree_pointer : string; + } let to_bytes relation = Wire.encode - ([ ("type", "relation"); ("name", relation.name); ("kind", "stored") ] + ([ ("type", "relation"); ("name", relation.name); ("kind", "stored"); + ("tree_pointer", relation.tree_pointer) ] @ List.map (fun (name, domain) -> ("attribute", name ^ ":" ^ domain)) relation.schema) @@ -76,31 +82,43 @@ module Relation = struct let fields = Wire.fields bytes in Wire.require_type "relation" fields; { - name = Wire.required "name" fields; - schema = List.map Wire.attribute (Wire.values "attribute" fields); + name = Wire.required "name" fields; + schema = List.map Wire.attribute (Wire.values "attribute" fields); + tree_pointer = Option.value (List.assoc_opt "tree_pointer" fields) ~default:""; } end module Multigroup = struct type t = { name : string; relations : Relation.t list } + (* Wire format: "name|attr1:dom1,attr2:dom2|" + The third segment is the Merkle root hex; empty string = empty relation. + A fourth segment for constraints is reserved but not yet implemented. + TODO: add constraints serialisation once a canonical sexp representation + is agreed upon (two syntactically distinct bodies may be semantically + equivalent — the round-trip must account for that). *) let relation_value relation = let attrs = relation.Relation.schema |> List.map (fun (name, domain) -> name ^ ":" ^ domain) |> String.concat "," in - relation.name ^ "|" ^ attrs + relation.name ^ "|" ^ attrs ^ "|" ^ relation.tree_pointer let parse_relation value = match Wire.split_once '|' value with - | None -> { Relation.name = value; schema = [] } - | Some (name, attrs) -> + | None -> { Relation.name = value; schema = []; tree_pointer = "" } + | Some (name, rest) -> + let attrs_str, tree_pointer = + match Wire.split_once '|' rest with + | None -> (rest, "") + | Some (a, tp) -> (a, tp) + in let schema = - if attrs = "" then [] - else attrs |> String.split_on_char ',' |> List.map Wire.attribute + if attrs_str = "" then [] + else attrs_str |> String.split_on_char ',' |> List.map Wire.attribute in - { Relation.name; schema } + { Relation.name; schema; tree_pointer } let to_bytes multigroup = Wire.encode -- cgit v1.2.3