Browse Source

return error tuple when an EXIT message is received

Will 16 years ago
parent
commit
7fd23f9030
3 changed files with 58 additions and 9 deletions
  1. 9 3
      README
  2. 12 6
      src/pgsql.erl
  3. 37 0
      test_src/pgsql_tests.erl

+ 9 - 3
README

@@ -24,7 +24,7 @@ Erlang PostgreSQL Database Client
 * Simple Query
 * Simple Query
 
 
   {ok, Columns, Rows} = pgsql:squery(C, Sql).
   {ok, Columns, Rows} = pgsql:squery(C, Sql).
-  {error, #error{}}   = pgsql:squery(C, InvalidSql).
+  {error, Error}      = pgsql:squery(C, InvalidSql).
 
 
   Columns       - list of column records, see pgsql.hrl for definition.
   Columns       - list of column records, see pgsql.hrl for definition.
   Rows          - list of tuples, one for each row.
   Rows          - list of tuples, one for each row.
@@ -38,7 +38,7 @@ Erlang PostgreSQL Database Client
   {ok, Count}                = pgsql:equery(C, "update ...", [Parameters]).
   {ok, Count}                = pgsql:equery(C, "update ...", [Parameters]).
   {ok, Count, Columns, Rows} = pgsql:equery(C, "insert ... returning ...", [Parameters]).
   {ok, Count, Columns, Rows} = pgsql:equery(C, "insert ... returning ...", [Parameters]).
 
 
-  {error, #error{}}          = pgsql:equery(C, "invalid SQL", [Parameters]).
+  {error, Error}             = pgsql:equery(C, "invalid SQL", [Parameters]).
 
 
   Parameters    - optional list of values to be bound to $1, $2, $3, etc.
   Parameters    - optional list of values to be bound to $1, $2, $3, etc.
 
 
@@ -79,7 +79,7 @@ Erlang PostgreSQL Database Client
   ok = pgsql:close(C, statement | portal, Name).
   ok = pgsql:close(C, statement | portal, Name).
   ok = pgsql:sync(C).
   ok = pgsql:sync(C).
 
 
-  All functions return {error, #error{}} when an error occurs.
+  All functions return {error, Error} when an error occurs.
 
 
 * Data Representation
 * Data Representation
 
 
@@ -99,3 +99,9 @@ Erlang PostgreSQL Database Client
   bytea       = <<1, 2>>
   bytea       = <<1, 2>>
 
 
   record      = {int2, time, text, ...} (decode only)
   record      = {int2, time, text, ...} (decode only)
+
+* Errors
+
+  Errors originating from the PostgreSQL backend are returned as {error, #error{}},
+  see pgsql.hrl for the record definition. epgsql may also return {error, Atom}
+  where Atom is 'timeout' or 'closed'.

+ 12 - 6
src/pgsql.erl

@@ -112,17 +112,19 @@ with_transaction(C, F) ->
 %% -- internal functions --
 %% -- internal functions --
 
 
 receive_result(C, Result) ->
 receive_result(C, Result) ->
-    case receive_result(C, [], []) of
+    try receive_result(C, [], []) of
         done    -> Result;
         done    -> Result;
-        timeout -> {error, timeout};
         R       -> receive_result(C, R)
         R       -> receive_result(C, R)
+    catch
+        throw:E -> E
     end.
     end.
 
 
 receive_results(C, Results) ->
 receive_results(C, Results) ->
-    case receive_result(C, [], []) of
+    try receive_result(C, [], []) of
         done    -> lists:reverse(Results);
         done    -> lists:reverse(Results);
-        timeout -> lists:reverse([{error, timeout} | Results]);
         R       -> receive_results(C, [R | Results])
         R       -> receive_results(C, [R | Results])
+    catch
+        throw:E -> E
     end.
     end.
 
 
 receive_result(C, Cols, Rows) ->
 receive_result(C, Cols, Rows) ->
@@ -145,7 +147,9 @@ receive_result(C, Cols, Rows) ->
         {pgsql, C, done} ->
         {pgsql, C, done} ->
             done;
             done;
         {pgsql, C, timeout} ->
         {pgsql, C, timeout} ->
-            timeout
+            throw({error, timeout});
+        {'EXIT', C, _Reason} ->
+            throw({error, closed})
     end.
     end.
 
 
 receive_extended_result(C)->
 receive_extended_result(C)->
@@ -169,5 +173,7 @@ receive_extended_result(C, Rows) ->
         {pgsql, C, {notice, _N}} ->
         {pgsql, C, {notice, _N}} ->
             receive_extended_result(C, Rows);
             receive_extended_result(C, Rows);
         {pgsql, C, timeout} ->
         {pgsql, C, timeout} ->
-            {error, timeout}
+            {error, timeout};
+        {'EXIT', C, _Reason} ->
+            {error, closed}
     end.
     end.

+ 37 - 0
test_src/pgsql_tests.erl

@@ -431,6 +431,43 @@ execute_timeout_test() ->
       end,
       end,
       [{timeout, 10}]).
       [{timeout, 10}]).
 
 
+connection_closed_test() ->
+    P = self(),
+    F = fun() ->
+                process_flag(trap_exit, true),
+                {ok, C} = pgsql:connect(?host, [{port, ?port}]),
+                P ! {connected, C},
+                receive
+                    Any -> P ! Any
+                end
+        end,
+    spawn_link(F),
+    receive
+        {connected, C} ->
+            timer:sleep(100),
+            pgsql:close(C),
+            {'EXIT', C, _} = receive R -> R end
+    end,
+    flush().
+
+active_connection_closed_test() ->
+    P = self(),
+    F = fun() ->
+                process_flag(trap_exit, true),
+                {ok, C} = pgsql:connect(?host, [{port, ?port}]),
+                P ! {connected, C},
+                R = pgsql:squery(C, "select pg_sleep(10)"),
+                P ! R
+        end,
+    spawn_link(F),
+    receive
+        {connected, C} ->
+            timer:sleep(100),
+            pgsql:close(C),
+            {error, closed} = receive R -> R end
+    end,
+    flush().
+
 %% -- run all tests --
 %% -- run all tests --
 
 
 run_tests() ->
 run_tests() ->