I have an "issue" (probably coming from my understanding of the json, jsonb and jsonb[] types) which is the following:
My team and I insert 3D coordinates records into a table whose column type is jsonb[]
.
The table contains an id column, that is based on the text representation of the records.
With that said, when I select some data from the table, all the records containing coordinates whose values where equal to -0.0 (bit sign on), the data I get back does not contain the minus sign. -0.0 -> 0.0.
I am aware of the IEEE754 RFC on floating point numbers (and the comparison section), I was wondering, how does Postgres treat the elements inside the jsonb array?
Is there a conversion/casting done on the fly when inserting the data.
Is there a way to deactivate such behaviour?
Minimal reproducible code:
CREATE TABLE IF NOT EXISTS "my_test_table" (
coordinates jsonb[]
);
TRUNCATE TABLE "my_test_table";
INSERT INTO
"public"."my_test_table" ("coordinates")
VALUES (
ARRAY[jsonb_build_array(-0.0, 0.0,0.0)]::jsonb[]
);
select * from my_test_table;
The output is:
{"[0.0, 0.0, 0.0]"}
when one expects:
{"[-0.0, 0.0, 0.0]"}
2
Answers
PostgreSQL stores numbers as
numeric
injsonb
. See this code insrc/backend/utils/adt/jsonb.c
:Data type
numeric
has no notion of “negative zero”:numeric
is stored as binary coded decimal.Addressing the other question:
Yes, there is. At a price of everything
jsonb
offers overjson
: demo at db<>fiddleIf you need the
jsonb
functionality and the fields to be ofnumber
type while holding onto the bit sign for some other logic, you can save it under a separate, appropriately named key, or another array ofboolean
values that hold corresponding "source" bit signs of your coordinates: demo2That of course forces you to bind those coordinates as string types instead of numeric types.
You can also not use
number
-type fields, and save the coordinates asstring
fields injsonb
. The size, indexing and JSONPath processing won’t be the same, but other than that, most in-db type mapping onjson
/jsonb
output goes throughtext
type first anyways, before you get to interact with the field for the purpose of a query.