| commit 1: | a71f55eedb4f |
| parent 0: | 0d769bdbad94 |
| branch: | default |
properly decode all command complete tags
Will Glozer /
will
15 months ago
15 months ago
Changed (Δ1.1 KB):
raw changeset »
src/pgsql_connection.erl (20 lines added, 14 lines removed)
test_src/pgsql_tests.erl (20 lines added, 1 lines removed)
Up to file-list src/pgsql_connection.erl:
| … | … | @@ -83,7 +83,7 @@ handle_event({notice, Notice}, State_Nam |
83 |
83 |
handle_event({parameter_status, Name, Value}, State_Name, State) -> |
84 |
84 |
Parameters2 = lists:keystore(Name, 1, State#state.parameters, {Name, Value}), |
85 |
85 |
{next_state, State_Name, State#state{parameters = Parameters2}}; |
86 |
||
86 |
||
87 |
87 |
handle_event(stop, _State_Name, State) -> |
88 |
88 |
{stop, normal, State}; |
89 |
89 |
|
| … | … | @@ -98,8 +98,8 @@ handle_info({'EXIT', Pid, Reason}, _Stat |
98 |
98 |
|
99 |
99 |
handle_info(Info, _State_Name, State) -> |
100 |
100 |
{stop, {unsupported_info, Info}, State}. |
101 |
||
102 |
terminate(_Reason, _State_Name, State = #state{sock = Sock}) |
|
101 |
||
102 |
terminate(_Reason, _State_Name, State = #state{sock = Sock}) |
|
103 |
103 |
when Sock =/= undefined -> |
104 |
104 |
send(State, $X, []), |
105 |
105 |
gen_tcp:close(Sock); |
| … | … | @@ -113,7 +113,7 @@ code_change(_Old_Vsn, State_Name, State, |
113 |
113 |
%% -- states -- |
114 |
114 |
|
115 |
115 |
startup({connect, Host, Username, Password, Opts}, From, State) -> |
116 |
Port = proplists:get_value(port, Opts, 5432), |
|
116 |
Port = proplists:get_value(port, Opts, 5432), |
|
117 |
117 |
Sock_Opts = [{active, false}, {packet, raw}, binary], |
118 |
118 |
case gen_tcp:connect(Host, Port, Sock_Opts) of |
119 |
119 |
{ok, Sock} -> |
| … | … | @@ -124,14 +124,14 @@ startup({connect, Host, Username, Passwo |
124 |
124 |
undefined -> Opts3 = Opts2; |
125 |
125 |
Database -> Opts3 = [Opts2 | ["database", 0, Database, 0]] |
126 |
126 |
end, |
127 |
||
127 |
||
128 |
128 |
put(username, Username), |
129 |
129 |
put(password, Password), |
130 |
130 |
State2 = State#state{reader = Reader, |
131 |
131 |
sock = Sock, |
132 |
132 |
reply_to = From}, |
133 |
133 |
send(State2, [<<196608:32>>, Opts3, 0]), |
134 |
||
134 |
||
135 |
135 |
{next_state, auth, State2}; |
136 |
136 |
Error -> |
137 |
137 |
{stop, normal, Error, State} |
| … | … | @@ -284,7 +284,7 @@ querying({$3, <<>>}, State) -> |
284 |
284 |
%% RowDescription |
285 |
285 |
querying({$T, <<Count:?int16, Bin/binary>>}, State) -> |
286 |
286 |
Columns = decode_columns(Count, Bin), |
287 |
S2 = (State#state.statement)#statement{columns = Columns}, |
|
287 |
S2 = (State#state.statement)#statement{columns = Columns}, |
|
288 |
288 |
notify(State, {columns, Columns}), |
289 |
289 |
{next_state, querying, State#state{statement = S2}}; |
290 |
290 |
|
| … | … | @@ -496,12 +496,18 @@ decode_columns(N, Bin, Acc) -> |
496 |
496 |
decode_columns(N - 1, Rest2, [Desc | Acc]). |
497 |
497 |
|
498 |
498 |
%% decode command complete msg |
499 |
decode_complete(<<"SELECT", 0>>) -> select; |
|
500 |
decode_complete(<<"BEGIN", 0>>) -> 'begin'; |
|
501 |
decode_complete(<<"ROLLBACK", 0>>) -> rollback; |
|
499 |
502 |
decode_complete(Bin) -> |
500 |
503 |
{Str, _} = decode_string(Bin), |
501 |
504 |
case string:tokens(binary_to_list(Str), " ") of |
502 |
[Type] -> lower_atom(Type); |
|
503 |
[Type, _Oid, Rows] -> {lower_atom(Type), list_to_integer(Rows)}; |
|
504 |
[ |
|
505 |
["INSERT", _Oid, Rows] -> {insert, list_to_integer(Rows)}; |
|
506 |
["UPDATE", Rows] -> {update, list_to_integer(Rows)}; |
|
507 |
["DELETE", Rows] -> {delete, list_to_integer(Rows)}; |
|
508 |
["MOVE", Rows] -> {move, list_to_integer(Rows)}; |
|
509 |
["FETCH", _Rows] -> fetch; |
|
510 |
[Type | _Rest] -> lower_atom(Type) |
|
505 |
511 |
end. |
506 |
512 |
|
507 |
513 |
%% decode ErrorResponse |
| … | … | @@ -517,7 +523,7 @@ decode_error(Bin) -> |
517 |
523 |
decode_error_extra(Fields) -> |
518 |
524 |
Types = [{$D, detail}, {$H, hint}, {$P, position}], |
519 |
525 |
decode_error_extra(Types, Fields, []). |
520 |
||
526 |
||
521 |
527 |
decode_error_extra([], _Fields, Extra) -> |
522 |
528 |
Extra; |
523 |
529 |
decode_error_extra([{Type, Name} | T], Fields, Extra) -> |
| … | … | @@ -608,7 +614,7 @@ hex(Bin) -> |
608 |
614 |
|
609 |
615 |
send(#state{sock = Sock}, Type, Data) -> |
610 |
616 |
Bin = iolist_to_binary(Data), |
611 |
gen_tcp:send(Sock, <<Type:8, (byte_size(Bin) + 4):?int32, Bin/binary>>). |
|
617 |
gen_tcp:send(Sock, <<Type:8, (byte_size(Bin) + 4):?int32, Bin/binary>>). |
|
612 |
618 |
|
613 |
619 |
send(#state{sock = Sock}, Data) -> |
614 |
620 |
Bin = iolist_to_binary(Data), |
| … | … | @@ -636,7 +642,7 @@ decode(Fsm, Sock, <<Type:8, Len:?int32, |
636 |
642 |
gen_fsm:send_event(Fsm, {Type, Data}), |
637 |
643 |
decode(Fsm, Sock, Tail); |
638 |
644 |
_Other -> |
639 |
|
|
645 |
?MODULE:read(Fsm, Sock, Bin) |
|
640 |
646 |
end; |
641 |
647 |
decode(Fsm, Sock, Bin) -> |
642 |
|
|
648 |
?MODULE:read(Fsm, Sock, Bin). |
Up to file-list test_src/pgsql_tests.erl:
| … | … | @@ -66,6 +66,25 @@ update_test() -> |
66 |
66 |
{ok, _, [{<<"2">>}]} = pgsql:squery(C, "select count(*) from test_table1 where value = 'foo'") |
67 |
67 |
end). |
68 |
68 |
|
69 |
create_and_drop_table_test() -> |
|
70 |
with_rollback( |
|
71 |
fun(C) -> |
|
72 |
{ok, [], []} = pgsql:squery(C, "create table test_table3 (id int4)"), |
|
73 |
{ok, [#column{type = int4}], []} = pgsql:squery(C, "select * from test_table3"), |
|
74 |
{ok, [], []} = pgsql:squery(C, "drop table test_table3") |
|
75 |
end). |
|
76 |
||
77 |
cursor_test() -> |
|
78 |
with_connection( |
|
79 |
fun(C) -> |
|
80 |
{ok, [], []} = pgsql:squery(C, "begin"), |
|
81 |
{ok, [], []} = pgsql:squery(C, "declare c cursor for select id from test_table1"), |
|
82 |
{ok, 2} = pgsql:squery(C, "move forward 2 from c"), |
|
83 |
{ok, 1} = pgsql:squery(C, "move backward 1 from c"), |
|
84 |
{ok, _Cols, [{<<"2">>}]} = pgsql:squery(C, "fetch next from c"), |
|
85 |
{ok, [], []} = pgsql:squery(C, "close c") |
|
86 |
end). |
|
87 |
||
69 |
88 |
multiple_result_test() -> |
70 |
89 |
with_connection( |
71 |
90 |
fun(C) -> |
| … | … | @@ -219,7 +238,7 @@ describe_error_test() -> |
219 |
238 |
{ok, S} = pgsql:parse(C, "select * from test_table1"), |
220 |
239 |
{ok, S} = pgsql:describe(C, statement, ""), |
221 |
240 |
ok = pgsql:sync(C) |
222 |
||
241 |
||
223 |
242 |
end). |
224 |
243 |
|
225 |
244 |
portal_test() -> |
