Просмотр исходного кода

Handle skipped commands in epgsql/a/i:execute_batch

Enid Gjoleka 5 лет назад
Родитель
Сommit
5b16d12ff2
3 измененных файлов с 17 добавлено и 9 удалено
  1. 4 2
      README.md
  2. 6 4
      src/commands/epgsql_cmd_batch.erl
  3. 7 3
      test/epgsql_SUITE.erl

+ 4 - 2
README.md

@@ -430,8 +430,10 @@ epgsql:execute_batch(C, "INSERT INTO account (name, age) VALUES ($1, $2) RETURNI
                      [ ["Joe", 35], ["Paul", 26], ["Mary", 24] ]).
 ```
 
-In case one of the batch items causes an error, the result returned for this particular
-item will be `{error, #error{}}` and no more results will be produced.
+In case one of the batch items causes an error, the returned result will be
+`{error, [{error, #error{}} | {error, skipped}]}`. The first element of the list
+will represent the received error. The remaining elements will represent
+every skipped command.
 
 `epgsqla:execute_batch/{2,3}` sends `{C, Ref, Results}`
 

+ 6 - 4
src/commands/epgsql_cmd_batch.erl

@@ -36,7 +36,8 @@
 -type response() :: [{ok, Count :: non_neg_integer(), Rows :: [tuple()]}
                      | {ok, Count :: non_neg_integer()}
                      | {ok, Rows :: [tuple()]}
-                     | {error, epgsql:query_error()}].
+                     | {error, [{error, epgsql:query_error()} | {error, skipped}]}
+                     ].
 -type state() :: #batch{}.
 
 -spec init(arguments()) -> state().
@@ -110,13 +111,14 @@ handle_message(?COMMAND_COMPLETE, Bin, Sock,
                      {ok, Rows}
              end,
     {add_result, Result, {complete, Complete}, Sock, State#batch{batch = Batch}};
-handle_message(?READY_FOR_QUERY, _Status, Sock, #batch{batch = B} = _State) when
-      length(B) =< 1 ->
+handle_message(?READY_FOR_QUERY, _Status, Sock, _State) ->
     Results = epgsql_sock:get_results(Sock),
     {finish, Results, done, Sock};
 handle_message(?ERROR, Error, Sock, #batch{batch = [_ | Batch]} = State) ->
     Result = {error, Error},
-    {add_result, Result, Result, Sock, State#batch{batch = Batch}};
+    Skipped = lists:duplicate(length(Batch), {error, skipped}),
+    FinalResult = {error, [Result | Skipped]},
+    {add_result, FinalResult, FinalResult, Sock, State#batch{batch = Batch}};
 handle_message(_, _, _, _) ->
     unknown.
 

+ 7 - 3
test/epgsql_SUITE.erl

@@ -479,13 +479,17 @@ batch_error(Config) ->
     Module = ?config(module, Config),
     epgsql_ct:with_rollback(Config, fun(C) ->
         {ok, S} = Module:parse(C, "insert into test_table1(id, value) values($1, $2)"),
-        [{ok, 1}, {error, _}] =
+        [{ok, 1}, {error, [Error, Skipped1, Skipped2]}] =
             Module:execute_batch(
               C,
               [{S, [3, "batch_error 3"]},
                {S, [2, "batch_error 2"]}, % duplicate key error
-               {S, [5, "batch_error 5"]}  % won't be executed
-              ])
+               {S, [5, "batch_error 5"]},  % won't be executed
+               {S, [6, "batch_error 6"]}  % won't be executed
+              ]),
+        ?assertMatch({error, #error{}}, Error),
+        ?assertEqual({error, skipped}, Skipped1),
+        ?assertEqual({error, skipped}, Skipped2)
     end).
 
 single_batch(Config) ->