Current section
Files
Jump to
Current section
Files
src/postgleam.erl
-module(postgleam).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/postgleam.gleam").
-export([connect/1, 'query'/3, simple_query/2, prepare/3, execute/3, close/2, disconnect/1, transaction/2, query_error/1, int/1, float/1, text/1, bool/1, null/0, bytea/1, uuid/1, uuid_string/1, json/1, jsonb/1, numeric/1, date/1, timestamp/1, timestamptz/1, nullable/2, query_with/4, query_one/4]).
-export_type([response/1, connection/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 response(IWX) :: {response, list(IWX), integer(), binary()}.
-opaque connection() :: {connection,
gleam@erlang@process:subject(postgleam@internal@connection_actor:message()),
postgleam@config:config()}.
-file("src/postgleam.gleam", 49).
?DOC(
" Connect to PostgreSQL and return a connection handle.\n"
" The connection is managed by an OTP actor process.\n"
).
-spec connect(postgleam@config:config()) -> {ok, connection()} |
{error, postgleam@error:error()}.
connect(Config) ->
case postgleam@internal@connection_actor:start(Config) of
{ok, Started} ->
{ok, {connection, erlang:element(3, Started), Config}};
{error, init_timeout} ->
{error,
{connection_error,
<<"Connection initialization timed out"/utf8>>}};
{error, {init_failed, Reason}} ->
{error, {connection_error, Reason}};
{error, {init_exited, _}} ->
{error,
{connection_error,
<<"Connection process exited during init"/utf8>>}}
end.
-file("src/postgleam.gleam", 65).
?DOC(
" Execute a parameterized query using the extended protocol (binary format).\n"
" Returns typed values decoded through the codec registry.\n"
"\n"
" Panics if the actor does not respond within the configured timeout.\n"
).
-spec 'query'(
connection(),
binary(),
list(gleam@option:option(postgleam@value:value()))
) -> {ok, postgleam@connection:extended_query_result()} |
{error, postgleam@error:error()}.
'query'(Conn, Sql, Params) ->
gleam@erlang@process:call(
erlang:element(2, Conn),
erlang:element(7, erlang:element(3, Conn)),
fun(Reply) -> {'query', Sql, Params, Reply} end
).
-file("src/postgleam.gleam", 116).
?DOC(
" Execute a simple text query (no parameters).\n"
" Returns text-formatted results.\n"
).
-spec simple_query(connection(), binary()) -> {ok,
list(postgleam@connection:simple_query_result())} |
{error, postgleam@error:error()}.
simple_query(Conn, Sql) ->
gleam@erlang@process:call(
erlang:element(2, Conn),
erlang:element(7, erlang:element(3, Conn)),
fun(Reply) -> {simple_query, Sql, Reply} end
).
-file("src/postgleam.gleam", 126).
?DOC(" Prepare a named statement for later execution.\n").
-spec prepare(connection(), binary(), binary()) -> {ok,
postgleam@connection:prepared_statement()} |
{error, postgleam@error:error()}.
prepare(Conn, Name, Sql) ->
gleam@erlang@process:call(
erlang:element(2, Conn),
erlang:element(7, erlang:element(3, Conn)),
fun(Reply) -> {prepare, Name, Sql, Reply} end
).
-file("src/postgleam.gleam", 137).
?DOC(" Execute a previously prepared statement.\n").
-spec execute(
connection(),
postgleam@connection:prepared_statement(),
list(gleam@option:option(postgleam@value:value()))
) -> {ok, postgleam@connection:extended_query_result()} |
{error, postgleam@error:error()}.
execute(Conn, Prepared, Params) ->
gleam@erlang@process:call(
erlang:element(2, Conn),
erlang:element(7, erlang:element(3, Conn)),
fun(Reply) -> {execute_prepared, Prepared, Params, Reply} end
).
-file("src/postgleam.gleam", 148).
?DOC(" Close a prepared statement.\n").
-spec close(connection(), binary()) -> {ok, nil} |
{error, postgleam@error:error()}.
close(Conn, Name) ->
gleam@erlang@process:call(
erlang:element(2, Conn),
erlang:element(7, erlang:element(3, Conn)),
fun(Reply) -> {close_statement, Name, Reply} end
).
-file("src/postgleam.gleam", 155).
?DOC(" Disconnect from PostgreSQL and stop the actor.\n").
-spec disconnect(connection()) -> nil.
disconnect(Conn) ->
gleam@erlang@process:call(
erlang:element(2, Conn),
erlang:element(7, erlang:element(3, Conn)),
fun(Reply) -> {disconnect, Reply} end
).
-file("src/postgleam.gleam", 163).
?DOC(
" Execute a function within a transaction.\n"
" Automatically BEGINs, and COMMITs on Ok or ROLLBACKs on Error.\n"
).
-spec transaction(
connection(),
fun((connection()) -> {ok, IXZ} | {error, postgleam@error:error()})
) -> {ok, IXZ} | {error, postgleam@error:error()}.
transaction(Conn, F) ->
case simple_query(Conn, <<"BEGIN"/utf8>>) of
{error, E} ->
{error, E};
{ok, _} ->
case F(Conn) of
{ok, Val} ->
case simple_query(Conn, <<"COMMIT"/utf8>>) of
{ok, _} ->
{ok, Val};
{error, E@1} ->
{error, E@1}
end;
{error, E@2} ->
_ = simple_query(Conn, <<"ROLLBACK"/utf8>>),
{error, E@2}
end
end.
-file("src/postgleam.gleam", 187).
?DOC(" Create an error value for use in transactions or other contexts.\n").
-spec query_error(binary()) -> postgleam@error:error().
query_error(Message) ->
{connection_error, Message}.
-file("src/postgleam.gleam", 196).
?DOC(" Create an integer parameter (int2, int4, int8).\n").
-spec int(integer()) -> gleam@option:option(postgleam@value:value()).
int(Val) ->
{some, {integer, Val}}.
-file("src/postgleam.gleam", 201).
?DOC(" Create a float parameter (float4, float8).\n").
-spec float(float()) -> gleam@option:option(postgleam@value:value()).
float(Val) ->
{some, {float, Val}}.
-file("src/postgleam.gleam", 206).
?DOC(" Create a text/string parameter.\n").
-spec text(binary()) -> gleam@option:option(postgleam@value:value()).
text(Val) ->
{some, {text, Val}}.
-file("src/postgleam.gleam", 211).
?DOC(" Create a boolean parameter.\n").
-spec bool(boolean()) -> gleam@option:option(postgleam@value:value()).
bool(Val) ->
{some, {boolean, Val}}.
-file("src/postgleam.gleam", 216).
?DOC(" Create a NULL parameter.\n").
-spec null() -> gleam@option:option(postgleam@value:value()).
null() ->
none.
-file("src/postgleam.gleam", 221).
?DOC(" Create a bytea (binary data) parameter.\n").
-spec bytea(bitstring()) -> gleam@option:option(postgleam@value:value()).
bytea(Val) ->
{some, {bytea, Val}}.
-file("src/postgleam.gleam", 226).
?DOC(" Create a UUID parameter (16-byte binary).\n").
-spec uuid(bitstring()) -> gleam@option:option(postgleam@value:value()).
uuid(Val) ->
{some, {uuid, Val}}.
-file("src/postgleam.gleam", 232).
?DOC(
" Create a UUID parameter from a string like \"550e8400-e29b-41d4-a716-446655440000\".\n"
" Returns None (NULL) if the string is not a valid UUID.\n"
).
-spec uuid_string(binary()) -> gleam@option:option(postgleam@value:value()).
uuid_string(Val) ->
case postgleam@value:uuid_from_string(Val) of
{ok, V} ->
{some, V};
{error, _} ->
none
end.
-file("src/postgleam.gleam", 240).
?DOC(" Create a JSON parameter.\n").
-spec json(binary()) -> gleam@option:option(postgleam@value:value()).
json(Val) ->
{some, {json, Val}}.
-file("src/postgleam.gleam", 245).
?DOC(" Create a JSONB parameter.\n").
-spec jsonb(binary()) -> gleam@option:option(postgleam@value:value()).
jsonb(Val) ->
{some, {jsonb, Val}}.
-file("src/postgleam.gleam", 250).
?DOC(" Create a numeric/decimal parameter (string representation).\n").
-spec numeric(binary()) -> gleam@option:option(postgleam@value:value()).
numeric(Val) ->
{some, {numeric, Val}}.
-file("src/postgleam.gleam", 255).
?DOC(" Create a date parameter (days since 2000-01-01).\n").
-spec date(integer()) -> gleam@option:option(postgleam@value:value()).
date(Val) ->
{some, {date, Val}}.
-file("src/postgleam.gleam", 260).
?DOC(" Create a timestamp parameter (microseconds since 2000-01-01 00:00:00).\n").
-spec timestamp(integer()) -> gleam@option:option(postgleam@value:value()).
timestamp(Val) ->
{some, {timestamp, Val}}.
-file("src/postgleam.gleam", 265).
?DOC(" Create a timestamptz parameter (microseconds since 2000-01-01 00:00:00 UTC).\n").
-spec timestamptz(integer()) -> gleam@option:option(postgleam@value:value()).
timestamptz(Val) ->
{some, {timestamptz, Val}}.
-file("src/postgleam.gleam", 278).
?DOC(
" Create a nullable parameter from an Option value.\n"
"\n"
" ```gleam\n"
" postgleam.nullable(Some(\"hello\"), postgleam.text)\n"
" // => Some(value.Text(\"hello\"))\n"
"\n"
" postgleam.nullable(None, postgleam.text)\n"
" // => None\n"
" ```\n"
).
-spec nullable(
gleam@option:option(IYE),
fun((IYE) -> gleam@option:option(postgleam@value:value()))
) -> gleam@option:option(postgleam@value:value()).
nullable(Val, To_param) ->
case Val of
{some, V} ->
To_param(V);
none ->
none
end.
-file("src/postgleam.gleam", 289).
-spec decode_rows(
list(list(gleam@option:option(postgleam@value:value()))),
postgleam@decode:row_decoder(IYJ),
list(IYJ)
) -> {ok, list(IYJ)} | {error, postgleam@error:error()}.
decode_rows(Rows, Decoder, Acc) ->
case Rows of
[] ->
{ok, lists:reverse(Acc)};
[Row | Rest] ->
case postgleam@decode:run(Decoder, Row) of
{ok, Val} ->
decode_rows(Rest, Decoder, [Val | Acc]);
{error, E} ->
{error, E}
end
end.
-file("src/postgleam.gleam", 76).
?DOC(" Execute a parameterized query and decode each row using the provided decoder.\n").
-spec query_with(
connection(),
binary(),
list(gleam@option:option(postgleam@value:value())),
postgleam@decode:row_decoder(IXF)
) -> {ok, response(IXF)} | {error, postgleam@error:error()}.
query_with(Conn, Sql, Params, Decoder) ->
case 'query'(Conn, Sql, Params) of
{ok, Result} ->
case decode_rows(erlang:element(4, Result), Decoder, []) of
{ok, Decoded} ->
{ok,
{response,
Decoded,
erlang:length(Decoded),
erlang:element(2, Result)}};
{error, E} ->
{error, E}
end;
{error, E@1} ->
{error, E@1}
end.
-file("src/postgleam.gleam", 98).
?DOC(" Execute a query and return the first decoded row, or error if no rows.\n").
-spec query_one(
connection(),
binary(),
list(gleam@option:option(postgleam@value:value())),
postgleam@decode:row_decoder(IXL)
) -> {ok, IXL} | {error, postgleam@error:error()}.
query_one(Conn, Sql, Params, Decoder) ->
case query_with(Conn, Sql, Params, Decoder) of
{ok, Response} ->
case erlang:element(2, Response) of
[First | _] ->
{ok, First};
[] ->
{error,
{decode_error,
<<"Expected at least one row, got none"/utf8>>}}
end;
{error, E} ->
{error, E}
end.