Packages

SQL query builder core for Gleam

Current section

Files

Jump to
galchemy src galchemy@schema@migration@postgres.erl
Raw

src/galchemy@schema@migration@postgres.erl

-module(galchemy@schema@migration@postgres).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src\\galchemy\\schema\\migration\\postgres.gleam").
-export([plan/3, statuses/2, ensure_history_table_query/0, history_query/0, applied_migration_query/1, record_migration_query/1, apply/2]).
-export_type([migration_plan/0, applied_migration/0, migration_status/0, apply_error/0]).
-type migration_plan() :: {migration_plan,
binary(),
list(galchemy@schema@diff:schema_operation()),
list(binary())}.
-type applied_migration() :: {applied_migration, binary(), binary(), integer()}.
-type migration_status() :: {pending, migration_plan()} |
{applied, migration_plan(), applied_migration()}.
-type apply_error() :: {already_applied, binary()} |
{history_query_error, pog:query_error()} |
{statement_error, binary(), pog:query_error()} |
{record_error, pog:query_error()}.
-file("src\\galchemy\\schema\\migration\\postgres.gleam", 39).
-spec plan(
binary(),
galchemy@schema@model:schema_snapshot(),
galchemy@schema@model:schema_snapshot()
) -> {ok, migration_plan()} |
{error, galchemy@schema@ddl@postgres:ddl_compile_error()}.
plan(Name, Current, Target) ->
Operations = galchemy@schema@diff:diff(Current, Target),
gleam@result:'try'(
galchemy@schema@ddl@postgres:compile(Operations),
fun(Statements) ->
{ok, {migration_plan, Name, Operations, Statements}}
end
).
-file("src\\galchemy\\schema\\migration\\postgres.gleam", 182).
-spec execute_unit_query(
pog:'query'(any()),
pog:connection(),
fun((pog:query_error()) -> OSX)
) -> {ok, nil} | {error, OSX}.
execute_unit_query(Query, Connection, Map_error) ->
case pog:execute(Query, Connection) of
{ok, _} ->
{ok, nil};
{error, Error} ->
{error, Map_error(Error)}
end.
-file("src\\galchemy\\schema\\migration\\postgres.gleam", 163).
-spec apply_statements(list(binary()), pog:connection()) -> {ok, nil} |
{error, apply_error()}.
apply_statements(Statements, Connection) ->
case Statements of
[] ->
{ok, nil};
[Statement | Rest] ->
case execute_unit_query(
pog:'query'(Statement),
Connection,
fun(Error) -> {statement_error, Statement, Error} end
) of
{error, Error@1} ->
{error, Error@1};
{ok, _} ->
apply_statements(Rest, Connection)
end
end.
-file("src\\galchemy\\schema\\migration\\postgres.gleam", 193).
-spec find_applied(list(applied_migration()), binary()) -> gleam@option:option(applied_migration()).
find_applied(Applied, Name) ->
case Applied of
[] ->
none;
[Migration | Rest] ->
case erlang:element(2, Migration) =:= Name of
true ->
{some, Migration};
false ->
find_applied(Rest, Name)
end
end.
-file("src\\galchemy\\schema\\migration\\postgres.gleam", 208).
-spec applied_migration_decoder() -> gleam@dynamic@decode:decoder(applied_migration()).
applied_migration_decoder() ->
_pipe = gleam@dynamic@decode:at(
[0],
{decoder, fun gleam@dynamic@decode:decode_string/1}
),
gleam@dynamic@decode:then(
_pipe,
fun(Name) ->
_pipe@1 = gleam@dynamic@decode:at(
[1],
{decoder, fun gleam@dynamic@decode:decode_string/1}
),
gleam@dynamic@decode:then(
_pipe@1,
fun(Applied_at) ->
_pipe@2 = gleam@dynamic@decode:at(
[2],
{decoder, fun gleam@dynamic@decode:decode_int/1}
),
gleam@dynamic@decode:map(
_pipe@2,
fun(Statement_count) ->
{applied_migration,
Name,
Applied_at,
Statement_count}
end
)
end
)
end
).
-file("src\\galchemy\\schema\\migration\\postgres.gleam", 231).
-spec compile_identifier(binary()) -> binary().
compile_identifier(Identifier) ->
<<<<"\""/utf8,
(gleam@string:replace(Identifier, <<"\""/utf8>>, <<"\"\""/utf8>>))/binary>>/binary,
"\""/utf8>>.
-file("src\\galchemy\\schema\\migration\\postgres.gleam", 239).
-spec reverse_loop(list(OTG), list(OTG)) -> list(OTG).
reverse_loop(Items, Acc) ->
case Items of
[] ->
Acc;
[Item | Rest] ->
reverse_loop(Rest, [Item | Acc])
end.
-file("src\\galchemy\\schema\\migration\\postgres.gleam", 235).
-spec reverse(list(OTD)) -> list(OTD).
reverse(Items) ->
reverse_loop(Items, []).
-file("src\\galchemy\\schema\\migration\\postgres.gleam", 133).
-spec statuses_loop(
list(migration_plan()),
list(applied_migration()),
list(migration_status())
) -> list(migration_status()).
statuses_loop(Plans, Applied, Acc) ->
case Plans of
[] ->
reverse(Acc);
[Plan | Rest] ->
Next_status = case find_applied(Applied, erlang:element(2, Plan)) of
{some, Record} ->
{applied, Plan, Record};
none ->
{pending, Plan}
end,
statuses_loop(Rest, Applied, [Next_status | Acc])
end.
-file("src\\galchemy\\schema\\migration\\postgres.gleam", 92).
-spec statuses(list(migration_plan()), list(applied_migration())) -> list(migration_status()).
statuses(Plans, Applied) ->
statuses_loop(Plans, Applied, []).
-file("src\\galchemy\\schema\\migration\\postgres.gleam", 225).
-spec compile_history_table_ref() -> binary().
compile_history_table_ref() ->
<<<<(compile_identifier(<<"public"/utf8>>))/binary, "."/utf8>>/binary,
(compile_identifier(<<"galchemy_schema_migrations"/utf8>>))/binary>>.
-file("src\\galchemy\\schema\\migration\\postgres.gleam", 49).
-spec ensure_history_table_query() -> pog:'query'(nil).
ensure_history_table_query() ->
pog:'query'(
<<<<<<<<<<<<"CREATE TABLE IF NOT EXISTS "/utf8,
(compile_history_table_ref())/binary>>/binary,
" ("/utf8>>/binary,
"\"name\" TEXT PRIMARY KEY, "/utf8>>/binary,
"\"applied_at\" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(), "/utf8>>/binary,
"\"statement_count\" INTEGER NOT NULL"/utf8>>/binary,
")"/utf8>>
).
-file("src\\galchemy\\schema\\migration\\postgres.gleam", 61).
-spec history_query() -> pog:'query'(applied_migration()).
history_query() ->
_pipe = pog:'query'(
<<<<<<"SELECT \"name\", \"applied_at\"::text, \"statement_count\" "/utf8,
"FROM "/utf8>>/binary,
(compile_history_table_ref())/binary>>/binary,
" ORDER BY \"applied_at\", \"name\""/utf8>>
),
pog:returning(_pipe, applied_migration_decoder()).
-file("src\\galchemy\\schema\\migration\\postgres.gleam", 71).
-spec applied_migration_query(binary()) -> pog:'query'(applied_migration()).
applied_migration_query(Name) ->
_pipe = pog:'query'(
<<<<<<"SELECT \"name\", \"applied_at\"::text, \"statement_count\" "/utf8,
"FROM "/utf8>>/binary,
(compile_history_table_ref())/binary>>/binary,
" WHERE \"name\" = $1"/utf8>>
),
_pipe@1 = pog:parameter(_pipe, pog_ffi:coerce(Name)),
pog:returning(_pipe@1, applied_migration_decoder()).
-file("src\\galchemy\\schema\\migration\\postgres.gleam", 82).
-spec record_migration_query(migration_plan()) -> pog:'query'(nil).
record_migration_query(Plan) ->
_pipe = pog:'query'(
<<<<"INSERT INTO "/utf8, (compile_history_table_ref())/binary>>/binary,
" (\"name\", \"statement_count\") VALUES ($1, $2)"/utf8>>
),
_pipe@1 = pog:parameter(_pipe, pog_ffi:coerce(erlang:element(2, Plan))),
pog:parameter(
_pipe@1,
pog_ffi:coerce(erlang:length(erlang:element(4, Plan)))
).
-file("src\\galchemy\\schema\\migration\\postgres.gleam", 151).
-spec fetch_applied_migration(pog:connection(), binary()) -> {ok,
gleam@option:option(applied_migration())} |
{error, apply_error()}.
fetch_applied_migration(Connection, Name) ->
case pog:execute(applied_migration_query(Name), Connection) of
{ok, {returned, 0, _}} ->
{ok, none};
{ok, {returned, _, []}} ->
{ok, none};
{ok, {returned, _, [First | _]}} ->
{ok, {some, First}};
{error, Error} ->
{error, {history_query_error, Error}}
end.
-file("src\\galchemy\\schema\\migration\\postgres.gleam", 99).
-spec apply(pog:connection(), migration_plan()) -> {ok, nil} |
{error, pog:transaction_error(apply_error())}.
apply(Connection, Plan) ->
pog:transaction(
Connection,
fun(Tx_connection) ->
case execute_unit_query(
ensure_history_table_query(),
Tx_connection,
fun(Field@0) -> {history_query_error, Field@0} end
) of
{error, Error} ->
{error, Error};
{ok, _} ->
case fetch_applied_migration(
Tx_connection,
erlang:element(2, Plan)
) of
{error, Error@1} ->
{error, Error@1};
{ok, {some, _}} ->
{error, {already_applied, erlang:element(2, Plan)}};
{ok, none} ->
case apply_statements(
erlang:element(4, Plan),
Tx_connection
) of
{error, Error@2} ->
{error, Error@2};
{ok, _} ->
execute_unit_query(
record_migration_query(Plan),
Tx_connection,
fun(Field@0) -> {record_error, Field@0} end
)
end
end
end
end
).