Browse Source

prepared_query as equery without closing statement

Eugene Shubin 9 years ago
parent
commit
fc262b2545
3 changed files with 30 additions and 28 deletions
  1. 9 16
      src/epgsql.erl
  2. 18 9
      src/epgsql_sock.erl
  3. 3 3
      test/epgsql_tests.erl

+ 9 - 16
src/epgsql.erl

@@ -150,22 +150,15 @@ equery(C, Name, Sql, Parameters) ->
 
 -spec prepared_query(connection(), string(), [bind_param()]) -> reply(equery_row()).
 prepared_query(C, Name, Parameters) ->
-  case epgsql:describe(C, statement, Name) of
-    {ok, Statement} ->
-      case epgsql:bind(C, Statement, Parameters) of
-        ok ->
-          case epgsql:execute(C, Statement) of
-            {ok, _} = R ->
-              case epgsql:sync(C) of
-                ok -> R;
-                E -> E
-              end;
-            Er -> Er
-          end;
-        Error -> Error
-      end;
-    Err -> Err
-  end.
+    case describe(C, statement, Name) of
+        {ok, #statement{types = Types} = S} ->
+            Typed_Parameters = lists:zip(Types, Parameters),
+            gen_server:call(C, {prepared_query, S, Typed_Parameters}, infinity);
+        Error ->
+            Error
+    end.
+
+
 %% parse
 
 parse(C, Sql) ->

+ 18 - 9
src/epgsql_sock.erl

@@ -223,6 +223,15 @@ command({equery, Statement, Parameters}, #state{codec = Codec} = State) ->
     send(State, ?SYNC, []),
     {noreply, State};
 
+command({prepared_query, Statement, Parameters}, #state{codec = Codec} = State) ->
+    #statement{name = StatementName, columns = Columns} = Statement,
+    Bin1 = epgsql_wire:encode_parameters(Parameters, Codec),
+    Bin2 = epgsql_wire:encode_formats(Columns),
+    send(State, ?BIND, ["", 0, StatementName, 0, Bin1, Bin2]),
+    send(State, ?EXECUTE, ["", 0, <<0:?int32>>]),
+    send(State, ?SYNC, []),
+    {noreply, State};
+
 command({parse, Name, Sql, Types}, State) ->
     Bin = epgsql_wire:encode_types(Types, State#state.codec),
     send(State, ?PARSE, [Name, 0, Sql, 0, Bin]),
@@ -416,7 +425,7 @@ command_tag(#state{queue = Q}) ->
 get_columns(State) ->
     #state{queue = Q, columns = Columns, batch = Batch} = State,
     case queue:get(Q) of
-        {_, {equery, #statement{columns = C}, _}} ->
+        {_, {Command, #statement{columns = C}, _}}  when Command == equery; Command == prepared_query ->
             C;
         {_, {execute, #statement{columns = C}, _, _}} ->
             C;
@@ -578,7 +587,7 @@ on_message({?NO_DATA, <<>>}, State) ->
 %% BindComplete
 on_message({?BIND_COMPLETE, <<>>}, State) ->
     State2 = case command_tag(State) of
-                 equery ->
+                 Command when Command == equery; Command == prepared_query ->
                      %% TODO send Describe as a part of equery, needs text format support
                      notify(State, {columns, get_columns(State)});
                  bind ->
@@ -598,7 +607,7 @@ on_message({?BIND_COMPLETE, <<>>}, State) ->
 %% CloseComplete
 on_message({?CLOSE_COMPLETE, <<>>}, State) ->
     State2 = case command_tag(State) of
-                 equery ->
+                 Command when Command == equery; Command == prepared_query ->
                      State;
                  close ->
                      finish(State, ok)
@@ -636,11 +645,11 @@ on_message({?COMMAND_COMPLETE, Bin}, State) ->
                      add_result(State, Notice, {ok, Count, Rows});
                  {execute_batch, _, _} ->
                      add_result(State, Notice, {ok, Rows});
-                 {C, {_, Count}, []} when C == squery; C == equery ->
+                 {C, {_, Count}, []} when C == squery; C == equery; C == prepared_query ->
                      add_result(State, Notice, {ok, Count});
-                 {C, {_, Count}, _} when C == squery; C == equery ->
+                 {C, {_, Count}, _} when C == squery; C == equery; C == prepared_query ->
                      add_result(State, Notice, {ok, Count, get_columns(State), Rows});
-                 {C, _, _} when C == squery; C == equery ->
+                 {C, _, _} when C == squery; C == equery; C == prepared_query ->
                      add_result(State, Notice, {ok, get_columns(State), Rows})
              end,
     {noreply, State2};
@@ -651,7 +660,7 @@ on_message({?EMPTY_QUERY, _Bin}, State) ->
     State2 = case command_tag(State) of
                  execute ->
                      finish(State, Notice, {ok, [], []});
-                 C when C == squery; C == equery ->
+                 C when C == squery; C == equery; C == prepared_query ->
                      add_result(State, Notice, {ok, [], []})
              end,
     {noreply, State2};
@@ -668,7 +677,7 @@ on_message({?READY_FOR_QUERY, <<Status:8>>}, State) ->
                      end;
                  execute_batch ->
                      finish(State, done, lists:reverse(State#state.results));
-                 equery ->
+                 Command when Command == equery; Command == prepared_query ->
                      case State#state.results of
                          [Result] ->
                              finish(State, done, Result);
@@ -682,7 +691,7 @@ on_message({?READY_FOR_QUERY, <<Status:8>>}, State) ->
 
 on_message(Error = {error, _}, State) ->
     State2 = case command_tag(State) of
-                 C when C == squery; C == equery; C == execute_batch ->
+                 C when C == squery; C == equery; C == execute_batch; C == prepared_query ->
                      add_result(State, Error, Error);
                  _ ->
                      sync_required(finish(State, Error))

+ 3 - 3
test/epgsql_tests.erl

@@ -107,9 +107,9 @@ prepared_query_test(Module) ->
     Module,
     fun(C) ->
       {ok, _} = epgsql:parse(C, "inc", "select $1+1", []),
-      {ok,[{5}]} = epgsql:prepared_query(C, "inc", [4]),
-      {ok,[{2}]} = epgsql:prepared_query(C, "inc", [1]),
-      {ok,[{23}]} = epgsql:prepared_query(C, "inc", [22]),
+      {ok, Cols, [{5}]} = epgsql:prepared_query(C, "inc", [4]),
+      {ok, Cols, [{2}]} = epgsql:prepared_query(C, "inc", [1]),
+      {ok, Cols, [{23}]} = epgsql:prepared_query(C, "inc", [22]),
       {error, _} = epgsql:prepared_query(C, "non_existent_query", [4])
     end).