-module(common_sql_postgresql). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/common_sql_postgresql.gleam"). -export([driver/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. -file("src/common_sql_postgresql.gleam", 9). -spec param_to_value(common_sql:param()) -> pog:value(). param_to_value(Param) -> case Param of {p_int, N} -> pog_ffi:coerce(N); {p_string, S} -> pog_ffi:coerce(S); {p_float, F} -> pog_ffi:coerce(F); {p_bool, B} -> pog_ffi:coerce(B); p_null -> pog_ffi:null() end. -file("src/common_sql_postgresql.gleam", 19). -spec pog_error_to_db_error(pog:query_error()) -> common_sql:db_error(). pog_error_to_db_error(Err) -> case Err of connection_unavailable -> {connection_error, <<"Connection unavailable"/utf8>>}; {constraint_violated, Message, _, _} -> {query_error, <<"Constraint violated: "/utf8, Message/binary>>}; {postgresql_error, _, _, Message@1} -> {query_error, <<"PostgreSQL error: "/utf8, Message@1/binary>>}; {unexpected_argument_count, Expected, Got} -> {query_error, <<<<<<"Wrong argument count: expected "/utf8, (erlang:integer_to_binary(Expected))/binary>>/binary, ", got "/utf8>>/binary, (erlang:integer_to_binary(Got))/binary>>}; {unexpected_argument_type, Expected@1, Got@1} -> {query_error, <<<<<<"Wrong argument type: expected "/utf8, Expected@1/binary>>/binary, ", got "/utf8>>/binary, Got@1/binary>>}; {unexpected_result_type, Errors} -> {query_error, <<"Unexpected result type: "/utf8, (gleam@string:inspect(Errors))/binary>>}; query_timeout -> {query_error, <<"Query timed out"/utf8>>} end. -file("src/common_sql_postgresql.gleam", 55). ?DOC( " Returns a `common_sql.Driver` backed by PostgreSQL via the `pog` library.\n" "\n" " Call `driver()` once at application startup and pass it down. Each call\n" " creates one Erlang atom for the pool name — do not call it in a loop.\n" "\n" " Closing a pog connection pool has no explicit stop API; the pool runs as\n" " an OTP actor for the lifetime of the application. `common_sql.close/2` is\n" " a no-op for this driver. Use `pog.supervised/1` to manage the pool in an\n" " OTP supervision tree.\n" ). -spec driver() -> common_sql:driver(pog:connection()). driver() -> Pool_name = gleam_erlang_ffi:new_name(<<"common_sql_pg"/utf8>>), {driver, <<"postgresql"/utf8>>, fun(Url) -> case pog:url_config(Pool_name, Url) of {error, nil} -> {error, {connection_error, <<"Invalid PostgreSQL URL: "/utf8, Url/binary>>}}; {ok, Config} -> case pog:start(Config) of {ok, Started} -> {ok, erlang:element(3, Started)}; {error, _} -> case gleam_erlang_ffi:process_named(Pool_name) of {ok, _} -> {ok, pog:named_connection(Pool_name)}; {error, nil} -> {error, {connection_error, <<"Failed to start connection pool for: "/utf8, Url/binary>>}} end end end end, fun(Conn, Query, Params) -> Sql = case Query of {sql, S} -> S; {portable, S} -> S end, Q@1 = gleam@list:fold( Params, pog:'query'(Sql), fun(Q, Param) -> pog:parameter(Q, param_to_value(Param)) end ), Q@2 = pog:returning( Q@1, {decoder, fun gleam@dynamic@decode:decode_dynamic/1} ), case pog:execute(Q@2, Conn) of {ok, {returned, _, Rows}} -> {ok, Rows}; {error, Err} -> {error, pog_error_to_db_error(Err)} end end, fun(_) -> nil end}.