-module(aarondb). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/aarondb.gleam"). -export([start_link/2, new_with_adapter_and_timeout/2, new_with_adapter/1, new/0, start_named/2, start_distributed/2, connect/1, transact/2, transact_at/3, transact_with_timeout/3, retract/2, retract_at/3, prune/3, trigger_eviction/1, retract_entity/2, with_facts/2, explain_speculation/1, get/3, get_one/3, set_schema/3, set_schema_with_timeout/4, history/2, pull/3, diff/3, pull_all/0, pull_attr/1, pull_except/1, pull_recursive/2, 'query'/2, q/2, query_at/4, query_state/2, query_state_at/4, execute/2, query_state_with_rules/3, query_with_rules/3, as_of/3, as_of_valid/3, as_of_bitemporal/4, p/1, register_function/3, register_composite/2, register_predicate/3, store_rule/2, set_config/2, subscribe/3, subscribe_wal/2, get_state/1, sync/1, is_leader/1, traverse/4]). -export_type([speculative_result/0]). -if(?OTP_RELEASE >= 27). -define(MODULEDOC(Str), -moduledoc(Str)). -define(DOC(Str), -doc(Str)). -else. -define(MODULEDOC(Str), -compile([])). -define(DOC(Str), -compile([])). -endif. -type speculative_result() :: {speculative_result, aarondb@shared@state:db_state(), list(aarondb@fact:datom())}. -file("src/aarondb.gleam", 59). -spec start_link( gleam@option:option(aarondb@storage:storage_adapter()), integer() ) -> {ok, gleam@erlang@process:subject(aarondb@transactor:message())} | {error, gleam@otp@actor:start_error()}. start_link(Adapter, Timeout_ms) -> Store = case Adapter of {some, S} -> S; none -> aarondb@storage:ephemeral() end, aarondb@transactor:start_with_timeout(Store, Timeout_ms). -file("src/aarondb.gleam", 51). -spec new_with_adapter_and_timeout( gleam@option:option(aarondb@storage:storage_adapter()), integer() ) -> gleam@erlang@process:subject(aarondb@transactor:message()). new_with_adapter_and_timeout(Adapter, Timeout_ms) -> Db@1 = case start_link(Adapter, Timeout_ms) of {ok, Db} -> Db; _assert_fail -> erlang:error(#{gleam_error => let_assert, message => <<"Pattern match failed, no pattern matched the value."/utf8>>, file => <>, module => <<"aarondb"/utf8>>, function => <<"new_with_adapter_and_timeout"/utf8>>, line => 55, value => _assert_fail, start => 1170, 'end' => 1221, pattern_start => 1181, pattern_end => 1187}) end, Db@1. -file("src/aarondb.gleam", 47). -spec new_with_adapter(gleam@option:option(aarondb@storage:storage_adapter())) -> gleam@erlang@process:subject(aarondb@transactor:message()). new_with_adapter(Adapter) -> new_with_adapter_and_timeout(Adapter, 5000). -file("src/aarondb.gleam", 43). -spec new() -> gleam@erlang@process:subject(aarondb@transactor:message()). new() -> new_with_adapter(none). -file("src/aarondb.gleam", 71). -spec start_named( binary(), gleam@option:option(aarondb@storage:storage_adapter()) ) -> {ok, gleam@erlang@process:subject(aarondb@transactor:message())} | {error, gleam@otp@actor:start_error()}. start_named(Name, Adapter) -> Store = case Adapter of {some, S} -> S; none -> aarondb@storage:ephemeral() end, aarondb@transactor:start_named(Name, Store). -file("src/aarondb.gleam", 82). -spec start_distributed( binary(), gleam@option:option(aarondb@storage:storage_adapter()) ) -> {ok, gleam@erlang@process:subject(aarondb@transactor:message())} | {error, gleam@otp@actor:start_error()}. start_distributed(Name, Adapter) -> Store = case Adapter of {some, S} -> S; none -> aarondb@storage:ephemeral() end, aarondb@transactor:start_distributed(Name, Store). -file("src/aarondb.gleam", 93). -spec connect(binary()) -> {ok, gleam@erlang@process:subject(aarondb@transactor:message())} | {error, binary()}. connect(Name) -> case aarondb_global_ffi:whereis(<<"aarondb_"/utf8, Name/binary>>) of {ok, Pid} -> {ok, aarondb_process_ffi:pid_to_subject(Pid)}; {error, _} -> {error, <<"Could not find database named "/utf8, Name/binary>>} end. -file("src/aarondb.gleam", 100). -spec transact( gleam@erlang@process:subject(aarondb@transactor:message()), list({aarondb@fact:eid(), binary(), aarondb@fact:value()}) ) -> {ok, aarondb@shared@state:db_state()} | {error, binary()}. transact(Db, Facts) -> aarondb@transactor:transact(Db, Facts). -file("src/aarondb.gleam", 104). -spec transact_at( gleam@erlang@process:subject(aarondb@transactor:message()), list({aarondb@fact:eid(), binary(), aarondb@fact:value()}), integer() ) -> {ok, aarondb@shared@state:db_state()} | {error, binary()}. transact_at(Db, Facts, Valid_time) -> Reply = gleam@erlang@process:new_subject(), gleam@erlang@process:send(Db, {transact, Facts, {some, Valid_time}, Reply}), case gleam@erlang@process:'receive'(Reply, 5000) of {ok, Res} -> Res; {error, _} -> {error, <<"Timeout"/utf8>>} end. -file("src/aarondb.gleam", 117). -spec transact_with_timeout( gleam@erlang@process:subject(aarondb@transactor:message()), list({aarondb@fact:eid(), binary(), aarondb@fact:value()}), integer() ) -> {ok, aarondb@shared@state:db_state()} | {error, binary()}. transact_with_timeout(Db, Facts, Timeout_ms) -> aarondb@transactor:transact_with_timeout(Db, Facts, Timeout_ms). -file("src/aarondb.gleam", 125). -spec retract( gleam@erlang@process:subject(aarondb@transactor:message()), list({aarondb@fact:eid(), binary(), aarondb@fact:value()}) ) -> {ok, aarondb@shared@state:db_state()} | {error, binary()}. retract(Db, Facts) -> aarondb@transactor:retract(Db, Facts). -file("src/aarondb.gleam", 129). -spec retract_at( gleam@erlang@process:subject(aarondb@transactor:message()), list({aarondb@fact:eid(), binary(), aarondb@fact:value()}), integer() ) -> {ok, aarondb@shared@state:db_state()} | {error, binary()}. retract_at(Db, Facts, Valid_time) -> Reply = gleam@erlang@process:new_subject(), gleam@erlang@process:send(Db, {retract, Facts, {some, Valid_time}, Reply}), case gleam@erlang@process:'receive'(Reply, 5000) of {ok, Res} -> Res; {error, _} -> {error, <<"Timeout"/utf8>>} end. -file("src/aarondb.gleam", 142). -spec prune( gleam@erlang@process:subject(aarondb@transactor:message()), integer(), list(binary()) ) -> integer(). prune(Db, Threshold, Sovereign) -> Reply = gleam@erlang@process:new_subject(), gleam@erlang@process:send(Db, {prune, Threshold, Sovereign, Reply}), case gleam@erlang@process:'receive'(Reply, 5000) of {ok, Count} -> Count; {error, _} -> 0 end. -file("src/aarondb.gleam", 151). -spec trigger_eviction( gleam@erlang@process:subject(aarondb@transactor:message()) ) -> {ok, nil} | {error, binary()}. trigger_eviction(Db) -> gleam@erlang@process:send(Db, tick), {ok, nil}. -file("src/aarondb.gleam", 156). -spec retract_entity( gleam@erlang@process:subject(aarondb@transactor:message()), aarondb@fact:eid() ) -> {ok, aarondb@shared@state:db_state()} | {error, binary()}. retract_entity(Db, Eid) -> case Eid of {uid, Entity} -> Reply = gleam@erlang@process:new_subject(), gleam@erlang@process:send(Db, {retract_entity, Entity, Reply}), case gleam@erlang@process:'receive'(Reply, 5000) of {ok, Res} -> Res; {error, _} -> {error, <<"Timeout"/utf8>>} end; _ -> {error, <<"Only Uid supported for retract_entity"/utf8>>} end. -file("src/aarondb.gleam", 170). -spec with_facts( aarondb@shared@state:db_state(), list({aarondb@fact:eid(), binary(), aarondb@fact:value()}) ) -> {ok, speculative_result()} | {error, binary()}. with_facts(State, Facts) -> _pipe = aarondb@transactor:compute_next_state(State, Facts, none, assert), gleam@result:map( _pipe, fun(Res) -> {speculative_result, erlang:element(1, Res), erlang:element(2, Res)} end ). -file("src/aarondb.gleam", 179). ?DOC(" Provides a human-readable explanation of a speculative result or failure.\n"). -spec explain_speculation({ok, speculative_result()} | {error, binary()}) -> binary(). explain_speculation(Res) -> case Res of {ok, S} -> <<<<"Speculation successful: "/utf8, (erlang:integer_to_binary( erlang:length(erlang:element(3, S)) ))/binary>>/binary, " datoms predicted."/utf8>>; {error, E} -> <<"Speculation failed: "/utf8, E/binary>> end. -file("src/aarondb.gleam", 189). -spec get( gleam@erlang@process:subject(aarondb@transactor:message()), aarondb@fact:eid(), binary() ) -> list(aarondb@fact:value()). get(Db, Eid, Attr) -> State = aarondb@transactor:get_state(Db), Id = case Eid of {uid, I} -> I; {lookup, {A, V}} -> _pipe = aarondb@index:get_entity_by_av( erlang:element(5, State), A, V ), gleam@result:unwrap(_pipe, {entity_id, 0}) end, case erlang:element(14, State) of {some, Name} -> _pipe@1 = aarondb@index@ets:lookup_datoms( <>, Id ), _pipe@2 = gleam@list:filter( _pipe@1, fun(D) -> erlang:element(3, D) =:= Attr end ), gleam@list:map(_pipe@2, fun(D@1) -> erlang:element(4, D@1) end); none -> _pipe@3 = aarondb@index:get_datoms_by_entity_attr( erlang:element(3, State), Id, Attr ), gleam@list:map(_pipe@3, fun(D@2) -> erlang:element(4, D@2) end) end. -file("src/aarondb.gleam", 211). -spec get_one( gleam@erlang@process:subject(aarondb@transactor:message()), aarondb@fact:eid(), binary() ) -> {ok, aarondb@fact:value()} | {error, nil}. get_one(Db, Eid, Attr) -> _pipe = get(Db, Eid, Attr), gleam@list:first(_pipe). -file("src/aarondb.gleam", 215). -spec set_schema( gleam@erlang@process:subject(aarondb@transactor:message()), binary(), aarondb@fact:attribute_config() ) -> {ok, nil} | {error, binary()}. set_schema(Db, Attr, Config) -> aarondb@transactor:set_schema(Db, Attr, Config). -file("src/aarondb.gleam", 223). -spec set_schema_with_timeout( gleam@erlang@process:subject(aarondb@transactor:message()), binary(), aarondb@fact:attribute_config(), integer() ) -> {ok, nil} | {error, binary()}. set_schema_with_timeout(Db, Attr, Config, Timeout_ms) -> aarondb@transactor:set_schema_with_timeout(Db, Attr, Config, Timeout_ms). -file("src/aarondb.gleam", 232). -spec history( gleam@erlang@process:subject(aarondb@transactor:message()), aarondb@fact:eid() ) -> list(aarondb@fact:datom()). history(Db, Eid) -> State = aarondb@transactor:get_state(Db), Id = case Eid of {uid, I} -> I; {lookup, {A, V}} -> _pipe = aarondb@index:get_entity_by_av( erlang:element(5, State), A, V ), gleam@result:unwrap(_pipe, {entity_id, 0}) end, case erlang:element(14, State) of {some, Name} -> aarondb@index@ets:lookup_datoms(<>, Id); none -> aarondb@index:get_datoms_by_entity(erlang:element(3, State), Id) end. -file("src/aarondb.gleam", 247). -spec extract_pull_attributes(list(aarondb@shared@ast:pull_item())) -> list(binary()). extract_pull_attributes(Pattern) -> gleam@list:fold(Pattern, [], fun(Acc, P) -> case P of {attr, A} -> [A | Acc]; {nested, A@1, Inner} -> [A@1 | lists:append(extract_pull_attributes(Inner), Acc)]; _ -> Acc end end). -file("src/aarondb.gleam", 260). -spec pull( gleam@erlang@process:subject(aarondb@transactor:message()), aarondb@fact:eid(), list(aarondb@shared@ast:pull_item()) ) -> aarondb@shared@query_types:pull_result(). pull(Db, Eid, Pattern) -> State = aarondb@transactor:get_state(Db), case erlang:element(4, erlang:element(25, State)) of true -> Attrs = extract_pull_attributes(Pattern), Ctx = {query_context, Attrs, [], 0}, aarondb@transactor:log_query(Db, Ctx); false -> nil end, Id = case Eid of {uid, I} -> I; {lookup, {A, V}} -> _pipe = aarondb@index:get_entity_by_av( erlang:element(5, State), A, V ), gleam@result:unwrap(_pipe, {entity_id, 0}) end, aarondb@engine:pull(State, Id, Pattern). -file("src/aarondb.gleam", 281). -spec diff( gleam@erlang@process:subject(aarondb@transactor:message()), integer(), integer() ) -> list(aarondb@fact:datom()). diff(Db, From_tx, To_tx) -> State = aarondb@transactor:get_state(Db), aarondb@engine:diff(State, From_tx, To_tx). -file("src/aarondb.gleam", 286). -spec pull_all() -> list(aarondb@shared@ast:pull_item()). pull_all() -> [wildcard]. -file("src/aarondb.gleam", 290). -spec pull_attr(binary()) -> list(aarondb@shared@ast:pull_item()). pull_attr(Attr) -> [{attr, Attr}]. -file("src/aarondb.gleam", 294). -spec pull_except(list(binary())) -> list(aarondb@shared@ast:pull_item()). pull_except(Exclusions) -> [{except, Exclusions}]. -file("src/aarondb.gleam", 298). -spec pull_recursive(binary(), integer()) -> list(aarondb@shared@ast:pull_item()). pull_recursive(Attr, Depth) -> [{pull_recursion, Attr, Depth}]. -file("src/aarondb.gleam", 302). -spec 'query'( gleam@erlang@process:subject(aarondb@transactor:message()), list(aarondb@shared@ast:body_clause()) ) -> aarondb@shared@query_types:query_result(). 'query'(Db, Q_clauses) -> State = aarondb@transactor:get_state(Db), Q = {'query', [], Q_clauses, none, none, none}, aarondb@engine:run(State, Q, [], none, none). -file("src/aarondb.gleam", 315). -spec q( gleam@erlang@process:subject(aarondb@transactor:message()), aarondb@q:query_builder() ) -> aarondb@shared@query_types:query_result(). q(Db, Q_builder) -> State = aarondb@transactor:get_state(Db), Q = aarondb@q:to_query(Q_builder), aarondb@engine:run(State, Q, [], none, none). -file("src/aarondb.gleam", 321). -spec query_at( gleam@erlang@process:subject(aarondb@transactor:message()), list(aarondb@shared@ast:body_clause()), gleam@option:option(integer()), gleam@option:option(integer()) ) -> aarondb@shared@query_types:query_result(). query_at(Db, Q_clauses, As_of_tx, As_of_valid) -> State = aarondb@transactor:get_state(Db), Q = {'query', [], Q_clauses, none, none, none}, aarondb@engine:run( State, Q, erlang:element(22, State), As_of_tx, As_of_valid ). -file("src/aarondb.gleam", 339). -spec query_state( aarondb@shared@state:db_state(), list(aarondb@shared@ast:body_clause()) ) -> aarondb@shared@query_types:query_result(). query_state(State, Q_clauses) -> Q = {'query', [], Q_clauses, none, none, none}, aarondb@engine:run(State, Q, [], none, none). -file("src/aarondb.gleam", 351). -spec query_state_at( aarondb@shared@state:db_state(), list(aarondb@shared@ast:body_clause()), gleam@option:option(integer()), gleam@option:option(integer()) ) -> aarondb@shared@query_types:query_result(). query_state_at(State, Q_clauses, As_of_tx, As_of_valid) -> Q = {'query', [], Q_clauses, none, none, none}, aarondb@engine:run(State, Q, [], As_of_tx, As_of_valid). -file("src/aarondb.gleam", 368). -spec execute( gleam@erlang@process:subject(aarondb@transactor:message()), aarondb@shared@ast:'query'() ) -> aarondb@shared@query_types:query_result(). execute(Db, Query) -> State = aarondb@transactor:get_state(Db), aarondb@engine:run(State, Query, [], none, none). -file("src/aarondb.gleam", 373). -spec query_state_with_rules( aarondb@shared@state:db_state(), list(aarondb@shared@ast:body_clause()), list(aarondb@shared@ast:rule()) ) -> aarondb@shared@query_types:query_result(). query_state_with_rules(State, Q_clauses, Rules) -> Q = {'query', [], Q_clauses, none, none, none}, aarondb@engine:run(State, Q, Rules, none, none). -file("src/aarondb.gleam", 389). -spec query_with_rules( gleam@erlang@process:subject(aarondb@transactor:message()), list(aarondb@shared@ast:body_clause()), list(aarondb@shared@ast:rule()) ) -> aarondb@shared@query_types:query_result(). query_with_rules(Db, Q_clauses, Rules) -> State = aarondb@transactor:get_state(Db), Q = {'query', [], Q_clauses, none, none, none}, aarondb@engine:run(State, Q, Rules, none, none). -file("src/aarondb.gleam", 406). -spec as_of( gleam@erlang@process:subject(aarondb@transactor:message()), integer(), list(aarondb@shared@ast:body_clause()) ) -> aarondb@shared@query_types:query_result(). as_of(Db, Tx, Q_clauses) -> State = aarondb@transactor:get_state(Db), Q = {'query', [], Q_clauses, none, none, none}, aarondb@engine:run(State, Q, erlang:element(22, State), {some, Tx}, none). -file("src/aarondb.gleam", 419). -spec as_of_valid( gleam@erlang@process:subject(aarondb@transactor:message()), integer(), list(aarondb@shared@ast:body_clause()) ) -> aarondb@shared@query_types:query_result(). as_of_valid(Db, Valid_time, Q_clauses) -> State = aarondb@transactor:get_state(Db), Q = {'query', [], Q_clauses, none, none, none}, aarondb@engine:run( State, Q, erlang:element(22, State), none, {some, Valid_time} ). -file("src/aarondb.gleam", 436). -spec as_of_bitemporal( gleam@erlang@process:subject(aarondb@transactor:message()), integer(), integer(), list(aarondb@shared@ast:body_clause()) ) -> aarondb@shared@query_types:query_result(). as_of_bitemporal(Db, Tx, Valid_time, Q_clauses) -> State = aarondb@transactor:get_state(Db), Q = {'query', [], Q_clauses, none, none, none}, aarondb@engine:run( State, Q, erlang:element(22, State), {some, Tx}, {some, Valid_time} ). -file("src/aarondb.gleam", 454). -spec p({aarondb@shared@ast:part(), binary(), aarondb@shared@ast:part()}) -> aarondb@shared@ast:body_clause(). p(Triple) -> {positive, Triple}. -file("src/aarondb.gleam", 458). -spec register_function( gleam@erlang@process:subject(aarondb@transactor:message()), binary(), fun((aarondb@shared@state:db_state(), integer(), integer(), list(aarondb@fact:value())) -> list({aarondb@fact:eid(), binary(), aarondb@fact:value()})) ) -> nil. register_function(Db, Name, Func) -> aarondb@transactor:register_function(Db, Name, Func). -file("src/aarondb.gleam", 466). -spec register_composite( gleam@erlang@process:subject(aarondb@transactor:message()), list(binary()) ) -> {ok, nil} | {error, binary()}. register_composite(Db, Attrs) -> aarondb@transactor:register_composite(Db, Attrs). -file("src/aarondb.gleam", 470). -spec register_predicate( gleam@erlang@process:subject(aarondb@transactor:message()), binary(), fun((aarondb@fact:value()) -> boolean()) ) -> nil. register_predicate(Db, Name, Pred) -> aarondb@transactor:register_predicate(Db, Name, Pred). -file("src/aarondb.gleam", 478). -spec store_rule( gleam@erlang@process:subject(aarondb@transactor:message()), aarondb@shared@ast:rule() ) -> {ok, nil} | {error, binary()}. store_rule(Db, Rule) -> aarondb@transactor:store_rule(Db, Rule). -file("src/aarondb.gleam", 482). -spec set_config( gleam@erlang@process:subject(aarondb@transactor:message()), aarondb@shared@state:config() ) -> nil. set_config(Db, Config) -> aarondb@transactor:set_config(Db, Config). -file("src/aarondb.gleam", 486). -spec subscribe( gleam@erlang@process:subject(aarondb@transactor:message()), aarondb@shared@ast:'query'(), gleam@erlang@process:subject(aarondb@shared@query_types:reactive_delta()) ) -> nil. subscribe(Db, Query, Subscriber) -> State = aarondb@transactor:get_state(Db), Results = aarondb@engine:run(State, Query, [], none, none), Attrs = gleam@list:filter_map(erlang:element(3, Query), fun(C) -> case C of {positive, {_, A, _}} -> {ok, A}; {negative, {_, A@1, _}} -> {ok, A@1}; _ -> {error, nil} end end), Msg = {subscribe, Query, Attrs, Subscriber, Results}, gleam@erlang@process:send(erlang:element(11, State), Msg), gleam@erlang@process:send(Subscriber, {initial, Results}), nil. -file("src/aarondb.gleam", 509). -spec subscribe_wal( gleam@erlang@process:subject(aarondb@transactor:message()), gleam@erlang@process:subject(list(aarondb@fact:datom())) ) -> nil. subscribe_wal(Db, Subscriber) -> gleam@erlang@process:send(Db, {subscribe, Subscriber}). -file("src/aarondb.gleam", 513). -spec get_state(gleam@erlang@process:subject(aarondb@transactor:message())) -> aarondb@shared@state:db_state(). get_state(Db) -> aarondb@transactor:get_state(Db). -file("src/aarondb.gleam", 517). -spec sync(gleam@erlang@process:subject(aarondb@transactor:message())) -> nil. sync(Db) -> Reply = gleam@erlang@process:new_subject(), gleam@erlang@process:send(Db, {sync, Reply}), _ = gleam@erlang@process:'receive'(Reply, 5000), nil. -file("src/aarondb.gleam", 524). -spec is_leader(gleam@erlang@process:subject(aarondb@transactor:message())) -> boolean(). is_leader(Db) -> State = aarondb@transactor:get_state(Db), aarondb@raft:is_leader(erlang:element(15, State)). -file("src/aarondb.gleam", 529). -spec traverse( gleam@erlang@process:subject(aarondb@transactor:message()), aarondb@fact:eid(), list(aarondb@shared@ast:step()), integer() ) -> {ok, list(aarondb@fact:value())} | {error, binary()}. traverse(Db, Eid, Path, Max_depth) -> State = aarondb@transactor:get_state(Db), Id = case Eid of {uid, {entity_id, I}} -> I; {lookup, {A, V}} -> _pipe = aarondb@index:get_entity_by_av( erlang:element(5, State), A, V ), _pipe@1 = gleam@result:unwrap(_pipe, {entity_id, 0}), aarondb@fact:eid_to_integer(_pipe@1) end, Engine_path = gleam@list:map(Path, fun(S) -> case S of {in, A@1} -> {in, A@1}; {out, A@2} -> {out, A@2} end end), aarondb@engine:traverse(State, Id, Engine_path, Max_depth).