Bonfire.Common.Repo (Bonfire v1.0.0-social-rc.1.15)
View SourceMain Ecto Repo.
Note: functions are defined in Bonfire.Common.RepoTemplate
Summary
Functions
Callback implementation for Ecto.Repo.aggregate/3
.
Callback implementation for Ecto.Repo.aggregate/4
.
Callback implementation for Ecto.Repo.all/2
.
Callback implementation for Ecto.Repo.all_by/3
.
Callback implementation for Ecto.Repo.checked_out?/0
.
Callback implementation for Ecto.Repo.checkout/2
.
Callback implementation for Ecto.Repo.config/0
.
Callback implementation for Ecto.Repo.default_options/1
.
Callback implementation for Ecto.Repo.delete/2
.
Callback implementation for Ecto.Repo.delete!/2
.
Callback implementation for Ecto.Repo.delete_all/2
.
Forces all connections in the repo pool to disconnect within the given interval.
Callback implementation for Ecto.Repo.exists?/2
.
Executes an EXPLAIN statement or similar for the given query according to its kind and the adapter in the given repository.
Execute a query for one result where the primary key matches the given id, and return either an {:ok, result} tuple or a {:error, :not_found}.
Execute a query for multiple results given one or multiple IDs.
Execute a query for one result (using a keyword list to specify the key/value to query with), and return either an {:ok, result} tuple or a {:error, :not_found}.
Like single/1
, except on failure, adds an error to the changeset.
Callback implementation for Ecto.Repo.get/3
.
Callback implementation for Ecto.Repo.get!/3
.
Callback implementation for Ecto.Repo.get_by/3
.
Callback implementation for Ecto.Repo.get_by!/3
.
Callback implementation for Ecto.Repo.get_dynamic_repo/0
.
Callback implementation for Ecto.Repo.in_transaction?/0
.
Callback implementation for Ecto.Repo.insert/2
.
Callback implementation for Ecto.Repo.insert!/2
.
Callback implementation for Ecto.Repo.insert_all/3
.
Insert all or ignore a list of maps into a schema.
Insert or ignore a changeset or struct into a schema.
Insert or ignore a map (or iterate over a list of maps) into a schema.
Callback implementation for Ecto.Repo.insert_or_update/2
.
Callback implementation for Ecto.Repo.insert_or_update!/2
.
Callback implementation for Ecto.Repo.load/2
.
Execute a query for multiple results and return the results.
Execute a query for multiple results and return one page of results.
This uses the main implementation for pagination, which is cursor-based and powered by the Paginator
library.
Execute a query for one result and return either a result or a fallback value (nil
by default).
Add an ilike
clause to a query if the user query is safe.
Callback implementation for Ecto.Repo.one/2
.
Callback implementation for Ecto.Repo.one!/2
.
Different implementation for pagination using Scrivener (used by eg. rauversion).
Select and return only specific fields (specified as an atom or list of atoms)
Callback implementation for Ecto.Repo.preload/3
.
Callback implementation for Ecto.Repo.prepare_query/3
.
Callback implementation for Ecto.Repo.prepare_transaction/2
.
Like insert/1
, but understands remapping changeset errors to attr
names from config (and only config, no overrides at present!)
Callback implementation for Ecto.Repo.put_dynamic_repo/1
.
Like put/1
but for multiple changesets
Runs a custom SQL query.
Same as query/3
but returns result directly without :ok
tuple
and raises on invalid queries
Runs a custom SQL query that returns multiple results on the given repo.
Same as query_many/4
but returns result directly without :ok
tuple
and raises on invalid queries
Callback implementation for Ecto.Repo.reload/2
.
Callback implementation for Ecto.Repo.reload!/2
.
Callback implementation for Ecto.Repo.rollback/1
.
Execute a query for one result and return either an {:ok, result}
or {:error, :not_found}
tuple.
Executes raw SQL query.
Callback implementation for Ecto.Repo.start_link/1
.
Callback implementation for Ecto.Repo.stop/1
.
Callback implementation for Ecto.Repo.stream/2
.
Converts the given query to SQL according to its kind and the adapter in the given repository.
Can be used to log specific queries (by calling function) in production.
Callback implementation for Ecto.Repo.transact/2
.
Run a transaction, similar to Repo.transaction/1
, but it expects an ok or error
tuple. If an error tuple is returned, the transaction is aborted.
Callback implementation for Ecto.Repo.transaction/2
.
Callback implementation for Ecto.Repo.update/2
.
Callback implementation for Ecto.Repo.update!/2
.
Callback implementation for Ecto.Repo.update_all/3
.
Inserts or updates data in the database with upsert semantics.
Insert or update all entries with upsert semantics.
Functions
Callback implementation for Ecto.Repo.aggregate/3
.
Callback implementation for Ecto.Repo.aggregate/4
.
Callback implementation for Ecto.Repo.all/2
.
Callback implementation for Ecto.Repo.all_by/3
.
Callback implementation for Ecto.Repo.checked_out?/0
.
Callback implementation for Ecto.Repo.checkout/2
.
Callback implementation for Ecto.Repo.config/0
.
Callback implementation for Ecto.Repo.default_options/1
.
Callback implementation for Ecto.Repo.delete/2
.
Callback implementation for Ecto.Repo.delete!/2
.
Callback implementation for Ecto.Repo.delete_all/2
.
@spec disconnect_all(non_neg_integer(), opts :: Keyword.t()) :: :ok
Forces all connections in the repo pool to disconnect within the given interval.
Once this function is called, the pool will disconnect all of its connections
as they are checked in or as they are pinged. Checked in connections will be
randomly disconnected within the given time interval. Pinged connections are
immediately disconnected - as they are idle (according to :idle_interval
).
If the connection has a backoff configured (which is the case by default), disconnecting means an attempt at a new connection will be done immediately after, without starting a new process for each connection. However, if backoff has been disabled, the connection process will terminate. In such cases, disconnecting all connections may cause the pool supervisor to restart depending on the max_restarts/max_seconds configuration of the pool, so you will want to set those carefully.
Callback implementation for Ecto.Repo.exists?/2
.
@spec explain( :all | :update_all | :delete_all, Ecto.Queryable.t(), opts :: Keyword.t() ) :: String.t() | Exception.t() | [map()]
Executes an EXPLAIN statement or similar for the given query according to its kind and the adapter in the given repository.
Examples
# Postgres
iex> MyRepo.explain(:all, Post)
"Seq Scan on posts p0 (cost=0.00..12.12 rows=1 width=443)"
iex> Ecto.Adapters.SQL.explain(Repo, :all, Post)
"Seq Scan on posts p0 (cost=0.00..12.12 rows=1 width=443)"
# MySQL
iex> MyRepo.explain(:all, from(p in Post, where: p.title == "title")) |> IO.puts()
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
| 1 | SIMPLE | p0 | NULL | ALL | NULL | NULL | NULL | NULL | 1 | 100.0 | Using where |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
# Shared opts
iex> MyRepo.explain(:all, Post, analyze: true, timeout: 20_000)
"Seq Scan on posts p0 (cost=0.00..11.70 rows=170 width=443) (actual time=0.013..0.013 rows=0 loops=1)\nPlanning Time: 0.031 ms\nExecution Time: 0.021 ms"
It's safe to execute it for updates and deletes, no data change will be committed:
iex> MyRepo.explain(Repo, :update_all, from(p in Post, update: [set: [title: "new title"]]))
"Update on posts p0 (cost=0.00..11.70 rows=170 width=449)\n -> Seq Scan on posts p0 (cost=0.00..11.70 rows=170 width=449)"
This function is also available under the repository with name explain
:
iex> MyRepo.explain(:all, from(p in Post, where: p.title == "title"))
"Seq Scan on posts p0 (cost=0.00..12.12 rows=1 width=443)\n Filter: ((title)::text = 'title'::text)"
Options
Built-in adapters support passing opts
to the EXPLAIN statement according to the following:
Adapter | Supported opts |
---|---|
Postgrex | analyze , verbose , costs , settings , buffers , timing , summary , format , plan |
MyXQL | format |
All options except format
are boolean valued and default to false
.
The allowed format
values are :map
, :yaml
, and :text
:
:map
is the deserialized JSON encoding.:yaml
and:text
return the result as a string.
The built-in adapters support the following formats:
- Postgrex:
:map
,:yaml
and:text
- MyXQL:
:map
and:text
The :plan
option in Postgrex can take the values :custom
or :fallback_generic
. When :custom
is specified, the explain plan generated will consider the specific values of the query parameters
that are supplied. When using :fallback_generic
, the specific values of the query parameters will
be ignored. :fallback_generic
does not use PostgreSQL's built-in support for a generic explain
plan (available as of PostgreSQL 16), but instead uses a special implementation that works for PostgreSQL
versions 12 and above. Defaults to :custom
.
Any other value passed to opts
will be forwarded to the underlying adapter query function, including
shared Repo options such as :timeout
. Non built-in adapters may have specific behaviour and you should
consult their documentation for more details.
For version compatibility, please check your database's documentation:
- Postgrex: PostgreSQL doc.
- MyXQL: MySQL doc.
Execute a query for one result where the primary key matches the given id, and return either an {:ok, result} tuple or a {:error, :not_found}.
Examples
iex> fetch(User, 1)
{:ok, %User{}}
iex> fetch(User, 999)
{:error, :not_found}
Execute a query for multiple results given one or multiple IDs.
Examples
iex> fetch_all(User, [1, 2, 3])
[%User{}, %User{}, %User{}]
iex> fetch_all(User, 999)
[]
Execute a query for one result (using a keyword list to specify the key/value to query with), and return either an {:ok, result} tuple or a {:error, :not_found}.
Examples
iex> fetch_by(User, name: "Alice")
{:ok, %User{}}
iex> fetch_by(User, name: "Nonexistent")
{:error, :not_found}
Like single/1
, except on failure, adds an error to the changeset.
Examples
iex> changeset = %Ecto.Changeset{}
iex> find(from u in User, where: u.id == 1, changeset)
{:ok, %User{}}
iex> changeset = %Ecto.Changeset{}
iex> find(from u in User, where: u.id == 999, changeset)
{:error, %Ecto.Changeset{}}
Callback implementation for Ecto.Repo.get/3
.
Callback implementation for Ecto.Repo.get!/3
.
Callback implementation for Ecto.Repo.get_by/3
.
Callback implementation for Ecto.Repo.get_by!/3
.
Callback implementation for Ecto.Repo.get_dynamic_repo/0
.
Callback implementation for Ecto.Repo.in_transaction?/0
.
Callback implementation for Ecto.Repo.insert/2
.
Callback implementation for Ecto.Repo.insert!/2
.
Callback implementation for Ecto.Repo.insert_all/3
.
Insert all or ignore a list of maps into a schema.
Examples
iex> insert_all_or_ignore(MySchema, [%{field: "value1"}, %{field: "value2"}])
{:ok, _result}
Insert or ignore a changeset or struct into a schema.
Examples
iex> insert_or_ignore(%Ecto.Changeset{})
{:ok, _result}
iex> insert_or_ignore(%MySchema{field: "value"})
{:ok, _result}
Insert or ignore a map (or iterate over a list of maps) into a schema.
Examples
iex> insert_or_ignore(MySchema, %{field: "value"})
[{:ok, _result}]
iex> insert_or_ignore(MySchema, [%{field: "value1"}, %{field: "value2"}])
[{:ok, _result}]
Callback implementation for Ecto.Repo.insert_or_update/2
.
Callback implementation for Ecto.Repo.insert_or_update!/2
.
Callback implementation for Ecto.Repo.load/2
.
Execute a query for multiple results and return the results.
Examples
iex> many(from u in User)
[%User{}, %User{}]
iex> many(from u in User, return: :query)
#Ecto.Query<...>
Execute a query for multiple results and return one page of results.
This uses the main implementation for pagination, which is cursor-based and powered by the Paginator
library.
Examples
iex> many_paginated(User, [limit: 10])
%Paginator.Page{}
Execute a query for one result and return either a result or a fallback value (nil
by default).
Examples
iex> maybe_one(from u in User, where: u.id == 1)
%User{}
iex> maybe_one(from u in User, where: u.id == 999, "fallback")
"fallback"
Add an ilike
clause to a query if the user query is safe.
Examples
iex> maybe_where_ilike(Needle.Pointer, :id, "Alice")
#Ecto.Query<...>
iex> maybe_where_ilike(Needle.Pointer, :id, "Al%ice")
Needle.Pointer
# ^ unchanged due to unsafe query
Callback implementation for Ecto.Repo.one/2
.
Callback implementation for Ecto.Repo.one!/2
.
Different implementation for pagination using Scrivener (used by eg. rauversion).
Examples
iex> paginate(User, page: 1, page_size: 10)
%Scrivener.Page{}
Select and return only specific fields (specified as an atom or list of atoms)
Examples
> pluck(:id)
[id1, id2]
> pluck([:id, :inserted_at])
[%{id: id1, inserted_at: _}, %{id: id2, inserted_at: _}]
Callback implementation for Ecto.Repo.preload/3
.
Callback implementation for Ecto.Repo.prepare_query/3
.
Callback implementation for Ecto.Repo.prepare_transaction/2
.
Like insert/1
, but understands remapping changeset errors to attr
names from config (and only config, no overrides at present!)
Examples
iex> changeset = %Ecto.Changeset{valid?: false}
iex> put(changeset)
{:error, %Ecto.Changeset{}}
Callback implementation for Ecto.Repo.put_dynamic_repo/1
.
Like put/1
but for multiple changesets
Examples
iex> changesets = [%{valid?: true}, %{valid?: false}]
iex> put_many(changesets)
{:error, [%{valid?: false}]}
iex> changesets = [%{valid?: true}, %{valid?: true}]
iex> put_many(changesets)
{:ok, _result}
@spec query(iodata(), Ecto.Adapters.SQL.query_params(), Keyword.t()) :: {:ok, Ecto.Adapters.SQL.query_result()} | {:error, Exception.t()}
Runs a custom SQL query.
If the query was successful, it will return an :ok
tuple containing
a map with at least two keys:
:num_rows
- the number of rows affected:rows
- the result set as a list.nil
may be returned instead of the list if the command does not yield any row as result (but still yields the number of affected rows, like adelete
command without returning would)
Options
:log
- When false, does not log the query:timeout
- Execute request timeout, accepts::infinity
(default:15000
);
Examples
iex> MyRepo.query("SELECT $1::integer + $2", [40, 2])
{:ok, %{rows: [[42]], num_rows: 1}}
iex> Ecto.Adapters.SQL.query(MyRepo, "SELECT $1::integer + $2", [40, 2])
{:ok, %{rows: [[42]], num_rows: 1}}
@spec query!(iodata(), Ecto.Adapters.SQL.query_params(), Keyword.t()) :: Ecto.Adapters.SQL.query_result()
Same as query/3
but returns result directly without :ok
tuple
and raises on invalid queries
@spec query_many(iodata(), Ecto.Adapters.SQL.query_params(), Keyword.t()) :: {:ok, [Ecto.Adapters.SQL.query_result()]} | {:error, Exception.t()}
Runs a custom SQL query that returns multiple results on the given repo.
In case of success, it must return an :ok
tuple containing a list of
maps with at least two keys:
:num_rows
- the number of rows affected:rows
- the result set as a list.nil
may be returned instead of the list if the command does not yield any row as result (but still yields the number of affected rows, like adelete
command without returning would)
Options
:log
- When false, does not log the query:timeout
- Execute request timeout, accepts::infinity
(default:15000
);
Examples
iex> MyRepo.query_many("SELECT $1; SELECT $2;", [40, 2])
{:ok, [%{rows: [[40]], num_rows: 1}, %{rows: [[2]], num_rows: 1}]}
iex> Ecto.Adapters.SQL.query_many(MyRepo, "SELECT $1; SELECT $2;", [40, 2])
{:ok, [%{rows: [[40]], num_rows: 1}, %{rows: [[2]], num_rows: 1}]}
@spec query_many!(iodata(), Ecto.Adapters.SQL.query_params(), Keyword.t()) :: [ Ecto.Adapters.SQL.query_result() ]
Same as query_many/4
but returns result directly without :ok
tuple
and raises on invalid queries
Callback implementation for Ecto.Repo.reload/2
.
Callback implementation for Ecto.Repo.reload!/2
.
Callback implementation for Ecto.Repo.rollback/1
.
Execute a query for one result and return either an {:ok, result}
or {:error, :not_found}
tuple.
Examples
iex> single(from u in User, where: u.id == 1)
{:ok, %User{}}
iex> single(from u in User, where: u.id == 999)
{:error, :not_found}
Executes raw SQL query.
Examples
> YourModule.sql("SELECT * FROM pointers")
Callback implementation for Ecto.Repo.start_link/1
.
Callback implementation for Ecto.Repo.stop/1
.
Callback implementation for Ecto.Repo.stream/2
.
@spec to_sql(:all | :update_all | :delete_all, Ecto.Queryable.t()) :: {String.t(), Ecto.Adapters.SQL.query_params()}
Converts the given query to SQL according to its kind and the adapter in the given repository.
Examples
The examples below are meant for reference. Each adapter will return a different result:
iex> MyRepo.to_sql(:all, Post)
{"SELECT p.id, p.title, p.inserted_at, p.created_at FROM posts as p", []}
iex> MyRepo.to_sql(:update_all, from(p in Post, update: [set: [title: ^"hello"]]))
{"UPDATE posts AS p SET title = $1", ["hello"]}
iex> Ecto.Adapters.SQL.to_sql(:all, MyRepo, Post)
{"SELECT p.id, p.title, p.inserted_at, p.created_at FROM posts as p", []}
Can be used to log specific queries (by calling function) in production.
Examples
iex> trace(fn -> Repo.all(User) end)
[%User{}, %User{}]
Callback implementation for Ecto.Repo.transact/2
.
Run a transaction, similar to Repo.transaction/1
, but it expects an ok or error
tuple. If an error tuple is returned, the transaction is aborted.
Examples
iex> transact_with(fn -> {:ok, "success"} end)
"success"
iex> transact_with(fn -> {:error, "failure"} end)
** (Ecto.RollbackError) Rolling back the DB transaction, error reason: failure
Callback implementation for Ecto.Repo.transaction/2
.
Callback implementation for Ecto.Repo.update/2
.
Callback implementation for Ecto.Repo.update!/2
.
Callback implementation for Ecto.Repo.update_all/3
.
Inserts or updates data in the database with upsert semantics.
cs
- The changeset or schema to insert or update.keys_or_attrs_to_update
- A list of keys or a map of attributes to update.conflict_target
- The column(s) or constraint to check for conflicts, defaults to[:id]
.
Examples
iex> upsert(%Ecto.Changeset{}, [:field1, :field2])
{:ok, _result}
iex> upsert(%Ecto.Changeset{}, %{field1: "value"})
{:ok, _result}
Insert or update all entries with upsert semantics.
schema
- The schema or table name to insert or update.data
- A list of maps containing the data to insert or update.conflict_target
- The column(s) or constraint to check for conflicts, defaults to[:id]
.
Examples
iex> upsert_all(User, [%{id: 1, name: "Alice"}, %{id: 2, name: "Bob"}])
{:ok, _result}
iex> upsert_all(User, [%{id: 1, name: "Alice Updated"}], [:id])
{:ok, _result}