aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarcos Magueta <maguetamarcos@gmail.com>2026-09-23 02:49:23 -0300
committerMarcos Magueta <maguetamarcos@gmail.com>2026-09-23 02:49:23 -0300
commitc16240023545677548d254eecbfef608ebb2dee6 (patch)
tree1ba8050e8f40975b29781b3d9fff1cf053f1d452
parentc561666c2b65dee40ddec06e1da66c94c4c9d032 (diff)
downloadRNT-c16240023545677548d254eecbfef608ebb2dee6.tar.gz
RNT-c16240023545677548d254eecbfef608ebb2dee6.zip
fix cursor outliving ephemeral relation
Diffstat (limited to '')
-rw-r--r--lib/kernel/EphemeralRelation.ml31
1 files changed, 29 insertions, 2 deletions
diff --git a/lib/kernel/EphemeralRelation.ml b/lib/kernel/EphemeralRelation.ml
index 0b62517..54454fb 100644
--- a/lib/kernel/EphemeralRelation.ml
+++ b/lib/kernel/EphemeralRelation.ml
@@ -31,6 +31,21 @@ module Make (D : DERIVATION) = struct
| Some cardinality -> Concepts.Cardinality.exhaustible cardinality
| None -> false
+ (* A cursor holds a reference to its relation, so the edges it reads
+ outlive a release of the relation that produced it. *)
+ class retaining scan release_owner =
+ object (self)
+ inherit Lifecycle.counted
+ inherit Identity.of_id
+
+ method destroy =
+ Protocols.Handle.release (Protocols.Handle.from scan);
+ release_owner ()
+
+ method fetch limit = Protocols.Cursor.fetch scan limit
+ method protocols : Protocols.Handle.protocol list = [Protocols.Cursor.make self]
+ end
+
class ephemeral plan address declaration total edges =
object (self)
inherit Lifecycle.counted
@@ -39,8 +54,20 @@ module Make (D : DERIVATION) = struct
method predicate = Ok None
method local_constraints = Ok None
method modes = Ok declaration
- method generate binding = D.generate plan binding
- method enumerate = D.generate plan Protocols.Generative.nothing
+
+ method private retained binding =
+ let open Utilities.Result in
+ let* cursor = D.generate plan binding in
+ match Protocols.Cursor.require cursor with
+ | Error c ->
+ Protocols.Handle.release cursor;
+ Error c
+ | Ok scan ->
+ ignore self#reference;
+ Ok (new retaining scan (fun () -> self#release) |> Protocols.Handle.make)
+
+ method generate binding = self#retained binding
+ method enumerate = self#retained Protocols.Generative.nothing
method describe () =
D.describe plan |> Result.map (fun description -> Protocols.Schematics.Relation description)