From d7227cbe737597ec2343a5efecb576aac3c8cc78 Mon Sep 17 00:00:00 2001 From: Paul Guyot Date: Tue, 27 Dec 2016 11:35:40 +0100 Subject: [PATCH] Fix bug #28 in handling quoted values in arrays --- src/pgsql.app.src | 2 +- src/pgsql.appup | 8 +++++++- src/pgsql_protocol.erl | 30 ++++++++++++++++++------------ test/pgsql_connection_test.erl | 23 +++++++++++++++++++++++ 4 files changed, 49 insertions(+), 14 deletions(-) diff --git a/src/pgsql.app.src b/src/pgsql.app.src index a281dbe..155466e 100644 --- a/src/pgsql.app.src +++ b/src/pgsql.app.src @@ -2,7 +2,7 @@ [ {description, "pgsql driver"}, {id, "pgsql"}, - {vsn, "26.0.0"}, + {vsn, "26.0.1"}, {modules, [ pgsql_app, pgsql_connection, diff --git a/src/pgsql.appup b/src/pgsql.appup index 24cf45e..08ecb77 100644 --- a/src/pgsql.appup +++ b/src/pgsql.appup @@ -1,5 +1,8 @@ -{"26.0.0", +{"26.0.1", [ + {"26.0.0", [ + {load_module, pgsql_protocol, soft_purge, soft_purge, []} + ]}, {"26", [ {load_module, pgsql_protocol, soft_purge, soft_purge, []} ]}, @@ -37,6 +40,9 @@ ]} ], [ + {"26.0.0", [ + {load_module, pgsql_protocol, soft_purge, soft_purge, []} + ]}, {"26", [ {load_module, pgsql_protocol, soft_purge, soft_purge, []} ]}, diff --git a/src/pgsql_protocol.erl b/src/pgsql_protocol.erl index f17111a..9cfdeb8 100644 --- a/src/pgsql_protocol.erl +++ b/src/pgsql_protocol.erl @@ -934,19 +934,25 @@ decode_array_text(_Type, _OIDMap, <<"}", Next/binary>>, Acc) -> {lists:reverse(Acc), Next}; decode_array_text(Type, OIDMap, <<",", Next/binary>>, Acc) -> decode_array_text(Type, OIDMap, Next, Acc); -decode_array_text(Type, OIDMap, Content, Acc) -> - {Count, Next} = decode_array_text_find(Content, 0), - {Value, _} = split_binary(Content, Count), +decode_array_text(Type, OIDMap, Content0, Acc) -> + {Value, Rest} = decode_array_text0(Content0, false, []), Element = decode_value_text(Type, Value, OIDMap), - decode_array_text(Type, OIDMap, Next, [Element|Acc]). - -decode_array_text_find(<<",", Next/binary>>, Count) -> - {Count, Next}; -decode_array_text_find(<<"}", _Next/binary>> = N, Count) -> - {Count, N}; -decode_array_text_find(<<_, Next/binary>>, Count) -> - decode_array_text_find(Next, Count+1). - + decode_array_text(Type, OIDMap, Rest, [Element|Acc]). + +decode_array_text0(<<$", Rest/binary>>, false, []) -> + decode_array_text0(Rest, true, []); +decode_array_text0(<<$,, Rest/binary>>, false, Acc) -> + {list_to_binary(lists:reverse(Acc)), Rest}; +decode_array_text0(<<$}, _/binary>> = Content, false, Acc) -> + {list_to_binary(lists:reverse(Acc)), Content}; +decode_array_text0(<<$", $,, Rest/binary>>, true, Acc) -> + {list_to_binary(lists:reverse(Acc)), Rest}; +decode_array_text0(<<$", $}, Rest/binary>>, true, Acc) -> + {list_to_binary(lists:reverse(Acc)), <<$}, Rest/binary>>}; +decode_array_text0(<<$\\, C, Rest/binary>>, true, Acc) -> + decode_array_text0(Rest, true, [C | Acc]); +decode_array_text0(<>, Quoted, Acc) -> + decode_array_text0(Rest, Quoted, [C | Acc]). decode_value_bin(?BOOLOID, <<0>>, _OIDMap, _IntegerDateTimes) -> false; decode_value_bin(?BOOLOID, <<1>>, _OIDMap, _IntegerDateTimes) -> true; diff --git a/test/pgsql_connection_test.erl b/test/pgsql_connection_test.erl index 9e48307..5a93569 100644 --- a/test/pgsql_connection_test.erl +++ b/test/pgsql_connection_test.erl @@ -504,6 +504,29 @@ array_types_test_() -> end }. +% https://github.com/semiocast/pgsql/issues/28 +quoted_array_values_test_() -> + {setup, + fun() -> + {ok, SupPid} = pgsql_connection_sup:start_link(), + Conn = pgsql_connection:open("test", "test"), + {SupPid, Conn} + end, + fun({SupPid, Conn}) -> + pgsql_connection:close(Conn), + kill_sup(SupPid) + end, + fun({_SupPid, Conn}) -> + [ + ?_assertEqual({{select,1},[{{array,[<<"foo bar">>]}}]}, pgsql_connection:simple_query("select ARRAY['foo bar'];", Conn)), + ?_assertEqual({{select,1},[{{array,[<<"foo, bar">>]}}]}, pgsql_connection:simple_query("select ARRAY['foo, bar'];", Conn)), + ?_assertEqual({{select,1},[{{array,[<<"foo} bar">>]}}]}, pgsql_connection:simple_query("select ARRAY['foo} bar'];", Conn)), + ?_assertEqual({{select,1},[{{array,[<<"foo \" bar">>]}}]}, pgsql_connection:simple_query("select ARRAY['foo \" bar'];", Conn)), + ?_assertEqual({{select,1},[{{array,[{{2014,1,1},{12,12,12}}]}}]}, pgsql_connection:simple_query("select ARRAY['2014-01-01T12:12:12Z'::timestamp];", Conn)) + ] + end + }. + geometric_types_test_() -> [{setup, fun() ->