Current section
Files
Jump to
Current section
Files
src/cigogne@internal@database.erl
-module(cigogne@internal@database).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]).
-define(FILEPATH, "src/cigogne/internal/database.gleam").
-export([init/3, apply_migration/2, rollback_migration/2, get_applied_migrations/1, get_schema/1, migrations_table_exists/1, apply_cigogne_zero/1]).
-export_type([database_data/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).
-type database_data() :: {database_data,
pog:connection(),
binary(),
binary(),
gleam@option:option(binary())}.
-file("src/cigogne/internal/database.gleam", 20).
?DOC(false).
-spec create_migrations_table(binary(), binary()) -> binary().
create_migrations_table(Schema, Migrations_table) ->
<<<<<<<<"CREATE TABLE IF NOT EXISTS "/utf8, Schema/binary>>/binary,
"."/utf8>>/binary,
Migrations_table/binary>>/binary,
"(
id INTEGER PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
name VARCHAR(255) NOT NULL,
sha256 VARCHAR(64) NOT NULL,
createdAt TIMESTAMP WITHOUT TIME ZONE NOT NULL,
appliedAt TIMESTAMP NOT NULL DEFAULT NOW()
);"/utf8>>.
-file("src/cigogne/internal/database.gleam", 30).
?DOC(false).
-spec query_insert_migration(binary(), binary()) -> binary().
query_insert_migration(Schema, Migrations_table) ->
<<<<<<<<"INSERT INTO "/utf8, Schema/binary>>/binary, "."/utf8>>/binary,
Migrations_table/binary>>/binary,
"(createdAt, name, sha256) VALUES ($1, $2, $3);"/utf8>>.
-file("src/cigogne/internal/database.gleam", 38).
?DOC(false).
-spec query_drop_migration(binary(), binary()) -> binary().
query_drop_migration(Schema, Migrations_table) ->
<<<<<<<<"DELETE FROM "/utf8, Schema/binary>>/binary, "."/utf8>>/binary,
Migrations_table/binary>>/binary,
" WHERE name = $1 AND createdAt = $2;"/utf8>>.
-file("src/cigogne/internal/database.gleam", 46).
?DOC(false).
-spec query_applied_migrations(binary(), binary()) -> binary().
query_applied_migrations(Schema, Migrations_table) ->
<<<<<<<<"SELECT createdAt, name, sha256 FROM "/utf8, Schema/binary>>/binary,
"."/utf8>>/binary,
Migrations_table/binary>>/binary,
" ORDER BY appliedAt ASC;"/utf8>>.
-file("src/cigogne/internal/database.gleam", 97).
?DOC(false).
-spec connection_from_url(binary()) -> {ok, pog:connection()} |
{error, cigogne@types:migrate_error()}.
connection_from_url(Url) ->
Db_process_name = gleam_erlang_ffi:new_name(<<"cigogne"/utf8>>),
_pipe = pog:url_config(Db_process_name, Url),
_pipe@1 = gleam@result:replace_error(_pipe, {url_error, Url}),
_pipe@3 = gleam@result:'try'(_pipe@1, fun(C) -> _pipe@2 = pog:start(C),
gleam@result:map_error(
_pipe@2,
fun(Field@0) -> {actor_start_error, Field@0} end
) end),
gleam@result:map(_pipe@3, fun(Actor) -> erlang:element(3, Actor) end).
-file("src/cigogne/internal/database.gleam", 72).
?DOC(false).
-spec connect(cigogne@types:connection_config()) -> {ok,
{pog:connection(), gleam@option:option(binary())}} |
{error, cigogne@types:migrate_error()}.
connect(Config) ->
case Config of
{connection_config, Connection} ->
{ok, {Connection, none}};
env_var_config ->
_pipe = envoy_ffi:get(<<"DATABASE_URL"/utf8>>),
_pipe@1 = gleam@result:replace_error(
_pipe,
{env_var_error, <<"DATABASE_URL"/utf8>>}
),
gleam@result:'try'(
_pipe@1,
fun(Url) -> _pipe@2 = connection_from_url(Url),
gleam@result:map(_pipe@2, fun(C) -> {C, {some, Url}} end) end
);
{pog_config, Config@1} ->
_pipe@3 = Config@1,
_pipe@4 = pog:start(_pipe@3),
_pipe@5 = gleam@result:map_error(
_pipe@4,
fun(Field@0) -> {actor_start_error, Field@0} end
),
gleam@result:map(
_pipe@5,
fun(Actor) -> {erlang:element(3, Actor), none} end
);
{url_config, Url@1} ->
_pipe@6 = connection_from_url(Url@1),
gleam@result:map(_pipe@6, fun(C@1) -> {C@1, {some, Url@1}} end)
end.
-file("src/cigogne/internal/database.gleam", 63).
?DOC(false).
-spec init(cigogne@types:connection_config(), binary(), binary()) -> {ok,
database_data()} |
{error, cigogne@types:migrate_error()}.
init(Config, Schema, Migrations_table_name) ->
gleam@result:'try'(
connect(Config),
fun(_use0) ->
{Connection, Db_url} = _use0,
{ok,
{database_data,
Connection,
Migrations_table_name,
Schema,
Db_url}}
end
).
-file("src/cigogne/internal/database.gleam", 188).
?DOC(false).
-spec insert_migration_query(database_data(), cigogne@types:migration()) -> pog:'query'(nil).
insert_migration_query(Data, Migration) ->
_pipe = query_insert_migration(
erlang:element(4, Data),
erlang:element(3, Data)
),
_pipe@1 = pog:'query'(_pipe),
_pipe@2 = pog:parameter(
_pipe@1,
pog:timestamp(erlang:element(3, Migration))
),
_pipe@3 = pog:parameter(
_pipe@2,
pog_ffi:coerce(erlang:element(4, Migration))
),
pog:parameter(_pipe@3, pog_ffi:coerce(erlang:element(7, Migration))).
-file("src/cigogne/internal/database.gleam", 148).
?DOC(false).
-spec apply_migration(database_data(), cigogne@types:migration()) -> {ok, nil} |
{error, cigogne@types:migrate_error()}.
apply_migration(Data, Migration) ->
_pipe@5 = begin
pog:transaction(
erlang:element(2, Data),
fun(Transaction) ->
_pipe@1 = gleam@list:try_each(
erlang:element(5, Migration),
fun(Q) -> _pipe = pog:'query'(Q),
pog:execute(_pipe, Transaction) end
),
_pipe@4 = gleam@result:'try'(
_pipe@1,
fun(_) -> _pipe@2 = insert_migration_query(Data, Migration),
_pipe@3 = pog:execute(_pipe@2, Transaction),
gleam@result:replace(_pipe@3, nil) end
),
gleam@result:map_error(
_pipe@4,
fun cigogne@internal@utils:describe_query_error/1
)
end
)
end,
gleam@result:map_error(
_pipe@5,
fun(Field@0) -> {p_g_o_transaction_error, Field@0} end
).
-file("src/cigogne/internal/database.gleam", 199).
?DOC(false).
-spec drop_migration_query(database_data(), cigogne@types:migration()) -> pog:'query'(nil).
drop_migration_query(Data, Migration) ->
_pipe = query_drop_migration(
erlang:element(4, Data),
erlang:element(3, Data)
),
_pipe@1 = pog:'query'(_pipe),
_pipe@2 = pog:parameter(
_pipe@1,
pog_ffi:coerce(erlang:element(4, Migration))
),
pog:parameter(_pipe@2, pog:timestamp(erlang:element(3, Migration))).
-file("src/cigogne/internal/database.gleam", 168).
?DOC(false).
-spec rollback_migration(database_data(), cigogne@types:migration()) -> {ok,
nil} |
{error, cigogne@types:migrate_error()}.
rollback_migration(Data, Migration) ->
_pipe@5 = begin
pog:transaction(
erlang:element(2, Data),
fun(Transaction) ->
_pipe@1 = gleam@list:try_each(
erlang:element(6, Migration),
fun(Q) -> _pipe = pog:'query'(Q),
pog:execute(_pipe, Transaction) end
),
_pipe@4 = gleam@result:'try'(
_pipe@1,
fun(_) -> _pipe@2 = drop_migration_query(Data, Migration),
_pipe@3 = pog:execute(_pipe@2, Transaction),
gleam@result:replace(_pipe@3, nil) end
),
gleam@result:map_error(
_pipe@4,
fun cigogne@internal@utils:describe_query_error/1
)
end
)
end,
gleam@result:map_error(
_pipe@5,
fun(Field@0) -> {p_g_o_transaction_error, Field@0} end
).
-file("src/cigogne/internal/database.gleam", 230).
?DOC(false).
-spec build_migration_data(
{gleam@time@timestamp:timestamp(), binary(), binary()}
) -> cigogne@types:migration().
build_migration_data(Data) ->
{migration,
<<""/utf8>>,
erlang:element(1, Data),
erlang:element(2, Data),
[],
[],
erlang:element(3, Data)}.
-file("src/cigogne/internal/database.gleam", 209).
?DOC(false).
-spec get_applied_migrations(database_data()) -> {ok,
list(cigogne@types:migration())} |
{error, cigogne@types:migrate_error()}.
get_applied_migrations(Data) ->
_pipe = query_applied_migrations(
erlang:element(4, Data),
erlang:element(3, Data)
),
_pipe@1 = pog:'query'(_pipe),
_pipe@2 = pog:returning(
_pipe@1,
begin
gleam@dynamic@decode:field(
0,
pog:timestamp_decoder(),
fun(Timestamp) ->
gleam@dynamic@decode:field(
1,
{decoder, fun gleam@dynamic@decode:decode_string/1},
fun(Name) ->
gleam@dynamic@decode:field(
2,
{decoder,
fun gleam@dynamic@decode:decode_string/1},
fun(Hash) ->
gleam@dynamic@decode:success(
{Timestamp, Name, Hash}
)
end
)
end
)
end
)
end
),
_pipe@3 = pog:execute(_pipe@2, erlang:element(2, Data)),
_pipe@4 = gleam@result:map_error(
_pipe@3,
fun(Field@0) -> {p_g_o_query_error, Field@0} end
),
gleam@result:'try'(
_pipe@4,
fun(Returned) -> case erlang:element(3, Returned) of
[] ->
{error, no_result_error};
_ = Applied ->
_pipe@5 = Applied,
_pipe@6 = gleam@list:map(
_pipe@5,
fun build_migration_data/1
),
{ok, _pipe@6}
end end
).
-file("src/cigogne/internal/database.gleam", 236).
?DOC(false).
-spec get_schema(database_data()) -> {ok, binary()} |
{error, cigogne@types:migrate_error()}.
get_schema(Data) ->
case erlang:element(5, Data) of
none ->
{error, {url_error, <<"None"/utf8>>}};
{some, Url} ->
_pipe = shellout:command(
<<"psql"/utf8>>,
[Url,
<<"-c"/utf8>>,
<<<<"\\d "/utf8, (erlang:element(4, Data))/binary>>/binary,
".*"/utf8>>],
<<"."/utf8>>,
[]
),
gleam@result:map_error(
_pipe,
fun(Err) -> {schema_query_error, erlang:element(2, Err)} end
)
end.
-file("src/cigogne/internal/database.gleam", 110).
?DOC(false).
-spec migrations_table_exists(database_data()) -> {ok, boolean()} |
{error, cigogne@types:migrate_error()}.
migrations_table_exists(Data) ->
Tables_query = begin
_pipe = pog:'query'(
<<"SELECT table_name, table_schema
FROM information_schema.tables
WHERE table_type = 'BASE TABLE'
AND table_name = $1
AND table_schema = $2;"/utf8>>
),
_pipe@1 = pog:parameter(_pipe, pog_ffi:coerce(erlang:element(3, Data))),
_pipe@2 = pog:parameter(
_pipe@1,
pog_ffi:coerce(erlang:element(4, Data))
),
pog:returning(
_pipe@2,
begin
gleam@dynamic@decode:field(
0,
{decoder, fun gleam@dynamic@decode:decode_string/1},
fun(Name) ->
gleam@dynamic@decode:field(
1,
{decoder, fun gleam@dynamic@decode:decode_string/1},
fun(Schema) ->
gleam@dynamic@decode:success({Name, Schema})
end
)
end
)
end
)
end,
Tables_result = begin
_pipe@3 = Tables_query,
pog:execute(_pipe@3, erlang:element(2, Data))
end,
case Tables_result of
{ok, Tables} ->
{ok, erlang:element(2, Tables) > 0};
{error, Db_err} ->
{error, {p_g_o_query_error, Db_err}}
end.
-file("src/cigogne/internal/database.gleam", 133).
?DOC(false).
-spec apply_cigogne_zero(database_data()) -> {ok, nil} |
{error, cigogne@types:migrate_error()}.
apply_cigogne_zero(Data) ->
case migrations_table_exists(Data) of
{ok, true} ->
{ok, nil};
{error, Err} ->
{error, Err};
{ok, false} ->
_pipe = cigogne@internal@migrations_utils:create_zero_migration(
<<"CreateMigrationTable"/utf8>>,
[create_migrations_table(
erlang:element(4, Data),
erlang:element(3, Data)
)],
[]
),
apply_migration(Data, _pipe)
end.