Re: Bug in searching path in jsonb_set when walking through JSONB array
От | Oleg Bartunov |
---|---|
Тема | Re: Bug in searching path in jsonb_set when walking through JSONB array |
Дата | |
Msg-id | CAF4Au4zV7R+9qjE6DXmjvEsjq=C8rcpQPyx6UML1iTphS02aKw@mail.gmail.com обсуждение исходный текст |
Ответ на | Bug in searching path in jsonb_set when walking through JSONB array (Vitaly Burovoy <vitaly.burovoy@gmail.com>) |
Ответы |
Re: Bug in searching path in jsonb_set when walking through
JSONB array
|
Список | pgsql-hackers |
On Wed, Mar 23, 2016 at 6:37 AM, Vitaly Burovoy <vitaly.burovoy@gmail.com> wrote:
Hello, Hackers!
While I was reviewed a patch with "json_insert" function I found a bug
which wasn't connected with the patch and reproduced at master.
It claims about non-integer whereas input values are obvious integers
and in an allowed range.
More testing lead to understanding it appears when numbers length are
multiplier of 4:
postgres=# select jsonb_set('{"a":[[],1,2,3],"b":[]}', '{"a", 9999}', '"4"');
ERROR: path element at the position 2 is not an integer
Hmm, I see in master
select version();
version
-----------------------------------------------------------------------------------------------------------------
PostgreSQL 9.6devel on x86_64-apple-darwin15.4.0, compiled by Apple LLVM version 7.3.0 (clang-703.0.29), 64-bit
(1 row)
select jsonb_set('{"a":[[],1,2,3],"b":[]}', '{"a", 9999}', '"4"');
jsonb_set
------------------------------------
{"a": [[], 1, 2, 3, "4"], "b": []}
(1 row)
select version();
version
-----------------------------------------------------------------------------------------------------------------
PostgreSQL 9.6devel on x86_64-apple-darwin15.4.0, compiled by Apple LLVM version 7.3.0 (clang-703.0.29), 64-bit
(1 row)
select jsonb_set('{"a":[[],1,2,3],"b":[]}', '{"a", 9999}', '"4"');
jsonb_set
------------------------------------
{"a": [[], 1, 2, 3, "4"], "b": []}
(1 row)
postgres=# select jsonb_set('{"a":[[],1,2,3],"b":[]}', '{"b", 1000}', '"4"');
ERROR: path element at the position 2 is not an integer
postgres=# select jsonb_set('{"a":[[],1,2,3],"b":[]}', '{"a", -999}', '"4"');
ERROR: path element at the position 2 is not an integer
postgres=# select jsonb_set('{"a":[[],1,2,3],"b":[]}', '{"a",
10009999}', '"4"');
ERROR: path element at the position 2 is not an integer
Close values are ok:
postgres=# select jsonb_set('{"a":[[],1,2,3]}', '{"a", 0, 999}', '"4"');
jsonb_set
-------------------------
{"a": [["4"], 1, 2, 3]}
(1 row)
postgres=# select jsonb_set('{"a":[[],1,2,3]}', '{"a", 0, 10000}', '"4"');
jsonb_set
-------------------------
{"a": [["4"], 1, 2, 3]}
(1 row)
Research lead to setPathArray where a string which is got via
VARDATA_ANY but is passed to strtol which expects cstring.
In case of string number length is not a multiplier of 4 rest bytes
are padding by '\0', when length is a multiplier of 4 there is no
padding, just garbage after the last digit of the value.
Proposed patch in an attachment fixes it.
There is a magic number "20" as a length of an array for copying key
from a path before passing it to strtol. It is a maximal length of a
value which can be parsed by the function. I could not find a proper
constant for it. Also I found similar direct value in the code (e.g.
in numeric.c).
I've added a comment, I hope it is enough for it.
--
Best regards,
Vitaly Burovoy
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
В списке pgsql-hackers по дате отправления: