aboutsummaryrefslogtreecommitdiffstats
path: root/lib/algebra.ml
diff options
context:
space:
mode:
authorMarcos Magueta <maguetamarcos@gmail.com>2026-05-18 12:35:26 -0300
committerGitHub <noreply@github.com>2026-05-18 12:35:26 -0300
commitcf0fffed43d0ca7618cd0013411151e057b7a32a (patch)
tree35915aee3f7160b9ff6b41c3c0502b34050f642c /lib/algebra.ml
parente3d3e20dfea253de291d5b31059cd55c0eaabf02 (diff)
downloadSakura-cf0fffed43d0ca7618cd0013411151e057b7a32a.tar.gz
Sakura-cf0fffed43d0ca7618cd0013411151e057b7a32a.zip
RNT interface
Co-authored-by: Estevan Castilho <tevo@riajuu.net>
Diffstat (limited to '')
-rw-r--r--lib/algebra.ml378
1 files changed, 27 insertions, 351 deletions
diff --git a/lib/algebra.ml b/lib/algebra.ml
index 0ef16df..9c620ee 100644
--- a/lib/algebra.ml
+++ b/lib/algebra.ml
@@ -1,61 +1,18 @@
-type error = StorageError of string | GeneratorError of string
-
-module Make (Storage : Management.Physical.S) = struct
- module Ops = Manipulation.Make (Storage)
-
- type storage = Storage.t
-
- (* Internal generator utilities *)
-
- let rec list_generator : Tuple.t list -> Generator.t = function
- | [] -> fun _pos -> Generator.Done
- | t :: rest -> fun _pos -> Generator.Value (t, list_generator rest)
-
- let drain gen =
- let rec go gen pos acc =
- match gen (Some pos) with
- | Generator.Done -> Ok (List.rev acc)
- | Generator.Error e -> Error (GeneratorError e)
- | Generator.Value (t, next) -> go next (pos + 1) (t :: acc)
- in
- go gen 0 []
-
- let to_generator (storage : storage) (rel : #Relation.relation) : Generator.t =
- match rel#kind with
- | `Ephemeral | `Domain ->
- ((Obj.magic rel) : < generator : Generator.t >)#generator
- | `Pseudo ->
- ((Obj.magic rel) : < as_generator : (string * Conventions.AbstractValue.t) list -> Generator.t >)#as_generator []
- | `Stored -> begin
- (* TODO: Avoid materializing all tuple hashes/tuples at once.
- Current implementation calls tuple_hashes rel which loads all hashes
- into memory, then load_tuples which loads all tuples. This defeats
- lazy evaluation and scales badly (fails for billions of tuples).
- Replace with paginated tuple_hashes or Merkle streaming to load
- hashes/tuples on demand in chunks. *)
- match Ops.load_tuples storage rel#hash with
- | Error _ ->
- fun _pos -> Generator.Error ("Failed to load: " ^ rel#name)
- | Ok ts -> list_generator (List.map (fun t -> Tuple.Materialized t) ts)
- end
- let of_generator ~name ~schema ?constraints ?cardinality generator membership_criteria: Relation.ephemeral =
- let cardinality =
- match cardinality with
- | Some c -> c
- | None -> Conventions.Cardinality.AlephZero
- in
- new Relation.ephemeral
- ~name
- ~schema
- ~constraints
- ~cardinality
- ~generator
- ~membership_criteria
- ~provenance:None
- ~lineage:None
-
- let const_relation (pairs : (string * Conventions.AbstractValue.t) list) :
- Relation.ephemeral =
+(* algebra.ml — plan compilation support.
+ Generator-based evaluation is removed; all query execution goes through the
+ Tarski VM via Nt.execute_query. This module retains only what is needed to
+ construct plan nodes and handle compile-time errors. *)
+
+type error = UnsupportedOperator of string
+
+(* const_relation is kept for the Ast.Const case which produces an in-memory
+ ephemeral relation from literal pairs. It is used only in DRL tests and
+ REPL exploration; it does not go through the VM.
+ TODO: materialise const tuples into InMemoryBackend and SCAN them so they
+ can participate in VM JOINs. *)
+let const_relation (pairs : (string * Conventions.AbstractValue.t) list) :
+ Relation.ephemeral =
+ let make_gen () =
let attrs =
List.fold_left
(fun acc (k, v) -> Tuple.AttributeMap.add k { Attribute.value = v } acc)
@@ -64,296 +21,15 @@ module Make (Storage : Management.Physical.S) = struct
let tuple =
Tuple.Materialized { Tuple.relation = "const"; attributes = attrs }
in
- let schema = List.map (fun (k, _) -> (k, "abstract")) pairs in
- (* TODO: Make it always true for now, gotta rework on this generator *)
- let membership_criteria _tuple = true in
- of_generator ~name:"const" ~schema (list_generator [ tuple ]) membership_criteria
-
- (* Operators *)
-
- let select_fn storage predicate rel =
- let gen = to_generator storage rel in
- let lazy_gen =
- let rec go g pos =
- match g pos with
- | Generator.Done -> Generator.Done
- | Generator.Error e -> Generator.Error e
- | Generator.Value (t, next) ->
- if predicate t then Generator.Value (t, go next)
- else go next (Option.map (( + ) 1) pos)
- in
- fun pos -> go gen pos
- in
- (* TODO: Make it always true for now, gotta rework on this generator *)
- let membership_criteria _tuple = true in
- Ok
- (of_generator
- ~name:("σ_" ^ rel#name)
- ~schema:rel#schema ?constraints:rel#constraints
- lazy_gen
- membership_criteria)
-
- let project storage (attrs : string list) rel =
- let gen = to_generator storage rel in
- let project_tuple = function
- | Tuple.Materialized t ->
- let attrs' =
- List.fold_left
- (fun acc k ->
- match Tuple.AttributeMap.find_opt k t.Tuple.attributes with
- | None -> acc
- | Some v -> Tuple.AttributeMap.add k v acc)
- Tuple.AttributeMap.empty attrs
- in
- Tuple.Materialized { t with attributes = attrs' }
- | other -> other
- in
- let new_schema =
- List.filter (fun (n, _) -> List.mem n attrs) rel#schema
- in
- let lazy_gen =
- let rec go g pos =
- match g pos with
- | Generator.Done -> Generator.Done
- | Generator.Error e -> Generator.Error e
- | Generator.Value (t, next) -> Generator.Value (project_tuple t, go next)
- in
- fun pos -> go gen pos
- in
- let filtered_constraints =
- match rel#constraints with
- | None | Some [] -> None
- | Some cs -> (
- let kept =
- List.filter_map
- (fun (name, c) ->
- match Constraint.filter_by_attrs attrs c with
- | Some c' -> Some (name, c')
- | None -> None)
- cs
- in
- match kept with [] -> None | _ -> Some kept)
- in
- (* TODO: Make it always true for now, gotta rework on this generator *)
- let membership_criteria _tuple = true in
- Ok
- (of_generator
- ~name:("π_" ^ rel#name)
- ~schema:new_schema ?constraints:filtered_constraints lazy_gen membership_criteria)
-
- let rename storage (renames : (string * string) list) rel =
- let rename_key k =
- match List.assoc_opt k renames with Some k' -> k' | None -> k
- in
- let rename_tuple = function
- | Tuple.Materialized t ->
- let attrs' =
- Tuple.AttributeMap.fold
- (fun k v acc -> Tuple.AttributeMap.add (rename_key k) v acc)
- t.Tuple.attributes Tuple.AttributeMap.empty
- in
- Tuple.Materialized { t with attributes = attrs' }
- | other -> other
- in
- let gen = to_generator storage rel in
- let new_schema =
- List.map (fun (n, d) -> (rename_key n, d)) rel#schema
- in
- let lazy_gen =
- let rec go g pos =
- match g pos with
- | Generator.Done -> Generator.Done
- | Generator.Error e -> Generator.Error e
- | Generator.Value (t, next) -> Generator.Value (rename_tuple t, go next)
- in
- fun pos -> go gen pos
- in
- let renamed_constraints =
- match rel#constraints with
- | None | Some [] -> None
- | Some cs ->
- Some
- (List.map
- (fun (name, c) -> (name, Constraint.rename_vars renames c))
- cs)
- in
- (* TODO: Make it always true for now, gotta rework on this generator *)
- let membership_criteria _tuple = true in
- Ok
- (of_generator
- ~name:("ρ_" ^ rel#name)
- ~schema:new_schema ?constraints:renamed_constraints lazy_gen membership_criteria)
-
- let equijoin storage (attrs : string list) left right: (Relation.ephemeral, error) result =
- let get_vals attr_list = function
- | Tuple.Materialized t ->
- List.map
- (fun a -> Tuple.AttributeMap.find_opt a t.Tuple.attributes)
- attr_list
- | _ -> List.map (fun _ -> None) attr_list
- in
- let merge lt rt =
- match (lt, rt) with
- | Tuple.Materialized l, Tuple.Materialized r ->
- Tuple.Materialized
- {
- l with
- attributes =
- Tuple.AttributeMap.union
- (fun _ a _ -> Some a)
- l.Tuple.attributes r.Tuple.attributes;
- }
- | _ -> lt
- in
- let merged_schema =
- left#schema
- @ List.filter
- (fun (n, _) ->
- (not (List.mem n attrs))
- && not (List.exists (fun (m, _) -> m = n) left#schema))
- right#schema
- in
- let merged_constraints =
- match (left#constraints, right#constraints) with
- | None, None -> None
- | Some cs, None | None, Some cs -> Some cs
- | Some cs1, Some cs2 -> Some (Constraint.merge cs1 cs2)
- in
- let name = "⋈_" ^ left#name ^ "_" ^ right#name in
- let rec chain_with_cont g cont pos =
- match g pos with
- | Generator.Done -> cont pos
- | Generator.Value (t, next) ->
- Generator.Value (t, fun p -> chain_with_cont next cont p)
- | Generator.Error e -> Generator.Error e
- in
- let make_join_gen left_gen right_tuples =
- let rec from_left lgen lpos =
- fun pos ->
- match lgen (Some lpos) with
- | Generator.Done -> Generator.Done
- | Generator.Error e -> Generator.Error e
- | Generator.Value (lt, next_left) -> (
- let lv = get_vals attrs lt in
- let matches =
- List.filter_map
- (fun rt ->
- if get_vals attrs rt = lv then Some (merge lt rt) else None)
- right_tuples
- in
- match matches with
- | [] -> from_left next_left (lpos + 1) pos
- | _ ->
- chain_with_cont (list_generator matches)
- (from_left next_left (lpos + 1))
- pos)
- in
- from_left left_gen 0
- in
-
- let right_gen = to_generator storage right in
- match drain right_gen with
- | Error e -> Error e
- | Ok right_tuples ->
- let left_gen = to_generator storage left in
- (* TODO: Make it always true for now, gotta rework on this generator *)
- let membership_criteria _tuple = true in
- Ok
- (of_generator ~name ~schema:merged_schema
- ?constraints:merged_constraints
- (make_join_gen left_gen right_tuples)
- membership_criteria)
-
- let union storage rel1 rel2 =
- let gen1 = to_generator storage rel1 in
- let gen2 = to_generator storage rel2 in
- let chain_gen =
- let rec go g1 g2 pos =
- match g1 pos with
- | Generator.Done -> g2 pos
- | Generator.Error _ -> g2 pos
- | Generator.Value (t, next) -> Generator.Value (t, fun p -> go next g2 p)
- in
- fun pos -> go gen1 gen2 pos
- in
- let name = "∪_" ^ rel1#name ^ "_" ^ rel2#name in
- (* TODO: Make it always true for now, gotta rework on this generator *)
- let membership_criteria _tuple = true in
- (* Conservative: drop constraints since they only hold if both inputs agree *)
- Ok (of_generator ~name ~schema:rel1#schema chain_gen membership_criteria)
-
- let attrs_equal (m1 : Attribute.materialized Tuple.AttributeMap.t)
- (m2 : Attribute.materialized Tuple.AttributeMap.t) =
- Tuple.AttributeMap.equal
- (fun a b -> Stdlib.( = ) a.Attribute.value b.Attribute.value)
- m1 m2
-
- let diff storage rel1 rel2 =
- let right_gen = to_generator storage rel2 in
- match drain right_gen with
- | Error e -> Error e
- | Ok right_tuples ->
- let right_mats =
- List.filter_map
- (function Tuple.Materialized t -> Some t | _ -> None)
- right_tuples
- in
- let left_gen = to_generator storage rel1 in
- let not_in_right = function
- | Tuple.Materialized t ->
- not
- (List.exists
- (fun r -> attrs_equal t.Tuple.attributes r.Tuple.attributes)
- right_mats)
- | _ -> true
- in
- let lazy_gen =
- let rec go g pos =
- match g pos with
- | Generator.Done -> Generator.Done
- | Generator.Error e -> Generator.Error e
- | Generator.Value (t, next) ->
- if not_in_right t then Generator.Value (t, go next)
- else go next (Option.map (( + ) 1) pos)
- in
- fun pos -> go left_gen pos
- in
- let name = "−_" ^ rel1#name ^ "_" ^ rel2#name in
- (* TODO: Make it always true for now, gotta rework on this generator *)
- let membership_criteria _tuple = true in
- Ok
- (of_generator ~name ~schema:rel1#schema
- ?constraints:rel1#constraints lazy_gen membership_criteria)
-
- let take storage n rel =
- let gen = to_generator storage rel in
- let lazy_gen =
- let rec go g count pos =
- if count = 0 then Generator.Done
- else
- match g pos with
- | Generator.Done -> Generator.Done
- | Generator.Error e -> Generator.Error e
- | Generator.Value (t, next) -> Generator.Value (t, go next (count - 1))
- in
- fun pos -> go gen n pos
- in
- (* TODO: Make it always true for now, gotta rework on this generator *)
- let membership_criteria _tuple = true in
- Ok
- (of_generator
- ~name:("τ_" ^ rel#name)
- ~schema:rel#schema ?constraints:rel#constraints
- ~cardinality:(Conventions.Cardinality.Finite n) lazy_gen membership_criteria)
-
- let materialize storage rel : (Tuple.materialized list, error) Result.t =
- match drain (to_generator storage rel) with
- | Error e -> Error e
- | Ok tuples ->
- Ok
- (List.filter_map
- (function Tuple.Materialized t -> Some t | _ -> None)
- tuples)
-end
-
-module Memory = Make (Management.Physical.Memory)
+ let gen = function
+ | None | Some 0 -> Generator.Value (tuple, fun _ -> Generator.Done)
+ | _ -> Generator.Done
+ in
+ gen
+ in
+ let schema = List.map (fun (k, _) -> (k, "abstract")) pairs in
+ new Relation.ephemeral ~name:"const" ~schema ~constraints:None
+ ~cardinality:(Conventions.Cardinality.Finite 1)
+ ~membership_criteria:(fun _ -> true)
+ ~lineage:None ~provenance:None
+ ~generator:(make_gen ())