epgsql_cmd_describe_statement.erl 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
  1. %% Almost the same as "parse"
  2. %% > Describe
  3. %% < ParameterDescription
  4. %% < RowDescription | NoData
  5. -module(epgsql_cmd_describe_statement).
  6. -behaviour(epgsql_command).
  7. -export([init/1, execute/2, handle_message/4]).
  8. -export_type([response/0]).
  9. -include("epgsql.hrl").
  10. -include("protocol.hrl").
  11. -type response() :: {ok, #statement{}} | {error, epgsql:query_error()}.
  12. -record(desc_stmt,
  13. {name :: iodata(),
  14. parameter_typenames = [],
  15. parameter_descr = []}).
  16. init(Name) ->
  17. #desc_stmt{name = Name}.
  18. execute(Sock, #desc_stmt{name = Name} = St) ->
  19. epgsql_sock:send_multi(
  20. Sock,
  21. [
  22. {?DESCRIBE, [?PREPARED_STATEMENT, Name, 0]},
  23. {?FLUSH, []}
  24. ]),
  25. {ok, Sock, St}.
  26. handle_message(?PARAMETER_DESCRIPTION, Bin, Sock, State) ->
  27. Codec = epgsql_sock:get_codec(Sock),
  28. TypeInfos = epgsql_wire:decode_parameters(Bin, Codec),
  29. OidInfos = [epgsql_binary:typeinfo_to_oid_info(Type, Codec) || Type <- TypeInfos],
  30. TypeNames = [epgsql_binary:typeinfo_to_name_array(Type, Codec) || Type <- TypeInfos],
  31. Sock2 = epgsql_sock:notify(Sock, {types, TypeNames}),
  32. {noaction, Sock2, State#desc_stmt{parameter_descr = OidInfos,
  33. parameter_typenames = TypeNames}};
  34. handle_message(?ROW_DESCRIPTION, <<Count:?int16, Bin/binary>>, Sock,
  35. #desc_stmt{name = Name, parameter_descr = Params,
  36. parameter_typenames = TypeNames}) ->
  37. Codec = epgsql_sock:get_codec(Sock),
  38. Columns = epgsql_wire:decode_columns(Count, Bin, Codec),
  39. Columns2 = [Col#column{format = epgsql_wire:format(Col, Codec)}
  40. || Col <- Columns],
  41. Result = {ok, #statement{name = Name,
  42. types = TypeNames,
  43. parameter_info = Params,
  44. columns = Columns2}},
  45. {finish, Result, {columns, Columns2}, Sock};
  46. handle_message(?NO_DATA, <<>>, Sock, #desc_stmt{name = Name, parameter_descr = Params,
  47. parameter_typenames = TypeNames}) ->
  48. Result = {ok, #statement{name = Name,
  49. types = TypeNames,
  50. parameter_info = Params,
  51. columns = []}},
  52. {finish, Result, no_data, Sock};
  53. handle_message(?ERROR, Error, _Sock, _State) ->
  54. Result = {error, Error},
  55. {sync_required, Result};
  56. handle_message(_, _, _, _) ->
  57. unknown.