Packages
ecto
0.7.1
3.14.1
3.14.0
3.13.6
3.13.5
3.13.4
3.13.3
3.13.2
3.13.1
3.13.0
3.12.6
3.12.5
3.12.4
3.12.3
3.12.2
3.12.1
3.12.0
3.11.2
3.11.1
3.11.0
3.10.3
3.10.2
3.10.1
3.10.0
3.9.6
3.9.5
3.9.4
3.9.3
3.9.2
3.9.1
3.9.0
3.8.4
3.8.3
3.8.2
3.8.1
3.8.0
3.7.2
3.7.1
3.7.0
3.6.2
3.6.1
3.6.0
3.5.8
3.5.7
3.5.6
3.5.5
3.5.4
3.5.3
3.5.2
3.5.1
3.5.0
3.5.0-rc.1
3.5.0-rc.0
3.4.6
3.4.5
3.4.4
3.4.3
3.4.2
3.4.1
3.4.0
3.3.4
3.3.3
3.3.2
3.3.1
3.3.0
3.2.5
3.2.4
3.2.3
3.2.2
3.2.1
3.2.0
3.1.7
3.1.6
3.1.5
3.1.4
3.1.3
3.1.2
3.1.1
3.1.0
3.0.9
3.0.8
3.0.7
3.0.6
3.0.5
3.0.4
3.0.3
3.0.2
3.0.1
3.0.0
3.0.0-rc.1
3.0.0-rc.0
2.2.12
2.2.11
2.2.10
2.2.9
2.2.8
2.2.7
2.2.6
2.2.5
2.2.4
2.2.3
2.2.2
2.2.1
2.2.0
2.2.0-rc.1
2.2.0-rc.0
2.1.6
2.1.5
2.1.4
2.1.3
2.1.2
2.1.1
2.1.0
2.1.0-rc.5
2.1.0-rc.4
2.1.0-rc.3
2.1.0-rc.2
2.1.0-rc.1
2.1.0-rc.0
2.0.6
2.0.5
2.0.4
2.0.3
2.0.2
2.0.1
2.0.0
2.0.0-rc.6
2.0.0-rc.5
2.0.0-rc.4
2.0.0-rc.3
2.0.0-rc.2
2.0.0-rc.1
2.0.0-rc.0
2.0.0-beta.2
2.0.0-beta.1
2.0.0-beta.0
1.1.9
1.1.8
1.1.7
1.1.6
1.1.5
1.1.4
1.1.3
1.1.2
1.1.1
1.1.0
1.0.7
1.0.6
1.0.5
1.0.4
1.0.3
1.0.2
1.0.1
1.0.0
0.16.0
0.15.0
0.14.3
0.14.2
0.14.1
0.14.0
0.13.1
0.13.0
0.12.1
0.12.0
0.12.0-rc
0.11.3
0.11.2
0.11.1
0.11.0
0.10.3
0.10.2
0.10.1
0.10.0
0.9.0
0.8.1
0.8.0
0.7.2
0.7.1
0.7.0
0.6.0
0.5.1
0.5.0
0.4.0
0.3.0
0.2.8
0.2.7
0.2.6
0.2.5
0.2.4
0.2.3
0.2.2
0.2.1
0.2.0
0.1.0
A toolkit for data mapping and language integrated query for Elixir
Current section
Files
Jump to
Current section
Files
lib/ecto/adapters/sql/worker.ex
defmodule Ecto.Adapters.SQL.Worker do
@moduledoc false
use GenServer
def start_link({module, args}) do
GenServer.start_link(__MODULE__, {module, args})
end
def start({module, args}) do
GenServer.start(__MODULE__, {module, args})
end
def query!(worker, sql, params, opts) do
case GenServer.call(worker, :query, opts[:timeout]) do
{:ok, {module, conn}} ->
case module.query(conn, sql, params, opts) do
{:ok, res} -> res
{:error, err} -> raise err
end
{:error, err} ->
raise err
end
end
def begin!(worker, opts) do
case GenServer.call(worker, {:begin, opts}, opts[:timeout]) do
:ok -> :ok
{:error, err} -> raise err
end
end
def commit!(worker, opts) do
case GenServer.call(worker, {:commit, opts}, opts[:timeout]) do
:ok -> :ok
{:error, err} -> raise err
end
end
def rollback!(worker, opts) do
case GenServer.call(worker, {:rollback, opts}, opts[:timeout]) do
:ok -> :ok
{:error, err} -> raise err
end
end
def link_me(worker) do
GenServer.cast(worker, {:link, self})
end
def unlink_me(worker) do
GenServer.cast(worker, {:unlink, self})
end
def init({module, params}) do
Process.flag(:trap_exit, true)
lazy? = Keyword.get(params, :lazy, true)
unless lazy? do
case module.connect(params) do
{:ok, conn} ->
conn = conn
_ ->
:ok
end
end
{:ok, %{conn: conn, params: params, link: nil, transactions: 0, module: module}}
end
def handle_cast({:link, pid}, %{link: nil} = s) do
Process.link(pid)
{:noreply, %{s | link: pid}}
end
def handle_cast({:unlink, pid}, %{link: pid} = s) do
Process.unlink(pid)
{:noreply, %{s | link: nil}}
end
# Connection is disconnected, reconnect before continuing
def handle_call(request, from, %{conn: nil, params: params, module: module} = s) do
case module.connect(params) do
{:ok, conn} ->
handle_call(request, from, %{s | conn: conn})
{:error, err} ->
{:reply, {:error, err}, s}
end
end
def handle_call(:query, _from, %{conn: conn, module: module} = s) do
{:reply, {:ok, {module, conn}}, s}
end
def handle_call({:begin, opts}, _from, s) do
%{conn: conn, transactions: trans, module: module} = s
sql =
if trans == 0 do
module.begin_transaction
else
module.savepoint "ecto_#{trans}"
end
case module.query(conn, sql, [], opts) do
{:ok, _} ->
{:reply, :ok, %{s | transactions: trans + 1}}
{:error, _} = err ->
{:stop, err, err, s}
end
end
def handle_call({:commit, opts}, _from, %{transactions: trans} = s) when trans >= 1 do
%{conn: conn, module: module} = s
reply =
case trans do
1 -> module.query(conn, module.commit, [], opts)
_ -> {:ok, {[], 0}}
end
case reply do
{:ok, _} ->
{:reply, :ok, %{s | transactions: trans - 1}}
{:error, _} = err ->
{:stop, err, err, s}
end
end
def handle_call({:rollback, opts}, _from, %{transactions: trans} = s) when trans >= 1 do
%{conn: conn, module: module} = s
sql =
case trans do
1 -> module.rollback
_ -> module.rollback_to_savepoint "ecto_#{trans-1}"
end
case module.query(conn, sql, [], opts) do
{:ok, _} ->
{:reply, :ok, %{s | transactions: trans - 1}}
{:error, _} = err ->
{:stop, err, err, s}
end
end
# If there are no transactions, there is no state, so we just ignore the connection crash.
def handle_info({:EXIT, conn, _reason}, %{conn: conn, transactions: 0} = s) do
{:noreply, %{s | conn: nil}}
end
# If we have a transaction, we need to crash, notifying all interested.
def handle_info({:EXIT, conn, reason}, %{conn: conn} = s) do
{:stop, reason, %{s | conn: nil}}
end
# If the linked process crashed, assume stale connection and close it.
def handle_info({:EXIT, link, _reason}, %{conn: conn, link: link, module: module} = s) do
conn && module.disconnect(conn)
{:noreply, %{s | link: nil, conn: nil}}
end
def handle_info(_info, s) do
{:noreply, s}
end
def terminate(_reason, %{conn: conn, module: module}) do
conn && module.disconnect(conn)
end
end