Current section
Files
Jump to
Current section
Files
src/pgl@internal@type_cache.erl
-module(pgl@internal@type_cache).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/pgl/internal/type_cache.gleam").
-export([on_connect/2, load/1, lookup/2, shutdown/1, new/0, start/1, supervised/1]).
-export_type([type_cache/0, message/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.
?MODULEDOC(false).
-opaque type_cache() :: {type_cache,
gleam@erlang@process:name(message()),
fun(() -> {ok, pgl@internal@socket:socket()} | {error, nil})}.
-opaque message() :: {load,
gleam@erlang@process:subject({ok, nil} | {error, nil}),
pgl@internal@socket:socket()} |
{lookup,
gleam@erlang@process:subject({ok, list(pg_value@type_info:type_info())} |
{error, nil}),
list(integer())} |
shutdown.
-file("src/pgl/internal/type_cache.gleam", 40).
?DOC(false).
-spec on_connect(
type_cache(),
fun(() -> {ok, pgl@internal@socket:socket()} | {error, nil})
) -> type_cache().
on_connect(Type_cache, Handle_connect) ->
{type_cache, erlang:element(2, Type_cache), Handle_connect}.
-file("src/pgl/internal/type_cache.gleam", 69).
?DOC(false).
-spec load(type_cache()) -> {ok, nil} | {error, nil}.
load(Type_cache) ->
_pipe = (erlang:element(3, Type_cache))(),
_pipe@1 = gleam@result:map_error(_pipe, fun(_) -> nil end),
gleam@result:'try'(
_pipe@1,
fun(Sock) ->
Res = begin
_pipe@2 = erlang:element(2, Type_cache),
_pipe@3 = gleam@erlang@process:named_subject(_pipe@2),
gleam@otp@actor:call(
_pipe@3,
1000,
fun(_capture) -> {load, _capture, Sock} end
)
end,
_ = pgl@internal@socket:shutdown(Sock),
Res
end
).
-file("src/pgl/internal/type_cache.gleam", 83).
?DOC(false).
-spec lookup(type_cache(), list(integer())) -> {ok,
list(pg_value@type_info:type_info())} |
{error, nil}.
lookup(Type_cache, Oids) ->
Do_lookup = fun(Oids@1) -> _pipe = erlang:element(2, Type_cache),
_pipe@1 = gleam@erlang@process:named_subject(_pipe),
gleam@otp@actor:call(
_pipe@1,
1000,
fun(_capture) -> {lookup, _capture, Oids@1} end
) end,
_pipe@2 = Do_lookup(Oids),
gleam@result:lazy_or(_pipe@2, fun() -> _pipe@3 = load(Type_cache),
gleam@result:'try'(_pipe@3, fun(_) -> Do_lookup(Oids) end) end).
-file("src/pgl/internal/type_cache.gleam", 100).
?DOC(false).
-spec shutdown(type_cache()) -> nil.
shutdown(Type_cache) ->
_pipe = gleam@erlang@process:named_subject(erlang:element(2, Type_cache)),
gleam@otp@actor:send(_pipe, shutdown).
-file("src/pgl/internal/type_cache.gleam", 141).
?DOC(false).
-spec handle_lookup(
pgl@internal@store:store(integer(), pg_value@type_info:type_info()),
list(integer()),
gleam@erlang@process:subject({ok, list(pg_value@type_info:type_info())} |
{error, nil})
) -> gleam@otp@actor:next(pgl@internal@store:store(integer(), pg_value@type_info:type_info()), any()).
handle_lookup(Store, Oids, Client) ->
_pipe = Oids,
_pipe@1 = gleam@list:try_map(
_pipe,
fun(_capture) -> pgl@internal@store:lookup(Store, _capture) end
),
gleam@otp@actor:send(Client, _pipe@1),
gleam@otp@actor:continue(Store).
-file("src/pgl/internal/type_cache.gleam", 153).
?DOC(false).
-spec parse_type_infos(
pgl@internal@store:store(integer(), pg_value@type_info:type_info()),
list(pg_value@type_info:type_info())
) -> pgl@internal@store:store(integer(), pg_value@type_info:type_info()).
parse_type_infos(Store, Infos) ->
Oid_to_info = begin
_pipe = Infos,
_pipe@1 = gleam@list:map(
_pipe,
fun(Ti) -> {erlang:element(2, Ti), Ti} end
),
maps:from_list(_pipe@1)
end,
_pipe@2 = Oid_to_info,
gleam@dict:fold(
_pipe@2,
Store,
fun(Store@1, Oid, Info) ->
_ = begin
_pipe@3 = erlang:element(12, Info),
_pipe@4 = gleam@list:try_map(
_pipe@3,
fun(_capture) ->
gleam_stdlib:map_get(Oid_to_info, _capture)
end
),
_pipe@7 = gleam@result:'try'(
_pipe@4,
fun(Comp_types) ->
gleam@result:map(
gleam_stdlib:map_get(
Oid_to_info,
erlang:element(9, Info)
),
fun(Elem_type) -> _pipe@5 = Info,
_pipe@6 = pg_value@type_info:elem_type(
_pipe@5,
{some, Elem_type}
),
pg_value@type_info:comp_types(
_pipe@6,
{some, Comp_types}
) end
)
end
),
_pipe@8 = gleam@result:unwrap(_pipe@7, Info),
pgl@internal@store:insert(Store@1, Oid, _pipe@8)
end,
Store@1
end
).
-file("src/pgl/internal/type_cache.gleam", 236).
?DOC(false).
-spec do_parse_comp_oids(binary()) -> {ok, list(integer())} | {error, nil}.
do_parse_comp_oids(Oids) ->
_pipe = gleam@string:split(Oids, <<"}"/utf8>>),
_pipe@1 = gleam@list:first(_pipe),
gleam@result:'try'(
_pipe@1,
fun(Oids1) -> _pipe@2 = gleam@string:split(Oids1, <<","/utf8>>),
gleam@list:try_fold(
_pipe@2,
[],
fun(Acc, Oid) -> _pipe@3 = gleam_stdlib:parse_int(Oid),
gleam@result:map(
_pipe@3,
fun(_capture) -> gleam@list:prepend(Acc, _capture) end
) end
) end
).
-file("src/pgl/internal/type_cache.gleam", 223).
?DOC(false).
-spec parse_comp_oids(bitstring()) -> {ok, list(integer())} | {error, nil}.
parse_comp_oids(Bits) ->
case Bits of
<<0>> ->
{ok, []};
<<>> ->
{ok, []};
<<"{}"/utf8>> ->
{ok, []};
<<"{"/utf8, Rest/bitstring>> ->
_pipe = gleam@bit_array:to_string(Rest),
gleam@result:'try'(_pipe, fun do_parse_comp_oids/1);
_ ->
{error, nil}
end.
-file("src/pgl/internal/type_cache.gleam", 248).
?DOC(false).
-spec bits_to_int(bitstring()) -> {ok, integer()} | {error, nil}.
bits_to_int(Bits) ->
_pipe = gleam@bit_array:to_string(Bits),
gleam@result:'try'(_pipe, fun gleam_stdlib:parse_int/1).
-file("src/pgl/internal/type_cache.gleam", 252).
?DOC(false).
-spec bits_to_oid(bitstring()) -> {ok, integer()} | {error, nil}.
bits_to_oid(Bits) ->
bits_to_int(Bits).
-file("src/pgl/internal/type_cache.gleam", 181).
?DOC(false).
-spec parse_type_info(list(bitstring())) -> {ok, pg_value@type_info:type_info()} |
{error, nil}.
parse_type_info(Row) ->
case Row of
[<<Oid/bitstring>>,
<<Name/bitstring>>,
<<Typesend/bitstring>>,
<<Typereceive/bitstring>>,
<<Typelen/bitstring>>,
<<Output/bitstring>>,
<<Input/bitstring>>,
<<Elem_oid/bitstring>>,
<<Base_oid/bitstring>>,
<<Comp_oids/bitstring>>] ->
begin
gleam@result:'try'(
bits_to_oid(Oid),
fun(Oid@1) ->
gleam@result:'try'(
gleam@bit_array:to_string(Name),
fun(Name@1) ->
gleam@result:'try'(
gleam@bit_array:to_string(Typesend),
fun(Typesend@1) ->
gleam@result:'try'(
gleam@bit_array:to_string(
Typereceive
),
fun(Typereceive@1) ->
gleam@result:'try'(
bits_to_int(Typelen),
fun(Typelen@1) ->
gleam@result:'try'(
gleam@bit_array:to_string(
Output
),
fun(Output@1) ->
gleam@result:'try'(
gleam@bit_array:to_string(
Input
),
fun(Input@1) ->
gleam@result:'try'(
bits_to_oid(
Elem_oid
),
fun(
Elem_oid@1
) ->
gleam@result:'try'(
bits_to_oid(
Base_oid
),
fun(
Base_oid@1
) ->
gleam@result:map(
parse_comp_oids(
Comp_oids
),
fun(
Comp_oids@1
) ->
_pipe = pg_value@type_info:new(
Oid@1
),
_pipe@1 = pg_value@type_info:name(
_pipe,
Name@1
),
_pipe@2 = pg_value@type_info:typesend(
_pipe@1,
Typesend@1
),
_pipe@3 = pg_value@type_info:typereceive(
_pipe@2,
Typereceive@1
),
_pipe@4 = pg_value@type_info:typelen(
_pipe@3,
Typelen@1
),
_pipe@5 = pg_value@type_info:output(
_pipe@4,
Output@1
),
_pipe@6 = pg_value@type_info:input(
_pipe@5,
Input@1
),
_pipe@7 = pg_value@type_info:elem_oid(
_pipe@6,
Elem_oid@1
),
_pipe@8 = pg_value@type_info:base_oid(
_pipe@7,
Base_oid@1
),
pg_value@type_info:comp_oids(
_pipe@8,
Comp_oids@1
)
end
)
end
)
end
)
end
)
end
)
end
)
end
)
end
)
end
)
end
)
end;
_ ->
{error, nil}
end.
-file("src/pgl/internal/type_cache.gleam", 32).
?DOC(false).
-spec new() -> type_cache().
new() ->
Handle_connect = fun() -> erlang:error(#{gleam_error => panic,
message => <<"TypeCache connect not configured"/utf8>>,
file => <<?FILEPATH/utf8>>,
module => <<"pgl/internal/type_cache"/utf8>>,
function => <<"new"/utf8>>,
line => 33}) end,
_pipe = <<"pgl_type_cache"/utf8>>,
_pipe@1 = gleam_erlang_ffi:new_name(_pipe),
{type_cache, _pipe@1, Handle_connect}.
-file("src/pgl/internal/type_cache.gleam", 115).
?DOC(false).
-spec handle_load(
pgl@internal@store:store(integer(), pg_value@type_info:type_info()),
pgl@internal@socket:socket(),
gleam@erlang@process:subject({ok, nil} | {error, nil})
) -> gleam@otp@actor:next(pgl@internal@store:store(integer(), pg_value@type_info:type_info()), any()).
handle_load(Store, Sock, Client) ->
_pipe = <<"SELECT t.oid AS oid, t.typname AS name, t.typsend AS typesend, t.typreceive AS typereceive, t.typlen AS typelen, t.typoutput AS output, t.typinput AS input, t.typelem AS elem_oid, coalesce(r.rngsubtype, 0) AS base_oid, ARRAY (SELECT a.atttypid FROM pg_attribute AS a WHERE a.attrelid = t.typrelid AND a.attnum > 0 AND NOT a.attisdropped ORDER BY a.attnum) AS comp_oids FROM pg_type AS t LEFT JOIN pg_range AS r ON r.rngtypid = t.oid OR (t.typbasetype <> 0 AND r.rngtypid = t.typbasetype) ORDER BY t.oid"/utf8>>,
_pipe@1 = pgl@internal@encode:'query'(_pipe),
_pipe@2 = pgl@internal@protocol:simple(_pipe@1, Sock),
_pipe@3 = gleam@result:map(
_pipe@2,
fun(Rows) -> case gleam@list:try_map(Rows, fun parse_type_info/1) of
{ok, Infos} ->
gleam@otp@actor:send(Client, {ok, nil}),
parse_type_infos(Store, Infos);
{error, _} ->
gleam@otp@actor:send(Client, {error, nil}),
Store
end end
),
_pipe@4 = gleam@result:unwrap(_pipe@3, Store),
gleam@otp@actor:continue(_pipe@4).
-file("src/pgl/internal/type_cache.gleam", 104).
?DOC(false).
-spec handle_message(
pgl@internal@store:store(integer(), pg_value@type_info:type_info()),
message()
) -> gleam@otp@actor:next(pgl@internal@store:store(integer(), pg_value@type_info:type_info()), any()).
handle_message(Store, Message) ->
case Message of
{load, Client, Sock} ->
handle_load(Store, Sock, Client);
{lookup, Client@1, Oids} ->
handle_lookup(Store, Oids, Client@1);
shutdown ->
gleam@otp@actor:stop()
end.
-file("src/pgl/internal/type_cache.gleam", 49).
?DOC(false).
-spec start(type_cache()) -> {ok, gleam@otp@actor:started(nil)} |
{error, gleam@otp@actor:start_error()}.
start(Type_cache) ->
_pipe@4 = gleam@otp@actor:new_with_initialiser(
1000,
fun(Subj) ->
Selector = begin
_pipe = gleam_erlang_ffi:new_selector(),
gleam@erlang@process:select(_pipe, Subj)
end,
_pipe@1 = pgl@internal@store:new(<<"pgl_type_cache_table"/utf8>>),
_pipe@2 = gleam@otp@actor:initialised(_pipe@1),
_pipe@3 = gleam@otp@actor:selecting(_pipe@2, Selector),
{ok, _pipe@3}
end
),
_pipe@5 = gleam@otp@actor:named(_pipe@4, erlang:element(2, Type_cache)),
_pipe@6 = gleam@otp@actor:on_message(_pipe@5, fun handle_message/2),
gleam@otp@actor:start(_pipe@6).
-file("src/pgl/internal/type_cache.gleam", 63).
?DOC(false).
-spec supervised(type_cache()) -> gleam@otp@supervision:child_specification(nil).
supervised(Type_cache) ->
_pipe = gleam@otp@supervision:worker(fun() -> start(Type_cache) end),
_pipe@1 = gleam@otp@supervision:timeout(_pipe, 1000),
gleam@otp@supervision:restart(_pipe@1, transient).