asobi_repo (asobi v0.84.0)
View SourceSummary
Functions
Add to integer counters on one row atomically, creating the row if absent.
The applications kura runs migrations from, beyond asobi itself: every installed extension.
Functions
-spec aggregate(#kura_query{from :: atom() | module() | undefined, select :: [atom() | term()] | {exprs, [term()]}, wheres :: [term()], joins :: [term()], order_bys :: [term()], group_bys :: [atom()], havings :: [term()], limit :: non_neg_integer() | undefined, offset :: non_neg_integer() | undefined, distinct :: boolean() | [atom()], lock :: binary() | undefined, prefix :: binary() | undefined, preloads :: [atom() | {atom(), list()}], ctes :: [{binary(), #kura_query{}}], combinations :: [{union | union_all | intersect | except, #kura_query{}}], include_deleted :: boolean()}, count | {count | sum | avg | min | max, atom()}) -> {ok, term()} | {error, term()}.
-spec all(#kura_query{from :: atom() | module() | undefined, select :: [atom() | term()] | {exprs, [term()]}, wheres :: [term()], joins :: [term()], order_bys :: [term()], group_bys :: [atom()], havings :: [term()], limit :: non_neg_integer() | undefined, offset :: non_neg_integer() | undefined, distinct :: boolean() | [atom()], lock :: binary() | undefined, prefix :: binary() | undefined, preloads :: [atom() | {atom(), list()}], ctes :: [{binary(), #kura_query{}}], combinations :: [{union | union_all | intersect | except, #kura_query{}}], include_deleted :: boolean()}) -> {ok, [map()]} | {error, term()}.
-spec delete(#kura_changeset{valid :: boolean(), schema :: module() | undefined, data :: map(), params :: map(), changes :: map(), errors :: [{atom(), binary()}], types :: #{atom() => kura_types:kura_type()}, required :: [atom()], action :: atom() | undefined, constraints :: [#kura_constraint{type :: unique | foreign_key | check | exclusion, constraint :: binary(), field :: atom(), message :: binary()}], assoc_changes :: #{atom() => #kura_changeset{} | [#kura_changeset{}]}, prepare :: [fun((#kura_changeset{}) -> #kura_changeset{})], optimistic_lock :: atom() | undefined}) -> {ok, map()} | {error, term()}.
-spec delete_all(#kura_query{from :: atom() | module() | undefined, select :: [atom() | term()] | {exprs, [term()]}, wheres :: [term()], joins :: [term()], order_bys :: [term()], group_bys :: [atom()], havings :: [term()], limit :: non_neg_integer() | undefined, offset :: non_neg_integer() | undefined, distinct :: boolean() | [atom()], lock :: binary() | undefined, prefix :: binary() | undefined, preloads :: [atom() | {atom(), list()}], ctes :: [{binary(), #kura_query{}}], combinations :: [{union | union_all | intersect | except, #kura_query{}}], include_deleted :: boolean()}) -> {ok, non_neg_integer()} | {error, term()}.
-spec exists(#kura_query{from :: atom() | module() | undefined, select :: [atom() | term()] | {exprs, [term()]}, wheres :: [term()], joins :: [term()], order_bys :: [term()], group_bys :: [atom()], havings :: [term()], limit :: non_neg_integer() | undefined, offset :: non_neg_integer() | undefined, distinct :: boolean() | [atom()], lock :: binary() | undefined, prefix :: binary() | undefined, preloads :: [atom() | {atom(), list()}], ctes :: [{binary(), #kura_query{}}], combinations :: [{union | union_all | intersect | except, #kura_query{}}], include_deleted :: boolean()}) -> {ok, boolean()} | {error, term()}.
-spec increment(module(), #{atom() => term()}, #{atom() => integer()}) -> {ok, map()} | {error, term()}.
Add to integer counters on one row atomically, creating the row if absent.
Key is the conflict target; Deltas the counters to accumulate. One
statement:
INSERT INTO quest_progress (player_id, quest_id, counter, inserted_at, updated_at)
VALUES ($1, $2, $3, now(), now())
ON CONFLICT (player_id, quest_id) DO UPDATE
SET counter = quest_progress.counter + EXCLUDED.counter, updated_at = now()
RETURNING *Neither half is expressible otherwise: update_all/2 SETs literals, and
kura's on_conflict overwrites with the excluded value rather than adding to
the stored one. A read-modify-write instead needs the wallet's advisory-lock
dance to stay correct under concurrency.
This is the whole of asobi's raw-SQL surface, and the shape is the point.
Every identifier in the statement is a field of Schema, matched against
Schema:fields() and rejected unless it is a plain SQL name; every caller
value is a bound parameter. So no caller-supplied string can reach the
statement, which is a promise a general query/2 could not make and the
reason there is not one.
Key must be a primary key or covered by a unique index, or Postgres rejects
the conflict target. The returned map is the database row, decoded but not
cast through the schema; use get/2 when the cast matters.
Timestamps are set when the schema declares them: inserted_at on the insert,
updated_at on both paths.
-spec insert(#kura_changeset{valid :: boolean(), schema :: module() | undefined, data :: map(), params :: map(), changes :: map(), errors :: [{atom(), binary()}], types :: #{atom() => kura_types:kura_type()}, required :: [atom()], action :: atom() | undefined, constraints :: [#kura_constraint{type :: unique | foreign_key | check | exclusion, constraint :: binary(), field :: atom(), message :: binary()}], assoc_changes :: #{atom() => #kura_changeset{} | [#kura_changeset{}]}, prepare :: [fun((#kura_changeset{}) -> #kura_changeset{})], optimistic_lock :: atom() | undefined}) -> {ok, map()} | {error, term()}.
-spec insert(#kura_changeset{valid :: boolean(), schema :: module() | undefined, data :: map(), params :: map(), changes :: map(), errors :: [{atom(), binary()}], types :: #{atom() => kura_types:kura_type()}, required :: [atom()], action :: atom() | undefined, constraints :: [#kura_constraint{type :: unique | foreign_key | check | exclusion, constraint :: binary(), field :: atom(), message :: binary()}], assoc_changes :: #{atom() => #kura_changeset{} | [#kura_changeset{}]}, prepare :: [fun((#kura_changeset{}) -> #kura_changeset{})], optimistic_lock :: atom() | undefined}, map()) -> {ok, map()} | {error, term()}.
-spec insert_all(module(), [map()]) -> {ok, non_neg_integer()} | {error, term()}.
-spec migration_apps() -> [atom()].
The applications kura runs migrations from, beyond asobi itself: every installed extension.
kura calls this optional kura_repo callback for multi-application migration
discovery, so extension migrations run inside core's transaction, under one
advisory lock.
kura adds the repo's own application and topologically sorts the result by
each application's OTP applications key, so this returns the extensions
only and does not restate an ordering kura already derives.
-spec otp_app() -> asobi.
-spec transaction(fun()) -> term().
-spec update(#kura_changeset{valid :: boolean(), schema :: module() | undefined, data :: map(), params :: map(), changes :: map(), errors :: [{atom(), binary()}], types :: #{atom() => kura_types:kura_type()}, required :: [atom()], action :: atom() | undefined, constraints :: [#kura_constraint{type :: unique | foreign_key | check | exclusion, constraint :: binary(), field :: atom(), message :: binary()}], assoc_changes :: #{atom() => #kura_changeset{} | [#kura_changeset{}]}, prepare :: [fun((#kura_changeset{}) -> #kura_changeset{})], optimistic_lock :: atom() | undefined}) -> {ok, map()} | {error, term()}.
-spec update_all(#kura_query{from :: atom() | module() | undefined, select :: [atom() | term()] | {exprs, [term()]}, wheres :: [term()], joins :: [term()], order_bys :: [term()], group_bys :: [atom()], havings :: [term()], limit :: non_neg_integer() | undefined, offset :: non_neg_integer() | undefined, distinct :: boolean() | [atom()], lock :: binary() | undefined, prefix :: binary() | undefined, preloads :: [atom() | {atom(), list()}], ctes :: [{binary(), #kura_query{}}], combinations :: [{union | union_all | intersect | except, #kura_query{}}], include_deleted :: boolean()}, map()) -> {ok, non_neg_integer()} | {error, term()}.