-module(strata_postgres). -behaviour(strata_driver). -export([up/1, down/1, list/1, add/3, delete/2, last/1, exec/2]). -spec exec(any(), iodata()) -> ok | {error, any()}. exec(_Conn, Query) -> case pgo:query(Query, []) of {error, _Err} = E -> E; #{rows := _} -> ok end. -spec up(any()) -> ok | {error, any()}. up(_Conn) -> case pgo:query([<<"CREATE TABLE IF NOT EXISTS __strata_migrations ( ">>, <<" id SERIAL PRIMARY KEY, ">>, <<" name TEXT NOT NULL, ">>, <<" timestamp INTEGER NOT NULL ">>, <<")">>], []) of {error, _Err} = E -> E; #{rows := _} -> ok end. -spec down(any()) -> ok | {error, any()}. down(_Conn) -> case pgo:query(<<"DROP TABLE IF EXISTS __strata_migrations">>, []) of {error, _Err} = E -> E; #{rows := _} -> ok end. -spec list(any()) -> {ok, list()} | {error, any()}. list(_Conn) -> case pgo:query(<<"SELECT id, name, timestamp FROM __strata_migrations ORDER BY timestamp ASC">>, []) of {error, _Err} = E -> E; #{rows := Rows} -> {ok, format_rows(Rows)} end. -spec format_rows(list()) -> list(). format_rows(Rows) -> lists:map(fun format_row/1, Rows). -spec format_row({integer(), binary(), integer()} | any()) -> {integer(), module(), integer()} | {error, invalid_row}. format_row({Id, Name, Timestamp}) -> {Id, binary_to_atom(Name), Timestamp}; format_row(_) -> {error, invalid_row}. -spec add(any(), binary(), integer()) -> ok | {error, any()}. add(_Conn, Name, Timestamp) -> case pgo:query(<<"INSERT INTO __strata_migrations (name, timestamp) VALUES ($1, $2)">>, [Name, Timestamp]) of {error, _Err} = E -> E; #{rows := _} -> ok end. -spec last(any()) -> {error, any()} | {ok, {integer(), module(), integer()}}. last(_Conn) -> case pgo:query(<<"SELECT id, name, timestamp FROM __strata_migrations ORDER BY timestamp DESC LIMIT 1">>, []) of {error, _Err} = E -> E; #{rows := [{Id, Name, Timestamp}]} -> {ok, {Id, binary_to_atom(Name), Timestamp}} end. -spec delete(any(), integer()) -> ok | {error, any()}. delete(_Conn, Id) -> case pgo:query(<<"DELETE FROM __strata_migrations WHERE id = $1">>, [Id]) of {error, _Err} = E -> E; #{rows := _} -> ok end.