File postgrex-0.13.5-git.patch of Package postgrex

diff --git a/lib/postgrex.ex b/lib/postgrex.ex
index c739950..4a18648 100644
--- a/lib/postgrex.ex
+++ b/lib/postgrex.ex
@@ -62,8 +62,10 @@ defmodule Postgrex do
     options, this option must be included with all requests contacting the pool
     if not `DBConnection.Connection` (default: `DBConnection.Connection`);
     * `:types` - The types module to use, see `Postgrex.TypeModule`, this
-    option is only required when using custom encoding or decoding (default:
-    `Postgrex.DefaultTypes`);
+      option is only required when using custom encoding or decoding (default:
+      `Postgrex.DefaultTypes`);
+    * `:disconnect_on_error_codes` - List of error code atoms that when encountered
+      will disconnect the connection (default: `[]`);
 
   `Postgrex` uses the `DBConnection` framework and supports all `DBConnection`
   options like `:idle`, `:after_connect` etc.
diff --git a/lib/postgrex/protocol.ex b/lib/postgrex/protocol.ex
index b56bf9a..9c6c29f 100644
--- a/lib/postgrex/protocol.ex
+++ b/lib/postgrex/protocol.ex
@@ -20,7 +20,7 @@ defmodule Postgrex.Protocol do
 
   defstruct [sock: nil, connection_id: nil, connection_key: nil, peer: nil,
              types: nil, null: nil, timeout: nil, parameters: %{}, queries: nil,
-             postgres: :idle, transactions: :naive, buffer: nil]
+             postgres: :idle, transactions: :naive, buffer: nil, disconnect_on_error_codes: []]
 
   @type state :: %__MODULE__{sock: {module, any},
                              connection_id: nil | pos_integer,
@@ -33,7 +33,8 @@ defmodule Postgrex.Protocol do
                              queries: nil | :ets.tid,
                              postgres: :idle | :transaction | :failed,
                              transactions: :strict | :naive,
-                             buffer: nil | binary | :active_once}
+                             buffer: nil | binary | :active_once,
+                             disconnect_on_error_codes: [atom()]}
   @type notify :: ((binary, binary) -> any)
 
   @reserved_prefix "POSTGREX_"
@@ -92,8 +93,14 @@ defmodule Postgrex.Protocol do
         :unnamed -> :unnamed
       end
 
-    s = %__MODULE__{timeout: timeout, postgres: :idle,
-                    transactions: transactions}
+    disconnect_on_error_codes = opts[:disconnect_on_error_codes] || []
+
+    s = %__MODULE__{
+      timeout: timeout,
+      postgres: :idle,
+      transactions: transactions,
+      disconnect_on_error_codes: disconnect_on_error_codes
+    }
 
     types_key = if types_mod, do: {host, port, Keyword.fetch!(opts, :database)}
     status = %{opts: opts, types_mod: types_mod, types_key: types_key,
@@ -218,7 +225,7 @@ defmodule Postgrex.Protocol do
       execute when is_function(execute, 4) ->
         %{buffer: buffer} = s
         s = %{s | buffer: nil}
-        execute.(s, status, params, buffer)
+        execute.(s, status, params, buffer) |> maybe_disconnect()
       {kind, _, _} = error when kind in [:error, :disconnect] ->
         error
     end
@@ -1187,6 +1194,7 @@ defmodule Postgrex.Protocol do
         lock_error(s, :bind, query)
     end
   end
+
   defp bind(s, _, %Query{name: @reserved_prefix <> _} = query, _, _) do
     reserved_error(query, s)
   end
@@ -1262,6 +1270,21 @@ defmodule Postgrex.Protocol do
     end
   end
 
+  defp maybe_disconnect({:error, _, %{disconnect_on_error_codes: []}} = result), do: result
+
+  defp maybe_disconnect({:error,
+         %Postgrex.Error{postgres: %{code: code}} = error,
+         %{disconnect_on_error_codes: codes} = state
+       } = result) do
+    if code in codes do
+      {:disconnect, error, state}
+    else
+      result
+    end
+  end
+
+  defp maybe_disconnect(other), do: other
+
   defp savepoint_msgs(s, :sync, msgs) do
     savepoint = transaction_msgs(s, ["SAVEPOINT postgrex_query"])
     release = transaction_msgs(s, ["RELEASE SAVEPOINT postgrex_query", :sync])
diff --git a/mix.lock b/mix.lock
index d3f4988..dd8b540 100644
--- a/mix.lock
+++ b/mix.lock
@@ -2,6 +2,9 @@
   "connection": {:hex, :connection, "1.0.4", "a1cae72211f0eef17705aaededacac3eb30e6625b04a6117c1b2db6ace7d5976", [:mix], [], "hexpm"},
   "db_connection": {:hex, :db_connection, "1.1.0", "b2b88db6d7d12f99997b584d09fad98e560b817a20dab6a526830e339f54cdb3", [:mix], [{:connection, "~> 1.0.2", [hex: :connection, repo: "hexpm", optional: false]}, {:poolboy, "~> 1.5", [hex: :poolboy, repo: "hexpm", optional: true]}, {:sbroker, "~> 1.0", [hex: :sbroker, repo: "hexpm", optional: true]}], "hexpm"},
   "decimal": {:hex, :decimal, "1.3.1", "157b3cedb2bfcb5359372a7766dd7a41091ad34578296e951f58a946fcab49c6", [:mix], [], "hexpm"},
-  "earmark": {:hex, :earmark, "1.2.4", "99b637c62a4d65a20a9fb674b8cffb8baa771c04605a80c911c4418c69b75439", [:mix], [], "hexpm"},
-  "ex_doc": {:hex, :ex_doc, "0.18.1", "37c69d2ef62f24928c1f4fdc7c724ea04aecfdf500c4329185f8e3649c915baf", [:mix], [{:earmark, "~> 1.1", [hex: :earmark, repo: "hexpm", optional: false]}], "hexpm"},
+  "earmark": {:hex, :earmark, "1.2.6", "b6da42b3831458d3ecc57314dff3051b080b9b2be88c2e5aa41cd642a5b044ed", [:mix], [], "hexpm"},
+  "ex_doc": {:hex, :ex_doc, "0.19.1", "519bb9c19526ca51d326c060cb1778d4a9056b190086a8c6c115828eaccea6cf", [:mix], [{:earmark, "~> 1.1", [hex: :earmark, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.7", [hex: :makeup_elixir, repo: "hexpm", optional: false]}], "hexpm"},
+  "makeup": {:hex, :makeup, "0.5.5", "9e08dfc45280c5684d771ad58159f718a7b5788596099bdfb0284597d368a882", [:mix], [{:nimble_parsec, "~> 0.4", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm"},
+  "makeup_elixir": {:hex, :makeup_elixir, "0.10.0", "0f09c2ddf352887a956d84f8f7e702111122ca32fbbc84c2f0569b8b65cbf7fa", [:mix], [{:makeup, "~> 0.5.5", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm"},
+  "nimble_parsec": {:hex, :nimble_parsec, "0.4.0", "ee261bb53214943679422be70f1658fff573c5d0b0a1ecd0f18738944f818efe", [:mix], [], "hexpm"},
 }
diff --git a/test/transaction_test.exs b/test/transaction_test.exs
index 2dff0fc..0007a6b 100644
--- a/test/transaction_test.exs
+++ b/test/transaction_test.exs
@@ -10,8 +10,16 @@ defmodule TransactionTest do
         :transaction -> :strict
         :savepoint   -> :naive
       end
-    opts = [ database: "postgrex_test", transactions: transactions, idle: :active,
-             backoff_type: :stop, prepare: context[:prepare] || :named]
+
+    opts = [
+      database: "postgrex_test",
+      transactions: transactions,
+      idle: :active,
+      backoff_type: :stop,
+      prepare: context[:prepare] || :named,
+      disconnect_on_error_codes: context[:disconnect_on_error_codes] || []
+    ]
+
     {:ok, pid} = P.start_link(opts)
     {:ok, [pid: pid]}
   end
@@ -123,6 +131,44 @@ defmodule TransactionTest do
     assert query("SELECT 42", []) == [[42]]
   end
 
+  @tag mode: :transaction
+  @tag disconnect_on_error_codes: [:read_only_sql_transaction]
+  test "transaction read-only only error disconnects with prepare and execute", context do
+    Process.flag(:trap_exit, true)
+
+    assert transaction(fn conn  ->
+      P.query!(conn, "SET TRANSACTION READ ONLY", []).connection_id
+
+      {:ok, query} = P.prepare(conn, "query_1", "insert into uniques values (1);", [])
+
+      assert capture_log(fn ->
+        {:error, %Postgrex.Error{postgres: %{code: :read_only_sql_transaction}}} =
+          P.execute(conn, query, [])
+
+        pid = context[:pid]
+        assert_receive {:EXIT, ^pid, {:shutdown, _}}
+      end) =~ "disconnected: ** (Postgrex.Error) ERROR 25006 (read_only_sql_transaction)"
+    end)
+  end
+
+  @tag mode: :transaction
+  @tag disconnect_on_error_codes: [:read_only_sql_transaction]
+  test "transaction read-only only error disconnects with prepare, execute, and close", context do
+    Process.flag(:trap_exit, true)
+
+    assert transaction(fn conn  ->
+      P.query!(conn, "SET TRANSACTION READ ONLY", []).connection_id
+
+      assert capture_log(fn ->
+        {:error, %Postgrex.Error{postgres: %{code: :read_only_sql_transaction}}} =
+          P.query(conn, "insert into uniques values (1);", [])
+
+        pid = context[:pid]
+        assert_receive {:EXIT, ^pid, {:shutdown, _}}
+      end) =~ "disconnected: ** (Postgrex.Error) ERROR 25006 (read_only_sql_transaction)"
+    end)
+  end
+
   @tag mode: :savepoint
   test "savepoint transaction releases savepoint", context do
     :ok = query("BEGIN", [])
openSUSE Build Service is sponsored by