2022-02-08 21:30:38 +01:00
-- directory paths are passed to us in environment variables
\getenv abs_srcdir PG_ABS_SRCDIR
CREATE TABLE testjsonb (
j jsonb
);
\set filename :abs_srcdir '/data/jsonb.data'
COPY testjsonb FROM :'filename';
Introduce jsonb, a structured format for storing json.
The new format accepts exactly the same data as the json type. However, it is
stored in a format that does not require reparsing the orgiginal text in order
to process it, making it much more suitable for indexing and other operations.
Insignificant whitespace is discarded, and the order of object keys is not
preserved. Neither are duplicate object keys kept - the later value for a given
key is the only one stored.
The new type has all the functions and operators that the json type has,
with the exception of the json generation functions (to_json, json_agg etc.)
and with identical semantics. In addition, there are operator classes for
hash and btree indexing, and two classes for GIN indexing, that have no
equivalent in the json type.
This feature grew out of previous work by Oleg Bartunov and Teodor Sigaev, which
was intended to provide similar facilities to a nested hstore type, but which
in the end proved to have some significant compatibility issues.
Authors: Oleg Bartunov, Teodor Sigaev, Peter Geoghegan and Andrew Dunstan.
Review: Andres Freund
2014-03-23 21:40:19 +01:00
-- Strings.
SELECT '""'::jsonb; -- OK.
jsonb
-------
""
(1 row)
SELECT $$''$$::jsonb; -- ERROR, single quotes are not allowed
ERROR: invalid input syntax for type json
LINE 1: SELECT $$''$$::jsonb;
^
DETAIL: Token "'" is invalid.
CONTEXT: JSON data, line 1: '...
SELECT '"abc"'::jsonb; -- OK
jsonb
-------
"abc"
(1 row)
SELECT '"abc'::jsonb; -- ERROR, quotes not closed
ERROR: invalid input syntax for type json
LINE 1: SELECT '"abc'::jsonb;
^
DETAIL: Token ""abc" is invalid.
CONTEXT: JSON data, line 1: "abc
SELECT '"abc
def"'::jsonb; -- ERROR, unescaped newline in string constant
ERROR: invalid input syntax for type json
LINE 1: SELECT '"abc
^
DETAIL: Character with value 0x0a must be escaped.
CONTEXT: JSON data, line 1: "abc
SELECT '"\n\"\\"'::jsonb; -- OK, legal escapes
jsonb
----------
"\n\"\\"
(1 row)
SELECT '"\v"'::jsonb; -- ERROR, not a valid JSON escape
ERROR: invalid input syntax for type json
LINE 1: SELECT '"\v"'::jsonb;
^
DETAIL: Escape sequence "\v" is invalid.
CONTEXT: JSON data, line 1: "\v...
2015-10-07 23:41:45 +02:00
-- see json_encoding test for input with unicode escapes
Introduce jsonb, a structured format for storing json.
The new format accepts exactly the same data as the json type. However, it is
stored in a format that does not require reparsing the orgiginal text in order
to process it, making it much more suitable for indexing and other operations.
Insignificant whitespace is discarded, and the order of object keys is not
preserved. Neither are duplicate object keys kept - the later value for a given
key is the only one stored.
The new type has all the functions and operators that the json type has,
with the exception of the json generation functions (to_json, json_agg etc.)
and with identical semantics. In addition, there are operator classes for
hash and btree indexing, and two classes for GIN indexing, that have no
equivalent in the json type.
This feature grew out of previous work by Oleg Bartunov and Teodor Sigaev, which
was intended to provide similar facilities to a nested hstore type, but which
in the end proved to have some significant compatibility issues.
Authors: Oleg Bartunov, Teodor Sigaev, Peter Geoghegan and Andrew Dunstan.
Review: Andres Freund
2014-03-23 21:40:19 +01:00
-- Numbers.
SELECT '1'::jsonb; -- OK
jsonb
-------
1
(1 row)
SELECT '0'::jsonb; -- OK
jsonb
-------
0
(1 row)
SELECT '01'::jsonb; -- ERROR, not valid according to JSON spec
ERROR: invalid input syntax for type json
LINE 1: SELECT '01'::jsonb;
^
DETAIL: Token "01" is invalid.
CONTEXT: JSON data, line 1: 01
SELECT '0.1'::jsonb; -- OK
jsonb
-------
0.1
(1 row)
SELECT '9223372036854775808'::jsonb; -- OK, even though it's too large for int8
jsonb
---------------------
9223372036854775808
(1 row)
SELECT '1e100'::jsonb; -- OK
jsonb
-------------------------------------------------------------------------------------------------------
10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
(1 row)
SELECT '1.3e100'::jsonb; -- OK
jsonb
-------------------------------------------------------------------------------------------------------
13000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
(1 row)
SELECT '1f2'::jsonb; -- ERROR
ERROR: invalid input syntax for type json
LINE 1: SELECT '1f2'::jsonb;
^
DETAIL: Token "1f2" is invalid.
CONTEXT: JSON data, line 1: 1f2
SELECT '0.x1'::jsonb; -- ERROR
ERROR: invalid input syntax for type json
LINE 1: SELECT '0.x1'::jsonb;
^
DETAIL: Token "0.x1" is invalid.
CONTEXT: JSON data, line 1: 0.x1
SELECT '1.3ex100'::jsonb; -- ERROR
ERROR: invalid input syntax for type json
LINE 1: SELECT '1.3ex100'::jsonb;
^
DETAIL: Token "1.3ex100" is invalid.
CONTEXT: JSON data, line 1: 1.3ex100
-- Arrays.
SELECT '[]'::jsonb; -- OK
jsonb
-------
[]
(1 row)
SELECT '[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]'::jsonb; -- OK
jsonb
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]
(1 row)
SELECT '[1,2]'::jsonb; -- OK
jsonb
--------
[1, 2]
(1 row)
SELECT '[1,2,]'::jsonb; -- ERROR, trailing comma
ERROR: invalid input syntax for type json
LINE 1: SELECT '[1,2,]'::jsonb;
^
DETAIL: Expected JSON value, but found "]".
CONTEXT: JSON data, line 1: [1,2,]
SELECT '[1,2'::jsonb; -- ERROR, no closing bracket
ERROR: invalid input syntax for type json
LINE 1: SELECT '[1,2'::jsonb;
^
DETAIL: The input string ended unexpectedly.
CONTEXT: JSON data, line 1: [1,2
SELECT '[1,[2]'::jsonb; -- ERROR, no closing bracket
ERROR: invalid input syntax for type json
LINE 1: SELECT '[1,[2]'::jsonb;
^
DETAIL: The input string ended unexpectedly.
CONTEXT: JSON data, line 1: [1,[2]
-- Objects.
SELECT '{}'::jsonb; -- OK
jsonb
-------
{}
(1 row)
SELECT '{"abc"}'::jsonb; -- ERROR, no value
ERROR: invalid input syntax for type json
LINE 1: SELECT '{"abc"}'::jsonb;
^
DETAIL: Expected ":", but found "}".
CONTEXT: JSON data, line 1: {"abc"}
SELECT '{"abc":1}'::jsonb; -- OK
jsonb
------------
{"abc": 1}
(1 row)
SELECT '{1:"abc"}'::jsonb; -- ERROR, keys must be strings
ERROR: invalid input syntax for type json
LINE 1: SELECT '{1:"abc"}'::jsonb;
^
DETAIL: Expected string or "}", but found "1".
CONTEXT: JSON data, line 1: {1...
SELECT '{"abc",1}'::jsonb; -- ERROR, wrong separator
ERROR: invalid input syntax for type json
LINE 1: SELECT '{"abc",1}'::jsonb;
^
DETAIL: Expected ":", but found ",".
CONTEXT: JSON data, line 1: {"abc",...
SELECT '{"abc"=1}'::jsonb; -- ERROR, totally wrong separator
ERROR: invalid input syntax for type json
LINE 1: SELECT '{"abc"=1}'::jsonb;
^
DETAIL: Token "=" is invalid.
CONTEXT: JSON data, line 1: {"abc"=...
SELECT '{"abc"::1}'::jsonb; -- ERROR, another wrong separator
ERROR: invalid input syntax for type json
LINE 1: SELECT '{"abc"::1}'::jsonb;
^
DETAIL: Expected JSON value, but found ":".
CONTEXT: JSON data, line 1: {"abc"::...
SELECT '{"abc":1,"def":2,"ghi":[3,4],"hij":{"klm":5,"nop":[6]}}'::jsonb; -- OK
jsonb
--------------------------------------------------------------------
{"abc": 1, "def": 2, "ghi": [3, 4], "hij": {"klm": 5, "nop": [6]}}
(1 row)
SELECT '{"abc":1:2}'::jsonb; -- ERROR, colon in wrong spot
ERROR: invalid input syntax for type json
LINE 1: SELECT '{"abc":1:2}'::jsonb;
^
DETAIL: Expected "," or "}", but found ":".
CONTEXT: JSON data, line 1: {"abc":1:...
SELECT '{"abc":1,3}'::jsonb; -- ERROR, no value
ERROR: invalid input syntax for type json
LINE 1: SELECT '{"abc":1,3}'::jsonb;
^
DETAIL: Expected string, but found "3".
CONTEXT: JSON data, line 1: {"abc":1,3...
2015-10-05 16:06:29 +02:00
-- Recursion.
SET max_stack_depth = '100kB';
2015-10-05 18:19:14 +02:00
SELECT repeat('[', 10000)::jsonb;
2015-10-05 16:06:29 +02:00
ERROR: stack depth limit exceeded
2023-11-30 06:11:45 +01:00
HINT: Increase the configuration parameter max_stack_depth (currently 100kB), after ensuring the platform's stack depth limit is adequate.
2015-10-05 18:19:14 +02:00
SELECT repeat('{"a":', 10000)::jsonb;
2015-10-05 16:06:29 +02:00
ERROR: stack depth limit exceeded
2023-11-30 06:11:45 +01:00
HINT: Increase the configuration parameter max_stack_depth (currently 100kB), after ensuring the platform's stack depth limit is adequate.
2015-10-05 16:06:29 +02:00
RESET max_stack_depth;
Introduce jsonb, a structured format for storing json.
The new format accepts exactly the same data as the json type. However, it is
stored in a format that does not require reparsing the orgiginal text in order
to process it, making it much more suitable for indexing and other operations.
Insignificant whitespace is discarded, and the order of object keys is not
preserved. Neither are duplicate object keys kept - the later value for a given
key is the only one stored.
The new type has all the functions and operators that the json type has,
with the exception of the json generation functions (to_json, json_agg etc.)
and with identical semantics. In addition, there are operator classes for
hash and btree indexing, and two classes for GIN indexing, that have no
equivalent in the json type.
This feature grew out of previous work by Oleg Bartunov and Teodor Sigaev, which
was intended to provide similar facilities to a nested hstore type, but which
in the end proved to have some significant compatibility issues.
Authors: Oleg Bartunov, Teodor Sigaev, Peter Geoghegan and Andrew Dunstan.
Review: Andres Freund
2014-03-23 21:40:19 +01:00
-- Miscellaneous stuff.
SELECT 'true'::jsonb; -- OK
jsonb
-------
true
(1 row)
SELECT 'false'::jsonb; -- OK
jsonb
-------
false
(1 row)
SELECT 'null'::jsonb; -- OK
jsonb
-------
null
(1 row)
SELECT ' true '::jsonb; -- OK, even with extra whitespace
jsonb
-------
true
(1 row)
SELECT 'true false'::jsonb; -- ERROR, too many values
ERROR: invalid input syntax for type json
LINE 1: SELECT 'true false'::jsonb;
^
DETAIL: Expected end of input, but found "false".
CONTEXT: JSON data, line 1: true false
SELECT 'true, false'::jsonb; -- ERROR, too many values
ERROR: invalid input syntax for type json
LINE 1: SELECT 'true, false'::jsonb;
^
DETAIL: Expected end of input, but found ",".
CONTEXT: JSON data, line 1: true,...
SELECT 'truf'::jsonb; -- ERROR, not a keyword
ERROR: invalid input syntax for type json
LINE 1: SELECT 'truf'::jsonb;
^
DETAIL: Token "truf" is invalid.
CONTEXT: JSON data, line 1: truf
SELECT 'trues'::jsonb; -- ERROR, not a keyword
ERROR: invalid input syntax for type json
LINE 1: SELECT 'trues'::jsonb;
^
DETAIL: Token "trues" is invalid.
CONTEXT: JSON data, line 1: trues
SELECT ''::jsonb; -- ERROR, no value
ERROR: invalid input syntax for type json
LINE 1: SELECT ''::jsonb;
^
DETAIL: The input string ended unexpectedly.
CONTEXT: JSON data, line 1:
SELECT ' '::jsonb; -- ERROR, no value
ERROR: invalid input syntax for type json
LINE 1: SELECT ' '::jsonb;
^
DETAIL: The input string ended unexpectedly.
CONTEXT: JSON data, line 1:
2021-03-01 22:44:17 +01:00
-- Multi-line JSON input to check ERROR reporting
SELECT '{
"one": 1,
"two":"two",
"three":
true}'::jsonb; -- OK
jsonb
-----------------------------------------
{"one": 1, "two": "two", "three": true}
(1 row)
SELECT '{
"one": 1,
"two":,"two", -- ERROR extraneous comma before field "two"
"three":
true}'::jsonb;
ERROR: invalid input syntax for type json
LINE 1: SELECT '{
^
DETAIL: Expected JSON value, but found ",".
CONTEXT: JSON data, line 3: "two":,...
SELECT '{
"one": 1,
"two":"two",
"averyveryveryveryveryveryveryveryveryverylongfieldname":}'::jsonb;
ERROR: invalid input syntax for type json
LINE 1: SELECT '{
^
DETAIL: Expected JSON value, but found "}".
CONTEXT: JSON data, line 4: ...yveryveryveryveryveryveryveryverylongfieldname":}
-- ERROR missing value for last field
2022-12-11 17:28:15 +01:00
-- test non-error-throwing input
select pg_input_is_valid('{"a":true}', 'jsonb');
pg_input_is_valid
-------------------
t
(1 row)
select pg_input_is_valid('{"a":true', 'jsonb');
pg_input_is_valid
-------------------
f
(1 row)
2023-02-28 00:04:13 +01:00
select * from pg_input_error_info('{"a":true', 'jsonb');
message | detail | hint | sql_error_code
------------------------------------+--------------------------------------+------+----------------
invalid input syntax for type json | The input string ended unexpectedly. | | 22P02
2022-12-11 17:28:15 +01:00
(1 row)
2023-02-28 00:04:13 +01:00
select * from pg_input_error_info('{"a":1e1000000}', 'jsonb');
message | detail | hint | sql_error_code
--------------------------------+--------+------+----------------
value overflows numeric format | | | 22003
2022-12-11 17:28:15 +01:00
(1 row)
Introduce jsonb, a structured format for storing json.
The new format accepts exactly the same data as the json type. However, it is
stored in a format that does not require reparsing the orgiginal text in order
to process it, making it much more suitable for indexing and other operations.
Insignificant whitespace is discarded, and the order of object keys is not
preserved. Neither are duplicate object keys kept - the later value for a given
key is the only one stored.
The new type has all the functions and operators that the json type has,
with the exception of the json generation functions (to_json, json_agg etc.)
and with identical semantics. In addition, there are operator classes for
hash and btree indexing, and two classes for GIN indexing, that have no
equivalent in the json type.
This feature grew out of previous work by Oleg Bartunov and Teodor Sigaev, which
was intended to provide similar facilities to a nested hstore type, but which
in the end proved to have some significant compatibility issues.
Authors: Oleg Bartunov, Teodor Sigaev, Peter Geoghegan and Andrew Dunstan.
Review: Andres Freund
2014-03-23 21:40:19 +01:00
-- make sure jsonb is passed through json generators without being escaped
SELECT array_to_json(ARRAY [jsonb '{"a":1}', jsonb '{"b":[2,3]}']);
array_to_json
--------------------------
[{"a": 1},{"b": [2, 3]}]
(1 row)
2017-02-22 17:10:49 +01:00
-- anyarray column
2019-08-21 16:43:23 +02:00
CREATE TEMP TABLE rows AS
SELECT x, 'txt' || x as y
FROM generate_series(1,3) AS x;
analyze rows;
select attname, to_jsonb(histogram_bounds) histogram_bounds
2017-02-22 17:10:49 +01:00
from pg_stats
2019-08-21 16:43:23 +02:00
where tablename = 'rows' and
schemaname = pg_my_temp_schema()::regnamespace::text
order by 1;
attname | histogram_bounds
---------+--------------------------
x | [1, 2, 3]
y | ["txt1", "txt2", "txt3"]
(2 rows)
2017-02-22 17:10:49 +01:00
2014-12-12 21:31:14 +01:00
-- to_jsonb, timestamps
select to_jsonb(timestamp '2014-05-28 12:22:35.614298');
to_jsonb
------------------------------
"2014-05-28T12:22:35.614298"
(1 row)
BEGIN;
SET LOCAL TIME ZONE 10.5;
select to_jsonb(timestamptz '2014-05-28 12:22:35.614298-04');
to_jsonb
------------------------------------
"2014-05-29T02:52:35.614298+10:30"
(1 row)
SET LOCAL TIME ZONE -8;
select to_jsonb(timestamptz '2014-05-28 12:22:35.614298-04');
to_jsonb
------------------------------------
"2014-05-28T08:22:35.614298-08:00"
(1 row)
COMMIT;
2015-02-26 18:25:21 +01:00
select to_jsonb(date '2014-05-28');
to_jsonb
--------------
"2014-05-28"
(1 row)
select to_jsonb(date 'Infinity');
to_jsonb
------------
"infinity"
(1 row)
2015-10-20 20:06:24 +02:00
select to_jsonb(date '-Infinity');
to_jsonb
-------------
"-infinity"
(1 row)
2015-02-26 18:25:21 +01:00
select to_jsonb(timestamp 'Infinity');
to_jsonb
------------
"infinity"
(1 row)
2015-10-20 20:06:24 +02:00
select to_jsonb(timestamp '-Infinity');
to_jsonb
-------------
"-infinity"
(1 row)
2015-02-26 18:25:21 +01:00
select to_jsonb(timestamptz 'Infinity');
to_jsonb
------------
"infinity"
(1 row)
2015-10-20 20:06:24 +02:00
select to_jsonb(timestamptz '-Infinity');
to_jsonb
-------------
"-infinity"
(1 row)
2014-12-12 21:31:14 +01:00
--jsonb_agg
SELECT jsonb_agg(q)
FROM ( SELECT $$a$$ || x AS b, y AS c,
ARRAY[ROW(x.*,ARRAY[1,2,3]),
ROW(y.*,ARRAY[4,5,6])] AS z
FROM generate_series(1,2) x,
generate_series(4,5) y) q;
jsonb_agg
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
[{"b": "a1", "c": 4, "z": [{"f1": 1, "f2": [1, 2, 3]}, {"f1": 4, "f2": [4, 5, 6]}]}, {"b": "a1", "c": 5, "z": [{"f1": 1, "f2": [1, 2, 3]}, {"f1": 5, "f2": [4, 5, 6]}]}, {"b": "a2", "c": 4, "z": [{"f1": 2, "f2": [1, 2, 3]}, {"f1": 4, "f2": [4, 5, 6]}]}, {"b": "a2", "c": 5, "z": [{"f1": 2, "f2": [1, 2, 3]}, {"f1": 5, "f2": [4, 5, 6]}]}]
(1 row)
2015-07-24 15:40:46 +02:00
SELECT jsonb_agg(q ORDER BY x, y)
2014-12-12 21:31:14 +01:00
FROM rows q;
jsonb_agg
-----------------------------------------------------------------------
[{"x": 1, "y": "txt1"}, {"x": 2, "y": "txt2"}, {"x": 3, "y": "txt3"}]
(1 row)
2015-07-24 15:40:46 +02:00
UPDATE rows SET x = NULL WHERE x = 1;
SELECT jsonb_agg(q ORDER BY x NULLS FIRST, y)
FROM rows q;
jsonb_agg
--------------------------------------------------------------------------
[{"x": null, "y": "txt1"}, {"x": 2, "y": "txt2"}, {"x": 3, "y": "txt3"}]
(1 row)
Introduce jsonb, a structured format for storing json.
The new format accepts exactly the same data as the json type. However, it is
stored in a format that does not require reparsing the orgiginal text in order
to process it, making it much more suitable for indexing and other operations.
Insignificant whitespace is discarded, and the order of object keys is not
preserved. Neither are duplicate object keys kept - the later value for a given
key is the only one stored.
The new type has all the functions and operators that the json type has,
with the exception of the json generation functions (to_json, json_agg etc.)
and with identical semantics. In addition, there are operator classes for
hash and btree indexing, and two classes for GIN indexing, that have no
equivalent in the json type.
This feature grew out of previous work by Oleg Bartunov and Teodor Sigaev, which
was intended to provide similar facilities to a nested hstore type, but which
in the end proved to have some significant compatibility issues.
Authors: Oleg Bartunov, Teodor Sigaev, Peter Geoghegan and Andrew Dunstan.
Review: Andres Freund
2014-03-23 21:40:19 +01:00
-- jsonb extraction functions
CREATE TEMP TABLE test_jsonb (
json_type text,
test_json jsonb
);
INSERT INTO test_jsonb VALUES
('scalar','"a scalar"'),
('array','["zero", "one","two",null,"four","five", [1,2,3],{"f1":9}]'),
('object','{"field1":"val1","field2":"val2","field3":null, "field4": 4, "field5": [1,2,3], "field6": {"f1":9}}');
SELECT test_json -> 'x' FROM test_jsonb WHERE json_type = 'scalar';
2014-08-22 19:17:58 +02:00
?column?
----------
(1 row)
Introduce jsonb, a structured format for storing json.
The new format accepts exactly the same data as the json type. However, it is
stored in a format that does not require reparsing the orgiginal text in order
to process it, making it much more suitable for indexing and other operations.
Insignificant whitespace is discarded, and the order of object keys is not
preserved. Neither are duplicate object keys kept - the later value for a given
key is the only one stored.
The new type has all the functions and operators that the json type has,
with the exception of the json generation functions (to_json, json_agg etc.)
and with identical semantics. In addition, there are operator classes for
hash and btree indexing, and two classes for GIN indexing, that have no
equivalent in the json type.
This feature grew out of previous work by Oleg Bartunov and Teodor Sigaev, which
was intended to provide similar facilities to a nested hstore type, but which
in the end proved to have some significant compatibility issues.
Authors: Oleg Bartunov, Teodor Sigaev, Peter Geoghegan and Andrew Dunstan.
Review: Andres Freund
2014-03-23 21:40:19 +01:00
SELECT test_json -> 'x' FROM test_jsonb WHERE json_type = 'array';
2014-08-22 19:17:58 +02:00
?column?
----------
(1 row)
Introduce jsonb, a structured format for storing json.
The new format accepts exactly the same data as the json type. However, it is
stored in a format that does not require reparsing the orgiginal text in order
to process it, making it much more suitable for indexing and other operations.
Insignificant whitespace is discarded, and the order of object keys is not
preserved. Neither are duplicate object keys kept - the later value for a given
key is the only one stored.
The new type has all the functions and operators that the json type has,
with the exception of the json generation functions (to_json, json_agg etc.)
and with identical semantics. In addition, there are operator classes for
hash and btree indexing, and two classes for GIN indexing, that have no
equivalent in the json type.
This feature grew out of previous work by Oleg Bartunov and Teodor Sigaev, which
was intended to provide similar facilities to a nested hstore type, but which
in the end proved to have some significant compatibility issues.
Authors: Oleg Bartunov, Teodor Sigaev, Peter Geoghegan and Andrew Dunstan.
Review: Andres Freund
2014-03-23 21:40:19 +01:00
SELECT test_json -> 'x' FROM test_jsonb WHERE json_type = 'object';
?column?
----------
(1 row)
SELECT test_json -> 'field2' FROM test_jsonb WHERE json_type = 'object';
?column?
----------
"val2"
(1 row)
SELECT test_json ->> 'field2' FROM test_jsonb WHERE json_type = 'scalar';
2014-08-22 19:17:58 +02:00
?column?
----------
(1 row)
Introduce jsonb, a structured format for storing json.
The new format accepts exactly the same data as the json type. However, it is
stored in a format that does not require reparsing the orgiginal text in order
to process it, making it much more suitable for indexing and other operations.
Insignificant whitespace is discarded, and the order of object keys is not
preserved. Neither are duplicate object keys kept - the later value for a given
key is the only one stored.
The new type has all the functions and operators that the json type has,
with the exception of the json generation functions (to_json, json_agg etc.)
and with identical semantics. In addition, there are operator classes for
hash and btree indexing, and two classes for GIN indexing, that have no
equivalent in the json type.
This feature grew out of previous work by Oleg Bartunov and Teodor Sigaev, which
was intended to provide similar facilities to a nested hstore type, but which
in the end proved to have some significant compatibility issues.
Authors: Oleg Bartunov, Teodor Sigaev, Peter Geoghegan and Andrew Dunstan.
Review: Andres Freund
2014-03-23 21:40:19 +01:00
SELECT test_json ->> 'field2' FROM test_jsonb WHERE json_type = 'array';
2014-08-22 19:17:58 +02:00
?column?
----------
(1 row)
Introduce jsonb, a structured format for storing json.
The new format accepts exactly the same data as the json type. However, it is
stored in a format that does not require reparsing the orgiginal text in order
to process it, making it much more suitable for indexing and other operations.
Insignificant whitespace is discarded, and the order of object keys is not
preserved. Neither are duplicate object keys kept - the later value for a given
key is the only one stored.
The new type has all the functions and operators that the json type has,
with the exception of the json generation functions (to_json, json_agg etc.)
and with identical semantics. In addition, there are operator classes for
hash and btree indexing, and two classes for GIN indexing, that have no
equivalent in the json type.
This feature grew out of previous work by Oleg Bartunov and Teodor Sigaev, which
was intended to provide similar facilities to a nested hstore type, but which
in the end proved to have some significant compatibility issues.
Authors: Oleg Bartunov, Teodor Sigaev, Peter Geoghegan and Andrew Dunstan.
Review: Andres Freund
2014-03-23 21:40:19 +01:00
SELECT test_json ->> 'field2' FROM test_jsonb WHERE json_type = 'object';
?column?
----------
val2
(1 row)
SELECT test_json -> 2 FROM test_jsonb WHERE json_type = 'scalar';
2014-08-22 19:17:58 +02:00
?column?
----------
(1 row)
Introduce jsonb, a structured format for storing json.
The new format accepts exactly the same data as the json type. However, it is
stored in a format that does not require reparsing the orgiginal text in order
to process it, making it much more suitable for indexing and other operations.
Insignificant whitespace is discarded, and the order of object keys is not
preserved. Neither are duplicate object keys kept - the later value for a given
key is the only one stored.
The new type has all the functions and operators that the json type has,
with the exception of the json generation functions (to_json, json_agg etc.)
and with identical semantics. In addition, there are operator classes for
hash and btree indexing, and two classes for GIN indexing, that have no
equivalent in the json type.
This feature grew out of previous work by Oleg Bartunov and Teodor Sigaev, which
was intended to provide similar facilities to a nested hstore type, but which
in the end proved to have some significant compatibility issues.
Authors: Oleg Bartunov, Teodor Sigaev, Peter Geoghegan and Andrew Dunstan.
Review: Andres Freund
2014-03-23 21:40:19 +01:00
SELECT test_json -> 2 FROM test_jsonb WHERE json_type = 'array';
?column?
----------
"two"
(1 row)
SELECT test_json -> 9 FROM test_jsonb WHERE json_type = 'array';
?column?
----------
(1 row)
SELECT test_json -> 2 FROM test_jsonb WHERE json_type = 'object';
2014-08-22 19:17:58 +02:00
?column?
----------
(1 row)
Introduce jsonb, a structured format for storing json.
The new format accepts exactly the same data as the json type. However, it is
stored in a format that does not require reparsing the orgiginal text in order
to process it, making it much more suitable for indexing and other operations.
Insignificant whitespace is discarded, and the order of object keys is not
preserved. Neither are duplicate object keys kept - the later value for a given
key is the only one stored.
The new type has all the functions and operators that the json type has,
with the exception of the json generation functions (to_json, json_agg etc.)
and with identical semantics. In addition, there are operator classes for
hash and btree indexing, and two classes for GIN indexing, that have no
equivalent in the json type.
This feature grew out of previous work by Oleg Bartunov and Teodor Sigaev, which
was intended to provide similar facilities to a nested hstore type, but which
in the end proved to have some significant compatibility issues.
Authors: Oleg Bartunov, Teodor Sigaev, Peter Geoghegan and Andrew Dunstan.
Review: Andres Freund
2014-03-23 21:40:19 +01:00
SELECT test_json ->> 6 FROM test_jsonb WHERE json_type = 'array';
?column?
-----------
[1, 2, 3]
(1 row)
SELECT test_json ->> 7 FROM test_jsonb WHERE json_type = 'array';
?column?
-----------
{"f1": 9}
(1 row)
SELECT test_json ->> 'field4' FROM test_jsonb WHERE json_type = 'object';
?column?
----------
4
(1 row)
SELECT test_json ->> 'field5' FROM test_jsonb WHERE json_type = 'object';
?column?
-----------
[1, 2, 3]
(1 row)
SELECT test_json ->> 'field6' FROM test_jsonb WHERE json_type = 'object';
?column?
-----------
{"f1": 9}
(1 row)
SELECT test_json ->> 2 FROM test_jsonb WHERE json_type = 'scalar';
2014-08-22 19:17:58 +02:00
?column?
----------
(1 row)
Introduce jsonb, a structured format for storing json.
The new format accepts exactly the same data as the json type. However, it is
stored in a format that does not require reparsing the orgiginal text in order
to process it, making it much more suitable for indexing and other operations.
Insignificant whitespace is discarded, and the order of object keys is not
preserved. Neither are duplicate object keys kept - the later value for a given
key is the only one stored.
The new type has all the functions and operators that the json type has,
with the exception of the json generation functions (to_json, json_agg etc.)
and with identical semantics. In addition, there are operator classes for
hash and btree indexing, and two classes for GIN indexing, that have no
equivalent in the json type.
This feature grew out of previous work by Oleg Bartunov and Teodor Sigaev, which
was intended to provide similar facilities to a nested hstore type, but which
in the end proved to have some significant compatibility issues.
Authors: Oleg Bartunov, Teodor Sigaev, Peter Geoghegan and Andrew Dunstan.
Review: Andres Freund
2014-03-23 21:40:19 +01:00
SELECT test_json ->> 2 FROM test_jsonb WHERE json_type = 'array';
?column?
----------
two
(1 row)
SELECT test_json ->> 2 FROM test_jsonb WHERE json_type = 'object';
2014-08-22 19:17:58 +02:00
?column?
----------
(1 row)
Introduce jsonb, a structured format for storing json.
The new format accepts exactly the same data as the json type. However, it is
stored in a format that does not require reparsing the orgiginal text in order
to process it, making it much more suitable for indexing and other operations.
Insignificant whitespace is discarded, and the order of object keys is not
preserved. Neither are duplicate object keys kept - the later value for a given
key is the only one stored.
The new type has all the functions and operators that the json type has,
with the exception of the json generation functions (to_json, json_agg etc.)
and with identical semantics. In addition, there are operator classes for
hash and btree indexing, and two classes for GIN indexing, that have no
equivalent in the json type.
This feature grew out of previous work by Oleg Bartunov and Teodor Sigaev, which
was intended to provide similar facilities to a nested hstore type, but which
in the end proved to have some significant compatibility issues.
Authors: Oleg Bartunov, Teodor Sigaev, Peter Geoghegan and Andrew Dunstan.
Review: Andres Freund
2014-03-23 21:40:19 +01:00
SELECT jsonb_object_keys(test_json) FROM test_jsonb WHERE json_type = 'scalar';
ERROR: cannot call jsonb_object_keys on a scalar
SELECT jsonb_object_keys(test_json) FROM test_jsonb WHERE json_type = 'array';
ERROR: cannot call jsonb_object_keys on an array
SELECT jsonb_object_keys(test_json) FROM test_jsonb WHERE json_type = 'object';
jsonb_object_keys
-------------------
field1
field2
field3
field4
field5
field6
(6 rows)
-- nulls
SELECT (test_json->'field3') IS NULL AS expect_false FROM test_jsonb WHERE json_type = 'object';
expect_false
--------------
f
(1 row)
SELECT (test_json->>'field3') IS NULL AS expect_true FROM test_jsonb WHERE json_type = 'object';
expect_true
-------------
t
(1 row)
SELECT (test_json->3) IS NULL AS expect_false FROM test_jsonb WHERE json_type = 'array';
expect_false
--------------
f
(1 row)
SELECT (test_json->>3) IS NULL AS expect_true FROM test_jsonb WHERE json_type = 'array';
expect_true
-------------
t
(1 row)
2014-08-20 22:48:35 +02:00
-- corner cases
select '{"a": [{"b": "c"}, {"b": "cc"}]}'::jsonb -> null::text;
?column?
----------
(1 row)
select '{"a": [{"b": "c"}, {"b": "cc"}]}'::jsonb -> null::int;
?column?
----------
(1 row)
select '{"a": [{"b": "c"}, {"b": "cc"}]}'::jsonb -> 1;
2014-08-22 19:17:58 +02:00
?column?
----------
(1 row)
2014-08-20 22:48:35 +02:00
select '{"a": [{"b": "c"}, {"b": "cc"}]}'::jsonb -> 'z';
?column?
----------
(1 row)
2014-08-21 01:05:05 +02:00
select '{"a": [{"b": "c"}, {"b": "cc"}]}'::jsonb -> '';
?column?
----------
(1 row)
2014-08-20 22:48:35 +02:00
select '[{"b": "c"}, {"b": "cc"}]'::jsonb -> 1;
?column?
-------------
{"b": "cc"}
(1 row)
select '[{"b": "c"}, {"b": "cc"}]'::jsonb -> 3;
?column?
----------
(1 row)
select '[{"b": "c"}, {"b": "cc"}]'::jsonb -> 'z';
2014-08-22 19:17:58 +02:00
?column?
----------
(1 row)
select '{"a": "c", "b": null}'::jsonb -> 'b';
?column?
----------
null
(1 row)
2014-08-20 22:48:35 +02:00
select '"foo"'::jsonb -> 1;
2014-08-22 19:17:58 +02:00
?column?
----------
(1 row)
2014-08-20 22:48:35 +02:00
select '"foo"'::jsonb -> 'z';
2014-08-22 19:17:58 +02:00
?column?
----------
(1 row)
2014-08-21 01:05:05 +02:00
select '{"a": [{"b": "c"}, {"b": "cc"}]}'::jsonb ->> null::text;
?column?
----------
(1 row)
select '{"a": [{"b": "c"}, {"b": "cc"}]}'::jsonb ->> null::int;
?column?
----------
(1 row)
select '{"a": [{"b": "c"}, {"b": "cc"}]}'::jsonb ->> 1;
2014-08-22 19:17:58 +02:00
?column?
----------
(1 row)
2014-08-21 01:05:05 +02:00
select '{"a": [{"b": "c"}, {"b": "cc"}]}'::jsonb ->> 'z';
?column?
----------
(1 row)
select '{"a": [{"b": "c"}, {"b": "cc"}]}'::jsonb ->> '';
?column?
----------
(1 row)
select '[{"b": "c"}, {"b": "cc"}]'::jsonb ->> 1;
?column?
-------------
{"b": "cc"}
(1 row)
select '[{"b": "c"}, {"b": "cc"}]'::jsonb ->> 3;
?column?
----------
(1 row)
select '[{"b": "c"}, {"b": "cc"}]'::jsonb ->> 'z';
2014-08-22 19:17:58 +02:00
?column?
----------
(1 row)
select '{"a": "c", "b": null}'::jsonb ->> 'b';
?column?
----------
(1 row)
2014-08-21 01:05:05 +02:00
select '"foo"'::jsonb ->> 1;
2014-08-22 19:17:58 +02:00
?column?
----------
(1 row)
2014-08-21 01:05:05 +02:00
select '"foo"'::jsonb ->> 'z';
2014-08-22 19:17:58 +02:00
?column?
----------
(1 row)
Introduce jsonb, a structured format for storing json.
The new format accepts exactly the same data as the json type. However, it is
stored in a format that does not require reparsing the orgiginal text in order
to process it, making it much more suitable for indexing and other operations.
Insignificant whitespace is discarded, and the order of object keys is not
preserved. Neither are duplicate object keys kept - the later value for a given
key is the only one stored.
The new type has all the functions and operators that the json type has,
with the exception of the json generation functions (to_json, json_agg etc.)
and with identical semantics. In addition, there are operator classes for
hash and btree indexing, and two classes for GIN indexing, that have no
equivalent in the json type.
This feature grew out of previous work by Oleg Bartunov and Teodor Sigaev, which
was intended to provide similar facilities to a nested hstore type, but which
in the end proved to have some significant compatibility issues.
Authors: Oleg Bartunov, Teodor Sigaev, Peter Geoghegan and Andrew Dunstan.
Review: Andres Freund
2014-03-23 21:40:19 +01:00
-- equality and inequality
SELECT '{"x":"y"}'::jsonb = '{"x":"y"}'::jsonb;
?column?
----------
t
(1 row)
SELECT '{"x":"y"}'::jsonb = '{"x":"z"}'::jsonb;
?column?
----------
f
(1 row)
SELECT '{"x":"y"}'::jsonb <> '{"x":"y"}'::jsonb;
?column?
----------
f
(1 row)
SELECT '{"x":"y"}'::jsonb <> '{"x":"z"}'::jsonb;
?column?
----------
t
(1 row)
-- containment
SELECT jsonb_contains('{"a":"b", "b":1, "c":null}', '{"a":"b"}');
jsonb_contains
----------------
t
(1 row)
SELECT jsonb_contains('{"a":"b", "b":1, "c":null}', '{"a":"b", "c":null}');
jsonb_contains
----------------
t
(1 row)
SELECT jsonb_contains('{"a":"b", "b":1, "c":null}', '{"a":"b", "g":null}');
jsonb_contains
----------------
f
(1 row)
SELECT jsonb_contains('{"a":"b", "b":1, "c":null}', '{"g":null}');
jsonb_contains
----------------
f
(1 row)
SELECT jsonb_contains('{"a":"b", "b":1, "c":null}', '{"a":"c"}');
jsonb_contains
----------------
f
(1 row)
SELECT jsonb_contains('{"a":"b", "b":1, "c":null}', '{"a":"b"}');
jsonb_contains
----------------
t
(1 row)
SELECT jsonb_contains('{"a":"b", "b":1, "c":null}', '{"a":"b", "c":"q"}');
jsonb_contains
----------------
f
(1 row)
SELECT '{"a":"b", "b":1, "c":null}'::jsonb @> '{"a":"b"}';
?column?
----------
t
(1 row)
SELECT '{"a":"b", "b":1, "c":null}'::jsonb @> '{"a":"b", "c":null}';
?column?
----------
t
(1 row)
SELECT '{"a":"b", "b":1, "c":null}'::jsonb @> '{"a":"b", "g":null}';
?column?
----------
f
(1 row)
SELECT '{"a":"b", "b":1, "c":null}'::jsonb @> '{"g":null}';
?column?
----------
f
(1 row)
SELECT '{"a":"b", "b":1, "c":null}'::jsonb @> '{"a":"c"}';
?column?
----------
f
(1 row)
SELECT '{"a":"b", "b":1, "c":null}'::jsonb @> '{"a":"b"}';
?column?
----------
t
(1 row)
SELECT '{"a":"b", "b":1, "c":null}'::jsonb @> '{"a":"b", "c":"q"}';
?column?
----------
f
(1 row)
2014-10-11 20:13:51 +02:00
SELECT '[1,2]'::jsonb @> '[1,2,2]'::jsonb;
?column?
----------
t
(1 row)
SELECT '[1,1,2]'::jsonb @> '[1,2,2]'::jsonb;
?column?
----------
t
(1 row)
SELECT '[[1,2]]'::jsonb @> '[[1,2,2]]'::jsonb;
?column?
----------
t
(1 row)
SELECT '[1,2,2]'::jsonb <@ '[1,2]'::jsonb;
?column?
----------
t
(1 row)
SELECT '[1,2,2]'::jsonb <@ '[1,1,2]'::jsonb;
?column?
----------
t
(1 row)
SELECT '[[1,2,2]]'::jsonb <@ '[[1,2]]'::jsonb;
?column?
----------
t
(1 row)
Introduce jsonb, a structured format for storing json.
The new format accepts exactly the same data as the json type. However, it is
stored in a format that does not require reparsing the orgiginal text in order
to process it, making it much more suitable for indexing and other operations.
Insignificant whitespace is discarded, and the order of object keys is not
preserved. Neither are duplicate object keys kept - the later value for a given
key is the only one stored.
The new type has all the functions and operators that the json type has,
with the exception of the json generation functions (to_json, json_agg etc.)
and with identical semantics. In addition, there are operator classes for
hash and btree indexing, and two classes for GIN indexing, that have no
equivalent in the json type.
This feature grew out of previous work by Oleg Bartunov and Teodor Sigaev, which
was intended to provide similar facilities to a nested hstore type, but which
in the end proved to have some significant compatibility issues.
Authors: Oleg Bartunov, Teodor Sigaev, Peter Geoghegan and Andrew Dunstan.
Review: Andres Freund
2014-03-23 21:40:19 +01:00
SELECT jsonb_contained('{"a":"b"}', '{"a":"b", "b":1, "c":null}');
jsonb_contained
-----------------
t
(1 row)
SELECT jsonb_contained('{"a":"b", "c":null}', '{"a":"b", "b":1, "c":null}');
jsonb_contained
-----------------
t
(1 row)
SELECT jsonb_contained('{"a":"b", "g":null}', '{"a":"b", "b":1, "c":null}');
jsonb_contained
-----------------
f
(1 row)
SELECT jsonb_contained('{"g":null}', '{"a":"b", "b":1, "c":null}');
jsonb_contained
-----------------
f
(1 row)
SELECT jsonb_contained('{"a":"c"}', '{"a":"b", "b":1, "c":null}');
jsonb_contained
-----------------
f
(1 row)
SELECT jsonb_contained('{"a":"b"}', '{"a":"b", "b":1, "c":null}');
jsonb_contained
-----------------
t
(1 row)
SELECT jsonb_contained('{"a":"b", "c":"q"}', '{"a":"b", "b":1, "c":null}');
jsonb_contained
-----------------
f
(1 row)
SELECT '{"a":"b"}'::jsonb <@ '{"a":"b", "b":1, "c":null}';
?column?
----------
t
(1 row)
SELECT '{"a":"b", "c":null}'::jsonb <@ '{"a":"b", "b":1, "c":null}';
?column?
----------
t
(1 row)
SELECT '{"a":"b", "g":null}'::jsonb <@ '{"a":"b", "b":1, "c":null}';
?column?
----------
f
(1 row)
SELECT '{"g":null}'::jsonb <@ '{"a":"b", "b":1, "c":null}';
?column?
----------
f
(1 row)
SELECT '{"a":"c"}'::jsonb <@ '{"a":"b", "b":1, "c":null}';
?column?
----------
f
(1 row)
SELECT '{"a":"b"}'::jsonb <@ '{"a":"b", "b":1, "c":null}';
?column?
----------
t
(1 row)
SELECT '{"a":"b", "c":"q"}'::jsonb <@ '{"a":"b", "b":1, "c":null}';
?column?
----------
f
(1 row)
-- Raw scalar may contain another raw scalar, array may contain a raw scalar
SELECT '[5]'::jsonb @> '[5]';
?column?
----------
t
(1 row)
SELECT '5'::jsonb @> '5';
?column?
----------
t
(1 row)
SELECT '[5]'::jsonb @> '5';
?column?
----------
t
(1 row)
-- But a raw scalar cannot contain an array
SELECT '5'::jsonb @> '[5]';
?column?
----------
f
(1 row)
-- In general, one thing should always contain itself. Test array containment:
SELECT '["9", ["7", "3"], 1]'::jsonb @> '["9", ["7", "3"], 1]'::jsonb;
?column?
----------
t
(1 row)
SELECT '["9", ["7", "3"], ["1"]]'::jsonb @> '["9", ["7", "3"], ["1"]]'::jsonb;
?column?
----------
t
(1 row)
-- array containment string matching confusion bug
SELECT '{ "name": "Bob", "tags": [ "enim", "qui"]}'::jsonb @> '{"tags":["qu"]}';
?column?
----------
f
(1 row)
-- array length
SELECT jsonb_array_length('[1,2,3,{"f1":1,"f2":[5,6]},4]');
jsonb_array_length
--------------------
5
(1 row)
SELECT jsonb_array_length('[]');
jsonb_array_length
--------------------
0
(1 row)
SELECT jsonb_array_length('{"f1":1,"f2":[5,6]}');
ERROR: cannot get array length of a non-array
SELECT jsonb_array_length('4');
ERROR: cannot get array length of a scalar
-- each
SELECT jsonb_each('{"f1":[1,2,3],"f2":{"f3":1},"f4":null}');
jsonb_each
--------------------
(f1,"[1, 2, 3]")
(f2,"{""f3"": 1}")
(f4,null)
(3 rows)
SELECT jsonb_each('{"a":{"b":"c","c":"b","1":"first"},"b":[1,2],"c":"cc","1":"first","n":null}'::jsonb) AS q;
q
------------------------------------------------------
(1,"""first""")
(a,"{""1"": ""first"", ""b"": ""c"", ""c"": ""b""}")
(b,"[1, 2]")
(c,"""cc""")
(n,null)
(5 rows)
SELECT * FROM jsonb_each('{"f1":[1,2,3],"f2":{"f3":1},"f4":null,"f5":99,"f6":"stringy"}') q;
key | value
-----+-----------
f1 | [1, 2, 3]
f2 | {"f3": 1}
f4 | null
f5 | 99
f6 | "stringy"
(5 rows)
SELECT * FROM jsonb_each('{"a":{"b":"c","c":"b","1":"first"},"b":[1,2],"c":"cc","1":"first","n":null}'::jsonb) AS q;
key | value
-----+------------------------------------
1 | "first"
a | {"1": "first", "b": "c", "c": "b"}
b | [1, 2]
c | "cc"
n | null
(5 rows)
SELECT jsonb_each_text('{"f1":[1,2,3],"f2":{"f3":1},"f4":null,"f5":"null"}');
jsonb_each_text
--------------------
(f1,"[1, 2, 3]")
(f2,"{""f3"": 1}")
(f4,)
(f5,null)
(4 rows)
SELECT jsonb_each_text('{"a":{"b":"c","c":"b","1":"first"},"b":[1,2],"c":"cc","1":"first","n":null}'::jsonb) AS q;
q
------------------------------------------------------
(1,first)
(a,"{""1"": ""first"", ""b"": ""c"", ""c"": ""b""}")
(b,"[1, 2]")
(c,cc)
(n,)
(5 rows)
SELECT * FROM jsonb_each_text('{"f1":[1,2,3],"f2":{"f3":1},"f4":null,"f5":99,"f6":"stringy"}') q;
key | value
-----+-----------
f1 | [1, 2, 3]
f2 | {"f3": 1}
f4 |
f5 | 99
f6 | stringy
(5 rows)
SELECT * FROM jsonb_each_text('{"a":{"b":"c","c":"b","1":"first"},"b":[1,2],"c":"cc","1":"first","n":null}'::jsonb) AS q;
key | value
-----+------------------------------------
1 | first
a | {"1": "first", "b": "c", "c": "b"}
b | [1, 2]
c | cc
n |
(5 rows)
-- exists
SELECT jsonb_exists('{"a":null, "b":"qq"}', 'a');
jsonb_exists
--------------
t
(1 row)
SELECT jsonb_exists('{"a":null, "b":"qq"}', 'b');
jsonb_exists
--------------
t
(1 row)
SELECT jsonb_exists('{"a":null, "b":"qq"}', 'c');
jsonb_exists
--------------
f
(1 row)
SELECT jsonb_exists('{"a":"null", "b":"qq"}', 'a');
jsonb_exists
--------------
t
(1 row)
SELECT jsonb '{"a":null, "b":"qq"}' ? 'a';
?column?
----------
t
(1 row)
SELECT jsonb '{"a":null, "b":"qq"}' ? 'b';
?column?
----------
t
(1 row)
SELECT jsonb '{"a":null, "b":"qq"}' ? 'c';
?column?
----------
f
(1 row)
SELECT jsonb '{"a":"null", "b":"qq"}' ? 'a';
?column?
----------
t
(1 row)
-- array exists - array elements should behave as keys
SELECT count(*) from testjsonb WHERE j->'array' ? 'bar';
count
-------
3
(1 row)
-- type sensitive array exists - should return no rows (since "exists" only
-- matches strings that are either object keys or array elements)
SELECT count(*) from testjsonb WHERE j->'array' ? '5'::text;
count
-------
0
(1 row)
-- However, a raw scalar is *contained* within the array
SELECT count(*) from testjsonb WHERE j->'array' @> '5'::jsonb;
count
-------
1
(1 row)
SELECT jsonb_exists_any('{"a":null, "b":"qq"}', ARRAY['a','b']);
jsonb_exists_any
------------------
t
(1 row)
SELECT jsonb_exists_any('{"a":null, "b":"qq"}', ARRAY['b','a']);
jsonb_exists_any
------------------
t
(1 row)
SELECT jsonb_exists_any('{"a":null, "b":"qq"}', ARRAY['c','a']);
jsonb_exists_any
------------------
t
(1 row)
SELECT jsonb_exists_any('{"a":null, "b":"qq"}', ARRAY['c','d']);
jsonb_exists_any
------------------
f
(1 row)
SELECT jsonb_exists_any('{"a":null, "b":"qq"}', '{}'::text[]);
jsonb_exists_any
------------------
f
(1 row)
SELECT jsonb '{"a":null, "b":"qq"}' ?| ARRAY['a','b'];
?column?
----------
t
(1 row)
SELECT jsonb '{"a":null, "b":"qq"}' ?| ARRAY['b','a'];
?column?
----------
t
(1 row)
SELECT jsonb '{"a":null, "b":"qq"}' ?| ARRAY['c','a'];
?column?
----------
t
(1 row)
SELECT jsonb '{"a":null, "b":"qq"}' ?| ARRAY['c','d'];
?column?
----------
f
(1 row)
SELECT jsonb '{"a":null, "b":"qq"}' ?| '{}'::text[];
?column?
----------
f
(1 row)
SELECT jsonb_exists_all('{"a":null, "b":"qq"}', ARRAY['a','b']);
jsonb_exists_all
------------------
t
(1 row)
SELECT jsonb_exists_all('{"a":null, "b":"qq"}', ARRAY['b','a']);
jsonb_exists_all
------------------
t
(1 row)
SELECT jsonb_exists_all('{"a":null, "b":"qq"}', ARRAY['c','a']);
jsonb_exists_all
------------------
f
(1 row)
SELECT jsonb_exists_all('{"a":null, "b":"qq"}', ARRAY['c','d']);
jsonb_exists_all
------------------
f
(1 row)
SELECT jsonb_exists_all('{"a":null, "b":"qq"}', '{}'::text[]);
jsonb_exists_all
------------------
t
(1 row)
SELECT jsonb '{"a":null, "b":"qq"}' ?& ARRAY['a','b'];
?column?
----------
t
(1 row)
SELECT jsonb '{"a":null, "b":"qq"}' ?& ARRAY['b','a'];
?column?
----------
t
(1 row)
SELECT jsonb '{"a":null, "b":"qq"}' ?& ARRAY['c','a'];
?column?
----------
f
(1 row)
SELECT jsonb '{"a":null, "b":"qq"}' ?& ARRAY['c','d'];
?column?
----------
f
(1 row)
SELECT jsonb '{"a":null, "b":"qq"}' ?& ARRAY['a','a', 'b', 'b', 'b'];
?column?
----------
t
(1 row)
SELECT jsonb '{"a":null, "b":"qq"}' ?& '{}'::text[];
?column?
----------
t
(1 row)
-- typeof
SELECT jsonb_typeof('{}') AS object;
object
--------
object
(1 row)
SELECT jsonb_typeof('{"c":3,"p":"o"}') AS object;
object
--------
object
(1 row)
SELECT jsonb_typeof('[]') AS array;
array
-------
array
(1 row)
SELECT jsonb_typeof('["a", 1]') AS array;
array
-------
array
(1 row)
SELECT jsonb_typeof('null') AS "null";
null
------
null
(1 row)
SELECT jsonb_typeof('1') AS number;
number
--------
number
(1 row)
SELECT jsonb_typeof('-1') AS number;
number
--------
number
(1 row)
SELECT jsonb_typeof('1.0') AS number;
number
--------
number
(1 row)
SELECT jsonb_typeof('1e2') AS number;
number
--------
number
(1 row)
SELECT jsonb_typeof('-1.0') AS number;
number
--------
number
(1 row)
SELECT jsonb_typeof('true') AS boolean;
boolean
---------
boolean
(1 row)
SELECT jsonb_typeof('false') AS boolean;
boolean
---------
boolean
(1 row)
SELECT jsonb_typeof('"hello"') AS string;
string
--------
string
(1 row)
SELECT jsonb_typeof('"true"') AS string;
string
--------
string
(1 row)
SELECT jsonb_typeof('"1.0"') AS string;
string
--------
string
(1 row)
2014-12-12 21:31:14 +01:00
-- jsonb_build_array, jsonb_build_object, jsonb_object_agg
SELECT jsonb_build_array('a',1,'b',1.2,'c',true,'d',null,'e',json '{"x": 3, "y": [1,2,3]}');
jsonb_build_array
-------------------------------------------------------------------------
["a", 1, "b", 1.2, "c", true, "d", null, "e", {"x": 3, "y": [1, 2, 3]}]
(1 row)
2017-10-25 13:34:00 +02:00
SELECT jsonb_build_array('a', NULL); -- ok
jsonb_build_array
-------------------
["a", null]
(1 row)
SELECT jsonb_build_array(VARIADIC NULL::text[]); -- ok
jsonb_build_array
-------------------
(1 row)
SELECT jsonb_build_array(VARIADIC '{}'::text[]); -- ok
jsonb_build_array
-------------------
[]
(1 row)
SELECT jsonb_build_array(VARIADIC '{a,b,c}'::text[]); -- ok
jsonb_build_array
-------------------
["a", "b", "c"]
(1 row)
SELECT jsonb_build_array(VARIADIC ARRAY['a', NULL]::text[]); -- ok
jsonb_build_array
-------------------
["a", null]
(1 row)
SELECT jsonb_build_array(VARIADIC '{1,2,3,4}'::text[]); -- ok
jsonb_build_array
----------------------
["1", "2", "3", "4"]
(1 row)
SELECT jsonb_build_array(VARIADIC '{1,2,3,4}'::int[]); -- ok
jsonb_build_array
-------------------
[1, 2, 3, 4]
(1 row)
SELECT jsonb_build_array(VARIADIC '{{1,4},{2,5},{3,6}}'::int[][]); -- ok
jsonb_build_array
--------------------
[1, 4, 2, 5, 3, 6]
(1 row)
2014-12-12 21:31:14 +01:00
SELECT jsonb_build_object('a',1,'b',1.2,'c',true,'d',null,'e',json '{"x": 3, "y": [1,2,3]}');
jsonb_build_object
-------------------------------------------------------------------------
{"a": 1, "b": 1.2, "c": true, "d": null, "e": {"x": 3, "y": [1, 2, 3]}}
(1 row)
SELECT jsonb_build_object(
'a', jsonb_build_object('b',false,'c',99),
'd', jsonb_build_object('e',array[9,8,7]::int[],
'f', (select row_to_json(r) from ( select relkind, oid::regclass as name from pg_class where relname = 'pg_class') r)));
jsonb_build_object
------------------------------------------------------------------------------------------------
{"a": {"b": false, "c": 99}, "d": {"e": [9, 8, 7], "f": {"name": "pg_class", "relkind": "r"}}}
(1 row)
2017-10-25 13:34:00 +02:00
SELECT jsonb_build_object('{a,b,c}'::text[]); -- error
ERROR: argument list must have even number of elements
HINT: The arguments of jsonb_build_object() must consist of alternating keys and values.
SELECT jsonb_build_object('{a,b,c}'::text[], '{d,e,f}'::text[]); -- error, key cannot be array
ERROR: key value must be scalar, not array, composite, or json
SELECT jsonb_build_object('a', 'b', 'c'); -- error
ERROR: argument list must have even number of elements
HINT: The arguments of jsonb_build_object() must consist of alternating keys and values.
SELECT jsonb_build_object(NULL, 'a'); -- error, key cannot be NULL
ERROR: argument 1: key must not be null
SELECT jsonb_build_object('a', NULL); -- ok
jsonb_build_object
--------------------
{"a": null}
(1 row)
SELECT jsonb_build_object(VARIADIC NULL::text[]); -- ok
jsonb_build_object
--------------------
(1 row)
SELECT jsonb_build_object(VARIADIC '{}'::text[]); -- ok
jsonb_build_object
--------------------
{}
(1 row)
SELECT jsonb_build_object(VARIADIC '{a,b,c}'::text[]); -- error
ERROR: argument list must have even number of elements
HINT: The arguments of jsonb_build_object() must consist of alternating keys and values.
SELECT jsonb_build_object(VARIADIC ARRAY['a', NULL]::text[]); -- ok
jsonb_build_object
--------------------
{"a": null}
(1 row)
SELECT jsonb_build_object(VARIADIC ARRAY[NULL, 'a']::text[]); -- error, key cannot be NULL
ERROR: argument 1: key must not be null
SELECT jsonb_build_object(VARIADIC '{1,2,3,4}'::text[]); -- ok
jsonb_build_object
----------------------
{"1": "2", "3": "4"}
(1 row)
SELECT jsonb_build_object(VARIADIC '{1,2,3,4}'::int[]); -- ok
jsonb_build_object
--------------------
{"1": 2, "3": 4}
(1 row)
SELECT jsonb_build_object(VARIADIC '{{1,4},{2,5},{3,6}}'::int[][]); -- ok
jsonb_build_object
--------------------------
{"1": 4, "2": 5, "3": 6}
(1 row)
2014-12-12 21:31:14 +01:00
-- empty objects/arrays
SELECT jsonb_build_array();
jsonb_build_array
-------------------
[]
(1 row)
SELECT jsonb_build_object();
jsonb_build_object
--------------------
{}
(1 row)
-- make sure keys are quoted
SELECT jsonb_build_object(1,2);
jsonb_build_object
--------------------
{"1": 2}
(1 row)
-- keys must be scalar and not null
SELECT jsonb_build_object(null,2);
2015-11-17 03:16:42 +01:00
ERROR: argument 1: key must not be null
2014-12-12 21:31:14 +01:00
SELECT jsonb_build_object(r,2) FROM (SELECT 1 AS a, 2 AS b) r;
2015-10-29 01:23:53 +01:00
ERROR: key value must be scalar, not array, composite, or json
2014-12-12 21:31:14 +01:00
SELECT jsonb_build_object(json '{"a":1,"b":2}', 3);
2015-10-29 01:23:53 +01:00
ERROR: key value must be scalar, not array, composite, or json
2014-12-12 21:31:14 +01:00
SELECT jsonb_build_object('{1,2,3}'::int[], 3);
2015-10-29 01:23:53 +01:00
ERROR: key value must be scalar, not array, composite, or json
2015-10-15 19:46:09 +02:00
-- handling of NULL values
SELECT jsonb_object_agg(1, NULL::jsonb);
jsonb_object_agg
------------------
{"1": null}
(1 row)
SELECT jsonb_object_agg(NULL, '{"a":1}');
ERROR: field name must not be null
2014-12-12 21:31:14 +01:00
CREATE TEMP TABLE foo (serial_num int, name text, type text);
INSERT INTO foo VALUES (847001,'t15','GE1043');
INSERT INTO foo VALUES (847002,'t16','GE1043');
INSERT INTO foo VALUES (847003,'sub-alpha','GESS90');
SELECT jsonb_build_object('turbines',jsonb_object_agg(serial_num,jsonb_build_object('name',name,'type',type)))
FROM foo;
jsonb_build_object
-------------------------------------------------------------------------------------------------------------------------------------------------------------
{"turbines": {"847001": {"name": "t15", "type": "GE1043"}, "847002": {"name": "t16", "type": "GE1043"}, "847003": {"name": "sub-alpha", "type": "GESS90"}}}
(1 row)
2015-07-24 15:40:46 +02:00
SELECT jsonb_object_agg(name, type) FROM foo;
jsonb_object_agg
-----------------------------------------------------------
{"t15": "GE1043", "t16": "GE1043", "sub-alpha": "GESS90"}
(1 row)
INSERT INTO foo VALUES (999999, NULL, 'bar');
SELECT jsonb_object_agg(name, type) FROM foo;
ERROR: field name must not be null
2023-11-06 16:38:00 +01:00
-- edge case for parser
SELECT jsonb_object_agg(DISTINCT 'a', 'abc');
jsonb_object_agg
------------------
{"a": "abc"}
(1 row)
2014-12-12 21:31:14 +01:00
-- jsonb_object
2016-02-21 16:30:49 +01:00
-- empty object, one dimension
SELECT jsonb_object('{}');
jsonb_object
--------------
{}
(1 row)
-- empty object, two dimensions
SELECT jsonb_object('{}', '{}');
jsonb_object
--------------
{}
(1 row)
2014-12-12 21:31:14 +01:00
-- one dimension
SELECT jsonb_object('{a,1,b,2,3,NULL,"d e f","a b c"}');
jsonb_object
---------------------------------------------------
{"3": null, "a": "1", "b": "2", "d e f": "a b c"}
(1 row)
-- same but with two dimensions
SELECT jsonb_object('{{a,1},{b,2},{3,NULL},{"d e f","a b c"}}');
jsonb_object
---------------------------------------------------
{"3": null, "a": "1", "b": "2", "d e f": "a b c"}
(1 row)
-- odd number error
SELECT jsonb_object('{a,b,c}');
ERROR: array must have even number of elements
-- one column error
SELECT jsonb_object('{{a},{b}}');
ERROR: array must have two columns
-- too many columns error
SELECT jsonb_object('{{a,b,c},{b,c,d}}');
ERROR: array must have two columns
-- too many dimensions error
SELECT jsonb_object('{{{a,b},{c,d}},{{b,c},{d,e}}}');
ERROR: wrong number of array subscripts
--two argument form of jsonb_object
select jsonb_object('{a,b,c,"d e f"}','{1,2,3,"a b c"}');
jsonb_object
--------------------------------------------------
{"a": "1", "b": "2", "c": "3", "d e f": "a b c"}
(1 row)
-- too many dimensions
SELECT jsonb_object('{{a,1},{b,2},{3,NULL},{"d e f","a b c"}}', '{{a,1},{b,2},{3,NULL},{"d e f","a b c"}}');
ERROR: wrong number of array subscripts
-- mismatched dimensions
select jsonb_object('{a,b,c,"d e f",g}','{1,2,3,"a b c"}');
ERROR: mismatched array dimensions
select jsonb_object('{a,b,c,"d e f"}','{1,2,3,"a b c",g}');
ERROR: mismatched array dimensions
-- null key error
select jsonb_object('{a,b,NULL,"d e f"}','{1,2,3,"a b c"}');
ERROR: null value not allowed for object key
-- empty key is allowed
select jsonb_object('{a,b,"","d e f"}','{1,2,3,"a b c"}');
jsonb_object
-------------------------------------------------
{"": "3", "a": "1", "b": "2", "d e f": "a b c"}
(1 row)
Introduce jsonb, a structured format for storing json.
The new format accepts exactly the same data as the json type. However, it is
stored in a format that does not require reparsing the orgiginal text in order
to process it, making it much more suitable for indexing and other operations.
Insignificant whitespace is discarded, and the order of object keys is not
preserved. Neither are duplicate object keys kept - the later value for a given
key is the only one stored.
The new type has all the functions and operators that the json type has,
with the exception of the json generation functions (to_json, json_agg etc.)
and with identical semantics. In addition, there are operator classes for
hash and btree indexing, and two classes for GIN indexing, that have no
equivalent in the json type.
This feature grew out of previous work by Oleg Bartunov and Teodor Sigaev, which
was intended to provide similar facilities to a nested hstore type, but which
in the end proved to have some significant compatibility issues.
Authors: Oleg Bartunov, Teodor Sigaev, Peter Geoghegan and Andrew Dunstan.
Review: Andres Freund
2014-03-23 21:40:19 +01:00
-- extract_path, extract_path_as_text
SELECT jsonb_extract_path('{"f2":{"f3":1},"f4":{"f5":99,"f6":"stringy"}}','f4','f6');
jsonb_extract_path
--------------------
"stringy"
(1 row)
SELECT jsonb_extract_path('{"f2":{"f3":1},"f4":{"f5":99,"f6":"stringy"}}','f2');
jsonb_extract_path
--------------------
{"f3": 1}
(1 row)
SELECT jsonb_extract_path('{"f2":["f3",1],"f4":{"f5":99,"f6":"stringy"}}','f2',0::text);
jsonb_extract_path
--------------------
"f3"
(1 row)
SELECT jsonb_extract_path('{"f2":["f3",1],"f4":{"f5":99,"f6":"stringy"}}','f2',1::text);
jsonb_extract_path
--------------------
1
(1 row)
SELECT jsonb_extract_path_text('{"f2":{"f3":1},"f4":{"f5":99,"f6":"stringy"}}','f4','f6');
jsonb_extract_path_text
-------------------------
stringy
(1 row)
SELECT jsonb_extract_path_text('{"f2":{"f3":1},"f4":{"f5":99,"f6":"stringy"}}','f2');
jsonb_extract_path_text
-------------------------
{"f3": 1}
(1 row)
SELECT jsonb_extract_path_text('{"f2":["f3",1],"f4":{"f5":99,"f6":"stringy"}}','f2',0::text);
jsonb_extract_path_text
-------------------------
f3
(1 row)
SELECT jsonb_extract_path_text('{"f2":["f3",1],"f4":{"f5":99,"f6":"stringy"}}','f2',1::text);
jsonb_extract_path_text
-------------------------
1
(1 row)
-- extract_path nulls
SELECT jsonb_extract_path('{"f2":{"f3":1},"f4":{"f5":null,"f6":"stringy"}}','f4','f5') IS NULL AS expect_false;
expect_false
--------------
f
(1 row)
SELECT jsonb_extract_path_text('{"f2":{"f3":1},"f4":{"f5":null,"f6":"stringy"}}','f4','f5') IS NULL AS expect_true;
expect_true
-------------
t
(1 row)
SELECT jsonb_extract_path('{"f2":{"f3":1},"f4":[0,1,2,null]}','f4','3') IS NULL AS expect_false;
expect_false
--------------
f
(1 row)
SELECT jsonb_extract_path_text('{"f2":{"f3":1},"f4":[0,1,2,null]}','f4','3') IS NULL AS expect_true;
expect_true
-------------
t
(1 row)
-- extract_path operators
SELECT '{"f2":{"f3":1},"f4":{"f5":99,"f6":"stringy"}}'::jsonb#>array['f4','f6'];
?column?
-----------
"stringy"
(1 row)
SELECT '{"f2":{"f3":1},"f4":{"f5":99,"f6":"stringy"}}'::jsonb#>array['f2'];
?column?
-----------
{"f3": 1}
(1 row)
SELECT '{"f2":["f3",1],"f4":{"f5":99,"f6":"stringy"}}'::jsonb#>array['f2','0'];
?column?
----------
"f3"
(1 row)
SELECT '{"f2":["f3",1],"f4":{"f5":99,"f6":"stringy"}}'::jsonb#>array['f2','1'];
?column?
----------
1
(1 row)
SELECT '{"f2":{"f3":1},"f4":{"f5":99,"f6":"stringy"}}'::jsonb#>>array['f4','f6'];
?column?
----------
stringy
(1 row)
SELECT '{"f2":{"f3":1},"f4":{"f5":99,"f6":"stringy"}}'::jsonb#>>array['f2'];
?column?
-----------
{"f3": 1}
(1 row)
SELECT '{"f2":["f3",1],"f4":{"f5":99,"f6":"stringy"}}'::jsonb#>>array['f2','0'];
?column?
----------
f3
(1 row)
SELECT '{"f2":["f3",1],"f4":{"f5":99,"f6":"stringy"}}'::jsonb#>>array['f2','1'];
?column?
----------
1
(1 row)
2014-08-20 22:48:35 +02:00
-- corner cases for same
2014-08-21 01:05:05 +02:00
select '{"a": {"b":{"c": "foo"}}}'::jsonb #> '{}';
2014-08-22 19:17:58 +02:00
?column?
----------------------------
{"a": {"b": {"c": "foo"}}}
(1 row)
select '[1,2,3]'::jsonb #> '{}';
?column?
-----------
[1, 2, 3]
(1 row)
select '"foo"'::jsonb #> '{}';
2014-08-20 22:48:35 +02:00
?column?
----------
2014-08-22 19:17:58 +02:00
"foo"
(1 row)
select '42'::jsonb #> '{}';
?column?
----------
42
(1 row)
select 'null'::jsonb #> '{}';
?column?
----------
null
Introduce jsonb, a structured format for storing json.
The new format accepts exactly the same data as the json type. However, it is
stored in a format that does not require reparsing the orgiginal text in order
to process it, making it much more suitable for indexing and other operations.
Insignificant whitespace is discarded, and the order of object keys is not
preserved. Neither are duplicate object keys kept - the later value for a given
key is the only one stored.
The new type has all the functions and operators that the json type has,
with the exception of the json generation functions (to_json, json_agg etc.)
and with identical semantics. In addition, there are operator classes for
hash and btree indexing, and two classes for GIN indexing, that have no
equivalent in the json type.
This feature grew out of previous work by Oleg Bartunov and Teodor Sigaev, which
was intended to provide similar facilities to a nested hstore type, but which
in the end proved to have some significant compatibility issues.
Authors: Oleg Bartunov, Teodor Sigaev, Peter Geoghegan and Andrew Dunstan.
Review: Andres Freund
2014-03-23 21:40:19 +01:00
(1 row)
2014-08-20 22:48:35 +02:00
select '{"a": {"b":{"c": "foo"}}}'::jsonb #> array['a'];
?column?
---------------------
{"b": {"c": "foo"}}
(1 row)
2014-08-21 01:05:05 +02:00
select '{"a": {"b":{"c": "foo"}}}'::jsonb #> array['a', null];
2014-08-22 19:17:58 +02:00
?column?
----------
(1 row)
2014-08-21 01:05:05 +02:00
select '{"a": {"b":{"c": "foo"}}}'::jsonb #> array['a', ''];
?column?
----------
(1 row)
2014-08-20 22:48:35 +02:00
select '{"a": {"b":{"c": "foo"}}}'::jsonb #> array['a','b'];
?column?
--------------
{"c": "foo"}
Introduce jsonb, a structured format for storing json.
The new format accepts exactly the same data as the json type. However, it is
stored in a format that does not require reparsing the orgiginal text in order
to process it, making it much more suitable for indexing and other operations.
Insignificant whitespace is discarded, and the order of object keys is not
preserved. Neither are duplicate object keys kept - the later value for a given
key is the only one stored.
The new type has all the functions and operators that the json type has,
with the exception of the json generation functions (to_json, json_agg etc.)
and with identical semantics. In addition, there are operator classes for
hash and btree indexing, and two classes for GIN indexing, that have no
equivalent in the json type.
This feature grew out of previous work by Oleg Bartunov and Teodor Sigaev, which
was intended to provide similar facilities to a nested hstore type, but which
in the end proved to have some significant compatibility issues.
Authors: Oleg Bartunov, Teodor Sigaev, Peter Geoghegan and Andrew Dunstan.
Review: Andres Freund
2014-03-23 21:40:19 +01:00
(1 row)
2014-08-20 22:48:35 +02:00
select '{"a": {"b":{"c": "foo"}}}'::jsonb #> array['a','b','c'];
Introduce jsonb, a structured format for storing json.
The new format accepts exactly the same data as the json type. However, it is
stored in a format that does not require reparsing the orgiginal text in order
to process it, making it much more suitable for indexing and other operations.
Insignificant whitespace is discarded, and the order of object keys is not
preserved. Neither are duplicate object keys kept - the later value for a given
key is the only one stored.
The new type has all the functions and operators that the json type has,
with the exception of the json generation functions (to_json, json_agg etc.)
and with identical semantics. In addition, there are operator classes for
hash and btree indexing, and two classes for GIN indexing, that have no
equivalent in the json type.
This feature grew out of previous work by Oleg Bartunov and Teodor Sigaev, which
was intended to provide similar facilities to a nested hstore type, but which
in the end proved to have some significant compatibility issues.
Authors: Oleg Bartunov, Teodor Sigaev, Peter Geoghegan and Andrew Dunstan.
Review: Andres Freund
2014-03-23 21:40:19 +01:00
?column?
----------
2014-08-20 22:48:35 +02:00
"foo"
Introduce jsonb, a structured format for storing json.
The new format accepts exactly the same data as the json type. However, it is
stored in a format that does not require reparsing the orgiginal text in order
to process it, making it much more suitable for indexing and other operations.
Insignificant whitespace is discarded, and the order of object keys is not
preserved. Neither are duplicate object keys kept - the later value for a given
key is the only one stored.
The new type has all the functions and operators that the json type has,
with the exception of the json generation functions (to_json, json_agg etc.)
and with identical semantics. In addition, there are operator classes for
hash and btree indexing, and two classes for GIN indexing, that have no
equivalent in the json type.
This feature grew out of previous work by Oleg Bartunov and Teodor Sigaev, which
was intended to provide similar facilities to a nested hstore type, but which
in the end proved to have some significant compatibility issues.
Authors: Oleg Bartunov, Teodor Sigaev, Peter Geoghegan and Andrew Dunstan.
Review: Andres Freund
2014-03-23 21:40:19 +01:00
(1 row)
2014-08-20 22:48:35 +02:00
select '{"a": {"b":{"c": "foo"}}}'::jsonb #> array['a','b','c','d'];
Introduce jsonb, a structured format for storing json.
The new format accepts exactly the same data as the json type. However, it is
stored in a format that does not require reparsing the orgiginal text in order
to process it, making it much more suitable for indexing and other operations.
Insignificant whitespace is discarded, and the order of object keys is not
preserved. Neither are duplicate object keys kept - the later value for a given
key is the only one stored.
The new type has all the functions and operators that the json type has,
with the exception of the json generation functions (to_json, json_agg etc.)
and with identical semantics. In addition, there are operator classes for
hash and btree indexing, and two classes for GIN indexing, that have no
equivalent in the json type.
This feature grew out of previous work by Oleg Bartunov and Teodor Sigaev, which
was intended to provide similar facilities to a nested hstore type, but which
in the end proved to have some significant compatibility issues.
Authors: Oleg Bartunov, Teodor Sigaev, Peter Geoghegan and Andrew Dunstan.
Review: Andres Freund
2014-03-23 21:40:19 +01:00
?column?
----------
2014-08-20 22:48:35 +02:00
Introduce jsonb, a structured format for storing json.
The new format accepts exactly the same data as the json type. However, it is
stored in a format that does not require reparsing the orgiginal text in order
to process it, making it much more suitable for indexing and other operations.
Insignificant whitespace is discarded, and the order of object keys is not
preserved. Neither are duplicate object keys kept - the later value for a given
key is the only one stored.
The new type has all the functions and operators that the json type has,
with the exception of the json generation functions (to_json, json_agg etc.)
and with identical semantics. In addition, there are operator classes for
hash and btree indexing, and two classes for GIN indexing, that have no
equivalent in the json type.
This feature grew out of previous work by Oleg Bartunov and Teodor Sigaev, which
was intended to provide similar facilities to a nested hstore type, but which
in the end proved to have some significant compatibility issues.
Authors: Oleg Bartunov, Teodor Sigaev, Peter Geoghegan and Andrew Dunstan.
Review: Andres Freund
2014-03-23 21:40:19 +01:00
(1 row)
2014-08-20 22:48:35 +02:00
select '{"a": {"b":{"c": "foo"}}}'::jsonb #> array['a','z','c'];
Introduce jsonb, a structured format for storing json.
The new format accepts exactly the same data as the json type. However, it is
stored in a format that does not require reparsing the orgiginal text in order
to process it, making it much more suitable for indexing and other operations.
Insignificant whitespace is discarded, and the order of object keys is not
preserved. Neither are duplicate object keys kept - the later value for a given
key is the only one stored.
The new type has all the functions and operators that the json type has,
with the exception of the json generation functions (to_json, json_agg etc.)
and with identical semantics. In addition, there are operator classes for
hash and btree indexing, and two classes for GIN indexing, that have no
equivalent in the json type.
This feature grew out of previous work by Oleg Bartunov and Teodor Sigaev, which
was intended to provide similar facilities to a nested hstore type, but which
in the end proved to have some significant compatibility issues.
Authors: Oleg Bartunov, Teodor Sigaev, Peter Geoghegan and Andrew Dunstan.
Review: Andres Freund
2014-03-23 21:40:19 +01:00
?column?
----------
2014-08-20 22:48:35 +02:00
Introduce jsonb, a structured format for storing json.
The new format accepts exactly the same data as the json type. However, it is
stored in a format that does not require reparsing the orgiginal text in order
to process it, making it much more suitable for indexing and other operations.
Insignificant whitespace is discarded, and the order of object keys is not
preserved. Neither are duplicate object keys kept - the later value for a given
key is the only one stored.
The new type has all the functions and operators that the json type has,
with the exception of the json generation functions (to_json, json_agg etc.)
and with identical semantics. In addition, there are operator classes for
hash and btree indexing, and two classes for GIN indexing, that have no
equivalent in the json type.
This feature grew out of previous work by Oleg Bartunov and Teodor Sigaev, which
was intended to provide similar facilities to a nested hstore type, but which
in the end proved to have some significant compatibility issues.
Authors: Oleg Bartunov, Teodor Sigaev, Peter Geoghegan and Andrew Dunstan.
Review: Andres Freund
2014-03-23 21:40:19 +01:00
(1 row)
2014-08-20 22:48:35 +02:00
select '{"a": [{"b": "c"}, {"b": "cc"}]}'::jsonb #> array['a','1','b'];
?column?
----------
"cc"
Introduce jsonb, a structured format for storing json.
The new format accepts exactly the same data as the json type. However, it is
stored in a format that does not require reparsing the orgiginal text in order
to process it, making it much more suitable for indexing and other operations.
Insignificant whitespace is discarded, and the order of object keys is not
preserved. Neither are duplicate object keys kept - the later value for a given
key is the only one stored.
The new type has all the functions and operators that the json type has,
with the exception of the json generation functions (to_json, json_agg etc.)
and with identical semantics. In addition, there are operator classes for
hash and btree indexing, and two classes for GIN indexing, that have no
equivalent in the json type.
This feature grew out of previous work by Oleg Bartunov and Teodor Sigaev, which
was intended to provide similar facilities to a nested hstore type, but which
in the end proved to have some significant compatibility issues.
Authors: Oleg Bartunov, Teodor Sigaev, Peter Geoghegan and Andrew Dunstan.
Review: Andres Freund
2014-03-23 21:40:19 +01:00
(1 row)
2014-08-20 22:48:35 +02:00
select '{"a": [{"b": "c"}, {"b": "cc"}]}'::jsonb #> array['a','z','b'];
Introduce jsonb, a structured format for storing json.
The new format accepts exactly the same data as the json type. However, it is
stored in a format that does not require reparsing the orgiginal text in order
to process it, making it much more suitable for indexing and other operations.
Insignificant whitespace is discarded, and the order of object keys is not
preserved. Neither are duplicate object keys kept - the later value for a given
key is the only one stored.
The new type has all the functions and operators that the json type has,
with the exception of the json generation functions (to_json, json_agg etc.)
and with identical semantics. In addition, there are operator classes for
hash and btree indexing, and two classes for GIN indexing, that have no
equivalent in the json type.
This feature grew out of previous work by Oleg Bartunov and Teodor Sigaev, which
was intended to provide similar facilities to a nested hstore type, but which
in the end proved to have some significant compatibility issues.
Authors: Oleg Bartunov, Teodor Sigaev, Peter Geoghegan and Andrew Dunstan.
Review: Andres Freund
2014-03-23 21:40:19 +01:00
?column?
----------
2014-08-20 22:48:35 +02:00
Introduce jsonb, a structured format for storing json.
The new format accepts exactly the same data as the json type. However, it is
stored in a format that does not require reparsing the orgiginal text in order
to process it, making it much more suitable for indexing and other operations.
Insignificant whitespace is discarded, and the order of object keys is not
preserved. Neither are duplicate object keys kept - the later value for a given
key is the only one stored.
The new type has all the functions and operators that the json type has,
with the exception of the json generation functions (to_json, json_agg etc.)
and with identical semantics. In addition, there are operator classes for
hash and btree indexing, and two classes for GIN indexing, that have no
equivalent in the json type.
This feature grew out of previous work by Oleg Bartunov and Teodor Sigaev, which
was intended to provide similar facilities to a nested hstore type, but which
in the end proved to have some significant compatibility issues.
Authors: Oleg Bartunov, Teodor Sigaev, Peter Geoghegan and Andrew Dunstan.
Review: Andres Freund
2014-03-23 21:40:19 +01:00
(1 row)
2014-08-20 22:48:35 +02:00
select '[{"b": "c"}, {"b": "cc"}]'::jsonb #> array['1','b'];
Introduce jsonb, a structured format for storing json.
The new format accepts exactly the same data as the json type. However, it is
stored in a format that does not require reparsing the orgiginal text in order
to process it, making it much more suitable for indexing and other operations.
Insignificant whitespace is discarded, and the order of object keys is not
preserved. Neither are duplicate object keys kept - the later value for a given
key is the only one stored.
The new type has all the functions and operators that the json type has,
with the exception of the json generation functions (to_json, json_agg etc.)
and with identical semantics. In addition, there are operator classes for
hash and btree indexing, and two classes for GIN indexing, that have no
equivalent in the json type.
This feature grew out of previous work by Oleg Bartunov and Teodor Sigaev, which
was intended to provide similar facilities to a nested hstore type, but which
in the end proved to have some significant compatibility issues.
Authors: Oleg Bartunov, Teodor Sigaev, Peter Geoghegan and Andrew Dunstan.
Review: Andres Freund
2014-03-23 21:40:19 +01:00
?column?
----------
2014-08-20 22:48:35 +02:00
"cc"
Introduce jsonb, a structured format for storing json.
The new format accepts exactly the same data as the json type. However, it is
stored in a format that does not require reparsing the orgiginal text in order
to process it, making it much more suitable for indexing and other operations.
Insignificant whitespace is discarded, and the order of object keys is not
preserved. Neither are duplicate object keys kept - the later value for a given
key is the only one stored.
The new type has all the functions and operators that the json type has,
with the exception of the json generation functions (to_json, json_agg etc.)
and with identical semantics. In addition, there are operator classes for
hash and btree indexing, and two classes for GIN indexing, that have no
equivalent in the json type.
This feature grew out of previous work by Oleg Bartunov and Teodor Sigaev, which
was intended to provide similar facilities to a nested hstore type, but which
in the end proved to have some significant compatibility issues.
Authors: Oleg Bartunov, Teodor Sigaev, Peter Geoghegan and Andrew Dunstan.
Review: Andres Freund
2014-03-23 21:40:19 +01:00
(1 row)
2014-08-20 22:48:35 +02:00
select '[{"b": "c"}, {"b": "cc"}]'::jsonb #> array['z','b'];
?column?
----------
(1 row)
2014-08-22 19:17:58 +02:00
select '[{"b": "c"}, {"b": null}]'::jsonb #> array['1','b'];
?column?
----------
null
(1 row)
2014-08-20 22:48:35 +02:00
select '"foo"'::jsonb #> array['z'];
2014-08-22 19:17:58 +02:00
?column?
----------
(1 row)
2014-08-20 22:48:35 +02:00
select '42'::jsonb #> array['f2'];
2014-08-22 19:17:58 +02:00
?column?
----------
(1 row)
2014-08-20 22:48:35 +02:00
select '42'::jsonb #> array['0'];
2014-08-22 19:17:58 +02:00
?column?
----------
(1 row)
2014-08-21 01:05:05 +02:00
select '{"a": {"b":{"c": "foo"}}}'::jsonb #>> '{}';
2014-08-22 19:17:58 +02:00
?column?
----------------------------
{"a": {"b": {"c": "foo"}}}
(1 row)
select '[1,2,3]'::jsonb #>> '{}';
?column?
-----------
[1, 2, 3]
(1 row)
select '"foo"'::jsonb #>> '{}';
?column?
----------
foo
(1 row)
select '42'::jsonb #>> '{}';
?column?
----------
42
(1 row)
select 'null'::jsonb #>> '{}';
2014-08-20 22:48:35 +02:00
?column?
----------
(1 row)
select '{"a": {"b":{"c": "foo"}}}'::jsonb #>> array['a'];
?column?
---------------------
{"b": {"c": "foo"}}
(1 row)
2014-08-21 01:05:05 +02:00
select '{"a": {"b":{"c": "foo"}}}'::jsonb #>> array['a', null];
2014-08-22 19:17:58 +02:00
?column?
----------
(1 row)
2014-08-21 01:05:05 +02:00
select '{"a": {"b":{"c": "foo"}}}'::jsonb #>> array['a', ''];
?column?
----------
(1 row)
2014-08-20 22:48:35 +02:00
select '{"a": {"b":{"c": "foo"}}}'::jsonb #>> array['a','b'];
?column?
--------------
{"c": "foo"}
(1 row)
select '{"a": {"b":{"c": "foo"}}}'::jsonb #>> array['a','b','c'];
?column?
----------
foo
(1 row)
select '{"a": {"b":{"c": "foo"}}}'::jsonb #>> array['a','b','c','d'];
?column?
----------
(1 row)
select '{"a": {"b":{"c": "foo"}}}'::jsonb #>> array['a','z','c'];
?column?
----------
(1 row)
select '{"a": [{"b": "c"}, {"b": "cc"}]}'::jsonb #>> array['a','1','b'];
?column?
----------
cc
(1 row)
select '{"a": [{"b": "c"}, {"b": "cc"}]}'::jsonb #>> array['a','z','b'];
?column?
----------
(1 row)
select '[{"b": "c"}, {"b": "cc"}]'::jsonb #>> array['1','b'];
?column?
----------
cc
(1 row)
select '[{"b": "c"}, {"b": "cc"}]'::jsonb #>> array['z','b'];
?column?
----------
(1 row)
2014-08-22 19:17:58 +02:00
select '[{"b": "c"}, {"b": null}]'::jsonb #>> array['1','b'];
?column?
----------
(1 row)
2014-08-20 22:48:35 +02:00
select '"foo"'::jsonb #>> array['z'];
2014-08-22 19:17:58 +02:00
?column?
----------
(1 row)
2014-08-20 22:48:35 +02:00
select '42'::jsonb #>> array['f2'];
2014-08-22 19:17:58 +02:00
?column?
----------
(1 row)
2014-08-20 22:48:35 +02:00
select '42'::jsonb #>> array['0'];
2014-08-22 19:17:58 +02:00
?column?
----------
(1 row)
Introduce jsonb, a structured format for storing json.
The new format accepts exactly the same data as the json type. However, it is
stored in a format that does not require reparsing the orgiginal text in order
to process it, making it much more suitable for indexing and other operations.
Insignificant whitespace is discarded, and the order of object keys is not
preserved. Neither are duplicate object keys kept - the later value for a given
key is the only one stored.
The new type has all the functions and operators that the json type has,
with the exception of the json generation functions (to_json, json_agg etc.)
and with identical semantics. In addition, there are operator classes for
hash and btree indexing, and two classes for GIN indexing, that have no
equivalent in the json type.
This feature grew out of previous work by Oleg Bartunov and Teodor Sigaev, which
was intended to provide similar facilities to a nested hstore type, but which
in the end proved to have some significant compatibility issues.
Authors: Oleg Bartunov, Teodor Sigaev, Peter Geoghegan and Andrew Dunstan.
Review: Andres Freund
2014-03-23 21:40:19 +01:00
-- array_elements
SELECT jsonb_array_elements('[1,true,[1,[2,3]],null,{"f1":1,"f2":[7,8,9]},false]');
jsonb_array_elements
----------------------------
1
true
[1, [2, 3]]
null
{"f1": 1, "f2": [7, 8, 9]}
false
(6 rows)
SELECT * FROM jsonb_array_elements('[1,true,[1,[2,3]],null,{"f1":1,"f2":[7,8,9]},false]') q;
value
----------------------------
1
true
[1, [2, 3]]
null
{"f1": 1, "f2": [7, 8, 9]}
false
(6 rows)
SELECT jsonb_array_elements_text('[1,true,[1,[2,3]],null,{"f1":1,"f2":[7,8,9]},false,"stringy"]');
jsonb_array_elements_text
----------------------------
1
true
[1, [2, 3]]
{"f1": 1, "f2": [7, 8, 9]}
false
stringy
(7 rows)
SELECT * FROM jsonb_array_elements_text('[1,true,[1,[2,3]],null,{"f1":1,"f2":[7,8,9]},false,"stringy"]') q;
value
----------------------------
1
true
[1, [2, 3]]
{"f1": 1, "f2": [7, 8, 9]}
false
stringy
(7 rows)
-- populate_record
CREATE TYPE jbpop AS (a text, b int, c timestamp);
2017-04-07 04:11:21 +02:00
CREATE DOMAIN jsb_int_not_null AS int NOT NULL;
CREATE DOMAIN jsb_int_array_1d AS int[] CHECK(array_length(VALUE, 1) = 3);
CREATE DOMAIN jsb_int_array_2d AS int[][] CHECK(array_length(VALUE, 2) = 3);
2017-10-26 19:47:45 +02:00
create type jb_unordered_pair as (x int, y int);
create domain jb_ordered_pair as jb_unordered_pair check((value).x <= (value).y);
2017-04-07 04:11:21 +02:00
CREATE TYPE jsbrec AS (
i int,
ia _int4,
ia1 int[],
ia2 int[][],
ia3 int[][][],
ia1d jsb_int_array_1d,
ia2d jsb_int_array_2d,
t text,
ta text[],
c char(10),
ca char(10)[],
ts timestamp,
js json,
jsb jsonb,
jsa json[],
rec jbpop,
reca jbpop[]
);
CREATE TYPE jsbrec_i_not_null AS (
i jsb_int_not_null
);
Introduce jsonb, a structured format for storing json.
The new format accepts exactly the same data as the json type. However, it is
stored in a format that does not require reparsing the orgiginal text in order
to process it, making it much more suitable for indexing and other operations.
Insignificant whitespace is discarded, and the order of object keys is not
preserved. Neither are duplicate object keys kept - the later value for a given
key is the only one stored.
The new type has all the functions and operators that the json type has,
with the exception of the json generation functions (to_json, json_agg etc.)
and with identical semantics. In addition, there are operator classes for
hash and btree indexing, and two classes for GIN indexing, that have no
equivalent in the json type.
This feature grew out of previous work by Oleg Bartunov and Teodor Sigaev, which
was intended to provide similar facilities to a nested hstore type, but which
in the end proved to have some significant compatibility issues.
Authors: Oleg Bartunov, Teodor Sigaev, Peter Geoghegan and Andrew Dunstan.
Review: Andres Freund
2014-03-23 21:40:19 +01:00
SELECT * FROM jsonb_populate_record(NULL::jbpop,'{"a":"blurfl","x":43.2}') q;
a | b | c
--------+---+---
blurfl | |
(1 row)
SELECT * FROM jsonb_populate_record(row('x',3,'2012-12-31 15:30:56')::jbpop,'{"a":"blurfl","x":43.2}') q;
a | b | c
--------+---+--------------------------
blurfl | 3 | Mon Dec 31 15:30:56 2012
(1 row)
2014-06-29 19:50:58 +02:00
SELECT * FROM jsonb_populate_record(NULL::jbpop,'{"a":"blurfl","x":43.2}') q;
Introduce jsonb, a structured format for storing json.
The new format accepts exactly the same data as the json type. However, it is
stored in a format that does not require reparsing the orgiginal text in order
to process it, making it much more suitable for indexing and other operations.
Insignificant whitespace is discarded, and the order of object keys is not
preserved. Neither are duplicate object keys kept - the later value for a given
key is the only one stored.
The new type has all the functions and operators that the json type has,
with the exception of the json generation functions (to_json, json_agg etc.)
and with identical semantics. In addition, there are operator classes for
hash and btree indexing, and two classes for GIN indexing, that have no
equivalent in the json type.
This feature grew out of previous work by Oleg Bartunov and Teodor Sigaev, which
was intended to provide similar facilities to a nested hstore type, but which
in the end proved to have some significant compatibility issues.
Authors: Oleg Bartunov, Teodor Sigaev, Peter Geoghegan and Andrew Dunstan.
Review: Andres Freund
2014-03-23 21:40:19 +01:00
a | b | c
--------+---+---
blurfl | |
(1 row)
2014-06-29 19:50:58 +02:00
SELECT * FROM jsonb_populate_record(row('x',3,'2012-12-31 15:30:56')::jbpop,'{"a":"blurfl","x":43.2}') q;
Introduce jsonb, a structured format for storing json.
The new format accepts exactly the same data as the json type. However, it is
stored in a format that does not require reparsing the orgiginal text in order
to process it, making it much more suitable for indexing and other operations.
Insignificant whitespace is discarded, and the order of object keys is not
preserved. Neither are duplicate object keys kept - the later value for a given
key is the only one stored.
The new type has all the functions and operators that the json type has,
with the exception of the json generation functions (to_json, json_agg etc.)
and with identical semantics. In addition, there are operator classes for
hash and btree indexing, and two classes for GIN indexing, that have no
equivalent in the json type.
This feature grew out of previous work by Oleg Bartunov and Teodor Sigaev, which
was intended to provide similar facilities to a nested hstore type, but which
in the end proved to have some significant compatibility issues.
Authors: Oleg Bartunov, Teodor Sigaev, Peter Geoghegan and Andrew Dunstan.
Review: Andres Freund
2014-03-23 21:40:19 +01:00
a | b | c
--------+---+--------------------------
blurfl | 3 | Mon Dec 31 15:30:56 2012
(1 row)
2014-06-29 19:50:58 +02:00
SELECT * FROM jsonb_populate_record(NULL::jbpop,'{"a":[100,200,false],"x":43.2}') q;
Introduce jsonb, a structured format for storing json.
The new format accepts exactly the same data as the json type. However, it is
stored in a format that does not require reparsing the orgiginal text in order
to process it, making it much more suitable for indexing and other operations.
Insignificant whitespace is discarded, and the order of object keys is not
preserved. Neither are duplicate object keys kept - the later value for a given
key is the only one stored.
The new type has all the functions and operators that the json type has,
with the exception of the json generation functions (to_json, json_agg etc.)
and with identical semantics. In addition, there are operator classes for
hash and btree indexing, and two classes for GIN indexing, that have no
equivalent in the json type.
This feature grew out of previous work by Oleg Bartunov and Teodor Sigaev, which
was intended to provide similar facilities to a nested hstore type, but which
in the end proved to have some significant compatibility issues.
Authors: Oleg Bartunov, Teodor Sigaev, Peter Geoghegan and Andrew Dunstan.
Review: Andres Freund
2014-03-23 21:40:19 +01:00
a | b | c
-------------------+---+---
[100, 200, false] | |
(1 row)
2014-06-29 19:50:58 +02:00
SELECT * FROM jsonb_populate_record(row('x',3,'2012-12-31 15:30:56')::jbpop,'{"a":[100,200,false],"x":43.2}') q;
Introduce jsonb, a structured format for storing json.
The new format accepts exactly the same data as the json type. However, it is
stored in a format that does not require reparsing the orgiginal text in order
to process it, making it much more suitable for indexing and other operations.
Insignificant whitespace is discarded, and the order of object keys is not
preserved. Neither are duplicate object keys kept - the later value for a given
key is the only one stored.
The new type has all the functions and operators that the json type has,
with the exception of the json generation functions (to_json, json_agg etc.)
and with identical semantics. In addition, there are operator classes for
hash and btree indexing, and two classes for GIN indexing, that have no
equivalent in the json type.
This feature grew out of previous work by Oleg Bartunov and Teodor Sigaev, which
was intended to provide similar facilities to a nested hstore type, but which
in the end proved to have some significant compatibility issues.
Authors: Oleg Bartunov, Teodor Sigaev, Peter Geoghegan and Andrew Dunstan.
Review: Andres Freund
2014-03-23 21:40:19 +01:00
a | b | c
-------------------+---+--------------------------
[100, 200, false] | 3 | Mon Dec 31 15:30:56 2012
(1 row)
2014-06-29 19:50:58 +02:00
SELECT * FROM jsonb_populate_record(row('x',3,'2012-12-31 15:30:56')::jbpop,'{"c":[100,200,false],"x":43.2}') q;
Introduce jsonb, a structured format for storing json.
The new format accepts exactly the same data as the json type. However, it is
stored in a format that does not require reparsing the orgiginal text in order
to process it, making it much more suitable for indexing and other operations.
Insignificant whitespace is discarded, and the order of object keys is not
preserved. Neither are duplicate object keys kept - the later value for a given
key is the only one stored.
The new type has all the functions and operators that the json type has,
with the exception of the json generation functions (to_json, json_agg etc.)
and with identical semantics. In addition, there are operator classes for
hash and btree indexing, and two classes for GIN indexing, that have no
equivalent in the json type.
This feature grew out of previous work by Oleg Bartunov and Teodor Sigaev, which
was intended to provide similar facilities to a nested hstore type, but which
in the end proved to have some significant compatibility issues.
Authors: Oleg Bartunov, Teodor Sigaev, Peter Geoghegan and Andrew Dunstan.
Review: Andres Freund
2014-03-23 21:40:19 +01:00
ERROR: invalid input syntax for type timestamp: "[100, 200, false]"
2017-04-07 04:11:21 +02:00
SELECT * FROM jsonb_populate_record(row('x',3,'2012-12-31 15:30:56')::jbpop, '{}') q;
a | b | c
---+---+--------------------------
x | 3 | Mon Dec 31 15:30:56 2012
(1 row)
SELECT i FROM jsonb_populate_record(NULL::jsbrec_i_not_null, '{"x": 43.2}') q;
ERROR: domain jsb_int_not_null does not allow null values
SELECT i FROM jsonb_populate_record(NULL::jsbrec_i_not_null, '{"i": null}') q;
ERROR: domain jsb_int_not_null does not allow null values
SELECT i FROM jsonb_populate_record(NULL::jsbrec_i_not_null, '{"i": 12345}') q;
i
-------
12345
(1 row)
SELECT ia FROM jsonb_populate_record(NULL::jsbrec, '{"ia": null}') q;
ia
----
(1 row)
SELECT ia FROM jsonb_populate_record(NULL::jsbrec, '{"ia": 123}') q;
2018-05-08 20:36:31 +02:00
ERROR: expected JSON array
2017-09-11 17:20:47 +02:00
HINT: See the value of key "ia".
2017-04-07 04:11:21 +02:00
SELECT ia FROM jsonb_populate_record(NULL::jsbrec, '{"ia": [1, "2", null, 4]}') q;
ia
--------------
{1,2,NULL,4}
(1 row)
SELECT ia FROM jsonb_populate_record(NULL::jsbrec, '{"ia": [[1, 2], [3, 4]]}') q;
ia
---------------
{{1,2},{3,4}}
(1 row)
SELECT ia FROM jsonb_populate_record(NULL::jsbrec, '{"ia": [[1], 2]}') q;
2018-05-08 20:36:31 +02:00
ERROR: expected JSON array
2017-09-11 17:20:47 +02:00
HINT: See the array element [1] of key "ia".
2017-04-07 04:11:21 +02:00
SELECT ia FROM jsonb_populate_record(NULL::jsbrec, '{"ia": [[1], [2, 3]]}') q;
2018-05-08 20:36:31 +02:00
ERROR: malformed JSON array
2017-04-07 04:11:21 +02:00
DETAIL: Multidimensional arrays must have sub-arrays with matching dimensions.
SELECT ia FROM jsonb_populate_record(NULL::jsbrec, '{"ia": "{1,2,3}"}') q;
ia
---------
{1,2,3}
(1 row)
SELECT ia1 FROM jsonb_populate_record(NULL::jsbrec, '{"ia1": null}') q;
ia1
-----
(1 row)
SELECT ia1 FROM jsonb_populate_record(NULL::jsbrec, '{"ia1": 123}') q;
2018-05-08 20:36:31 +02:00
ERROR: expected JSON array
2017-09-11 17:20:47 +02:00
HINT: See the value of key "ia1".
2017-04-07 04:11:21 +02:00
SELECT ia1 FROM jsonb_populate_record(NULL::jsbrec, '{"ia1": [1, "2", null, 4]}') q;
ia1
--------------
{1,2,NULL,4}
(1 row)
SELECT ia1 FROM jsonb_populate_record(NULL::jsbrec, '{"ia1": [[1, 2, 3]]}') q;
ia1
-----------
{{1,2,3}}
(1 row)
SELECT ia1d FROM jsonb_populate_record(NULL::jsbrec, '{"ia1d": null}') q;
ia1d
------
(1 row)
SELECT ia1d FROM jsonb_populate_record(NULL::jsbrec, '{"ia1d": 123}') q;
2018-05-08 20:36:31 +02:00
ERROR: expected JSON array
2017-09-11 17:20:47 +02:00
HINT: See the value of key "ia1d".
2017-04-07 04:11:21 +02:00
SELECT ia1d FROM jsonb_populate_record(NULL::jsbrec, '{"ia1d": [1, "2", null, 4]}') q;
ERROR: value for domain jsb_int_array_1d violates check constraint "jsb_int_array_1d_check"
SELECT ia1d FROM jsonb_populate_record(NULL::jsbrec, '{"ia1d": [1, "2", null]}') q;
ia1d
------------
{1,2,NULL}
(1 row)
SELECT ia2 FROM jsonb_populate_record(NULL::jsbrec, '{"ia2": [1, "2", null, 4]}') q;
ia2
--------------
{1,2,NULL,4}
(1 row)
SELECT ia2 FROM jsonb_populate_record(NULL::jsbrec, '{"ia2": [[1, 2], [null, 4]]}') q;
ia2
------------------
{{1,2},{NULL,4}}
(1 row)
SELECT ia2 FROM jsonb_populate_record(NULL::jsbrec, '{"ia2": [[], []]}') q;
ia2
-----
{}
(1 row)
SELECT ia2 FROM jsonb_populate_record(NULL::jsbrec, '{"ia2": [[1, 2], [3]]}') q;
2018-05-08 20:36:31 +02:00
ERROR: malformed JSON array
2017-04-07 04:11:21 +02:00
DETAIL: Multidimensional arrays must have sub-arrays with matching dimensions.
SELECT ia2 FROM jsonb_populate_record(NULL::jsbrec, '{"ia2": [[1, 2], 3, 4]}') q;
2018-05-08 20:36:31 +02:00
ERROR: expected JSON array
2017-09-11 17:20:47 +02:00
HINT: See the array element [1] of key "ia2".
2017-04-07 04:11:21 +02:00
SELECT ia2d FROM jsonb_populate_record(NULL::jsbrec, '{"ia2d": [[1, "2"], [null, 4]]}') q;
ERROR: value for domain jsb_int_array_2d violates check constraint "jsb_int_array_2d_check"
SELECT ia2d FROM jsonb_populate_record(NULL::jsbrec, '{"ia2d": [[1, "2", 3], [null, 5, 6]]}') q;
ia2d
----------------------
{{1,2,3},{NULL,5,6}}
(1 row)
SELECT ia3 FROM jsonb_populate_record(NULL::jsbrec, '{"ia3": [1, "2", null, 4]}') q;
ia3
--------------
{1,2,NULL,4}
(1 row)
SELECT ia3 FROM jsonb_populate_record(NULL::jsbrec, '{"ia3": [[1, 2], [null, 4]]}') q;
ia3
------------------
{{1,2},{NULL,4}}
(1 row)
SELECT ia3 FROM jsonb_populate_record(NULL::jsbrec, '{"ia3": [ [[], []], [[], []], [[], []] ]}') q;
ia3
-----
{}
(1 row)
SELECT ia3 FROM jsonb_populate_record(NULL::jsbrec, '{"ia3": [ [[1, 2]], [[3, 4]] ]}') q;
ia3
-------------------
{{{1,2}},{{3,4}}}
(1 row)
SELECT ia3 FROM jsonb_populate_record(NULL::jsbrec, '{"ia3": [ [[1, 2], [3, 4]], [[5, 6], [7, 8]] ]}') q;
ia3
-------------------------------
{{{1,2},{3,4}},{{5,6},{7,8}}}
(1 row)
SELECT ia3 FROM jsonb_populate_record(NULL::jsbrec, '{"ia3": [ [[1, 2], [3, 4]], [[5, 6], [7, 8], [9, 10]] ]}') q;
2018-05-08 20:36:31 +02:00
ERROR: malformed JSON array
2017-04-07 04:11:21 +02:00
DETAIL: Multidimensional arrays must have sub-arrays with matching dimensions.
SELECT ta FROM jsonb_populate_record(NULL::jsbrec, '{"ta": null}') q;
ta
----
(1 row)
SELECT ta FROM jsonb_populate_record(NULL::jsbrec, '{"ta": 123}') q;
2018-05-08 20:36:31 +02:00
ERROR: expected JSON array
2017-09-11 17:20:47 +02:00
HINT: See the value of key "ta".
2017-04-07 04:11:21 +02:00
SELECT ta FROM jsonb_populate_record(NULL::jsbrec, '{"ta": [1, "2", null, 4]}') q;
ta
--------------
{1,2,NULL,4}
(1 row)
SELECT ta FROM jsonb_populate_record(NULL::jsbrec, '{"ta": [[1, 2, 3], {"k": "v"}]}') q;
2018-05-08 20:36:31 +02:00
ERROR: expected JSON array
2017-09-11 17:20:47 +02:00
HINT: See the array element [1] of key "ta".
2017-04-07 04:11:21 +02:00
SELECT c FROM jsonb_populate_record(NULL::jsbrec, '{"c": null}') q;
c
---
(1 row)
SELECT c FROM jsonb_populate_record(NULL::jsbrec, '{"c": "aaa"}') q;
c
------------
aaa
(1 row)
SELECT c FROM jsonb_populate_record(NULL::jsbrec, '{"c": "aaaaaaaaaa"}') q;
c
------------
aaaaaaaaaa
(1 row)
SELECT c FROM jsonb_populate_record(NULL::jsbrec, '{"c": "aaaaaaaaaaaaa"}') q;
ERROR: value too long for type character(10)
SELECT ca FROM jsonb_populate_record(NULL::jsbrec, '{"ca": null}') q;
ca
----
(1 row)
SELECT ca FROM jsonb_populate_record(NULL::jsbrec, '{"ca": 123}') q;
2018-05-08 20:36:31 +02:00
ERROR: expected JSON array
2017-09-11 17:20:47 +02:00
HINT: See the value of key "ca".
2017-04-07 04:11:21 +02:00
SELECT ca FROM jsonb_populate_record(NULL::jsbrec, '{"ca": [1, "2", null, 4]}') q;
ca
-----------------------------------------------
{"1 ","2 ",NULL,"4 "}
(1 row)
SELECT ca FROM jsonb_populate_record(NULL::jsbrec, '{"ca": ["aaaaaaaaaaaaaaaa"]}') q;
ERROR: value too long for type character(10)
SELECT ca FROM jsonb_populate_record(NULL::jsbrec, '{"ca": [[1, 2, 3], {"k": "v"}]}') q;
2018-05-08 20:36:31 +02:00
ERROR: expected JSON array
2017-09-11 17:20:47 +02:00
HINT: See the array element [1] of key "ca".
2017-04-07 04:11:21 +02:00
SELECT js FROM jsonb_populate_record(NULL::jsbrec, '{"js": null}') q;
js
----
(1 row)
SELECT js FROM jsonb_populate_record(NULL::jsbrec, '{"js": true}') q;
js
------
true
(1 row)
SELECT js FROM jsonb_populate_record(NULL::jsbrec, '{"js": 123.45}') q;
js
--------
123.45
(1 row)
SELECT js FROM jsonb_populate_record(NULL::jsbrec, '{"js": "123.45"}') q;
js
----------
"123.45"
(1 row)
SELECT js FROM jsonb_populate_record(NULL::jsbrec, '{"js": "abc"}') q;
js
-------
"abc"
(1 row)
SELECT js FROM jsonb_populate_record(NULL::jsbrec, '{"js": [123, "123", null, {"key": "value"}]}') q;
js
--------------------------------------
[123, "123", null, {"key": "value"}]
(1 row)
SELECT js FROM jsonb_populate_record(NULL::jsbrec, '{"js": {"a": "bbb", "b": null, "c": 123.45}}') q;
js
--------------------------------------
{"a": "bbb", "b": null, "c": 123.45}
(1 row)
SELECT jsb FROM jsonb_populate_record(NULL::jsbrec, '{"jsb": null}') q;
jsb
-----
(1 row)
SELECT jsb FROM jsonb_populate_record(NULL::jsbrec, '{"jsb": true}') q;
jsb
------
true
(1 row)
SELECT jsb FROM jsonb_populate_record(NULL::jsbrec, '{"jsb": 123.45}') q;
jsb
--------
123.45
(1 row)
SELECT jsb FROM jsonb_populate_record(NULL::jsbrec, '{"jsb": "123.45"}') q;
jsb
----------
"123.45"
(1 row)
SELECT jsb FROM jsonb_populate_record(NULL::jsbrec, '{"jsb": "abc"}') q;
jsb
-------
"abc"
(1 row)
SELECT jsb FROM jsonb_populate_record(NULL::jsbrec, '{"jsb": [123, "123", null, {"key": "value"}]}') q;
jsb
--------------------------------------
[123, "123", null, {"key": "value"}]
(1 row)
SELECT jsb FROM jsonb_populate_record(NULL::jsbrec, '{"jsb": {"a": "bbb", "b": null, "c": 123.45}}') q;
jsb
--------------------------------------
{"a": "bbb", "b": null, "c": 123.45}
(1 row)
SELECT jsa FROM jsonb_populate_record(NULL::jsbrec, '{"jsa": null}') q;
jsa
-----
(1 row)
SELECT jsa FROM jsonb_populate_record(NULL::jsbrec, '{"jsa": 123}') q;
2018-05-08 20:36:31 +02:00
ERROR: expected JSON array
2017-09-11 17:20:47 +02:00
HINT: See the value of key "jsa".
2017-04-07 04:11:21 +02:00
SELECT jsa FROM jsonb_populate_record(NULL::jsbrec, '{"jsa": [1, "2", null, 4]}') q;
jsa
--------------------
{1,"\"2\"",NULL,4}
(1 row)
SELECT jsa FROM jsonb_populate_record(NULL::jsbrec, '{"jsa": ["aaa", null, [1, 2, "3", {}], { "k" : "v" }]}') q;
jsa
-------------------------------------------------------
{"\"aaa\"",NULL,"[1, 2, \"3\", {}]","{\"k\": \"v\"}"}
(1 row)
SELECT rec FROM jsonb_populate_record(NULL::jsbrec, '{"rec": 123}') q;
2017-05-30 01:29:42 +02:00
ERROR: cannot call populate_composite on a scalar
2017-04-07 04:11:21 +02:00
SELECT rec FROM jsonb_populate_record(NULL::jsbrec, '{"rec": [1, 2]}') q;
2017-05-30 01:29:42 +02:00
ERROR: cannot call populate_composite on an array
2017-04-07 04:11:21 +02:00
SELECT rec FROM jsonb_populate_record(NULL::jsbrec, '{"rec": {"a": "abc", "c": "01.02.2003", "x": 43.2}}') q;
rec
-----------------------------------
(abc,,"Thu Jan 02 00:00:00 2003")
(1 row)
SELECT rec FROM jsonb_populate_record(NULL::jsbrec, '{"rec": "(abc,42,01.02.2003)"}') q;
rec
-------------------------------------
(abc,42,"Thu Jan 02 00:00:00 2003")
(1 row)
SELECT reca FROM jsonb_populate_record(NULL::jsbrec, '{"reca": 123}') q;
2018-05-08 20:36:31 +02:00
ERROR: expected JSON array
2017-09-11 17:20:47 +02:00
HINT: See the value of key "reca".
2017-04-07 04:11:21 +02:00
SELECT reca FROM jsonb_populate_record(NULL::jsbrec, '{"reca": [1, 2]}') q;
2017-05-30 01:29:42 +02:00
ERROR: cannot call populate_composite on a scalar
2017-04-07 04:11:21 +02:00
SELECT reca FROM jsonb_populate_record(NULL::jsbrec, '{"reca": [{"a": "abc", "b": 456}, null, {"c": "01.02.2003", "x": 43.2}]}') q;
reca
--------------------------------------------------------
{"(abc,456,)",NULL,"(,,\"Thu Jan 02 00:00:00 2003\")"}
(1 row)
SELECT reca FROM jsonb_populate_record(NULL::jsbrec, '{"reca": ["(abc,42,01.02.2003)"]}') q;
reca
-------------------------------------------
{"(abc,42,\"Thu Jan 02 00:00:00 2003\")"}
(1 row)
SELECT reca FROM jsonb_populate_record(NULL::jsbrec, '{"reca": "{\"(abc,42,01.02.2003)\"}"}') q;
reca
-------------------------------------------
{"(abc,42,\"Thu Jan 02 00:00:00 2003\")"}
(1 row)
SELECT rec FROM jsonb_populate_record(
row(NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
row('x',3,'2012-12-31 15:30:56')::jbpop,NULL)::jsbrec,
'{"rec": {"a": "abc", "c": "01.02.2003", "x": 43.2}}'
) q;
rec
------------------------------------
(abc,3,"Thu Jan 02 00:00:00 2003")
(1 row)
Adjust populate_record_field() to handle errors softly
This adds a Node *escontext parameter to it and a bunch of functions
downstream to it, replacing any ereport()s in that path by either
errsave() or ereturn() as appropriate. This also adds code to those
functions where necessary to return early upon encountering a soft
error.
The changes here are mainly intended to suppress errors in the
functions of jsonfuncs.c. Functions in any external modules, such as
arrayfuncs.c, that those functions may in turn call are not changed
here based on the assumption that the various checks in jsonfuncs.c
functions should ensure that only values that are structurally valid
get passed to the functions in those external modules. An exception
is made for domain_check() to allow handling domain constraint
violation errors softly.
For testing, this adds a function jsonb_populate_record_valid(),
which returns true if jsonb_populate_record() would finish without
causing an error for the provided JSON object, false otherwise. Note
that jsonb_populate_record() internally calls populate_record(),
which in turn uses populate_record_field().
Extracted from a much larger patch to add SQL/JSON query functions.
Author: Nikita Glukhov <n.gluhov@postgrespro.ru>
Author: Teodor Sigaev <teodor@sigaev.ru>
Author: Oleg Bartunov <obartunov@gmail.com>
Author: Alexander Korotkov <aekorotkov@gmail.com>
Author: Andrew Dunstan <andrew@dunslane.net>
Author: Amit Langote <amitlangote09@gmail.com>
Reviewers have included (in no particular order) Andres Freund,
Alexander Korotkov, Pavel Stehule, Andrew Alsup, Erik Rijkers,
Zihong Yu, Himanshu Upadhyaya, Daniel Gustafsson, Justin Pryzby,
Álvaro Herrera, Jian He, Peter Eisentraut
Discussion: https://postgr.es/m/cd0bb935-0158-78a7-08b5-904886deac4b@postgrespro.ru
Discussion: https://postgr.es/m/20220616233130.rparivafipt6doj3@alap3.anarazel.de
Discussion: https://postgr.es/m/abd9b83b-aa66-f230-3d6d-734817f0995d%40postgresql.org
Discussion: https://postgr.es/m/CA+HiwqHROpf9e644D8BRqYvaAPmgBZVup-xKMDPk-nd4EpgzHw@mail.gmail.com
Discussion: https://postgr.es/m/CA+HiwqE4XTdfb1nW=Ojoy_tQSRhYt-q_kb6i5d4xcKyrLC1Nbg@mail.gmail.com
2024-01-24 05:35:28 +01:00
-- Tests to check soft-error support for populate_record_field()
-- populate_scalar()
create type jsb_char2 as (a char(2));
select jsonb_populate_record_valid(NULL::jsb_char2, '{"a": "aaa"}');
jsonb_populate_record_valid
-----------------------------
f
(1 row)
select * from jsonb_populate_record(NULL::jsb_char2, '{"a": "aaa"}') q;
ERROR: value too long for type character(2)
select jsonb_populate_record_valid(NULL::jsb_char2, '{"a": "aa"}');
jsonb_populate_record_valid
-----------------------------
t
(1 row)
select * from jsonb_populate_record(NULL::jsb_char2, '{"a": "aa"}') q;
a
----
aa
(1 row)
-- populate_array()
create type jsb_ia as (a int[]);
create type jsb_ia2 as (a int[][]);
select jsonb_populate_record_valid(NULL::jsb_ia, '{"a": 43.2}');
jsonb_populate_record_valid
-----------------------------
f
(1 row)
select * from jsonb_populate_record(NULL::jsb_ia, '{"a": 43.2}') q;
ERROR: expected JSON array
HINT: See the value of key "a".
select jsonb_populate_record_valid(NULL::jsb_ia, '{"a": [1, 2]}');
jsonb_populate_record_valid
-----------------------------
t
(1 row)
select * from jsonb_populate_record(NULL::jsb_ia, '{"a": [1, 2]}') q;
a
-------
{1,2}
(1 row)
select jsonb_populate_record_valid(NULL::jsb_ia2, '{"a": [[1], [2, 3]]}');
jsonb_populate_record_valid
-----------------------------
f
(1 row)
select * from jsonb_populate_record(NULL::jsb_ia2, '{"a": [[1], [2, 3]]}') q;
ERROR: malformed JSON array
DETAIL: Multidimensional arrays must have sub-arrays with matching dimensions.
select jsonb_populate_record_valid(NULL::jsb_ia2, '{"a": [[1, 0], [2, 3]]}');
jsonb_populate_record_valid
-----------------------------
t
(1 row)
select * from jsonb_populate_record(NULL::jsb_ia2, '{"a": [[1, 0], [2, 3]]}') q;
a
---------------
{{1,0},{2,3}}
(1 row)
-- populate_domain()
create domain jsb_i_not_null as int not null;
create domain jsb_i_gt_1 as int check (value > 1);
create type jsb_i_not_null_rec as (a jsb_i_not_null);
create type jsb_i_gt_1_rec as (a jsb_i_gt_1);
select jsonb_populate_record_valid(NULL::jsb_i_not_null_rec, '{"a": null}');
jsonb_populate_record_valid
-----------------------------
f
(1 row)
select * from jsonb_populate_record(NULL::jsb_i_not_null_rec, '{"a": null}') q;
ERROR: domain jsb_i_not_null does not allow null values
select jsonb_populate_record_valid(NULL::jsb_i_not_null_rec, '{"a": 1}');
jsonb_populate_record_valid
-----------------------------
t
(1 row)
select * from jsonb_populate_record(NULL::jsb_i_not_null_rec, '{"a": 1}') q;
a
---
1
(1 row)
select jsonb_populate_record_valid(NULL::jsb_i_gt_1_rec, '{"a": 1}');
jsonb_populate_record_valid
-----------------------------
f
(1 row)
select * from jsonb_populate_record(NULL::jsb_i_gt_1_rec, '{"a": 1}') q;
ERROR: value for domain jsb_i_gt_1 violates check constraint "jsb_i_gt_1_check"
select jsonb_populate_record_valid(NULL::jsb_i_gt_1_rec, '{"a": 2}');
jsonb_populate_record_valid
-----------------------------
t
(1 row)
select * from jsonb_populate_record(NULL::jsb_i_gt_1_rec, '{"a": 2}') q;
a
---
2
(1 row)
drop type jsb_ia, jsb_ia2, jsb_char2, jsb_i_not_null_rec, jsb_i_gt_1_rec;
drop domain jsb_i_not_null, jsb_i_gt_1;
2017-10-26 19:47:45 +02:00
-- anonymous record type
SELECT jsonb_populate_record(null::record, '{"x": 0, "y": 1}');
Restore json{b}_populate_record{set}'s ability to take type info from AS.
If the record argument is NULL and has no declared type more concrete
than RECORD, we can't extract useful information about the desired
rowtype from it. In this case, see if we're in FROM with an AS clause,
and if so extract the needed rowtype info from AS.
It worked like this before v11, but commit 37a795a60 removed the
behavior, reasoning that it was undocumented, inefficient, and utterly
not self-consistent. If you want to take type info from an AS clause,
you should be using the json_to_record() family of functions not the
json_populate_record() family. Also, it was already the case that
the "populate" functions would fail for a null-valued RECORD input
(with an unfriendly "record type has not been registered" error)
when there wasn't an AS clause at hand, and it wasn't obvious that
that behavior wasn't OK when there was one. However, it emerges
that some people were depending on this to work, and indeed the
rather off-point error message you got if you left off AS encouraged
slapping on AS without switching to the json_to_record() family.
Hence, put back the fallback behavior of looking for AS. While at it,
improve the run-time error you get when there's no place to obtain type
info; we can do a lot better than "record type has not been registered".
(We can't, unfortunately, easily improve the parse-time error message
that leads people down this path in the first place.)
While at it, I refactored the code a bit to avoid duplicating the
same logic in several different places.
Per bug #15940 from Jaroslav Sivy. Back-patch to v11 where the
current coding came in. (The pre-v11 deficiencies in this area
aren't regressions, so we'll leave those branches alone.)
Patch by me, based on preliminary analysis by Dmitry Dolgov.
Discussion: https://postgr.es/m/15940-2ab76dc58ffb85b6@postgresql.org
2019-08-20 00:00:57 +02:00
ERROR: could not determine row type for result of jsonb_populate_record
HINT: Provide a non-null record argument, or call the function in the FROM clause using a column definition list.
2017-10-26 19:47:45 +02:00
SELECT jsonb_populate_record(row(1,2), '{"f1": 0, "f2": 1}');
jsonb_populate_record
-----------------------
(0,1)
(1 row)
Restore json{b}_populate_record{set}'s ability to take type info from AS.
If the record argument is NULL and has no declared type more concrete
than RECORD, we can't extract useful information about the desired
rowtype from it. In this case, see if we're in FROM with an AS clause,
and if so extract the needed rowtype info from AS.
It worked like this before v11, but commit 37a795a60 removed the
behavior, reasoning that it was undocumented, inefficient, and utterly
not self-consistent. If you want to take type info from an AS clause,
you should be using the json_to_record() family of functions not the
json_populate_record() family. Also, it was already the case that
the "populate" functions would fail for a null-valued RECORD input
(with an unfriendly "record type has not been registered" error)
when there wasn't an AS clause at hand, and it wasn't obvious that
that behavior wasn't OK when there was one. However, it emerges
that some people were depending on this to work, and indeed the
rather off-point error message you got if you left off AS encouraged
slapping on AS without switching to the json_to_record() family.
Hence, put back the fallback behavior of looking for AS. While at it,
improve the run-time error you get when there's no place to obtain type
info; we can do a lot better than "record type has not been registered".
(We can't, unfortunately, easily improve the parse-time error message
that leads people down this path in the first place.)
While at it, I refactored the code a bit to avoid duplicating the
same logic in several different places.
Per bug #15940 from Jaroslav Sivy. Back-patch to v11 where the
current coding came in. (The pre-v11 deficiencies in this area
aren't regressions, so we'll leave those branches alone.)
Patch by me, based on preliminary analysis by Dmitry Dolgov.
Discussion: https://postgr.es/m/15940-2ab76dc58ffb85b6@postgresql.org
2019-08-20 00:00:57 +02:00
SELECT * FROM
jsonb_populate_record(null::record, '{"x": 776}') AS (x int, y int);
x | y
-----+---
776 |
(1 row)
2017-10-26 19:47:45 +02:00
-- composite domain
SELECT jsonb_populate_record(null::jb_ordered_pair, '{"x": 0, "y": 1}');
jsonb_populate_record
-----------------------
(0,1)
(1 row)
SELECT jsonb_populate_record(row(1,2)::jb_ordered_pair, '{"x": 0}');
jsonb_populate_record
-----------------------
(0,2)
(1 row)
SELECT jsonb_populate_record(row(1,2)::jb_ordered_pair, '{"x": 1, "y": 0}');
ERROR: value for domain jb_ordered_pair violates check constraint "jb_ordered_pair_check"
Introduce jsonb, a structured format for storing json.
The new format accepts exactly the same data as the json type. However, it is
stored in a format that does not require reparsing the orgiginal text in order
to process it, making it much more suitable for indexing and other operations.
Insignificant whitespace is discarded, and the order of object keys is not
preserved. Neither are duplicate object keys kept - the later value for a given
key is the only one stored.
The new type has all the functions and operators that the json type has,
with the exception of the json generation functions (to_json, json_agg etc.)
and with identical semantics. In addition, there are operator classes for
hash and btree indexing, and two classes for GIN indexing, that have no
equivalent in the json type.
This feature grew out of previous work by Oleg Bartunov and Teodor Sigaev, which
was intended to provide similar facilities to a nested hstore type, but which
in the end proved to have some significant compatibility issues.
Authors: Oleg Bartunov, Teodor Sigaev, Peter Geoghegan and Andrew Dunstan.
Review: Andres Freund
2014-03-23 21:40:19 +01:00
-- populate_recordset
2014-06-29 19:50:58 +02:00
SELECT * FROM jsonb_populate_recordset(NULL::jbpop,'[{"a":"blurfl","x":43.2},{"b":3,"c":"2012-01-20 10:42:53"}]') q;
Introduce jsonb, a structured format for storing json.
The new format accepts exactly the same data as the json type. However, it is
stored in a format that does not require reparsing the orgiginal text in order
to process it, making it much more suitable for indexing and other operations.
Insignificant whitespace is discarded, and the order of object keys is not
preserved. Neither are duplicate object keys kept - the later value for a given
key is the only one stored.
The new type has all the functions and operators that the json type has,
with the exception of the json generation functions (to_json, json_agg etc.)
and with identical semantics. In addition, there are operator classes for
hash and btree indexing, and two classes for GIN indexing, that have no
equivalent in the json type.
This feature grew out of previous work by Oleg Bartunov and Teodor Sigaev, which
was intended to provide similar facilities to a nested hstore type, but which
in the end proved to have some significant compatibility issues.
Authors: Oleg Bartunov, Teodor Sigaev, Peter Geoghegan and Andrew Dunstan.
Review: Andres Freund
2014-03-23 21:40:19 +01:00
a | b | c
--------+---+--------------------------
blurfl | |
| 3 | Fri Jan 20 10:42:53 2012
(2 rows)
2014-06-29 19:50:58 +02:00
SELECT * FROM jsonb_populate_recordset(row('def',99,NULL)::jbpop,'[{"a":"blurfl","x":43.2},{"b":3,"c":"2012-01-20 10:42:53"}]') q;
Introduce jsonb, a structured format for storing json.
The new format accepts exactly the same data as the json type. However, it is
stored in a format that does not require reparsing the orgiginal text in order
to process it, making it much more suitable for indexing and other operations.
Insignificant whitespace is discarded, and the order of object keys is not
preserved. Neither are duplicate object keys kept - the later value for a given
key is the only one stored.
The new type has all the functions and operators that the json type has,
with the exception of the json generation functions (to_json, json_agg etc.)
and with identical semantics. In addition, there are operator classes for
hash and btree indexing, and two classes for GIN indexing, that have no
equivalent in the json type.
This feature grew out of previous work by Oleg Bartunov and Teodor Sigaev, which
was intended to provide similar facilities to a nested hstore type, but which
in the end proved to have some significant compatibility issues.
Authors: Oleg Bartunov, Teodor Sigaev, Peter Geoghegan and Andrew Dunstan.
Review: Andres Freund
2014-03-23 21:40:19 +01:00
a | b | c
--------+----+--------------------------
blurfl | 99 |
def | 3 | Fri Jan 20 10:42:53 2012
(2 rows)
2014-06-29 19:50:58 +02:00
SELECT * FROM jsonb_populate_recordset(NULL::jbpop,'[{"a":"blurfl","x":43.2},{"b":3,"c":"2012-01-20 10:42:53"}]') q;
Introduce jsonb, a structured format for storing json.
The new format accepts exactly the same data as the json type. However, it is
stored in a format that does not require reparsing the orgiginal text in order
to process it, making it much more suitable for indexing and other operations.
Insignificant whitespace is discarded, and the order of object keys is not
preserved. Neither are duplicate object keys kept - the later value for a given
key is the only one stored.
The new type has all the functions and operators that the json type has,
with the exception of the json generation functions (to_json, json_agg etc.)
and with identical semantics. In addition, there are operator classes for
hash and btree indexing, and two classes for GIN indexing, that have no
equivalent in the json type.
This feature grew out of previous work by Oleg Bartunov and Teodor Sigaev, which
was intended to provide similar facilities to a nested hstore type, but which
in the end proved to have some significant compatibility issues.
Authors: Oleg Bartunov, Teodor Sigaev, Peter Geoghegan and Andrew Dunstan.
Review: Andres Freund
2014-03-23 21:40:19 +01:00
a | b | c
--------+---+--------------------------
blurfl | |
| 3 | Fri Jan 20 10:42:53 2012
(2 rows)
2014-06-29 19:50:58 +02:00
SELECT * FROM jsonb_populate_recordset(row('def',99,NULL)::jbpop,'[{"a":"blurfl","x":43.2},{"b":3,"c":"2012-01-20 10:42:53"}]') q;
Introduce jsonb, a structured format for storing json.
The new format accepts exactly the same data as the json type. However, it is
stored in a format that does not require reparsing the orgiginal text in order
to process it, making it much more suitable for indexing and other operations.
Insignificant whitespace is discarded, and the order of object keys is not
preserved. Neither are duplicate object keys kept - the later value for a given
key is the only one stored.
The new type has all the functions and operators that the json type has,
with the exception of the json generation functions (to_json, json_agg etc.)
and with identical semantics. In addition, there are operator classes for
hash and btree indexing, and two classes for GIN indexing, that have no
equivalent in the json type.
This feature grew out of previous work by Oleg Bartunov and Teodor Sigaev, which
was intended to provide similar facilities to a nested hstore type, but which
in the end proved to have some significant compatibility issues.
Authors: Oleg Bartunov, Teodor Sigaev, Peter Geoghegan and Andrew Dunstan.
Review: Andres Freund
2014-03-23 21:40:19 +01:00
a | b | c
--------+----+--------------------------
blurfl | 99 |
def | 3 | Fri Jan 20 10:42:53 2012
(2 rows)
2014-06-29 19:50:58 +02:00
SELECT * FROM jsonb_populate_recordset(row('def',99,NULL)::jbpop,'[{"a":[100,200,300],"x":43.2},{"a":{"z":true},"b":3,"c":"2012-01-20 10:42:53"}]') q;
Introduce jsonb, a structured format for storing json.
The new format accepts exactly the same data as the json type. However, it is
stored in a format that does not require reparsing the orgiginal text in order
to process it, making it much more suitable for indexing and other operations.
Insignificant whitespace is discarded, and the order of object keys is not
preserved. Neither are duplicate object keys kept - the later value for a given
key is the only one stored.
The new type has all the functions and operators that the json type has,
with the exception of the json generation functions (to_json, json_agg etc.)
and with identical semantics. In addition, there are operator classes for
hash and btree indexing, and two classes for GIN indexing, that have no
equivalent in the json type.
This feature grew out of previous work by Oleg Bartunov and Teodor Sigaev, which
was intended to provide similar facilities to a nested hstore type, but which
in the end proved to have some significant compatibility issues.
Authors: Oleg Bartunov, Teodor Sigaev, Peter Geoghegan and Andrew Dunstan.
Review: Andres Freund
2014-03-23 21:40:19 +01:00
a | b | c
-----------------+----+--------------------------
[100, 200, 300] | 99 |
{"z": true} | 3 | Fri Jan 20 10:42:53 2012
(2 rows)
2014-06-29 19:50:58 +02:00
SELECT * FROM jsonb_populate_recordset(row('def',99,NULL)::jbpop,'[{"c":[100,200,300],"x":43.2},{"a":{"z":true},"b":3,"c":"2012-01-20 10:42:53"}]') q;
Introduce jsonb, a structured format for storing json.
The new format accepts exactly the same data as the json type. However, it is
stored in a format that does not require reparsing the orgiginal text in order
to process it, making it much more suitable for indexing and other operations.
Insignificant whitespace is discarded, and the order of object keys is not
preserved. Neither are duplicate object keys kept - the later value for a given
key is the only one stored.
The new type has all the functions and operators that the json type has,
with the exception of the json generation functions (to_json, json_agg etc.)
and with identical semantics. In addition, there are operator classes for
hash and btree indexing, and two classes for GIN indexing, that have no
equivalent in the json type.
This feature grew out of previous work by Oleg Bartunov and Teodor Sigaev, which
was intended to provide similar facilities to a nested hstore type, but which
in the end proved to have some significant compatibility issues.
Authors: Oleg Bartunov, Teodor Sigaev, Peter Geoghegan and Andrew Dunstan.
Review: Andres Freund
2014-03-23 21:40:19 +01:00
ERROR: invalid input syntax for type timestamp: "[100, 200, 300]"
SELECT * FROM jsonb_populate_recordset(NULL::jbpop,'[{"a":"blurfl","x":43.2},{"b":3,"c":"2012-01-20 10:42:53"}]') q;
a | b | c
--------+---+--------------------------
blurfl | |
| 3 | Fri Jan 20 10:42:53 2012
(2 rows)
SELECT * FROM jsonb_populate_recordset(row('def',99,NULL)::jbpop,'[{"a":"blurfl","x":43.2},{"b":3,"c":"2012-01-20 10:42:53"}]') q;
a | b | c
--------+----+--------------------------
blurfl | 99 |
def | 3 | Fri Jan 20 10:42:53 2012
(2 rows)
SELECT * FROM jsonb_populate_recordset(row('def',99,NULL)::jbpop,'[{"a":[100,200,300],"x":43.2},{"a":{"z":true},"b":3,"c":"2012-01-20 10:42:53"}]') q;
2014-06-29 19:50:58 +02:00
a | b | c
-----------------+----+--------------------------
[100, 200, 300] | 99 |
{"z": true} | 3 | Fri Jan 20 10:42:53 2012
(2 rows)
2017-10-26 19:47:45 +02:00
-- anonymous record type
SELECT jsonb_populate_recordset(null::record, '[{"x": 0, "y": 1}]');
Restore json{b}_populate_record{set}'s ability to take type info from AS.
If the record argument is NULL and has no declared type more concrete
than RECORD, we can't extract useful information about the desired
rowtype from it. In this case, see if we're in FROM with an AS clause,
and if so extract the needed rowtype info from AS.
It worked like this before v11, but commit 37a795a60 removed the
behavior, reasoning that it was undocumented, inefficient, and utterly
not self-consistent. If you want to take type info from an AS clause,
you should be using the json_to_record() family of functions not the
json_populate_record() family. Also, it was already the case that
the "populate" functions would fail for a null-valued RECORD input
(with an unfriendly "record type has not been registered" error)
when there wasn't an AS clause at hand, and it wasn't obvious that
that behavior wasn't OK when there was one. However, it emerges
that some people were depending on this to work, and indeed the
rather off-point error message you got if you left off AS encouraged
slapping on AS without switching to the json_to_record() family.
Hence, put back the fallback behavior of looking for AS. While at it,
improve the run-time error you get when there's no place to obtain type
info; we can do a lot better than "record type has not been registered".
(We can't, unfortunately, easily improve the parse-time error message
that leads people down this path in the first place.)
While at it, I refactored the code a bit to avoid duplicating the
same logic in several different places.
Per bug #15940 from Jaroslav Sivy. Back-patch to v11 where the
current coding came in. (The pre-v11 deficiencies in this area
aren't regressions, so we'll leave those branches alone.)
Patch by me, based on preliminary analysis by Dmitry Dolgov.
Discussion: https://postgr.es/m/15940-2ab76dc58ffb85b6@postgresql.org
2019-08-20 00:00:57 +02:00
ERROR: could not determine row type for result of jsonb_populate_recordset
HINT: Provide a non-null record argument, or call the function in the FROM clause using a column definition list.
2017-10-26 19:47:45 +02:00
SELECT jsonb_populate_recordset(row(1,2), '[{"f1": 0, "f2": 1}]');
jsonb_populate_recordset
--------------------------
(0,1)
(1 row)
2018-07-13 20:16:47 +02:00
SELECT i, jsonb_populate_recordset(row(i,50), '[{"f1":"42"},{"f2":"43"}]')
FROM (VALUES (1),(2)) v(i);
i | jsonb_populate_recordset
---+--------------------------
1 | (42,50)
1 | (1,43)
2 | (42,50)
2 | (2,43)
(4 rows)
Restore json{b}_populate_record{set}'s ability to take type info from AS.
If the record argument is NULL and has no declared type more concrete
than RECORD, we can't extract useful information about the desired
rowtype from it. In this case, see if we're in FROM with an AS clause,
and if so extract the needed rowtype info from AS.
It worked like this before v11, but commit 37a795a60 removed the
behavior, reasoning that it was undocumented, inefficient, and utterly
not self-consistent. If you want to take type info from an AS clause,
you should be using the json_to_record() family of functions not the
json_populate_record() family. Also, it was already the case that
the "populate" functions would fail for a null-valued RECORD input
(with an unfriendly "record type has not been registered" error)
when there wasn't an AS clause at hand, and it wasn't obvious that
that behavior wasn't OK when there was one. However, it emerges
that some people were depending on this to work, and indeed the
rather off-point error message you got if you left off AS encouraged
slapping on AS without switching to the json_to_record() family.
Hence, put back the fallback behavior of looking for AS. While at it,
improve the run-time error you get when there's no place to obtain type
info; we can do a lot better than "record type has not been registered".
(We can't, unfortunately, easily improve the parse-time error message
that leads people down this path in the first place.)
While at it, I refactored the code a bit to avoid duplicating the
same logic in several different places.
Per bug #15940 from Jaroslav Sivy. Back-patch to v11 where the
current coding came in. (The pre-v11 deficiencies in this area
aren't regressions, so we'll leave those branches alone.)
Patch by me, based on preliminary analysis by Dmitry Dolgov.
Discussion: https://postgr.es/m/15940-2ab76dc58ffb85b6@postgresql.org
2019-08-20 00:00:57 +02:00
SELECT * FROM
jsonb_populate_recordset(null::record, '[{"x": 776}]') AS (x int, y int);
x | y
-----+---
776 |
(1 row)
2018-11-22 21:14:01 +01:00
-- empty array is a corner case
SELECT jsonb_populate_recordset(null::record, '[]');
Restore json{b}_populate_record{set}'s ability to take type info from AS.
If the record argument is NULL and has no declared type more concrete
than RECORD, we can't extract useful information about the desired
rowtype from it. In this case, see if we're in FROM with an AS clause,
and if so extract the needed rowtype info from AS.
It worked like this before v11, but commit 37a795a60 removed the
behavior, reasoning that it was undocumented, inefficient, and utterly
not self-consistent. If you want to take type info from an AS clause,
you should be using the json_to_record() family of functions not the
json_populate_record() family. Also, it was already the case that
the "populate" functions would fail for a null-valued RECORD input
(with an unfriendly "record type has not been registered" error)
when there wasn't an AS clause at hand, and it wasn't obvious that
that behavior wasn't OK when there was one. However, it emerges
that some people were depending on this to work, and indeed the
rather off-point error message you got if you left off AS encouraged
slapping on AS without switching to the json_to_record() family.
Hence, put back the fallback behavior of looking for AS. While at it,
improve the run-time error you get when there's no place to obtain type
info; we can do a lot better than "record type has not been registered".
(We can't, unfortunately, easily improve the parse-time error message
that leads people down this path in the first place.)
While at it, I refactored the code a bit to avoid duplicating the
same logic in several different places.
Per bug #15940 from Jaroslav Sivy. Back-patch to v11 where the
current coding came in. (The pre-v11 deficiencies in this area
aren't regressions, so we'll leave those branches alone.)
Patch by me, based on preliminary analysis by Dmitry Dolgov.
Discussion: https://postgr.es/m/15940-2ab76dc58ffb85b6@postgresql.org
2019-08-20 00:00:57 +02:00
ERROR: could not determine row type for result of jsonb_populate_recordset
HINT: Provide a non-null record argument, or call the function in the FROM clause using a column definition list.
2018-11-22 21:14:01 +01:00
SELECT jsonb_populate_recordset(row(1,2), '[]');
jsonb_populate_recordset
--------------------------
(0 rows)
SELECT * FROM jsonb_populate_recordset(NULL::jbpop,'[]') q;
a | b | c
---+---+---
(0 rows)
Restore json{b}_populate_record{set}'s ability to take type info from AS.
If the record argument is NULL and has no declared type more concrete
than RECORD, we can't extract useful information about the desired
rowtype from it. In this case, see if we're in FROM with an AS clause,
and if so extract the needed rowtype info from AS.
It worked like this before v11, but commit 37a795a60 removed the
behavior, reasoning that it was undocumented, inefficient, and utterly
not self-consistent. If you want to take type info from an AS clause,
you should be using the json_to_record() family of functions not the
json_populate_record() family. Also, it was already the case that
the "populate" functions would fail for a null-valued RECORD input
(with an unfriendly "record type has not been registered" error)
when there wasn't an AS clause at hand, and it wasn't obvious that
that behavior wasn't OK when there was one. However, it emerges
that some people were depending on this to work, and indeed the
rather off-point error message you got if you left off AS encouraged
slapping on AS without switching to the json_to_record() family.
Hence, put back the fallback behavior of looking for AS. While at it,
improve the run-time error you get when there's no place to obtain type
info; we can do a lot better than "record type has not been registered".
(We can't, unfortunately, easily improve the parse-time error message
that leads people down this path in the first place.)
While at it, I refactored the code a bit to avoid duplicating the
same logic in several different places.
Per bug #15940 from Jaroslav Sivy. Back-patch to v11 where the
current coding came in. (The pre-v11 deficiencies in this area
aren't regressions, so we'll leave those branches alone.)
Patch by me, based on preliminary analysis by Dmitry Dolgov.
Discussion: https://postgr.es/m/15940-2ab76dc58ffb85b6@postgresql.org
2019-08-20 00:00:57 +02:00
SELECT * FROM
jsonb_populate_recordset(null::record, '[]') AS (x int, y int);
x | y
---+---
(0 rows)
2017-10-26 19:47:45 +02:00
-- composite domain
SELECT jsonb_populate_recordset(null::jb_ordered_pair, '[{"x": 0, "y": 1}]');
jsonb_populate_recordset
--------------------------
(0,1)
(1 row)
SELECT jsonb_populate_recordset(row(1,2)::jb_ordered_pair, '[{"x": 0}, {"y": 3}]');
jsonb_populate_recordset
--------------------------
(0,2)
(1,3)
(2 rows)
SELECT jsonb_populate_recordset(row(1,2)::jb_ordered_pair, '[{"x": 1, "y": 0}]');
ERROR: value for domain jb_ordered_pair violates check constraint "jb_ordered_pair_check"
2017-11-06 16:29:11 +01:00
-- negative cases where the wrong record type is supplied
select * from jsonb_populate_recordset(row(0::int),'[{"a":"1","b":"2"},{"a":"3"}]') q (a text, b text);
ERROR: function return row and query-specified return row do not match
DETAIL: Returned row contains 1 attribute, but query expects 2.
select * from jsonb_populate_recordset(row(0::int,0::int),'[{"a":"1","b":"2"},{"a":"3"}]') q (a text, b text);
ERROR: function return row and query-specified return row do not match
DETAIL: Returned type integer at ordinal position 1, but query expects text.
select * from jsonb_populate_recordset(row(0::int,0::int,0::int),'[{"a":"1","b":"2"},{"a":"3"}]') q (a text, b text);
ERROR: function return row and query-specified return row do not match
DETAIL: Returned row contains 3 attributes, but query expects 2.
select * from jsonb_populate_recordset(row(1000000000::int,50::int),'[{"b":"2"},{"a":"3"}]') q (a text, b text);
ERROR: function return row and query-specified return row do not match
DETAIL: Returned type integer at ordinal position 1, but query expects text.
2014-03-26 15:18:24 +01:00
-- jsonb_to_record and jsonb_to_recordset
2014-06-29 19:50:58 +02:00
select * from jsonb_to_record('{"a":1,"b":"foo","c":"bar"}')
2014-03-26 15:18:24 +01:00
as x(a int, b text, d text);
a | b | d
---+-----+---
1 | foo |
(1 row)
2014-06-29 19:50:58 +02:00
select * from jsonb_to_recordset('[{"a":1,"b":"foo","d":false},{"a":2,"b":"bar","c":true}]')
2014-03-26 15:18:24 +01:00
as x(a int, b text, c boolean);
a | b | c
---+-----+---
1 | foo |
2 | bar | t
(2 rows)
2016-03-03 05:31:39 +01:00
select *, c is null as c_is_null
2017-04-07 04:11:21 +02:00
from jsonb_to_record('{"a":1, "b":{"c":16, "d":2}, "x":8, "ca": ["1 2", 3], "ia": [[1,2],[3,4]], "r": {"a": "aaa", "b": 123}}'::jsonb)
as t(a int, b jsonb, c text, x int, ca char(5)[], ia int[][], r jbpop);
a | b | c | x | ca | ia | r | c_is_null
---+-------------------+---+---+-------------------+---------------+------------+-----------
1 | {"c": 16, "d": 2} | | 8 | {"1 2 ","3 "} | {{1,2},{3,4}} | (aaa,123,) | t
2016-03-03 05:31:39 +01:00
(1 row)
select *, c is null as c_is_null
from jsonb_to_recordset('[{"a":1, "b":{"c":16, "d":2}, "x":8}]'::jsonb)
as t(a int, b jsonb, c text, x int);
a | b | c | x | c_is_null
---+-------------------+---+---+-----------
1 | {"c": 16, "d": 2} | | 8 | t
(1 row)
2017-04-07 04:11:21 +02:00
select * from jsonb_to_record('{"ia": null}') as x(ia _int4);
ia
----
(1 row)
select * from jsonb_to_record('{"ia": 123}') as x(ia _int4);
2018-05-08 20:36:31 +02:00
ERROR: expected JSON array
2017-09-11 17:20:47 +02:00
HINT: See the value of key "ia".
2017-04-07 04:11:21 +02:00
select * from jsonb_to_record('{"ia": [1, "2", null, 4]}') as x(ia _int4);
ia
--------------
{1,2,NULL,4}
(1 row)
select * from jsonb_to_record('{"ia": [[1, 2], [3, 4]]}') as x(ia _int4);
ia
---------------
{{1,2},{3,4}}
(1 row)
select * from jsonb_to_record('{"ia": [[1], 2]}') as x(ia _int4);
2018-05-08 20:36:31 +02:00
ERROR: expected JSON array
2017-09-11 17:20:47 +02:00
HINT: See the array element [1] of key "ia".
2017-04-07 04:11:21 +02:00
select * from jsonb_to_record('{"ia": [[1], [2, 3]]}') as x(ia _int4);
2018-05-08 20:36:31 +02:00
ERROR: malformed JSON array
2017-04-07 04:11:21 +02:00
DETAIL: Multidimensional arrays must have sub-arrays with matching dimensions.
select * from jsonb_to_record('{"ia2": [1, 2, 3]}') as x(ia2 int[][]);
ia2
---------
{1,2,3}
(1 row)
select * from jsonb_to_record('{"ia2": [[1, 2], [3, 4]]}') as x(ia2 int4[][]);
ia2
---------------
{{1,2},{3,4}}
(1 row)
select * from jsonb_to_record('{"ia2": [[[1], [2], [3]]]}') as x(ia2 int4[][]);
ia2
-----------------
{{{1},{2},{3}}}
(1 row)
2019-06-11 19:33:08 +02:00
select * from jsonb_to_record('{"out": {"key": 1}}') as x(out json);
out
------------
{"key": 1}
(1 row)
select * from jsonb_to_record('{"out": [{"key": 1}]}') as x(out json);
out
--------------
[{"key": 1}]
(1 row)
select * from jsonb_to_record('{"out": "{\"key\": 1}"}') as x(out json);
out
----------------
"{\"key\": 1}"
(1 row)
select * from jsonb_to_record('{"out": {"key": 1}}') as x(out jsonb);
out
------------
{"key": 1}
(1 row)
select * from jsonb_to_record('{"out": [{"key": 1}]}') as x(out jsonb);
out
--------------
[{"key": 1}]
(1 row)
select * from jsonb_to_record('{"out": "{\"key\": 1}"}') as x(out jsonb);
out
----------------
"{\"key\": 1}"
(1 row)
2017-04-07 04:11:21 +02:00
-- test type info caching in jsonb_populate_record()
CREATE TEMP TABLE jsbpoptest (js jsonb);
INSERT INTO jsbpoptest
SELECT '{
"jsa": [1, "2", null, 4],
"rec": {"a": "abc", "c": "01.02.2003", "x": 43.2},
"reca": [{"a": "abc", "b": 456}, null, {"c": "01.02.2003", "x": 43.2}]
}'::jsonb
FROM generate_series(1, 3);
SELECT (jsonb_populate_record(NULL::jsbrec, js)).* FROM jsbpoptest;
i | ia | ia1 | ia2 | ia3 | ia1d | ia2d | t | ta | c | ca | ts | js | jsb | jsa | rec | reca
---+----+-----+-----+-----+------+------+---+----+---+----+----+----+-----+--------------------+-----------------------------------+--------------------------------------------------------
| | | | | | | | | | | | | | {1,"\"2\"",NULL,4} | (abc,,"Thu Jan 02 00:00:00 2003") | {"(abc,456,)",NULL,"(,,\"Thu Jan 02 00:00:00 2003\")"}
| | | | | | | | | | | | | | {1,"\"2\"",NULL,4} | (abc,,"Thu Jan 02 00:00:00 2003") | {"(abc,456,)",NULL,"(,,\"Thu Jan 02 00:00:00 2003\")"}
| | | | | | | | | | | | | | {1,"\"2\"",NULL,4} | (abc,,"Thu Jan 02 00:00:00 2003") | {"(abc,456,)",NULL,"(,,\"Thu Jan 02 00:00:00 2003\")"}
(3 rows)
DROP TYPE jsbrec;
DROP TYPE jsbrec_i_not_null;
DROP DOMAIN jsb_int_not_null;
DROP DOMAIN jsb_int_array_1d;
DROP DOMAIN jsb_int_array_2d;
2017-10-26 19:47:45 +02:00
DROP DOMAIN jb_ordered_pair;
DROP TYPE jb_unordered_pair;
Introduce jsonb, a structured format for storing json.
The new format accepts exactly the same data as the json type. However, it is
stored in a format that does not require reparsing the orgiginal text in order
to process it, making it much more suitable for indexing and other operations.
Insignificant whitespace is discarded, and the order of object keys is not
preserved. Neither are duplicate object keys kept - the later value for a given
key is the only one stored.
The new type has all the functions and operators that the json type has,
with the exception of the json generation functions (to_json, json_agg etc.)
and with identical semantics. In addition, there are operator classes for
hash and btree indexing, and two classes for GIN indexing, that have no
equivalent in the json type.
This feature grew out of previous work by Oleg Bartunov and Teodor Sigaev, which
was intended to provide similar facilities to a nested hstore type, but which
in the end proved to have some significant compatibility issues.
Authors: Oleg Bartunov, Teodor Sigaev, Peter Geoghegan and Andrew Dunstan.
Review: Andres Freund
2014-03-23 21:40:19 +01:00
-- indexing
SELECT count(*) FROM testjsonb WHERE j @> '{"wait":null}';
count
-------
1
(1 row)
SELECT count(*) FROM testjsonb WHERE j @> '{"wait":"CC"}';
count
-------
15
(1 row)
SELECT count(*) FROM testjsonb WHERE j @> '{"wait":"CC", "public":true}';
count
-------
2
(1 row)
SELECT count(*) FROM testjsonb WHERE j @> '{"age":25}';
count
-------
2
(1 row)
SELECT count(*) FROM testjsonb WHERE j @> '{"age":25.0}';
count
-------
2
(1 row)
SELECT count(*) FROM testjsonb WHERE j ? 'public';
count
-------
194
(1 row)
2014-05-09 14:41:26 +02:00
SELECT count(*) FROM testjsonb WHERE j ? 'bar';
count
-------
0
(1 row)
Introduce jsonb, a structured format for storing json.
The new format accepts exactly the same data as the json type. However, it is
stored in a format that does not require reparsing the orgiginal text in order
to process it, making it much more suitable for indexing and other operations.
Insignificant whitespace is discarded, and the order of object keys is not
preserved. Neither are duplicate object keys kept - the later value for a given
key is the only one stored.
The new type has all the functions and operators that the json type has,
with the exception of the json generation functions (to_json, json_agg etc.)
and with identical semantics. In addition, there are operator classes for
hash and btree indexing, and two classes for GIN indexing, that have no
equivalent in the json type.
This feature grew out of previous work by Oleg Bartunov and Teodor Sigaev, which
was intended to provide similar facilities to a nested hstore type, but which
in the end proved to have some significant compatibility issues.
Authors: Oleg Bartunov, Teodor Sigaev, Peter Geoghegan and Andrew Dunstan.
Review: Andres Freund
2014-03-23 21:40:19 +01:00
SELECT count(*) FROM testjsonb WHERE j ?| ARRAY['public','disabled'];
count
-------
337
(1 row)
SELECT count(*) FROM testjsonb WHERE j ?& ARRAY['public','disabled'];
count
-------
42
(1 row)
2019-04-01 17:08:15 +02:00
SELECT count(*) FROM testjsonb WHERE j @@ '$.wait == null';
count
-------
1
(1 row)
SELECT count(*) FROM testjsonb WHERE j @@ '"CC" == $.wait';
count
-------
15
(1 row)
SELECT count(*) FROM testjsonb WHERE j @@ '$.wait == "CC" && true == $.public';
count
-------
2
(1 row)
SELECT count(*) FROM testjsonb WHERE j @@ '$.age == 25';
count
-------
2
(1 row)
SELECT count(*) FROM testjsonb WHERE j @@ '$.age == 25.0';
count
-------
2
(1 row)
SELECT count(*) FROM testjsonb WHERE j @@ 'exists($)';
count
-------
1012
(1 row)
SELECT count(*) FROM testjsonb WHERE j @@ 'exists($.public)';
count
-------
194
(1 row)
SELECT count(*) FROM testjsonb WHERE j @@ 'exists($.bar)';
count
-------
0
(1 row)
SELECT count(*) FROM testjsonb WHERE j @@ 'exists($.public) || exists($.disabled)';
count
-------
337
(1 row)
SELECT count(*) FROM testjsonb WHERE j @@ 'exists($.public) && exists($.disabled)';
count
-------
42
(1 row)
SELECT count(*) FROM testjsonb WHERE j @? '$.wait ? (@ == null)';
count
-------
1
(1 row)
SELECT count(*) FROM testjsonb WHERE j @? '$.wait ? ("CC" == @)';
count
-------
15
(1 row)
SELECT count(*) FROM testjsonb WHERE j @? '$ ? (@.wait == "CC" && true == @.public)';
count
-------
2
(1 row)
SELECT count(*) FROM testjsonb WHERE j @? '$.age ? (@ == 25)';
count
-------
2
(1 row)
SELECT count(*) FROM testjsonb WHERE j @? '$ ? (@.age == 25.0)';
count
-------
2
(1 row)
SELECT count(*) FROM testjsonb WHERE j @? '$';
count
-------
1012
(1 row)
SELECT count(*) FROM testjsonb WHERE j @? '$.public';
count
-------
194
(1 row)
SELECT count(*) FROM testjsonb WHERE j @? '$.bar';
count
-------
0
(1 row)
Introduce jsonb, a structured format for storing json.
The new format accepts exactly the same data as the json type. However, it is
stored in a format that does not require reparsing the orgiginal text in order
to process it, making it much more suitable for indexing and other operations.
Insignificant whitespace is discarded, and the order of object keys is not
preserved. Neither are duplicate object keys kept - the later value for a given
key is the only one stored.
The new type has all the functions and operators that the json type has,
with the exception of the json generation functions (to_json, json_agg etc.)
and with identical semantics. In addition, there are operator classes for
hash and btree indexing, and two classes for GIN indexing, that have no
equivalent in the json type.
This feature grew out of previous work by Oleg Bartunov and Teodor Sigaev, which
was intended to provide similar facilities to a nested hstore type, but which
in the end proved to have some significant compatibility issues.
Authors: Oleg Bartunov, Teodor Sigaev, Peter Geoghegan and Andrew Dunstan.
Review: Andres Freund
2014-03-23 21:40:19 +01:00
CREATE INDEX jidx ON testjsonb USING gin (j);
SET enable_seqscan = off;
SELECT count(*) FROM testjsonb WHERE j @> '{"wait":null}';
count
-------
1
(1 row)
SELECT count(*) FROM testjsonb WHERE j @> '{"wait":"CC"}';
count
-------
15
(1 row)
SELECT count(*) FROM testjsonb WHERE j @> '{"wait":"CC", "public":true}';
count
-------
2
(1 row)
SELECT count(*) FROM testjsonb WHERE j @> '{"age":25}';
count
-------
2
(1 row)
SELECT count(*) FROM testjsonb WHERE j @> '{"age":25.0}';
count
-------
2
(1 row)
SELECT count(*) FROM testjsonb WHERE j @> '{"array":["foo"]}';
count
-------
3
(1 row)
SELECT count(*) FROM testjsonb WHERE j @> '{"array":["bar"]}';
count
-------
3
(1 row)
2015-07-05 19:14:38 +02:00
-- exercise GIN_SEARCH_MODE_ALL
Introduce jsonb, a structured format for storing json.
The new format accepts exactly the same data as the json type. However, it is
stored in a format that does not require reparsing the orgiginal text in order
to process it, making it much more suitable for indexing and other operations.
Insignificant whitespace is discarded, and the order of object keys is not
preserved. Neither are duplicate object keys kept - the later value for a given
key is the only one stored.
The new type has all the functions and operators that the json type has,
with the exception of the json generation functions (to_json, json_agg etc.)
and with identical semantics. In addition, there are operator classes for
hash and btree indexing, and two classes for GIN indexing, that have no
equivalent in the json type.
This feature grew out of previous work by Oleg Bartunov and Teodor Sigaev, which
was intended to provide similar facilities to a nested hstore type, but which
in the end proved to have some significant compatibility issues.
Authors: Oleg Bartunov, Teodor Sigaev, Peter Geoghegan and Andrew Dunstan.
Review: Andres Freund
2014-03-23 21:40:19 +01:00
SELECT count(*) FROM testjsonb WHERE j @> '{}';
count
-------
2014-05-09 14:41:26 +02:00
1012
Introduce jsonb, a structured format for storing json.
The new format accepts exactly the same data as the json type. However, it is
stored in a format that does not require reparsing the orgiginal text in order
to process it, making it much more suitable for indexing and other operations.
Insignificant whitespace is discarded, and the order of object keys is not
preserved. Neither are duplicate object keys kept - the later value for a given
key is the only one stored.
The new type has all the functions and operators that the json type has,
with the exception of the json generation functions (to_json, json_agg etc.)
and with identical semantics. In addition, there are operator classes for
hash and btree indexing, and two classes for GIN indexing, that have no
equivalent in the json type.
This feature grew out of previous work by Oleg Bartunov and Teodor Sigaev, which
was intended to provide similar facilities to a nested hstore type, but which
in the end proved to have some significant compatibility issues.
Authors: Oleg Bartunov, Teodor Sigaev, Peter Geoghegan and Andrew Dunstan.
Review: Andres Freund
2014-03-23 21:40:19 +01:00
(1 row)
SELECT count(*) FROM testjsonb WHERE j ? 'public';
count
-------
194
(1 row)
2014-05-09 14:41:26 +02:00
SELECT count(*) FROM testjsonb WHERE j ? 'bar';
count
-------
0
(1 row)
Introduce jsonb, a structured format for storing json.
The new format accepts exactly the same data as the json type. However, it is
stored in a format that does not require reparsing the orgiginal text in order
to process it, making it much more suitable for indexing and other operations.
Insignificant whitespace is discarded, and the order of object keys is not
preserved. Neither are duplicate object keys kept - the later value for a given
key is the only one stored.
The new type has all the functions and operators that the json type has,
with the exception of the json generation functions (to_json, json_agg etc.)
and with identical semantics. In addition, there are operator classes for
hash and btree indexing, and two classes for GIN indexing, that have no
equivalent in the json type.
This feature grew out of previous work by Oleg Bartunov and Teodor Sigaev, which
was intended to provide similar facilities to a nested hstore type, but which
in the end proved to have some significant compatibility issues.
Authors: Oleg Bartunov, Teodor Sigaev, Peter Geoghegan and Andrew Dunstan.
Review: Andres Freund
2014-03-23 21:40:19 +01:00
SELECT count(*) FROM testjsonb WHERE j ?| ARRAY['public','disabled'];
count
-------
337
(1 row)
SELECT count(*) FROM testjsonb WHERE j ?& ARRAY['public','disabled'];
count
-------
42
(1 row)
2019-04-01 17:08:15 +02:00
EXPLAIN (COSTS OFF)
SELECT count(*) FROM testjsonb WHERE j @@ '$.wait == null';
QUERY PLAN
-----------------------------------------------------------------
Aggregate
-> Bitmap Heap Scan on testjsonb
Recheck Cond: (j @@ '($."wait" == null)'::jsonpath)
-> Bitmap Index Scan on jidx
Index Cond: (j @@ '($."wait" == null)'::jsonpath)
(5 rows)
SELECT count(*) FROM testjsonb WHERE j @@ '$.wait == null';
count
-------
1
(1 row)
SELECT count(*) FROM testjsonb WHERE j @@ 'exists($ ? (@.wait == null))';
count
-------
1
(1 row)
SELECT count(*) FROM testjsonb WHERE j @@ 'exists($.wait ? (@ == null))';
count
-------
1
(1 row)
SELECT count(*) FROM testjsonb WHERE j @@ '"CC" == $.wait';
count
-------
15
(1 row)
SELECT count(*) FROM testjsonb WHERE j @@ '$.wait == "CC" && true == $.public';
count
-------
2
(1 row)
SELECT count(*) FROM testjsonb WHERE j @@ '$.age == 25';
count
-------
2
(1 row)
SELECT count(*) FROM testjsonb WHERE j @@ '$.age == 25.0';
count
-------
2
(1 row)
SELECT count(*) FROM testjsonb WHERE j @@ '$.array[*] == "foo"';
count
-------
3
(1 row)
SELECT count(*) FROM testjsonb WHERE j @@ '$.array[*] == "bar"';
count
-------
3
(1 row)
SELECT count(*) FROM testjsonb WHERE j @@ 'exists($ ? (@.array[*] == "bar"))';
count
-------
3
(1 row)
SELECT count(*) FROM testjsonb WHERE j @@ 'exists($.array ? (@[*] == "bar"))';
count
-------
3
(1 row)
SELECT count(*) FROM testjsonb WHERE j @@ 'exists($.array[*] ? (@ == "bar"))';
count
-------
3
(1 row)
SELECT count(*) FROM testjsonb WHERE j @@ 'exists($)';
count
-------
1012
(1 row)
SELECT count(*) FROM testjsonb WHERE j @@ 'exists($.public)';
count
-------
194
(1 row)
SELECT count(*) FROM testjsonb WHERE j @@ 'exists($.bar)';
count
-------
0
(1 row)
SELECT count(*) FROM testjsonb WHERE j @@ 'exists($.public) || exists($.disabled)';
count
-------
337
(1 row)
SELECT count(*) FROM testjsonb WHERE j @@ 'exists($.public) && exists($.disabled)';
count
-------
42
(1 row)
EXPLAIN (COSTS OFF)
SELECT count(*) FROM testjsonb WHERE j @? '$.wait ? (@ == null)';
QUERY PLAN
-------------------------------------------------------------------
Aggregate
-> Bitmap Heap Scan on testjsonb
Recheck Cond: (j @? '$."wait"?(@ == null)'::jsonpath)
-> Bitmap Index Scan on jidx
Index Cond: (j @? '$."wait"?(@ == null)'::jsonpath)
(5 rows)
SELECT count(*) FROM testjsonb WHERE j @? '$.wait ? (@ == null)';
count
-------
1
(1 row)
SELECT count(*) FROM testjsonb WHERE j @? '$.wait ? ("CC" == @)';
count
-------
15
(1 row)
SELECT count(*) FROM testjsonb WHERE j @? '$ ? (@.wait == "CC" && true == @.public)';
count
-------
2
(1 row)
SELECT count(*) FROM testjsonb WHERE j @? '$.age ? (@ == 25)';
count
-------
2
(1 row)
SELECT count(*) FROM testjsonb WHERE j @? '$ ? (@.age == 25.0)';
count
-------
2
(1 row)
SELECT count(*) FROM testjsonb WHERE j @? '$ ? (@.array[*] == "bar")';
count
-------
3
(1 row)
SELECT count(*) FROM testjsonb WHERE j @? '$.array ? (@[*] == "bar")';
count
-------
3
(1 row)
SELECT count(*) FROM testjsonb WHERE j @? '$.array[*] ? (@ == "bar")';
count
-------
3
(1 row)
SELECT count(*) FROM testjsonb WHERE j @? '$';
count
-------
1012
(1 row)
SELECT count(*) FROM testjsonb WHERE j @? '$.public';
count
-------
194
(1 row)
SELECT count(*) FROM testjsonb WHERE j @? '$.bar';
count
-------
0
(1 row)
Introduce jsonb, a structured format for storing json.
The new format accepts exactly the same data as the json type. However, it is
stored in a format that does not require reparsing the orgiginal text in order
to process it, making it much more suitable for indexing and other operations.
Insignificant whitespace is discarded, and the order of object keys is not
preserved. Neither are duplicate object keys kept - the later value for a given
key is the only one stored.
The new type has all the functions and operators that the json type has,
with the exception of the json generation functions (to_json, json_agg etc.)
and with identical semantics. In addition, there are operator classes for
hash and btree indexing, and two classes for GIN indexing, that have no
equivalent in the json type.
This feature grew out of previous work by Oleg Bartunov and Teodor Sigaev, which
was intended to provide similar facilities to a nested hstore type, but which
in the end proved to have some significant compatibility issues.
Authors: Oleg Bartunov, Teodor Sigaev, Peter Geoghegan and Andrew Dunstan.
Review: Andres Freund
2014-03-23 21:40:19 +01:00
-- array exists - array elements should behave as keys (for GIN index scans too)
CREATE INDEX jidx_array ON testjsonb USING gin((j->'array'));
SELECT count(*) from testjsonb WHERE j->'array' ? 'bar';
count
-------
3
(1 row)
-- type sensitive array exists - should return no rows (since "exists" only
-- matches strings that are either object keys or array elements)
SELECT count(*) from testjsonb WHERE j->'array' ? '5'::text;
count
-------
0
(1 row)
-- However, a raw scalar is *contained* within the array
SELECT count(*) from testjsonb WHERE j->'array' @> '5'::jsonb;
count
-------
1
(1 row)
RESET enable_seqscan;
SELECT count(*) FROM (SELECT (jsonb_each(j)).key FROM testjsonb) AS wow;
count
-------
2014-05-09 14:41:26 +02:00
4791
Introduce jsonb, a structured format for storing json.
The new format accepts exactly the same data as the json type. However, it is
stored in a format that does not require reparsing the orgiginal text in order
to process it, making it much more suitable for indexing and other operations.
Insignificant whitespace is discarded, and the order of object keys is not
preserved. Neither are duplicate object keys kept - the later value for a given
key is the only one stored.
The new type has all the functions and operators that the json type has,
with the exception of the json generation functions (to_json, json_agg etc.)
and with identical semantics. In addition, there are operator classes for
hash and btree indexing, and two classes for GIN indexing, that have no
equivalent in the json type.
This feature grew out of previous work by Oleg Bartunov and Teodor Sigaev, which
was intended to provide similar facilities to a nested hstore type, but which
in the end proved to have some significant compatibility issues.
Authors: Oleg Bartunov, Teodor Sigaev, Peter Geoghegan and Andrew Dunstan.
Review: Andres Freund
2014-03-23 21:40:19 +01:00
(1 row)
SELECT key, count(*) FROM (SELECT (jsonb_each(j)).key FROM testjsonb) AS wow GROUP BY key ORDER BY count DESC, key;
key | count
-----------+-------
line | 884
query | 207
pos | 203
node | 202
space | 197
status | 195
public | 194
title | 190
wait | 190
org | 189
user | 189
coauthors | 188
disabled | 185
indexed | 184
cleaned | 180
bad | 179
date | 179
world | 176
state | 172
subtitle | 169
auth | 168
abstract | 161
array | 5
age | 2
2014-05-09 14:41:26 +02:00
foo | 2
fool | 1
(26 rows)
Introduce jsonb, a structured format for storing json.
The new format accepts exactly the same data as the json type. However, it is
stored in a format that does not require reparsing the orgiginal text in order
to process it, making it much more suitable for indexing and other operations.
Insignificant whitespace is discarded, and the order of object keys is not
preserved. Neither are duplicate object keys kept - the later value for a given
key is the only one stored.
The new type has all the functions and operators that the json type has,
with the exception of the json generation functions (to_json, json_agg etc.)
and with identical semantics. In addition, there are operator classes for
hash and btree indexing, and two classes for GIN indexing, that have no
equivalent in the json type.
This feature grew out of previous work by Oleg Bartunov and Teodor Sigaev, which
was intended to provide similar facilities to a nested hstore type, but which
in the end proved to have some significant compatibility issues.
Authors: Oleg Bartunov, Teodor Sigaev, Peter Geoghegan and Andrew Dunstan.
Review: Andres Freund
2014-03-23 21:40:19 +01:00
-- sort/hash
SELECT count(distinct j) FROM testjsonb;
count
-------
2014-05-09 14:41:26 +02:00
894
Introduce jsonb, a structured format for storing json.
The new format accepts exactly the same data as the json type. However, it is
stored in a format that does not require reparsing the orgiginal text in order
to process it, making it much more suitable for indexing and other operations.
Insignificant whitespace is discarded, and the order of object keys is not
preserved. Neither are duplicate object keys kept - the later value for a given
key is the only one stored.
The new type has all the functions and operators that the json type has,
with the exception of the json generation functions (to_json, json_agg etc.)
and with identical semantics. In addition, there are operator classes for
hash and btree indexing, and two classes for GIN indexing, that have no
equivalent in the json type.
This feature grew out of previous work by Oleg Bartunov and Teodor Sigaev, which
was intended to provide similar facilities to a nested hstore type, but which
in the end proved to have some significant compatibility issues.
Authors: Oleg Bartunov, Teodor Sigaev, Peter Geoghegan and Andrew Dunstan.
Review: Andres Freund
2014-03-23 21:40:19 +01:00
(1 row)
SET enable_hashagg = off;
SELECT count(*) FROM (SELECT j FROM (SELECT * FROM testjsonb UNION ALL SELECT * FROM testjsonb) js GROUP BY j) js2;
count
-------
2014-05-09 14:41:26 +02:00
894
Introduce jsonb, a structured format for storing json.
The new format accepts exactly the same data as the json type. However, it is
stored in a format that does not require reparsing the orgiginal text in order
to process it, making it much more suitable for indexing and other operations.
Insignificant whitespace is discarded, and the order of object keys is not
preserved. Neither are duplicate object keys kept - the later value for a given
key is the only one stored.
The new type has all the functions and operators that the json type has,
with the exception of the json generation functions (to_json, json_agg etc.)
and with identical semantics. In addition, there are operator classes for
hash and btree indexing, and two classes for GIN indexing, that have no
equivalent in the json type.
This feature grew out of previous work by Oleg Bartunov and Teodor Sigaev, which
was intended to provide similar facilities to a nested hstore type, but which
in the end proved to have some significant compatibility issues.
Authors: Oleg Bartunov, Teodor Sigaev, Peter Geoghegan and Andrew Dunstan.
Review: Andres Freund
2014-03-23 21:40:19 +01:00
(1 row)
SET enable_hashagg = on;
SET enable_sort = off;
SELECT count(*) FROM (SELECT j FROM (SELECT * FROM testjsonb UNION ALL SELECT * FROM testjsonb) js GROUP BY j) js2;
count
-------
2014-05-09 14:41:26 +02:00
894
Introduce jsonb, a structured format for storing json.
The new format accepts exactly the same data as the json type. However, it is
stored in a format that does not require reparsing the orgiginal text in order
to process it, making it much more suitable for indexing and other operations.
Insignificant whitespace is discarded, and the order of object keys is not
preserved. Neither are duplicate object keys kept - the later value for a given
key is the only one stored.
The new type has all the functions and operators that the json type has,
with the exception of the json generation functions (to_json, json_agg etc.)
and with identical semantics. In addition, there are operator classes for
hash and btree indexing, and two classes for GIN indexing, that have no
equivalent in the json type.
This feature grew out of previous work by Oleg Bartunov and Teodor Sigaev, which
was intended to provide similar facilities to a nested hstore type, but which
in the end proved to have some significant compatibility issues.
Authors: Oleg Bartunov, Teodor Sigaev, Peter Geoghegan and Andrew Dunstan.
Review: Andres Freund
2014-03-23 21:40:19 +01:00
(1 row)
2015-05-12 21:52:45 +02:00
SELECT distinct * FROM (values (jsonb '{}' || ''::text),('{}')) v(j);
Introduce jsonb, a structured format for storing json.
The new format accepts exactly the same data as the json type. However, it is
stored in a format that does not require reparsing the orgiginal text in order
to process it, making it much more suitable for indexing and other operations.
Insignificant whitespace is discarded, and the order of object keys is not
preserved. Neither are duplicate object keys kept - the later value for a given
key is the only one stored.
The new type has all the functions and operators that the json type has,
with the exception of the json generation functions (to_json, json_agg etc.)
and with identical semantics. In addition, there are operator classes for
hash and btree indexing, and two classes for GIN indexing, that have no
equivalent in the json type.
This feature grew out of previous work by Oleg Bartunov and Teodor Sigaev, which
was intended to provide similar facilities to a nested hstore type, but which
in the end proved to have some significant compatibility issues.
Authors: Oleg Bartunov, Teodor Sigaev, Peter Geoghegan and Andrew Dunstan.
Review: Andres Freund
2014-03-23 21:40:19 +01:00
j
----
{}
(1 row)
SET enable_sort = on;
RESET enable_hashagg;
RESET enable_sort;
DROP INDEX jidx;
DROP INDEX jidx_array;
-- btree
CREATE INDEX jidx ON testjsonb USING btree (j);
SET enable_seqscan = off;
SELECT count(*) FROM testjsonb WHERE j > '{"p":1}';
count
-------
884
(1 row)
SELECT count(*) FROM testjsonb WHERE j = '{"pos":98, "line":371, "node":"CBA", "indexed":true}';
count
-------
1
(1 row)
2014-05-11 18:06:04 +02:00
--gin path opclass
Introduce jsonb, a structured format for storing json.
The new format accepts exactly the same data as the json type. However, it is
stored in a format that does not require reparsing the orgiginal text in order
to process it, making it much more suitable for indexing and other operations.
Insignificant whitespace is discarded, and the order of object keys is not
preserved. Neither are duplicate object keys kept - the later value for a given
key is the only one stored.
The new type has all the functions and operators that the json type has,
with the exception of the json generation functions (to_json, json_agg etc.)
and with identical semantics. In addition, there are operator classes for
hash and btree indexing, and two classes for GIN indexing, that have no
equivalent in the json type.
This feature grew out of previous work by Oleg Bartunov and Teodor Sigaev, which
was intended to provide similar facilities to a nested hstore type, but which
in the end proved to have some significant compatibility issues.
Authors: Oleg Bartunov, Teodor Sigaev, Peter Geoghegan and Andrew Dunstan.
Review: Andres Freund
2014-03-23 21:40:19 +01:00
DROP INDEX jidx;
2014-05-11 18:06:04 +02:00
CREATE INDEX jidx ON testjsonb USING gin (j jsonb_path_ops);
Introduce jsonb, a structured format for storing json.
The new format accepts exactly the same data as the json type. However, it is
stored in a format that does not require reparsing the orgiginal text in order
to process it, making it much more suitable for indexing and other operations.
Insignificant whitespace is discarded, and the order of object keys is not
preserved. Neither are duplicate object keys kept - the later value for a given
key is the only one stored.
The new type has all the functions and operators that the json type has,
with the exception of the json generation functions (to_json, json_agg etc.)
and with identical semantics. In addition, there are operator classes for
hash and btree indexing, and two classes for GIN indexing, that have no
equivalent in the json type.
This feature grew out of previous work by Oleg Bartunov and Teodor Sigaev, which
was intended to provide similar facilities to a nested hstore type, but which
in the end proved to have some significant compatibility issues.
Authors: Oleg Bartunov, Teodor Sigaev, Peter Geoghegan and Andrew Dunstan.
Review: Andres Freund
2014-03-23 21:40:19 +01:00
SET enable_seqscan = off;
SELECT count(*) FROM testjsonb WHERE j @> '{"wait":null}';
count
-------
1
(1 row)
SELECT count(*) FROM testjsonb WHERE j @> '{"wait":"CC"}';
count
-------
15
(1 row)
SELECT count(*) FROM testjsonb WHERE j @> '{"wait":"CC", "public":true}';
count
-------
2
(1 row)
SELECT count(*) FROM testjsonb WHERE j @> '{"age":25}';
count
-------
2
(1 row)
SELECT count(*) FROM testjsonb WHERE j @> '{"age":25.0}';
count
-------
2
(1 row)
2015-07-05 19:14:38 +02:00
-- exercise GIN_SEARCH_MODE_ALL
Introduce jsonb, a structured format for storing json.
The new format accepts exactly the same data as the json type. However, it is
stored in a format that does not require reparsing the orgiginal text in order
to process it, making it much more suitable for indexing and other operations.
Insignificant whitespace is discarded, and the order of object keys is not
preserved. Neither are duplicate object keys kept - the later value for a given
key is the only one stored.
The new type has all the functions and operators that the json type has,
with the exception of the json generation functions (to_json, json_agg etc.)
and with identical semantics. In addition, there are operator classes for
hash and btree indexing, and two classes for GIN indexing, that have no
equivalent in the json type.
This feature grew out of previous work by Oleg Bartunov and Teodor Sigaev, which
was intended to provide similar facilities to a nested hstore type, but which
in the end proved to have some significant compatibility issues.
Authors: Oleg Bartunov, Teodor Sigaev, Peter Geoghegan and Andrew Dunstan.
Review: Andres Freund
2014-03-23 21:40:19 +01:00
SELECT count(*) FROM testjsonb WHERE j @> '{}';
count
-------
2014-05-09 14:41:26 +02:00
1012
Introduce jsonb, a structured format for storing json.
The new format accepts exactly the same data as the json type. However, it is
stored in a format that does not require reparsing the orgiginal text in order
to process it, making it much more suitable for indexing and other operations.
Insignificant whitespace is discarded, and the order of object keys is not
preserved. Neither are duplicate object keys kept - the later value for a given
key is the only one stored.
The new type has all the functions and operators that the json type has,
with the exception of the json generation functions (to_json, json_agg etc.)
and with identical semantics. In addition, there are operator classes for
hash and btree indexing, and two classes for GIN indexing, that have no
equivalent in the json type.
This feature grew out of previous work by Oleg Bartunov and Teodor Sigaev, which
was intended to provide similar facilities to a nested hstore type, but which
in the end proved to have some significant compatibility issues.
Authors: Oleg Bartunov, Teodor Sigaev, Peter Geoghegan and Andrew Dunstan.
Review: Andres Freund
2014-03-23 21:40:19 +01:00
(1 row)
2019-04-01 17:08:15 +02:00
SELECT count(*) FROM testjsonb WHERE j @@ '$.wait == null';
count
-------
1
(1 row)
SELECT count(*) FROM testjsonb WHERE j @@ 'exists($ ? (@.wait == null))';
count
-------
1
(1 row)
SELECT count(*) FROM testjsonb WHERE j @@ 'exists($.wait ? (@ == null))';
count
-------
1
(1 row)
SELECT count(*) FROM testjsonb WHERE j @@ '"CC" == $.wait';
count
-------
15
(1 row)
SELECT count(*) FROM testjsonb WHERE j @@ '$.wait == "CC" && true == $.public';
count
-------
2
(1 row)
SELECT count(*) FROM testjsonb WHERE j @@ '$.age == 25';
count
-------
2
(1 row)
SELECT count(*) FROM testjsonb WHERE j @@ '$.age == 25.0';
count
-------
2
(1 row)
SELECT count(*) FROM testjsonb WHERE j @@ '$.array[*] == "foo"';
count
-------
3
(1 row)
SELECT count(*) FROM testjsonb WHERE j @@ '$.array[*] == "bar"';
count
-------
3
(1 row)
SELECT count(*) FROM testjsonb WHERE j @@ 'exists($ ? (@.array[*] == "bar"))';
count
-------
3
(1 row)
SELECT count(*) FROM testjsonb WHERE j @@ 'exists($.array ? (@[*] == "bar"))';
count
-------
3
(1 row)
SELECT count(*) FROM testjsonb WHERE j @@ 'exists($.array[*] ? (@ == "bar"))';
count
-------
3
(1 row)
SELECT count(*) FROM testjsonb WHERE j @@ 'exists($)';
count
-------
1012
(1 row)
EXPLAIN (COSTS OFF)
SELECT count(*) FROM testjsonb WHERE j @? '$.wait ? (@ == null)';
QUERY PLAN
-------------------------------------------------------------------
Aggregate
-> Bitmap Heap Scan on testjsonb
Recheck Cond: (j @? '$."wait"?(@ == null)'::jsonpath)
-> Bitmap Index Scan on jidx
Index Cond: (j @? '$."wait"?(@ == null)'::jsonpath)
(5 rows)
SELECT count(*) FROM testjsonb WHERE j @? '$.wait ? (@ == null)';
count
-------
1
(1 row)
SELECT count(*) FROM testjsonb WHERE j @? '$.wait ? ("CC" == @)';
count
-------
15
(1 row)
SELECT count(*) FROM testjsonb WHERE j @? '$ ? (@.wait == "CC" && true == @.public)';
count
-------
2
(1 row)
SELECT count(*) FROM testjsonb WHERE j @? '$.age ? (@ == 25)';
count
-------
2
(1 row)
SELECT count(*) FROM testjsonb WHERE j @? '$ ? (@.age == 25.0)';
count
-------
2
(1 row)
SELECT count(*) FROM testjsonb WHERE j @? '$ ? (@.array[*] == "bar")';
count
-------
3
(1 row)
SELECT count(*) FROM testjsonb WHERE j @? '$.array ? (@[*] == "bar")';
count
-------
3
(1 row)
SELECT count(*) FROM testjsonb WHERE j @? '$.array[*] ? (@ == "bar")';
count
-------
3
(1 row)
SELECT count(*) FROM testjsonb WHERE j @? '$';
count
-------
1012
(1 row)
SELECT count(*) FROM testjsonb WHERE j @? '$.public';
count
-------
194
(1 row)
SELECT count(*) FROM testjsonb WHERE j @? '$.bar';
count
-------
0
(1 row)
Introduce jsonb, a structured format for storing json.
The new format accepts exactly the same data as the json type. However, it is
stored in a format that does not require reparsing the orgiginal text in order
to process it, making it much more suitable for indexing and other operations.
Insignificant whitespace is discarded, and the order of object keys is not
preserved. Neither are duplicate object keys kept - the later value for a given
key is the only one stored.
The new type has all the functions and operators that the json type has,
with the exception of the json generation functions (to_json, json_agg etc.)
and with identical semantics. In addition, there are operator classes for
hash and btree indexing, and two classes for GIN indexing, that have no
equivalent in the json type.
This feature grew out of previous work by Oleg Bartunov and Teodor Sigaev, which
was intended to provide similar facilities to a nested hstore type, but which
in the end proved to have some significant compatibility issues.
Authors: Oleg Bartunov, Teodor Sigaev, Peter Geoghegan and Andrew Dunstan.
Review: Andres Freund
2014-03-23 21:40:19 +01:00
RESET enable_seqscan;
DROP INDEX jidx;
-- nested tests
SELECT '{"ff":{"a":12,"b":16}}'::jsonb;
jsonb
----------------------------
{"ff": {"a": 12, "b": 16}}
(1 row)
SELECT '{"ff":{"a":12,"b":16},"qq":123}'::jsonb;
jsonb
---------------------------------------
{"ff": {"a": 12, "b": 16}, "qq": 123}
(1 row)
SELECT '{"aa":["a","aaa"],"qq":{"a":12,"b":16,"c":["c1","c2"],"d":{"d1":"d1","d2":"d2","d1":"d3"}}}'::jsonb;
jsonb
--------------------------------------------------------------------------------------------------
{"aa": ["a", "aaa"], "qq": {"a": 12, "b": 16, "c": ["c1", "c2"], "d": {"d1": "d3", "d2": "d2"}}}
(1 row)
SELECT '{"aa":["a","aaa"],"qq":{"a":"12","b":"16","c":["c1","c2"],"d":{"d1":"d1","d2":"d2"}}}'::jsonb;
jsonb
------------------------------------------------------------------------------------------------------
{"aa": ["a", "aaa"], "qq": {"a": "12", "b": "16", "c": ["c1", "c2"], "d": {"d1": "d1", "d2": "d2"}}}
(1 row)
SELECT '{"aa":["a","aaa"],"qq":{"a":"12","b":"16","c":["c1","c2",["c3"],{"c4":4}],"d":{"d1":"d1","d2":"d2"}}}'::jsonb;
jsonb
-------------------------------------------------------------------------------------------------------------------------
{"aa": ["a", "aaa"], "qq": {"a": "12", "b": "16", "c": ["c1", "c2", ["c3"], {"c4": 4}], "d": {"d1": "d1", "d2": "d2"}}}
(1 row)
SELECT '{"ff":["a","aaa"]}'::jsonb;
jsonb
----------------------
{"ff": ["a", "aaa"]}
(1 row)
SELECT
'{"ff":{"a":12,"b":16},"qq":123,"x":[1,2],"Y":null}'::jsonb -> 'ff',
'{"ff":{"a":12,"b":16},"qq":123,"x":[1,2],"Y":null}'::jsonb -> 'qq',
('{"ff":{"a":12,"b":16},"qq":123,"x":[1,2],"Y":null}'::jsonb -> 'Y') IS NULL AS f,
('{"ff":{"a":12,"b":16},"qq":123,"x":[1,2],"Y":null}'::jsonb ->> 'Y') IS NULL AS t,
'{"ff":{"a":12,"b":16},"qq":123,"x":[1,2],"Y":null}'::jsonb -> 'x';
?column? | ?column? | f | t | ?column?
--------------------+----------+---+---+----------
{"a": 12, "b": 16} | 123 | f | t | [1, 2]
(1 row)
-- nested containment
SELECT '{"a":[1,2],"c":"b"}'::jsonb @> '{"a":[1,2]}';
?column?
----------
t
(1 row)
SELECT '{"a":[2,1],"c":"b"}'::jsonb @> '{"a":[1,2]}';
?column?
----------
t
(1 row)
SELECT '{"a":{"1":2},"c":"b"}'::jsonb @> '{"a":[1,2]}';
?column?
----------
f
(1 row)
SELECT '{"a":{"2":1},"c":"b"}'::jsonb @> '{"a":[1,2]}';
?column?
----------
f
(1 row)
SELECT '{"a":{"1":2},"c":"b"}'::jsonb @> '{"a":{"1":2}}';
?column?
----------
t
(1 row)
SELECT '{"a":{"2":1},"c":"b"}'::jsonb @> '{"a":{"1":2}}';
?column?
----------
f
(1 row)
SELECT '["a","b"]'::jsonb @> '["a","b","c","b"]';
?column?
----------
f
(1 row)
SELECT '["a","b","c","b"]'::jsonb @> '["a","b"]';
?column?
----------
t
(1 row)
SELECT '["a","b","c",[1,2]]'::jsonb @> '["a",[1,2]]';
?column?
----------
t
(1 row)
SELECT '["a","b","c",[1,2]]'::jsonb @> '["b",[1,2]]';
?column?
----------
t
(1 row)
SELECT '{"a":[1,2],"c":"b"}'::jsonb @> '{"a":[1]}';
?column?
----------
t
(1 row)
SELECT '{"a":[1,2],"c":"b"}'::jsonb @> '{"a":[2]}';
?column?
----------
t
(1 row)
SELECT '{"a":[1,2],"c":"b"}'::jsonb @> '{"a":[3]}';
?column?
----------
f
(1 row)
SELECT '{"a":[1,2,{"c":3,"x":4}],"c":"b"}'::jsonb @> '{"a":[{"c":3}]}';
?column?
----------
t
(1 row)
SELECT '{"a":[1,2,{"c":3,"x":4}],"c":"b"}'::jsonb @> '{"a":[{"x":4}]}';
?column?
----------
t
(1 row)
SELECT '{"a":[1,2,{"c":3,"x":4}],"c":"b"}'::jsonb @> '{"a":[{"x":4},3]}';
?column?
----------
f
(1 row)
SELECT '{"a":[1,2,{"c":3,"x":4}],"c":"b"}'::jsonb @> '{"a":[{"x":4},1]}';
?column?
----------
t
(1 row)
2015-11-06 00:15:48 +01:00
-- check some corner cases for indexed nested containment (bug #13756)
create temp table nestjsonb (j jsonb);
insert into nestjsonb (j) values ('{"a":[["b",{"x":1}],["b",{"x":2}]],"c":3}');
insert into nestjsonb (j) values ('[[14,2,3]]');
insert into nestjsonb (j) values ('[1,[14,2,3]]');
create index on nestjsonb using gin(j jsonb_path_ops);
set enable_seqscan = on;
set enable_bitmapscan = off;
select * from nestjsonb where j @> '{"a":[[{"x":2}]]}'::jsonb;
j
---------------------------------------------------
{"a": [["b", {"x": 1}], ["b", {"x": 2}]], "c": 3}
(1 row)
select * from nestjsonb where j @> '{"c":3}';
j
---------------------------------------------------
{"a": [["b", {"x": 1}], ["b", {"x": 2}]], "c": 3}
(1 row)
select * from nestjsonb where j @> '[[14]]';
j
-----------------
[[14, 2, 3]]
[1, [14, 2, 3]]
(2 rows)
set enable_seqscan = off;
set enable_bitmapscan = on;
select * from nestjsonb where j @> '{"a":[[{"x":2}]]}'::jsonb;
j
---------------------------------------------------
{"a": [["b", {"x": 1}], ["b", {"x": 2}]], "c": 3}
(1 row)
select * from nestjsonb where j @> '{"c":3}';
j
---------------------------------------------------
{"a": [["b", {"x": 1}], ["b", {"x": 2}]], "c": 3}
(1 row)
select * from nestjsonb where j @> '[[14]]';
j
-----------------
[[14, 2, 3]]
[1, [14, 2, 3]]
(2 rows)
reset enable_seqscan;
reset enable_bitmapscan;
Introduce jsonb, a structured format for storing json.
The new format accepts exactly the same data as the json type. However, it is
stored in a format that does not require reparsing the orgiginal text in order
to process it, making it much more suitable for indexing and other operations.
Insignificant whitespace is discarded, and the order of object keys is not
preserved. Neither are duplicate object keys kept - the later value for a given
key is the only one stored.
The new type has all the functions and operators that the json type has,
with the exception of the json generation functions (to_json, json_agg etc.)
and with identical semantics. In addition, there are operator classes for
hash and btree indexing, and two classes for GIN indexing, that have no
equivalent in the json type.
This feature grew out of previous work by Oleg Bartunov and Teodor Sigaev, which
was intended to provide similar facilities to a nested hstore type, but which
in the end proved to have some significant compatibility issues.
Authors: Oleg Bartunov, Teodor Sigaev, Peter Geoghegan and Andrew Dunstan.
Review: Andres Freund
2014-03-23 21:40:19 +01:00
-- nested object field / array index lookup
SELECT '{"n":null,"a":1,"b":[1,2],"c":{"1":2},"d":{"1":[2,3]}}'::jsonb -> 'n';
?column?
----------
null
(1 row)
SELECT '{"n":null,"a":1,"b":[1,2],"c":{"1":2},"d":{"1":[2,3]}}'::jsonb -> 'a';
?column?
----------
1
(1 row)
SELECT '{"n":null,"a":1,"b":[1,2],"c":{"1":2},"d":{"1":[2,3]}}'::jsonb -> 'b';
?column?
----------
[1, 2]
(1 row)
SELECT '{"n":null,"a":1,"b":[1,2],"c":{"1":2},"d":{"1":[2,3]}}'::jsonb -> 'c';
?column?
----------
{"1": 2}
(1 row)
SELECT '{"n":null,"a":1,"b":[1,2],"c":{"1":2},"d":{"1":[2,3]}}'::jsonb -> 'd';
?column?
---------------
{"1": [2, 3]}
(1 row)
SELECT '{"n":null,"a":1,"b":[1,2],"c":{"1":2},"d":{"1":[2,3]}}'::jsonb -> 'd' -> '1';
?column?
----------
[2, 3]
(1 row)
SELECT '{"n":null,"a":1,"b":[1,2],"c":{"1":2},"d":{"1":[2,3]}}'::jsonb -> 'e';
?column?
----------
(1 row)
SELECT '{"n":null,"a":1,"b":[1,2],"c":{"1":2},"d":{"1":[2,3]}}'::jsonb -> 0; --expecting error
2014-08-22 19:17:58 +02:00
?column?
----------
(1 row)
Introduce jsonb, a structured format for storing json.
The new format accepts exactly the same data as the json type. However, it is
stored in a format that does not require reparsing the orgiginal text in order
to process it, making it much more suitable for indexing and other operations.
Insignificant whitespace is discarded, and the order of object keys is not
preserved. Neither are duplicate object keys kept - the later value for a given
key is the only one stored.
The new type has all the functions and operators that the json type has,
with the exception of the json generation functions (to_json, json_agg etc.)
and with identical semantics. In addition, there are operator classes for
hash and btree indexing, and two classes for GIN indexing, that have no
equivalent in the json type.
This feature grew out of previous work by Oleg Bartunov and Teodor Sigaev, which
was intended to provide similar facilities to a nested hstore type, but which
in the end proved to have some significant compatibility issues.
Authors: Oleg Bartunov, Teodor Sigaev, Peter Geoghegan and Andrew Dunstan.
Review: Andres Freund
2014-03-23 21:40:19 +01:00
SELECT '["a","b","c",[1,2],null]'::jsonb -> 0;
?column?
----------
"a"
(1 row)
SELECT '["a","b","c",[1,2],null]'::jsonb -> 1;
?column?
----------
"b"
(1 row)
SELECT '["a","b","c",[1,2],null]'::jsonb -> 2;
?column?
----------
"c"
(1 row)
SELECT '["a","b","c",[1,2],null]'::jsonb -> 3;
?column?
----------
[1, 2]
(1 row)
SELECT '["a","b","c",[1,2],null]'::jsonb -> 3 -> 1;
?column?
----------
2
(1 row)
SELECT '["a","b","c",[1,2],null]'::jsonb -> 4;
?column?
----------
null
(1 row)
SELECT '["a","b","c",[1,2],null]'::jsonb -> 5;
?column?
----------
(1 row)
SELECT '["a","b","c",[1,2],null]'::jsonb -> -1;
?column?
----------
Support JSON negative array subscripts everywhere
Previously, there was an inconsistency across json/jsonb operators that
operate on datums containing JSON arrays -- only some operators
supported negative array count-from-the-end subscripting. Specifically,
only a new-to-9.5 jsonb deletion operator had support (the new "jsonb -
integer" operator). This inconsistency seemed likely to be
counter-intuitive to users. To fix, allow all places where the user can
supply an integer subscript to accept a negative subscript value,
including path-orientated operators and functions, as well as other
extraction operators. This will need to be called out as an
incompatibility in the 9.5 release notes, since it's possible that users
are relying on certain established extraction operators changed here
yielding NULL in the event of a negative subscript.
For the json type, this requires adding a way of cheaply getting the
total JSON array element count ahead of time when parsing arrays with a
negative subscript involved, necessitating an ad-hoc lex and parse.
This is followed by a "conversion" from a negative subscript to its
equivalent positive-wise value using the count. From there on, it's as
if a positive-wise value was originally provided.
Note that there is still a minor inconsistency here across jsonb
deletion operators. Unlike the aforementioned new "-" deletion operator
that accepts an integer on its right hand side, the new "#-" path
orientated deletion variant does not throw an error when it appears like
an array subscript (input that could be recognized by as an integer
literal) is being used on an object, which is wrong-headed. The reason
for not being stricter is that it could be the case that an object pair
happens to have a key value that looks like an integer; in general,
these two possibilities are impossible to differentiate with rhs path
text[] argument elements. However, we still don't allow the "#-"
path-orientated deletion operator to perform array-style subscripting.
Rather, we just return the original left operand value in the event of a
negative subscript (which seems analogous to how the established
"jsonb/json #> text[]" path-orientated operator may yield NULL in the
event of an invalid subscript).
In passing, make SetArrayPath() stricter about not accepting cases where
there is trailing non-numeric garbage bytes rather than a clean NUL
byte. This means, for example, that strings like "10e10" are now not
accepted as an array subscript of 10 by some new-to-9.5 path-orientated
jsonb operators (e.g. the new #- operator). Finally, remove dead code
for jsonb subscript deletion; arguably, this should have been done in
commit b81c7b409.
Peter Geoghegan and Andrew Dunstan
2015-07-18 02:56:13 +02:00
null
(1 row)
SELECT '["a","b","c",[1,2],null]'::jsonb -> -5;
?column?
----------
"a"
(1 row)
SELECT '["a","b","c",[1,2],null]'::jsonb -> -6;
?column?
----------
Introduce jsonb, a structured format for storing json.
The new format accepts exactly the same data as the json type. However, it is
stored in a format that does not require reparsing the orgiginal text in order
to process it, making it much more suitable for indexing and other operations.
Insignificant whitespace is discarded, and the order of object keys is not
preserved. Neither are duplicate object keys kept - the later value for a given
key is the only one stored.
The new type has all the functions and operators that the json type has,
with the exception of the json generation functions (to_json, json_agg etc.)
and with identical semantics. In addition, there are operator classes for
hash and btree indexing, and two classes for GIN indexing, that have no
equivalent in the json type.
This feature grew out of previous work by Oleg Bartunov and Teodor Sigaev, which
was intended to provide similar facilities to a nested hstore type, but which
in the end proved to have some significant compatibility issues.
Authors: Oleg Bartunov, Teodor Sigaev, Peter Geoghegan and Andrew Dunstan.
Review: Andres Freund
2014-03-23 21:40:19 +01:00
(1 row)
--nested path extraction
SELECT '{"a":"b","c":[1,2,3]}'::jsonb #> '{0}';
?column?
----------
(1 row)
SELECT '{"a":"b","c":[1,2,3]}'::jsonb #> '{a}';
?column?
----------
"b"
(1 row)
SELECT '{"a":"b","c":[1,2,3]}'::jsonb #> '{c}';
?column?
-----------
[1, 2, 3]
(1 row)
SELECT '{"a":"b","c":[1,2,3]}'::jsonb #> '{c,0}';
?column?
----------
1
(1 row)
SELECT '{"a":"b","c":[1,2,3]}'::jsonb #> '{c,1}';
?column?
----------
2
(1 row)
SELECT '{"a":"b","c":[1,2,3]}'::jsonb #> '{c,2}';
?column?
----------
3
(1 row)
SELECT '{"a":"b","c":[1,2,3]}'::jsonb #> '{c,3}';
?column?
----------
(1 row)
SELECT '{"a":"b","c":[1,2,3]}'::jsonb #> '{c,-1}';
?column?
----------
Support JSON negative array subscripts everywhere
Previously, there was an inconsistency across json/jsonb operators that
operate on datums containing JSON arrays -- only some operators
supported negative array count-from-the-end subscripting. Specifically,
only a new-to-9.5 jsonb deletion operator had support (the new "jsonb -
integer" operator). This inconsistency seemed likely to be
counter-intuitive to users. To fix, allow all places where the user can
supply an integer subscript to accept a negative subscript value,
including path-orientated operators and functions, as well as other
extraction operators. This will need to be called out as an
incompatibility in the 9.5 release notes, since it's possible that users
are relying on certain established extraction operators changed here
yielding NULL in the event of a negative subscript.
For the json type, this requires adding a way of cheaply getting the
total JSON array element count ahead of time when parsing arrays with a
negative subscript involved, necessitating an ad-hoc lex and parse.
This is followed by a "conversion" from a negative subscript to its
equivalent positive-wise value using the count. From there on, it's as
if a positive-wise value was originally provided.
Note that there is still a minor inconsistency here across jsonb
deletion operators. Unlike the aforementioned new "-" deletion operator
that accepts an integer on its right hand side, the new "#-" path
orientated deletion variant does not throw an error when it appears like
an array subscript (input that could be recognized by as an integer
literal) is being used on an object, which is wrong-headed. The reason
for not being stricter is that it could be the case that an object pair
happens to have a key value that looks like an integer; in general,
these two possibilities are impossible to differentiate with rhs path
text[] argument elements. However, we still don't allow the "#-"
path-orientated deletion operator to perform array-style subscripting.
Rather, we just return the original left operand value in the event of a
negative subscript (which seems analogous to how the established
"jsonb/json #> text[]" path-orientated operator may yield NULL in the
event of an invalid subscript).
In passing, make SetArrayPath() stricter about not accepting cases where
there is trailing non-numeric garbage bytes rather than a clean NUL
byte. This means, for example, that strings like "10e10" are now not
accepted as an array subscript of 10 by some new-to-9.5 path-orientated
jsonb operators (e.g. the new #- operator). Finally, remove dead code
for jsonb subscript deletion; arguably, this should have been done in
commit b81c7b409.
Peter Geoghegan and Andrew Dunstan
2015-07-18 02:56:13 +02:00
3
(1 row)
SELECT '{"a":"b","c":[1,2,3]}'::jsonb #> '{c,-3}';
?column?
----------
1
(1 row)
SELECT '{"a":"b","c":[1,2,3]}'::jsonb #> '{c,-4}';
?column?
----------
Introduce jsonb, a structured format for storing json.
The new format accepts exactly the same data as the json type. However, it is
stored in a format that does not require reparsing the orgiginal text in order
to process it, making it much more suitable for indexing and other operations.
Insignificant whitespace is discarded, and the order of object keys is not
preserved. Neither are duplicate object keys kept - the later value for a given
key is the only one stored.
The new type has all the functions and operators that the json type has,
with the exception of the json generation functions (to_json, json_agg etc.)
and with identical semantics. In addition, there are operator classes for
hash and btree indexing, and two classes for GIN indexing, that have no
equivalent in the json type.
This feature grew out of previous work by Oleg Bartunov and Teodor Sigaev, which
was intended to provide similar facilities to a nested hstore type, but which
in the end proved to have some significant compatibility issues.
Authors: Oleg Bartunov, Teodor Sigaev, Peter Geoghegan and Andrew Dunstan.
Review: Andres Freund
2014-03-23 21:40:19 +01:00
(1 row)
SELECT '[0,1,2,[3,4],{"5":"five"}]'::jsonb #> '{0}';
?column?
----------
0
(1 row)
SELECT '[0,1,2,[3,4],{"5":"five"}]'::jsonb #> '{3}';
?column?
----------
[3, 4]
(1 row)
SELECT '[0,1,2,[3,4],{"5":"five"}]'::jsonb #> '{4}';
?column?
---------------
{"5": "five"}
(1 row)
SELECT '[0,1,2,[3,4],{"5":"five"}]'::jsonb #> '{4,5}';
?column?
----------
"five"
(1 row)
--nested exists
SELECT '{"n":null,"a":1,"b":[1,2],"c":{"1":2},"d":{"1":[2,3]}}'::jsonb ? 'n';
?column?
----------
t
(1 row)
SELECT '{"n":null,"a":1,"b":[1,2],"c":{"1":2},"d":{"1":[2,3]}}'::jsonb ? 'a';
?column?
----------
t
(1 row)
SELECT '{"n":null,"a":1,"b":[1,2],"c":{"1":2},"d":{"1":[2,3]}}'::jsonb ? 'b';
?column?
----------
t
(1 row)
SELECT '{"n":null,"a":1,"b":[1,2],"c":{"1":2},"d":{"1":[2,3]}}'::jsonb ? 'c';
?column?
----------
t
(1 row)
SELECT '{"n":null,"a":1,"b":[1,2],"c":{"1":2},"d":{"1":[2,3]}}'::jsonb ? 'd';
?column?
----------
t
(1 row)
SELECT '{"n":null,"a":1,"b":[1,2],"c":{"1":2},"d":{"1":[2,3]}}'::jsonb ? 'e';
?column?
----------
f
(1 row)
2014-12-12 15:00:43 +01:00
-- jsonb_strip_nulls
select jsonb_strip_nulls(null);
jsonb_strip_nulls
-------------------
(1 row)
select jsonb_strip_nulls('1');
jsonb_strip_nulls
-------------------
1
(1 row)
select jsonb_strip_nulls('"a string"');
jsonb_strip_nulls
-------------------
"a string"
(1 row)
select jsonb_strip_nulls('null');
jsonb_strip_nulls
-------------------
null
(1 row)
select jsonb_strip_nulls('[1,2,null,3,4]');
jsonb_strip_nulls
--------------------
[1, 2, null, 3, 4]
(1 row)
select jsonb_strip_nulls('{"a":1,"b":null,"c":[2,null,3],"d":{"e":4,"f":null}}');
jsonb_strip_nulls
--------------------------------------------
{"a": 1, "c": [2, null, 3], "d": {"e": 4}}
(1 row)
select jsonb_strip_nulls('[1,{"a":1,"b":null,"c":2},3]');
jsonb_strip_nulls
--------------------------
[1, {"a": 1, "c": 2}, 3]
(1 row)
-- an empty object is not null and should not be stripped
select jsonb_strip_nulls('{"a": {"b": null, "c": null}, "d": {} }');
jsonb_strip_nulls
--------------------
{"a": {}, "d": {}}
(1 row)
2015-05-12 21:52:45 +02:00
select jsonb_pretty('{"a": "test", "b": [1, 2, 3], "c": "test3", "d":{"dd": "test4", "dd2":{"ddd": "test5"}}}');
jsonb_pretty
----------------------------
{ +
"a": "test", +
"b": [ +
1, +
2, +
3 +
], +
"c": "test3", +
"d": { +
"dd": "test4", +
"dd2": { +
"ddd": "test5"+
} +
} +
}
(1 row)
select jsonb_pretty('[{"f1":1,"f2":null},2,null,[[{"x":true},6,7],8],3]');
jsonb_pretty
---------------------------
[ +
{ +
"f1": 1, +
"f2": null +
}, +
2, +
null, +
[ +
[ +
{ +
"x": true+
}, +
6, +
7 +
], +
8 +
], +
3 +
]
(1 row)
select jsonb_pretty('{"a":["b", "c"], "d": {"e":"f"}}');
jsonb_pretty
------------------
{ +
"a": [ +
"b", +
"c" +
], +
"d": { +
"e": "f"+
} +
}
(1 row)
select jsonb_concat('{"d": "test", "a": [1, 2]}', '{"g": "test2", "c": {"c1":1, "c2":2}}');
jsonb_concat
-------------------------------------------------------------------
{"a": [1, 2], "c": {"c1": 1, "c2": 2}, "d": "test", "g": "test2"}
(1 row)
select '{"aa":1 , "b":2, "cq":3}'::jsonb || '{"cq":"l", "b":"g", "fg":false}';
?column?
---------------------------------------------
{"b": "g", "aa": 1, "cq": "l", "fg": false}
(1 row)
select '{"aa":1 , "b":2, "cq":3}'::jsonb || '{"aq":"l"}';
?column?
---------------------------------------
{"b": 2, "aa": 1, "aq": "l", "cq": 3}
(1 row)
select '{"aa":1 , "b":2, "cq":3}'::jsonb || '{"aa":"l"}';
?column?
------------------------------
{"b": 2, "aa": "l", "cq": 3}
(1 row)
select '{"aa":1 , "b":2, "cq":3}'::jsonb || '{}';
?column?
----------------------------
{"b": 2, "aa": 1, "cq": 3}
(1 row)
select '["a", "b"]'::jsonb || '["c"]';
?column?
-----------------
["a", "b", "c"]
(1 row)
select '["a", "b"]'::jsonb || '["c", "d"]';
?column?
----------------------
["a", "b", "c", "d"]
(1 row)
select '["c"]' || '["a", "b"]'::jsonb;
?column?
-----------------
["c", "a", "b"]
(1 row)
select '["a", "b"]'::jsonb || '"c"';
?column?
-----------------
["a", "b", "c"]
(1 row)
select '"c"' || '["a", "b"]'::jsonb;
?column?
-----------------
["c", "a", "b"]
(1 row)
2015-09-13 23:06:45 +02:00
select '[]'::jsonb || '["a"]'::jsonb;
?column?
----------
["a"]
(1 row)
select '[]'::jsonb || '"a"'::jsonb;
?column?
----------
["a"]
(1 row)
select '"b"'::jsonb || '"a"'::jsonb;
?column?
------------
["b", "a"]
(1 row)
select '{}'::jsonb || '{"a":"b"}'::jsonb;
?column?
------------
{"a": "b"}
(1 row)
select '[]'::jsonb || '{"a":"b"}'::jsonb;
?column?
--------------
[{"a": "b"}]
(1 row)
select '{"a":"b"}'::jsonb || '[]'::jsonb;
?column?
--------------
[{"a": "b"}]
(1 row)
2015-05-12 21:52:45 +02:00
select '"a"'::jsonb || '{"a":1}';
2020-12-21 19:11:29 +01:00
?column?
-----------------
["a", {"a": 1}]
(1 row)
2015-05-12 21:52:45 +02:00
select '{"a":1}' || '"a"'::jsonb;
2020-12-21 19:11:29 +01:00
?column?
-----------------
[{"a": 1}, "a"]
(1 row)
select '[3]'::jsonb || '{}'::jsonb;
?column?
----------
[3, {}]
(1 row)
select '3'::jsonb || '[]'::jsonb;
?column?
----------
[3]
(1 row)
select '3'::jsonb || '4'::jsonb;
?column?
----------
[3, 4]
(1 row)
select '3'::jsonb || '{}'::jsonb;
?column?
----------
[3, {}]
(1 row)
2015-05-12 21:52:45 +02:00
select '["a", "b"]'::jsonb || '{"c":1}';
?column?
----------------------
["a", "b", {"c": 1}]
(1 row)
select '{"c": 1}'::jsonb || '["a", "b"]';
?column?
----------------------
[{"c": 1}, "a", "b"]
(1 row)
select '{}'::jsonb || '{"cq":"l", "b":"g", "fg":false}';
?column?
------------------------------------
{"b": "g", "cq": "l", "fg": false}
(1 row)
select pg_column_size('{}'::jsonb || '{}'::jsonb) = pg_column_size('{}'::jsonb);
?column?
----------
t
(1 row)
select pg_column_size('{"aa":1}'::jsonb || '{"b":2}'::jsonb) = pg_column_size('{"aa":1, "b":2}'::jsonb);
?column?
----------
t
(1 row)
select pg_column_size('{"aa":1, "b":2}'::jsonb || '{}'::jsonb) = pg_column_size('{"aa":1, "b":2}'::jsonb);
?column?
----------
t
(1 row)
select pg_column_size('{}'::jsonb || '{"aa":1, "b":2}'::jsonb) = pg_column_size('{"aa":1, "b":2}'::jsonb);
?column?
----------
t
(1 row)
select jsonb_delete('{"a":1 , "b":2, "c":3}'::jsonb, 'a');
jsonb_delete
------------------
{"b": 2, "c": 3}
(1 row)
select jsonb_delete('{"a":null , "b":2, "c":3}'::jsonb, 'a');
jsonb_delete
------------------
{"b": 2, "c": 3}
(1 row)
select jsonb_delete('{"a":1 , "b":2, "c":3}'::jsonb, 'b');
jsonb_delete
------------------
{"a": 1, "c": 3}
(1 row)
select jsonb_delete('{"a":1 , "b":2, "c":3}'::jsonb, 'c');
jsonb_delete
------------------
{"a": 1, "b": 2}
(1 row)
select jsonb_delete('{"a":1 , "b":2, "c":3}'::jsonb, 'd');
jsonb_delete
--------------------------
{"a": 1, "b": 2, "c": 3}
(1 row)
2015-06-11 16:06:58 +02:00
select '{"a":1 , "b":2, "c":3}'::jsonb - 'a';
2015-05-12 21:52:45 +02:00
?column?
------------------
{"b": 2, "c": 3}
(1 row)
2015-06-11 16:06:58 +02:00
select '{"a":null , "b":2, "c":3}'::jsonb - 'a';
2015-05-12 21:52:45 +02:00
?column?
------------------
{"b": 2, "c": 3}
(1 row)
2015-06-11 16:06:58 +02:00
select '{"a":1 , "b":2, "c":3}'::jsonb - 'b';
2015-05-12 21:52:45 +02:00
?column?
------------------
{"a": 1, "c": 3}
(1 row)
2015-06-11 16:06:58 +02:00
select '{"a":1 , "b":2, "c":3}'::jsonb - 'c';
2015-05-12 21:52:45 +02:00
?column?
------------------
{"a": 1, "b": 2}
(1 row)
2015-06-11 16:06:58 +02:00
select '{"a":1 , "b":2, "c":3}'::jsonb - 'd';
2015-05-12 21:52:45 +02:00
?column?
--------------------------
{"a": 1, "b": 2, "c": 3}
(1 row)
2015-06-11 16:06:58 +02:00
select pg_column_size('{"a":1 , "b":2, "c":3}'::jsonb - 'b') = pg_column_size('{"a":1, "b":2}'::jsonb);
2015-05-12 21:52:45 +02:00
?column?
----------
t
(1 row)
select '["a","b","c"]'::jsonb - 3;
?column?
-----------------
["a", "b", "c"]
(1 row)
select '["a","b","c"]'::jsonb - 2;
?column?
------------
["a", "b"]
(1 row)
select '["a","b","c"]'::jsonb - 1;
?column?
------------
["a", "c"]
(1 row)
select '["a","b","c"]'::jsonb - 0;
?column?
------------
["b", "c"]
(1 row)
select '["a","b","c"]'::jsonb - -1;
?column?
------------
["a", "b"]
(1 row)
select '["a","b","c"]'::jsonb - -2;
?column?
------------
["a", "c"]
(1 row)
select '["a","b","c"]'::jsonb - -3;
?column?
------------
["b", "c"]
(1 row)
select '["a","b","c"]'::jsonb - -4;
?column?
-----------------
["a", "b", "c"]
(1 row)
2017-01-18 21:37:59 +01:00
select '{"a":1 , "b":2, "c":3}'::jsonb - '{b}'::text[];
?column?
------------------
{"a": 1, "c": 3}
(1 row)
select '{"a":1 , "b":2, "c":3}'::jsonb - '{c,b}'::text[];
?column?
----------
{"a": 1}
(1 row)
select '{"a":1 , "b":2, "c":3}'::jsonb - '{}'::text[];
?column?
--------------------------
{"a": 1, "b": 2, "c": 3}
(1 row)
2015-06-01 02:34:10 +02:00
select jsonb_set('{"n":null, "a":1, "b":[1,2], "c":{"1":2}, "d":{"1":[2,3]}}'::jsonb, '{n}', '[1,2,3]');
jsonb_set
2015-05-12 21:52:45 +02:00
--------------------------------------------------------------------------
{"a": 1, "b": [1, 2], "c": {"1": 2}, "d": {"1": [2, 3]}, "n": [1, 2, 3]}
(1 row)
2015-06-01 02:34:10 +02:00
select jsonb_set('{"n":null, "a":1, "b":[1,2], "c":{"1":2}, "d":{"1":[2,3]}}'::jsonb, '{b,-1}', '[1,2,3]');
jsonb_set
2015-05-12 21:52:45 +02:00
-----------------------------------------------------------------------------
{"a": 1, "b": [1, [1, 2, 3]], "c": {"1": 2}, "d": {"1": [2, 3]}, "n": null}
(1 row)
2015-06-01 02:34:10 +02:00
select jsonb_set('{"n":null, "a":1, "b":[1,2], "c":{"1":2}, "d":{"1":[2,3]}}'::jsonb, '{d,1,0}', '[1,2,3]');
jsonb_set
2015-05-12 21:52:45 +02:00
-----------------------------------------------------------------------------
{"a": 1, "b": [1, 2], "c": {"1": 2}, "d": {"1": [[1, 2, 3], 3]}, "n": null}
(1 row)
2015-06-01 02:34:10 +02:00
select jsonb_set('{"n":null, "a":1, "b":[1,2], "c":{"1":2}, "d":{"1":[2,3]}}'::jsonb, '{d,NULL,0}', '[1,2,3]');
2016-03-23 16:00:39 +01:00
ERROR: path element at position 2 is null
2015-06-01 02:34:10 +02:00
select jsonb_set('{"n":null, "a":1, "b":[1,2], "c":{"1":2}, "d":{"1":[2,3]}}'::jsonb, '{n}', '{"1": 2}');
jsonb_set
2015-05-12 21:52:45 +02:00
-------------------------------------------------------------------------
{"a": 1, "b": [1, 2], "c": {"1": 2}, "d": {"1": [2, 3]}, "n": {"1": 2}}
(1 row)
2015-06-01 02:34:10 +02:00
select jsonb_set('{"n":null, "a":1, "b":[1,2], "c":{"1":2}, "d":{"1":[2,3]}}'::jsonb, '{b,-1}', '{"1": 2}');
jsonb_set
2015-05-12 21:52:45 +02:00
----------------------------------------------------------------------------
{"a": 1, "b": [1, {"1": 2}], "c": {"1": 2}, "d": {"1": [2, 3]}, "n": null}
(1 row)
2015-06-01 02:34:10 +02:00
select jsonb_set('{"n":null, "a":1, "b":[1,2], "c":{"1":2}, "d":{"1":[2,3]}}'::jsonb, '{d,1,0}', '{"1": 2}');
jsonb_set
2015-05-12 21:52:45 +02:00
----------------------------------------------------------------------------
{"a": 1, "b": [1, 2], "c": {"1": 2}, "d": {"1": [{"1": 2}, 3]}, "n": null}
(1 row)
2015-06-01 02:34:10 +02:00
select jsonb_set('{"n":null, "a":1, "b":[1,2], "c":{"1":2}, "d":{"1":[2,3]}}'::jsonb, '{d,NULL,0}', '{"1": 2}');
2016-03-23 16:00:39 +01:00
ERROR: path element at position 2 is null
2015-06-01 02:34:10 +02:00
select jsonb_set('{"n":null, "a":1, "b":[1,2], "c":{"1":2}, "d":{"1":[2,3]}}'::jsonb, '{b,-1}', '"test"');
jsonb_set
2015-05-12 21:52:45 +02:00
--------------------------------------------------------------------------
{"a": 1, "b": [1, "test"], "c": {"1": 2}, "d": {"1": [2, 3]}, "n": null}
(1 row)
2015-06-01 02:34:10 +02:00
select jsonb_set('{"n":null, "a":1, "b":[1,2], "c":{"1":2}, "d":{"1":[2,3]}}'::jsonb, '{b,-1}', '{"f": "test"}');
jsonb_set
2015-05-12 21:52:45 +02:00
---------------------------------------------------------------------------------
{"a": 1, "b": [1, {"f": "test"}], "c": {"1": 2}, "d": {"1": [2, 3]}, "n": null}
(1 row)
2015-06-11 16:06:58 +02:00
select jsonb_delete_path('{"n":null, "a":1, "b":[1,2], "c":{"1":2}, "d":{"1":[2,3]}}', '{n}');
jsonb_delete_path
2015-05-12 21:52:45 +02:00
----------------------------------------------------------
{"a": 1, "b": [1, 2], "c": {"1": 2}, "d": {"1": [2, 3]}}
(1 row)
2015-06-11 16:06:58 +02:00
select jsonb_delete_path('{"n":null, "a":1, "b":[1,2], "c":{"1":2}, "d":{"1":[2,3]}}', '{b,-1}');
jsonb_delete_path
2015-05-12 21:52:45 +02:00
------------------------------------------------------------------
{"a": 1, "b": [1], "c": {"1": 2}, "d": {"1": [2, 3]}, "n": null}
(1 row)
2015-06-11 16:06:58 +02:00
select jsonb_delete_path('{"n":null, "a":1, "b":[1,2], "c":{"1":2}, "d":{"1":[2,3]}}', '{d,1,0}');
jsonb_delete_path
2015-05-12 21:52:45 +02:00
------------------------------------------------------------------
{"a": 1, "b": [1, 2], "c": {"1": 2}, "d": {"1": [3]}, "n": null}
(1 row)
2015-06-11 16:06:58 +02:00
select '{"n":null, "a":1, "b":[1,2], "c":{"1":2}, "d":{"1":[2,3]}}'::jsonb #- '{n}';
2015-05-12 21:52:45 +02:00
?column?
----------------------------------------------------------
{"a": 1, "b": [1, 2], "c": {"1": 2}, "d": {"1": [2, 3]}}
(1 row)
2015-06-11 16:06:58 +02:00
select '{"n":null, "a":1, "b":[1,2], "c":{"1":2}, "d":{"1":[2,3]}}'::jsonb #- '{b,-1}';
2015-05-12 21:52:45 +02:00
?column?
------------------------------------------------------------------
{"a": 1, "b": [1], "c": {"1": 2}, "d": {"1": [2, 3]}, "n": null}
(1 row)
Support JSON negative array subscripts everywhere
Previously, there was an inconsistency across json/jsonb operators that
operate on datums containing JSON arrays -- only some operators
supported negative array count-from-the-end subscripting. Specifically,
only a new-to-9.5 jsonb deletion operator had support (the new "jsonb -
integer" operator). This inconsistency seemed likely to be
counter-intuitive to users. To fix, allow all places where the user can
supply an integer subscript to accept a negative subscript value,
including path-orientated operators and functions, as well as other
extraction operators. This will need to be called out as an
incompatibility in the 9.5 release notes, since it's possible that users
are relying on certain established extraction operators changed here
yielding NULL in the event of a negative subscript.
For the json type, this requires adding a way of cheaply getting the
total JSON array element count ahead of time when parsing arrays with a
negative subscript involved, necessitating an ad-hoc lex and parse.
This is followed by a "conversion" from a negative subscript to its
equivalent positive-wise value using the count. From there on, it's as
if a positive-wise value was originally provided.
Note that there is still a minor inconsistency here across jsonb
deletion operators. Unlike the aforementioned new "-" deletion operator
that accepts an integer on its right hand side, the new "#-" path
orientated deletion variant does not throw an error when it appears like
an array subscript (input that could be recognized by as an integer
literal) is being used on an object, which is wrong-headed. The reason
for not being stricter is that it could be the case that an object pair
happens to have a key value that looks like an integer; in general,
these two possibilities are impossible to differentiate with rhs path
text[] argument elements. However, we still don't allow the "#-"
path-orientated deletion operator to perform array-style subscripting.
Rather, we just return the original left operand value in the event of a
negative subscript (which seems analogous to how the established
"jsonb/json #> text[]" path-orientated operator may yield NULL in the
event of an invalid subscript).
In passing, make SetArrayPath() stricter about not accepting cases where
there is trailing non-numeric garbage bytes rather than a clean NUL
byte. This means, for example, that strings like "10e10" are now not
accepted as an array subscript of 10 by some new-to-9.5 path-orientated
jsonb operators (e.g. the new #- operator). Finally, remove dead code
for jsonb subscript deletion; arguably, this should have been done in
commit b81c7b409.
Peter Geoghegan and Andrew Dunstan
2015-07-18 02:56:13 +02:00
select '{"n":null, "a":1, "b":[1,2], "c":{"1":2}, "d":{"1":[2,3]}}'::jsonb #- '{b,-1e}'; -- invalid array subscript
2016-03-23 16:00:39 +01:00
ERROR: path element at position 2 is not an integer: "-1e"
2015-06-11 16:06:58 +02:00
select '{"n":null, "a":1, "b":[1,2], "c":{"1":2}, "d":{"1":[2,3]}}'::jsonb #- '{d,1,0}';
2015-05-12 21:52:45 +02:00
?column?
------------------------------------------------------------------
{"a": 1, "b": [1, 2], "c": {"1": 2}, "d": {"1": [3]}, "n": null}
(1 row)
2015-05-13 19:52:08 +02:00
-- empty structure and error conditions for delete and replace
select '"a"'::jsonb - 'a'; -- error
ERROR: cannot delete from scalar
select '{}'::jsonb - 'a';
?column?
----------
{}
(1 row)
select '[]'::jsonb - 'a';
?column?
----------
[]
(1 row)
select '"a"'::jsonb - 1; -- error
ERROR: cannot delete from scalar
2015-06-08 02:46:00 +02:00
select '{}'::jsonb - 1; -- error
2015-12-11 04:05:27 +01:00
ERROR: cannot delete from object using integer index
2015-05-13 19:52:08 +02:00
select '[]'::jsonb - 1;
?column?
----------
[]
(1 row)
2015-06-11 16:06:58 +02:00
select '"a"'::jsonb #- '{a}'; -- error
2015-05-13 19:52:08 +02:00
ERROR: cannot delete path in scalar
2015-06-11 16:06:58 +02:00
select '{}'::jsonb #- '{a}';
2015-05-13 19:52:08 +02:00
?column?
----------
{}
(1 row)
2015-06-11 16:06:58 +02:00
select '[]'::jsonb #- '{a}';
2015-05-13 19:52:08 +02:00
?column?
----------
[]
(1 row)
2015-06-01 02:34:10 +02:00
select jsonb_set('"a"','{a}','"b"'); --error
ERROR: cannot set path in scalar
select jsonb_set('{}','{a}','"b"', false);
jsonb_set
-----------
2015-05-13 19:52:08 +02:00
{}
(1 row)
2015-06-01 02:34:10 +02:00
select jsonb_set('[]','{1}','"b"', false);
jsonb_set
-----------
2015-05-13 19:52:08 +02:00
[]
(1 row)
2016-10-13 06:25:28 +02:00
select jsonb_set('[{"f1":1,"f2":null},2,null,3]', '{0}','[2,3,4]', false);
jsonb_set
-------------------------
[[2, 3, 4], 2, null, 3]
(1 row)
2015-06-01 02:34:10 +02:00
-- jsonb_set adding instead of replacing
-- prepend to array
select jsonb_set('{"a":1,"b":[0,1,2],"c":{"d":4}}','{b,-33}','{"foo":123}');
jsonb_set
-------------------------------------------------------
{"a": 1, "b": [{"foo": 123}, 0, 1, 2], "c": {"d": 4}}
(1 row)
-- append to array
select jsonb_set('{"a":1,"b":[0,1,2],"c":{"d":4}}','{b,33}','{"foo":123}');
jsonb_set
-------------------------------------------------------
{"a": 1, "b": [0, 1, 2, {"foo": 123}], "c": {"d": 4}}
(1 row)
-- check nesting levels addition
select jsonb_set('{"a":1,"b":[4,5,[0,1,2],6,7],"c":{"d":4}}','{b,2,33}','{"foo":123}');
jsonb_set
---------------------------------------------------------------------
{"a": 1, "b": [4, 5, [0, 1, 2, {"foo": 123}], 6, 7], "c": {"d": 4}}
(1 row)
-- add new key
select jsonb_set('{"a":1,"b":[0,1,2],"c":{"d":4}}','{c,e}','{"foo":123}');
jsonb_set
------------------------------------------------------------
{"a": 1, "b": [0, 1, 2], "c": {"d": 4, "e": {"foo": 123}}}
(1 row)
-- adding doesn't do anything if elements before last aren't present
select jsonb_set('{"a":1,"b":[0,1,2],"c":{"d":4}}','{x,-33}','{"foo":123}');
jsonb_set
-----------------------------------------
{"a": 1, "b": [0, 1, 2], "c": {"d": 4}}
(1 row)
select jsonb_set('{"a":1,"b":[0,1,2],"c":{"d":4}}','{x,y}','{"foo":123}');
jsonb_set
-----------------------------------------
{"a": 1, "b": [0, 1, 2], "c": {"d": 4}}
(1 row)
-- add to empty object
select jsonb_set('{}','{x}','{"foo":123}');
jsonb_set
---------------------
{"x": {"foo": 123}}
(1 row)
--add to empty array
select jsonb_set('[]','{0}','{"foo":123}');
jsonb_set
----------------
[{"foo": 123}]
(1 row)
select jsonb_set('[]','{99}','{"foo":123}');
jsonb_set
----------------
[{"foo": 123}]
(1 row)
select jsonb_set('[]','{-99}','{"foo":123}');
jsonb_set
----------------
[{"foo": 123}]
(1 row)
2015-10-04 19:28:16 +02:00
select jsonb_set('{"a": [1, 2, 3]}', '{a, non_integer}', '"new_value"');
2016-03-23 16:00:39 +01:00
ERROR: path element at position 2 is not an integer: "non_integer"
2015-10-04 19:28:16 +02:00
select jsonb_set('{"a": {"b": [1, 2, 3]}}', '{a, b, non_integer}', '"new_value"');
2016-03-23 16:00:39 +01:00
ERROR: path element at position 3 is not an integer: "non_integer"
2015-10-04 19:28:16 +02:00
select jsonb_set('{"a": {"b": [1, 2, 3]}}', '{a, b, NULL}', '"new_value"');
2016-03-23 16:00:39 +01:00
ERROR: path element at position 3 is null
2020-01-17 02:11:35 +01:00
-- jsonb_set_lax
\pset null NULL
-- pass though non nulls to jsonb_set
select jsonb_set_lax('{"a":1,"b":2}','{b}','5') ;
jsonb_set_lax
------------------
{"a": 1, "b": 5}
(1 row)
select jsonb_set_lax('{"a":1,"b":2}','{d}','6', true) ;
jsonb_set_lax
--------------------------
{"a": 1, "b": 2, "d": 6}
(1 row)
-- using the default treatment
select jsonb_set_lax('{"a":1,"b":2}','{b}',null);
jsonb_set_lax
---------------------
{"a": 1, "b": null}
(1 row)
select jsonb_set_lax('{"a":1,"b":2}','{d}',null,true);
jsonb_set_lax
-----------------------------
{"a": 1, "b": 2, "d": null}
(1 row)
-- errors
select jsonb_set_lax('{"a":1,"b":2}', '{b}', null, true, null);
2020-01-20 20:26:56 +01:00
ERROR: null_value_treatment must be "delete_key", "return_target", "use_json_null", or "raise_exception"
2020-01-17 02:11:35 +01:00
select jsonb_set_lax('{"a":1,"b":2}', '{b}', null, true, 'no_such_treatment');
2020-01-20 20:26:56 +01:00
ERROR: null_value_treatment must be "delete_key", "return_target", "use_json_null", or "raise_exception"
2020-01-17 02:11:35 +01:00
-- explicit treatments
select jsonb_set_lax('{"a":1,"b":2}', '{b}', null, null_value_treatment => 'raise_exception') as raise_exception;
2020-01-20 20:26:56 +01:00
ERROR: JSON value must not be null
DETAIL: Exception was raised because null_value_treatment is "raise_exception".
HINT: To avoid, either change the null_value_treatment argument or ensure that an SQL NULL is not passed.
2020-01-17 02:11:35 +01:00
select jsonb_set_lax('{"a":1,"b":2}', '{b}', null, null_value_treatment => 'return_target') as return_target;
return_target
------------------
{"a": 1, "b": 2}
(1 row)
select jsonb_set_lax('{"a":1,"b":2}', '{b}', null, null_value_treatment => 'delete_key') as delete_key;
delete_key
------------
{"a": 1}
(1 row)
select jsonb_set_lax('{"a":1,"b":2}', '{b}', null, null_value_treatment => 'use_json_null') as use_json_null;
use_json_null
---------------------
{"a": 1, "b": null}
(1 row)
Implementation of subscripting for jsonb
Subscripting for jsonb does not support slices, does not have a limit for the
number of subscripts, and an assignment expects a replace value to have jsonb
type. There is also one functional difference between assignment via
subscripting and assignment via jsonb_set(). When an original jsonb container
is NULL, the subscripting replaces it with an empty jsonb and proceeds with
an assignment.
For the sake of code reuse, we rearrange some parts of jsonb functionality
to allow the usage of the same functions for jsonb_set and assign subscripting
operation.
The original idea belongs to Oleg Bartunov.
Catversion is bumped.
Discussion: https://postgr.es/m/CA%2Bq6zcV8qvGcDXurwwgUbwACV86Th7G80pnubg42e-p9gsSf%3Dg%40mail.gmail.com
Discussion: https://postgr.es/m/CA%2Bq6zcX3mdxGCgdThzuySwH-ApyHHM-G4oB1R0fn0j2hZqqkLQ%40mail.gmail.com
Discussion: https://postgr.es/m/CA%2Bq6zcVDuGBv%3DM0FqBYX8DPebS3F_0KQ6OVFobGJPM507_SZ_w%40mail.gmail.com
Discussion: https://postgr.es/m/CA%2Bq6zcVovR%2BXY4mfk-7oNk-rF91gH0PebnNfuUjuuDsyHjOcVA%40mail.gmail.com
Author: Dmitry Dolgov
Reviewed-by: Tom Lane, Arthur Zakirov, Pavel Stehule, Dian M Fay
Reviewed-by: Andrew Dunstan, Chapman Flack, Merlin Moncure, Peter Geoghegan
Reviewed-by: Alvaro Herrera, Jim Nasby, Josh Berkus, Victor Wagner
Reviewed-by: Aleksander Alekseev, Robert Haas, Oleg Bartunov
2021-01-31 21:50:40 +01:00
\pset null ''
2016-04-06 18:20:17 +02:00
-- jsonb_insert
select jsonb_insert('{"a": [0,1,2]}', '{a, 1}', '"new_value"');
jsonb_insert
-------------------------------
{"a": [0, "new_value", 1, 2]}
(1 row)
select jsonb_insert('{"a": [0,1,2]}', '{a, 1}', '"new_value"', true);
jsonb_insert
-------------------------------
{"a": [0, 1, "new_value", 2]}
(1 row)
select jsonb_insert('{"a": {"b": {"c": [0, 1, "test1", "test2"]}}}', '{a, b, c, 2}', '"new_value"');
jsonb_insert
------------------------------------------------------------
{"a": {"b": {"c": [0, 1, "new_value", "test1", "test2"]}}}
(1 row)
select jsonb_insert('{"a": {"b": {"c": [0, 1, "test1", "test2"]}}}', '{a, b, c, 2}', '"new_value"', true);
jsonb_insert
------------------------------------------------------------
{"a": {"b": {"c": [0, 1, "test1", "new_value", "test2"]}}}
(1 row)
select jsonb_insert('{"a": [0,1,2]}', '{a, 1}', '{"b": "value"}');
jsonb_insert
----------------------------------
{"a": [0, {"b": "value"}, 1, 2]}
(1 row)
select jsonb_insert('{"a": [0,1,2]}', '{a, 1}', '["value1", "value2"]');
jsonb_insert
----------------------------------------
{"a": [0, ["value1", "value2"], 1, 2]}
(1 row)
-- edge cases
select jsonb_insert('{"a": [0,1,2]}', '{a, 0}', '"new_value"');
jsonb_insert
-------------------------------
{"a": ["new_value", 0, 1, 2]}
(1 row)
select jsonb_insert('{"a": [0,1,2]}', '{a, 0}', '"new_value"', true);
jsonb_insert
-------------------------------
{"a": [0, "new_value", 1, 2]}
(1 row)
select jsonb_insert('{"a": [0,1,2]}', '{a, 2}', '"new_value"');
jsonb_insert
-------------------------------
{"a": [0, 1, "new_value", 2]}
(1 row)
select jsonb_insert('{"a": [0,1,2]}', '{a, 2}', '"new_value"', true);
jsonb_insert
-------------------------------
{"a": [0, 1, 2, "new_value"]}
(1 row)
select jsonb_insert('{"a": [0,1,2]}', '{a, -1}', '"new_value"');
jsonb_insert
-------------------------------
{"a": [0, 1, "new_value", 2]}
(1 row)
select jsonb_insert('{"a": [0,1,2]}', '{a, -1}', '"new_value"', true);
jsonb_insert
-------------------------------
{"a": [0, 1, 2, "new_value"]}
(1 row)
select jsonb_insert('[]', '{1}', '"new_value"');
jsonb_insert
---------------
["new_value"]
(1 row)
select jsonb_insert('[]', '{1}', '"new_value"', true);
jsonb_insert
---------------
["new_value"]
(1 row)
select jsonb_insert('{"a": []}', '{a, 1}', '"new_value"');
jsonb_insert
----------------------
{"a": ["new_value"]}
(1 row)
select jsonb_insert('{"a": []}', '{a, 1}', '"new_value"', true);
jsonb_insert
----------------------
{"a": ["new_value"]}
(1 row)
select jsonb_insert('{"a": [0,1,2]}', '{a, 10}', '"new_value"');
jsonb_insert
-------------------------------
{"a": [0, 1, 2, "new_value"]}
(1 row)
select jsonb_insert('{"a": [0,1,2]}', '{a, -10}', '"new_value"');
jsonb_insert
-------------------------------
{"a": ["new_value", 0, 1, 2]}
(1 row)
-- jsonb_insert should be able to insert new value for objects, but not to replace
select jsonb_insert('{"a": {"b": "value"}}', '{a, c}', '"new_value"');
jsonb_insert
-----------------------------------------
{"a": {"b": "value", "c": "new_value"}}
(1 row)
select jsonb_insert('{"a": {"b": "value"}}', '{a, c}', '"new_value"', true);
jsonb_insert
-----------------------------------------
{"a": {"b": "value", "c": "new_value"}}
(1 row)
select jsonb_insert('{"a": {"b": "value"}}', '{a, b}', '"new_value"');
ERROR: cannot replace existing key
HINT: Try using the function jsonb_set to replace key value.
select jsonb_insert('{"a": {"b": "value"}}', '{a, b}', '"new_value"', true);
ERROR: cannot replace existing key
HINT: Try using the function jsonb_set to replace key value.
Implementation of subscripting for jsonb
Subscripting for jsonb does not support slices, does not have a limit for the
number of subscripts, and an assignment expects a replace value to have jsonb
type. There is also one functional difference between assignment via
subscripting and assignment via jsonb_set(). When an original jsonb container
is NULL, the subscripting replaces it with an empty jsonb and proceeds with
an assignment.
For the sake of code reuse, we rearrange some parts of jsonb functionality
to allow the usage of the same functions for jsonb_set and assign subscripting
operation.
The original idea belongs to Oleg Bartunov.
Catversion is bumped.
Discussion: https://postgr.es/m/CA%2Bq6zcV8qvGcDXurwwgUbwACV86Th7G80pnubg42e-p9gsSf%3Dg%40mail.gmail.com
Discussion: https://postgr.es/m/CA%2Bq6zcX3mdxGCgdThzuySwH-ApyHHM-G4oB1R0fn0j2hZqqkLQ%40mail.gmail.com
Discussion: https://postgr.es/m/CA%2Bq6zcVDuGBv%3DM0FqBYX8DPebS3F_0KQ6OVFobGJPM507_SZ_w%40mail.gmail.com
Discussion: https://postgr.es/m/CA%2Bq6zcVovR%2BXY4mfk-7oNk-rF91gH0PebnNfuUjuuDsyHjOcVA%40mail.gmail.com
Author: Dmitry Dolgov
Reviewed-by: Tom Lane, Arthur Zakirov, Pavel Stehule, Dian M Fay
Reviewed-by: Andrew Dunstan, Chapman Flack, Merlin Moncure, Peter Geoghegan
Reviewed-by: Alvaro Herrera, Jim Nasby, Josh Berkus, Victor Wagner
Reviewed-by: Aleksander Alekseev, Robert Haas, Oleg Bartunov
2021-01-31 21:50:40 +01:00
-- jsonb subscript
select ('123'::jsonb)['a'];
jsonb
-------
(1 row)
select ('123'::jsonb)[0];
jsonb
-------
(1 row)
select ('123'::jsonb)[NULL];
jsonb
-------
(1 row)
select ('{"a": 1}'::jsonb)['a'];
jsonb
-------
1
(1 row)
select ('{"a": 1}'::jsonb)[0];
jsonb
-------
(1 row)
select ('{"a": 1}'::jsonb)['not_exist'];
jsonb
-------
(1 row)
select ('{"a": 1}'::jsonb)[NULL];
jsonb
-------
(1 row)
select ('[1, "2", null]'::jsonb)['a'];
jsonb
-------
(1 row)
select ('[1, "2", null]'::jsonb)[0];
jsonb
-------
1
(1 row)
select ('[1, "2", null]'::jsonb)['1'];
jsonb
-------
"2"
(1 row)
select ('[1, "2", null]'::jsonb)[1.0];
2021-09-16 14:48:52 +02:00
ERROR: subscript type numeric is not supported
Implementation of subscripting for jsonb
Subscripting for jsonb does not support slices, does not have a limit for the
number of subscripts, and an assignment expects a replace value to have jsonb
type. There is also one functional difference between assignment via
subscripting and assignment via jsonb_set(). When an original jsonb container
is NULL, the subscripting replaces it with an empty jsonb and proceeds with
an assignment.
For the sake of code reuse, we rearrange some parts of jsonb functionality
to allow the usage of the same functions for jsonb_set and assign subscripting
operation.
The original idea belongs to Oleg Bartunov.
Catversion is bumped.
Discussion: https://postgr.es/m/CA%2Bq6zcV8qvGcDXurwwgUbwACV86Th7G80pnubg42e-p9gsSf%3Dg%40mail.gmail.com
Discussion: https://postgr.es/m/CA%2Bq6zcX3mdxGCgdThzuySwH-ApyHHM-G4oB1R0fn0j2hZqqkLQ%40mail.gmail.com
Discussion: https://postgr.es/m/CA%2Bq6zcVDuGBv%3DM0FqBYX8DPebS3F_0KQ6OVFobGJPM507_SZ_w%40mail.gmail.com
Discussion: https://postgr.es/m/CA%2Bq6zcVovR%2BXY4mfk-7oNk-rF91gH0PebnNfuUjuuDsyHjOcVA%40mail.gmail.com
Author: Dmitry Dolgov
Reviewed-by: Tom Lane, Arthur Zakirov, Pavel Stehule, Dian M Fay
Reviewed-by: Andrew Dunstan, Chapman Flack, Merlin Moncure, Peter Geoghegan
Reviewed-by: Alvaro Herrera, Jim Nasby, Josh Berkus, Victor Wagner
Reviewed-by: Aleksander Alekseev, Robert Haas, Oleg Bartunov
2021-01-31 21:50:40 +01:00
LINE 1: select ('[1, "2", null]'::jsonb)[1.0];
^
2021-09-16 14:48:52 +02:00
HINT: jsonb subscript must be coercible to either integer or text.
Implementation of subscripting for jsonb
Subscripting for jsonb does not support slices, does not have a limit for the
number of subscripts, and an assignment expects a replace value to have jsonb
type. There is also one functional difference between assignment via
subscripting and assignment via jsonb_set(). When an original jsonb container
is NULL, the subscripting replaces it with an empty jsonb and proceeds with
an assignment.
For the sake of code reuse, we rearrange some parts of jsonb functionality
to allow the usage of the same functions for jsonb_set and assign subscripting
operation.
The original idea belongs to Oleg Bartunov.
Catversion is bumped.
Discussion: https://postgr.es/m/CA%2Bq6zcV8qvGcDXurwwgUbwACV86Th7G80pnubg42e-p9gsSf%3Dg%40mail.gmail.com
Discussion: https://postgr.es/m/CA%2Bq6zcX3mdxGCgdThzuySwH-ApyHHM-G4oB1R0fn0j2hZqqkLQ%40mail.gmail.com
Discussion: https://postgr.es/m/CA%2Bq6zcVDuGBv%3DM0FqBYX8DPebS3F_0KQ6OVFobGJPM507_SZ_w%40mail.gmail.com
Discussion: https://postgr.es/m/CA%2Bq6zcVovR%2BXY4mfk-7oNk-rF91gH0PebnNfuUjuuDsyHjOcVA%40mail.gmail.com
Author: Dmitry Dolgov
Reviewed-by: Tom Lane, Arthur Zakirov, Pavel Stehule, Dian M Fay
Reviewed-by: Andrew Dunstan, Chapman Flack, Merlin Moncure, Peter Geoghegan
Reviewed-by: Alvaro Herrera, Jim Nasby, Josh Berkus, Victor Wagner
Reviewed-by: Aleksander Alekseev, Robert Haas, Oleg Bartunov
2021-01-31 21:50:40 +01:00
select ('[1, "2", null]'::jsonb)[2];
jsonb
-------
null
(1 row)
select ('[1, "2", null]'::jsonb)[3];
jsonb
-------
(1 row)
select ('[1, "2", null]'::jsonb)[-2];
jsonb
-------
"2"
(1 row)
select ('[1, "2", null]'::jsonb)[1]['a'];
jsonb
-------
(1 row)
select ('[1, "2", null]'::jsonb)[1][0];
jsonb
-------
(1 row)
select ('{"a": 1, "b": "c", "d": [1, 2, 3]}'::jsonb)['b'];
jsonb
-------
"c"
(1 row)
select ('{"a": 1, "b": "c", "d": [1, 2, 3]}'::jsonb)['d'];
jsonb
-----------
[1, 2, 3]
(1 row)
select ('{"a": 1, "b": "c", "d": [1, 2, 3]}'::jsonb)['d'][1];
jsonb
-------
2
(1 row)
select ('{"a": 1, "b": "c", "d": [1, 2, 3]}'::jsonb)['d']['a'];
jsonb
-------
(1 row)
select ('{"a": {"a1": {"a2": "aaa"}}, "b": "bbb", "c": "ccc"}'::jsonb)['a']['a1'];
jsonb
---------------
{"a2": "aaa"}
(1 row)
select ('{"a": {"a1": {"a2": "aaa"}}, "b": "bbb", "c": "ccc"}'::jsonb)['a']['a1']['a2'];
jsonb
-------
"aaa"
(1 row)
select ('{"a": {"a1": {"a2": "aaa"}}, "b": "bbb", "c": "ccc"}'::jsonb)['a']['a1']['a2']['a3'];
jsonb
-------
(1 row)
select ('{"a": ["a1", {"b1": ["aaa", "bbb", "ccc"]}], "b": "bb"}'::jsonb)['a'][1]['b1'];
jsonb
-----------------------
["aaa", "bbb", "ccc"]
(1 row)
select ('{"a": ["a1", {"b1": ["aaa", "bbb", "ccc"]}], "b": "bb"}'::jsonb)['a'][1]['b1'][2];
jsonb
-------
"ccc"
(1 row)
-- slices are not supported
select ('{"a": 1}'::jsonb)['a':'b'];
ERROR: jsonb subscript does not support slices
LINE 1: select ('{"a": 1}'::jsonb)['a':'b'];
^
select ('[1, "2", null]'::jsonb)[1:2];
ERROR: jsonb subscript does not support slices
LINE 1: select ('[1, "2", null]'::jsonb)[1:2];
^
select ('[1, "2", null]'::jsonb)[:2];
ERROR: jsonb subscript does not support slices
LINE 1: select ('[1, "2", null]'::jsonb)[:2];
^
select ('[1, "2", null]'::jsonb)[1:];
ERROR: jsonb subscript does not support slices
LINE 1: select ('[1, "2", null]'::jsonb)[1:];
^
select ('[1, "2", null]'::jsonb)[:];
ERROR: jsonb subscript does not support slices
create TEMP TABLE test_jsonb_subscript (
id int,
test_json jsonb
);
insert into test_jsonb_subscript values
(1, '{}'), -- empty jsonb
(2, '{"key": "value"}'); -- jsonb with data
-- update empty jsonb
update test_jsonb_subscript set test_json['a'] = '1' where id = 1;
select * from test_jsonb_subscript;
id | test_json
----+------------------
2 | {"key": "value"}
1 | {"a": 1}
(2 rows)
-- update jsonb with some data
update test_jsonb_subscript set test_json['a'] = '1' where id = 2;
select * from test_jsonb_subscript;
id | test_json
----+--------------------------
1 | {"a": 1}
2 | {"a": 1, "key": "value"}
(2 rows)
-- replace jsonb
update test_jsonb_subscript set test_json['a'] = '"test"';
select * from test_jsonb_subscript;
id | test_json
----+-------------------------------
1 | {"a": "test"}
2 | {"a": "test", "key": "value"}
(2 rows)
-- replace by object
update test_jsonb_subscript set test_json['a'] = '{"b": 1}'::jsonb;
select * from test_jsonb_subscript;
id | test_json
----+---------------------------------
1 | {"a": {"b": 1}}
2 | {"a": {"b": 1}, "key": "value"}
(2 rows)
-- replace by array
update test_jsonb_subscript set test_json['a'] = '[1, 2, 3]'::jsonb;
select * from test_jsonb_subscript;
id | test_json
----+----------------------------------
1 | {"a": [1, 2, 3]}
2 | {"a": [1, 2, 3], "key": "value"}
(2 rows)
-- use jsonb subscription in where clause
select * from test_jsonb_subscript where test_json['key'] = '"value"';
id | test_json
----+----------------------------------
2 | {"a": [1, 2, 3], "key": "value"}
(1 row)
select * from test_jsonb_subscript where test_json['key_doesnt_exists'] = '"value"';
id | test_json
----+-----------
(0 rows)
select * from test_jsonb_subscript where test_json['key'] = '"wrong_value"';
id | test_json
----+-----------
(0 rows)
-- NULL
update test_jsonb_subscript set test_json[NULL] = '1';
ERROR: jsonb subscript in assignment must not be null
update test_jsonb_subscript set test_json['another_key'] = NULL;
select * from test_jsonb_subscript;
id | test_json
----+-------------------------------------------------------
1 | {"a": [1, 2, 3], "another_key": null}
2 | {"a": [1, 2, 3], "key": "value", "another_key": null}
(2 rows)
-- NULL as jsonb source
insert into test_jsonb_subscript values (3, NULL);
update test_jsonb_subscript set test_json['a'] = '1' where id = 3;
select * from test_jsonb_subscript;
id | test_json
----+-------------------------------------------------------
1 | {"a": [1, 2, 3], "another_key": null}
2 | {"a": [1, 2, 3], "key": "value", "another_key": null}
3 | {"a": 1}
(3 rows)
update test_jsonb_subscript set test_json = NULL where id = 3;
update test_jsonb_subscript set test_json[0] = '1';
select * from test_jsonb_subscript;
id | test_json
----+---------------------------------------------------------------
1 | {"0": 1, "a": [1, 2, 3], "another_key": null}
2 | {"0": 1, "a": [1, 2, 3], "key": "value", "another_key": null}
3 | [1]
(3 rows)
Filling array gaps during jsonb subscripting
This commit introduces two new flags for jsonb assignment:
* JB_PATH_FILL_GAPS: Appending array elements on the specified position, gaps
are filled with nulls (similar to the JavaScript behavior). This mode also
instructs to create the whole path in a jsonb object if some part of the
path (more than just the last element) is not present.
* JB_PATH_CONSISTENT_POSITION: Assigning keeps array positions consistent by
preventing prepending of elements.
Both flags are used only in jsonb subscripting assignment.
Initially proposed by Nikita Glukhov based on polymorphic subscripting
patch, but transformed into an independent change.
Discussion: https://postgr.es/m/CA%2Bq6zcV8qvGcDXurwwgUbwACV86Th7G80pnubg42e-p9gsSf%3Dg%40mail.gmail.com
Discussion: https://postgr.es/m/CA%2Bq6zcX3mdxGCgdThzuySwH-ApyHHM-G4oB1R0fn0j2hZqqkLQ%40mail.gmail.com
Discussion: https://postgr.es/m/CA%2Bq6zcVDuGBv%3DM0FqBYX8DPebS3F_0KQ6OVFobGJPM507_SZ_w%40mail.gmail.com
Discussion: https://postgr.es/m/CA%2Bq6zcVovR%2BXY4mfk-7oNk-rF91gH0PebnNfuUjuuDsyHjOcVA%40mail.gmail.com
Author: Dmitry Dolgov
Reviewed-by: Tom Lane, Arthur Zakirov, Pavel Stehule, Dian M Fay
Reviewed-by: Andrew Dunstan, Chapman Flack, Merlin Moncure, Peter Geoghegan
Reviewed-by: Alvaro Herrera, Jim Nasby, Josh Berkus, Victor Wagner
Reviewed-by: Aleksander Alekseev, Robert Haas, Oleg Bartunov
2021-01-31 21:51:01 +01:00
-- Fill the gaps logic
delete from test_jsonb_subscript;
insert into test_jsonb_subscript values (1, '[0]');
update test_jsonb_subscript set test_json[5] = '1';
select * from test_jsonb_subscript;
id | test_json
----+--------------------------------
1 | [0, null, null, null, null, 1]
(1 row)
update test_jsonb_subscript set test_json[-4] = '1';
select * from test_jsonb_subscript;
id | test_json
----+-----------------------------
1 | [0, null, 1, null, null, 1]
(1 row)
update test_jsonb_subscript set test_json[-8] = '1';
ERROR: path element at position 1 is out of range: -8
select * from test_jsonb_subscript;
id | test_json
----+-----------------------------
1 | [0, null, 1, null, null, 1]
(1 row)
-- keep consistent values position
delete from test_jsonb_subscript;
insert into test_jsonb_subscript values (1, '[]');
update test_jsonb_subscript set test_json[5] = '1';
select * from test_jsonb_subscript;
id | test_json
----+-----------------------------------
1 | [null, null, null, null, null, 1]
(1 row)
-- create the whole path
delete from test_jsonb_subscript;
insert into test_jsonb_subscript values (1, '{}');
update test_jsonb_subscript set test_json['a'][0]['b'][0]['c'] = '1';
select * from test_jsonb_subscript;
id | test_json
----+----------------------------
1 | {"a": [{"b": [{"c": 1}]}]}
(1 row)
delete from test_jsonb_subscript;
insert into test_jsonb_subscript values (1, '{}');
update test_jsonb_subscript set test_json['a'][2]['b'][2]['c'][2] = '1';
select * from test_jsonb_subscript;
id | test_json
----+------------------------------------------------------------------
1 | {"a": [null, null, {"b": [null, null, {"c": [null, null, 1]}]}]}
(1 row)
-- create the whole path with already existing keys
delete from test_jsonb_subscript;
insert into test_jsonb_subscript values (1, '{"b": 1}');
update test_jsonb_subscript set test_json['a'][0] = '2';
select * from test_jsonb_subscript;
id | test_json
----+--------------------
1 | {"a": [2], "b": 1}
(1 row)
-- the start jsonb is an object, first subscript is treated as a key
delete from test_jsonb_subscript;
insert into test_jsonb_subscript values (1, '{}');
update test_jsonb_subscript set test_json[0]['a'] = '1';
select * from test_jsonb_subscript;
id | test_json
----+-----------------
1 | {"0": {"a": 1}}
(1 row)
-- the start jsonb is an array
delete from test_jsonb_subscript;
insert into test_jsonb_subscript values (1, '[]');
update test_jsonb_subscript set test_json[0]['a'] = '1';
update test_jsonb_subscript set test_json[2]['b'] = '2';
select * from test_jsonb_subscript;
id | test_json
----+----------------------------
1 | [{"a": 1}, null, {"b": 2}]
(1 row)
-- overwriting an existing path
delete from test_jsonb_subscript;
insert into test_jsonb_subscript values (1, '{}');
update test_jsonb_subscript set test_json['a']['b'][1] = '1';
update test_jsonb_subscript set test_json['a']['b'][10] = '1';
select * from test_jsonb_subscript;
id | test_json
----+----------------------------------------------------------------------------
1 | {"a": {"b": [null, 1, null, null, null, null, null, null, null, null, 1]}}
(1 row)
delete from test_jsonb_subscript;
insert into test_jsonb_subscript values (1, '[]');
update test_jsonb_subscript set test_json[0][0][0] = '1';
update test_jsonb_subscript set test_json[0][0][1] = '1';
select * from test_jsonb_subscript;
id | test_json
----+------------
1 | [[[1, 1]]]
(1 row)
delete from test_jsonb_subscript;
insert into test_jsonb_subscript values (1, '{}');
update test_jsonb_subscript set test_json['a']['b'][10] = '1';
update test_jsonb_subscript set test_json['a'][10][10] = '1';
select * from test_jsonb_subscript;
id | test_json
----+------------------------------------------------------------------------------------------------------------------------------------------------------
1 | {"a": {"b": [null, null, null, null, null, null, null, null, null, null, 1], "10": [null, null, null, null, null, null, null, null, null, null, 1]}}
(1 row)
-- an empty sub element
delete from test_jsonb_subscript;
insert into test_jsonb_subscript values (1, '{"a": {}}');
update test_jsonb_subscript set test_json['a']['b']['c'][2] = '1';
select * from test_jsonb_subscript;
id | test_json
----+--------------------------------------
1 | {"a": {"b": {"c": [null, null, 1]}}}
(1 row)
delete from test_jsonb_subscript;
insert into test_jsonb_subscript values (1, '{"a": []}');
update test_jsonb_subscript set test_json['a'][1]['c'][2] = '1';
select * from test_jsonb_subscript;
id | test_json
----+---------------------------------------
1 | {"a": [null, {"c": [null, null, 1]}]}
(1 row)
Throw error when assigning jsonb scalar instead of a composite object
During the jsonb subscripting assignment, the provided path might assume an
object or an array where the source jsonb has a scalar value. Initial
subscripting assignment logic will skip such an update operation with no
message shown. This commit makes it throw an error to indicate this type
of situation.
Discussion: https://postgr.es/m/CA%2Bq6zcV8qvGcDXurwwgUbwACV86Th7G80pnubg42e-p9gsSf%3Dg%40mail.gmail.com
Discussion: https://postgr.es/m/CA%2Bq6zcX3mdxGCgdThzuySwH-ApyHHM-G4oB1R0fn0j2hZqqkLQ%40mail.gmail.com
Discussion: https://postgr.es/m/CA%2Bq6zcVDuGBv%3DM0FqBYX8DPebS3F_0KQ6OVFobGJPM507_SZ_w%40mail.gmail.com
Discussion: https://postgr.es/m/CA%2Bq6zcVovR%2BXY4mfk-7oNk-rF91gH0PebnNfuUjuuDsyHjOcVA%40mail.gmail.com
Author: Dmitry Dolgov
Reviewed-by: Tom Lane, Arthur Zakirov, Pavel Stehule, Dian M Fay
Reviewed-by: Andrew Dunstan, Chapman Flack, Merlin Moncure, Peter Geoghegan
Reviewed-by: Alvaro Herrera, Jim Nasby, Josh Berkus, Victor Wagner
Reviewed-by: Aleksander Alekseev, Robert Haas, Oleg Bartunov
2021-01-31 21:51:06 +01:00
-- trying replace assuming a composite object, but it's an element or a value
delete from test_jsonb_subscript;
insert into test_jsonb_subscript values (1, '{"a": 1}');
update test_jsonb_subscript set test_json['a']['b'] = '1';
ERROR: cannot replace existing key
DETAIL: The path assumes key is a composite object, but it is a scalar value.
update test_jsonb_subscript set test_json['a']['b']['c'] = '1';
ERROR: cannot replace existing key
DETAIL: The path assumes key is a composite object, but it is a scalar value.
update test_jsonb_subscript set test_json['a'][0] = '1';
ERROR: cannot replace existing key
DETAIL: The path assumes key is a composite object, but it is a scalar value.
update test_jsonb_subscript set test_json['a'][0]['c'] = '1';
ERROR: cannot replace existing key
DETAIL: The path assumes key is a composite object, but it is a scalar value.
update test_jsonb_subscript set test_json['a'][0][0] = '1';
ERROR: cannot replace existing key
DETAIL: The path assumes key is a composite object, but it is a scalar value.
-- trying replace assuming a composite object, but it's a raw scalar
delete from test_jsonb_subscript;
insert into test_jsonb_subscript values (1, 'null');
update test_jsonb_subscript set test_json[0] = '1';
ERROR: cannot replace existing key
DETAIL: The path assumes key is a composite object, but it is a scalar value.
update test_jsonb_subscript set test_json[0][0] = '1';
ERROR: cannot replace existing key
DETAIL: The path assumes key is a composite object, but it is a scalar value.
Fix jsonb subscripting to cope with toasted subscript values.
jsonb_get_element() was incautious enough to use VARDATA() and
VARSIZE() directly on an arbitrary text Datum. That of course
fails if the Datum is short-header, compressed, or out-of-line.
The typical result would be failing to match any element of a
jsonb object, though matching the wrong one seems possible as well.
setPathObject() was slightly brighter, in that it used VARDATA_ANY
and VARSIZE_ANY_EXHDR, but that only kept it out of trouble for
short-header Datums. push_path() had the same issue. This could
result in faulty subscripted insertions, though keys long enough to
cause a problem are likely rare in the wild.
Having seen these, I looked around for unsafe usages in the rest
of the adt/json* files. There are a couple of places where it's not
immediately obvious that the Datum can't be compressed or out-of-line,
so I added pg_detoast_datum_packed() to cope if it is. Also, remove
some other usages of VARDATA/VARSIZE on Datums we just extracted from
a text array. Those aren't actively broken, but they will become so
if we ever start allowing short-header array elements, which does not
seem like a terribly unreasonable thing to do. In any case they are
not great coding examples, and they could also do with comments
pointing out that we're assuming we don't need pg_detoast_datum_packed.
Per report from exe-dealer@yandex.ru. Patch by me, but thanks to
David Johnston for initial investigation. Back-patch to v14 where
jsonb subscripting was introduced.
Discussion: https://postgr.es/m/205321670615953@mail.yandex.ru
2022-12-12 22:17:49 +01:00
-- try some things with short-header and toasted subscript values
drop table test_jsonb_subscript;
create temp table test_jsonb_subscript (
id text,
test_json jsonb
);
insert into test_jsonb_subscript values('foo', '{"foo": "bar"}');
insert into test_jsonb_subscript
select s, ('{"' || s || '": "bar"}')::jsonb from repeat('xyzzy', 500) s;
select length(id), test_json[id] from test_jsonb_subscript;
length | test_json
--------+-----------
3 | "bar"
2500 | "bar"
(2 rows)
update test_jsonb_subscript set test_json[id] = '"baz"';
select length(id), test_json[id] from test_jsonb_subscript;
length | test_json
--------+-----------
3 | "baz"
2500 | "baz"
(2 rows)
\x
table test_jsonb_subscript;
-[ RECORD 1 ]--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
id | foo
test_json | {"foo": "baz"}
-[ RECORD 2 ]--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
id | xyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzy
test_json | {"xyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzyxyzzy": "baz"}
\x
2017-03-31 20:26:03 +02:00
-- jsonb to tsvector
select to_tsvector('{"a": "aaa bbb ddd ccc", "b": ["eee fff ggg"], "c": {"d": "hhh iii"}}'::jsonb);
to_tsvector
---------------------------------------------------------------------------
'aaa':1 'bbb':2 'ccc':4 'ddd':3 'eee':6 'fff':7 'ggg':8 'hhh':10 'iii':11
(1 row)
-- jsonb to tsvector with config
select to_tsvector('simple', '{"a": "aaa bbb ddd ccc", "b": ["eee fff ggg"], "c": {"d": "hhh iii"}}'::jsonb);
to_tsvector
---------------------------------------------------------------------------
'aaa':1 'bbb':2 'ccc':4 'ddd':3 'eee':6 'fff':7 'ggg':8 'hhh':10 'iii':11
(1 row)
-- jsonb to tsvector with stop words
2017-04-01 02:24:12 +02:00
select to_tsvector('english', '{"a": "aaa in bbb ddd ccc", "b": ["the eee fff ggg"], "c": {"d": "hhh. iii"}}'::jsonb);
2017-03-31 20:26:03 +02:00
to_tsvector
----------------------------------------------------------------------------
'aaa':1 'bbb':3 'ccc':5 'ddd':4 'eee':8 'fff':9 'ggg':10 'hhh':12 'iii':13
(1 row)
2018-04-07 19:58:03 +02:00
-- jsonb to tsvector with numeric values
select to_tsvector('english', '{"a": "aaa in bbb ddd ccc", "b": 123, "c": 456}'::jsonb);
to_tsvector
---------------------------------
'aaa':1 'bbb':3 'ccc':5 'ddd':4
(1 row)
-- jsonb_to_tsvector
2018-04-07 20:29:48 +02:00
select jsonb_to_tsvector('english', '{"a": "aaa in bbb", "b": 123, "c": 456, "d": true, "f": false, "g": null}'::jsonb, '"all"');
2018-04-07 19:58:03 +02:00
jsonb_to_tsvector
----------------------------------------------------------------------------------------
'123':8 '456':12 'aaa':2 'b':6 'bbb':4 'c':10 'd':14 'f':18 'fals':20 'g':22 'true':16
(1 row)
2018-04-07 20:29:48 +02:00
select jsonb_to_tsvector('english', '{"a": "aaa in bbb", "b": 123, "c": 456, "d": true, "f": false, "g": null}'::jsonb, '"key"');
2018-04-07 19:58:03 +02:00
jsonb_to_tsvector
--------------------------------
'b':2 'c':4 'd':6 'f':8 'g':10
(1 row)
2018-04-07 20:29:48 +02:00
select jsonb_to_tsvector('english', '{"a": "aaa in bbb", "b": 123, "c": 456, "d": true, "f": false, "g": null}'::jsonb, '"string"');
2018-04-07 19:58:03 +02:00
jsonb_to_tsvector
-------------------
'aaa':1 'bbb':3
(1 row)
2018-04-07 20:29:48 +02:00
select jsonb_to_tsvector('english', '{"a": "aaa in bbb", "b": 123, "c": 456, "d": true, "f": false, "g": null}'::jsonb, '"numeric"');
2018-04-07 19:58:03 +02:00
jsonb_to_tsvector
-------------------
'123':1 '456':3
(1 row)
2018-04-07 20:29:48 +02:00
select jsonb_to_tsvector('english', '{"a": "aaa in bbb", "b": 123, "c": 456, "d": true, "f": false, "g": null}'::jsonb, '"boolean"');
2018-04-07 19:58:03 +02:00
jsonb_to_tsvector
-------------------
'fals':3 'true':1
(1 row)
2018-04-07 20:29:48 +02:00
select jsonb_to_tsvector('english', '{"a": "aaa in bbb", "b": 123, "c": 456, "d": true, "f": false, "g": null}'::jsonb, '["string", "numeric"]');
2018-04-07 19:58:03 +02:00
jsonb_to_tsvector
---------------------------------
'123':5 '456':7 'aaa':1 'bbb':3
(1 row)
select jsonb_to_tsvector('english', '{"a": "aaa in bbb", "b": 123, "c": 456, "d": true, "f": false, "g": null}'::jsonb, '"all"');
jsonb_to_tsvector
----------------------------------------------------------------------------------------
'123':8 '456':12 'aaa':2 'b':6 'bbb':4 'c':10 'd':14 'f':18 'fals':20 'g':22 'true':16
(1 row)
select jsonb_to_tsvector('english', '{"a": "aaa in bbb", "b": 123, "c": 456, "d": true, "f": false, "g": null}'::jsonb, '"key"');
jsonb_to_tsvector
--------------------------------
'b':2 'c':4 'd':6 'f':8 'g':10
(1 row)
select jsonb_to_tsvector('english', '{"a": "aaa in bbb", "b": 123, "c": 456, "d": true, "f": false, "g": null}'::jsonb, '"string"');
jsonb_to_tsvector
-------------------
'aaa':1 'bbb':3
(1 row)
select jsonb_to_tsvector('english', '{"a": "aaa in bbb", "b": 123, "c": 456, "d": true, "f": false, "g": null}'::jsonb, '"numeric"');
jsonb_to_tsvector
-------------------
'123':1 '456':3
(1 row)
select jsonb_to_tsvector('english', '{"a": "aaa in bbb", "b": 123, "c": 456, "d": true, "f": false, "g": null}'::jsonb, '"boolean"');
jsonb_to_tsvector
-------------------
'fals':3 'true':1
(1 row)
select jsonb_to_tsvector('english', '{"a": "aaa in bbb", "b": 123, "c": 456, "d": true, "f": false, "g": null}'::jsonb, '["string", "numeric"]');
jsonb_to_tsvector
---------------------------------
'123':5 '456':7 'aaa':1 'bbb':3
(1 row)
2019-03-15 08:20:11 +01:00
-- to_tsvector corner cases
2017-03-31 20:26:03 +02:00
select to_tsvector('""'::jsonb);
to_tsvector
-------------
(1 row)
select to_tsvector('{}'::jsonb);
to_tsvector
-------------
(1 row)
select to_tsvector('[]'::jsonb);
to_tsvector
-------------
(1 row)
select to_tsvector('null'::jsonb);
to_tsvector
-------------
(1 row)
2018-04-07 19:58:03 +02:00
-- jsonb_to_tsvector corner cases
select jsonb_to_tsvector('""'::jsonb, '"all"');
jsonb_to_tsvector
-------------------
(1 row)
select jsonb_to_tsvector('{}'::jsonb, '"all"');
jsonb_to_tsvector
-------------------
(1 row)
select jsonb_to_tsvector('[]'::jsonb, '"all"');
jsonb_to_tsvector
-------------------
(1 row)
select jsonb_to_tsvector('null'::jsonb, '"all"');
jsonb_to_tsvector
-------------------
(1 row)
2018-04-07 20:29:48 +02:00
select jsonb_to_tsvector('english', '{"a": "aaa in bbb", "b": 123, "c": 456, "d": true, "f": false, "g": null}'::jsonb, '""');
2018-04-07 19:58:03 +02:00
ERROR: wrong flag in flag array: ""
2018-12-06 23:47:42 +01:00
HINT: Possible values are: "string", "numeric", "boolean", "key", and "all".
2018-04-07 20:29:48 +02:00
select jsonb_to_tsvector('english', '{"a": "aaa in bbb", "b": 123, "c": 456, "d": true, "f": false, "g": null}'::jsonb, '{}');
2018-04-07 19:58:03 +02:00
ERROR: wrong flag type, only arrays and scalars are allowed
2018-04-07 20:29:48 +02:00
select jsonb_to_tsvector('english', '{"a": "aaa in bbb", "b": 123, "c": 456, "d": true, "f": false, "g": null}'::jsonb, '[]');
2018-04-07 19:58:03 +02:00
jsonb_to_tsvector
-------------------
(1 row)
2018-04-07 20:29:48 +02:00
select jsonb_to_tsvector('english', '{"a": "aaa in bbb", "b": 123, "c": 456, "d": true, "f": false, "g": null}'::jsonb, 'null');
2018-04-07 19:58:03 +02:00
ERROR: flag array element is not a string
2018-12-06 23:47:42 +01:00
HINT: Possible values are: "string", "numeric", "boolean", "key", and "all".
2018-04-07 20:29:48 +02:00
select jsonb_to_tsvector('english', '{"a": "aaa in bbb", "b": 123, "c": 456, "d": true, "f": false, "g": null}'::jsonb, '["all", null]');
2018-04-07 19:58:03 +02:00
ERROR: flag array element is not a string
2018-12-06 23:47:42 +01:00
HINT: Possible values are: "string", "numeric", "boolean", "key", and "all".
2017-03-31 20:26:03 +02:00
-- ts_headline for jsonb
select ts_headline('{"a": "aaa bbb", "b": {"c": "ccc ddd fff", "c1": "ccc1 ddd1"}, "d": ["ggg hhh", "iii jjj"]}'::jsonb, tsquery('bbb & ddd & hhh'));
ts_headline
------------------------------------------------------------------------------------------------------------------
{"a": "aaa <b>bbb</b>", "b": {"c": "ccc <b>ddd</b> fff", "c1": "ccc1 ddd1"}, "d": ["ggg <b>hhh</b>", "iii jjj"]}
(1 row)
select ts_headline('english', '{"a": "aaa bbb", "b": {"c": "ccc ddd fff"}, "d": ["ggg hhh", "iii jjj"]}'::jsonb, tsquery('bbb & ddd & hhh'));
ts_headline
-----------------------------------------------------------------------------------------------
{"a": "aaa <b>bbb</b>", "b": {"c": "ccc <b>ddd</b> fff"}, "d": ["ggg <b>hhh</b>", "iii jjj"]}
(1 row)
select ts_headline('{"a": "aaa bbb", "b": {"c": "ccc ddd fff", "c1": "ccc1 ddd1"}, "d": ["ggg hhh", "iii jjj"]}'::jsonb, tsquery('bbb & ddd & hhh'), 'StartSel = <, StopSel = >');
ts_headline
---------------------------------------------------------------------------------------------------
{"a": "aaa <bbb>", "b": {"c": "ccc <ddd> fff", "c1": "ccc1 ddd1"}, "d": ["ggg <hhh>", "iii jjj"]}
(1 row)
select ts_headline('english', '{"a": "aaa bbb", "b": {"c": "ccc ddd fff", "c1": "ccc1 ddd1"}, "d": ["ggg hhh", "iii jjj"]}'::jsonb, tsquery('bbb & ddd & hhh'), 'StartSel = <, StopSel = >');
ts_headline
---------------------------------------------------------------------------------------------------
{"a": "aaa <bbb>", "b": {"c": "ccc <ddd> fff", "c1": "ccc1 ddd1"}, "d": ["ggg <hhh>", "iii jjj"]}
(1 row)
-- corner cases for ts_headline with jsonb
select ts_headline('null'::jsonb, tsquery('aaa & bbb'));
ts_headline
-------------
null
(1 row)
select ts_headline('{}'::jsonb, tsquery('aaa & bbb'));
ts_headline
-------------
{}
(1 row)
select ts_headline('[]'::jsonb, tsquery('aaa & bbb'));
ts_headline
-------------
[]
(1 row)
2018-03-29 15:33:56 +02:00
-- casts
select 'true'::jsonb::bool;
bool
------
t
(1 row)
select '[]'::jsonb::bool;
2018-05-09 12:23:16 +02:00
ERROR: cannot cast jsonb array to type boolean
2018-03-29 15:33:56 +02:00
select '1.0'::jsonb::float;
float8
--------
1
(1 row)
select '[1.0]'::jsonb::float;
2018-05-09 12:23:16 +02:00
ERROR: cannot cast jsonb array to type double precision
2018-03-29 15:33:56 +02:00
select '12345'::jsonb::int4;
int4
-------
12345
(1 row)
select '"hello"'::jsonb::int4;
2018-05-09 12:23:16 +02:00
ERROR: cannot cast jsonb string to type integer
2018-03-29 15:33:56 +02:00
select '12345'::jsonb::numeric;
numeric
---------
12345
(1 row)
select '{}'::jsonb::numeric;
2018-05-09 12:23:16 +02:00
ERROR: cannot cast jsonb object to type numeric
2018-03-29 15:33:56 +02:00
select '12345.05'::jsonb::numeric;
numeric
----------
12345.05
(1 row)
select '12345.05'::jsonb::float4;
Change floating-point output format for improved performance.
Previously, floating-point output was done by rounding to a specific
decimal precision; by default, to 6 or 15 decimal digits (losing
information) or as requested using extra_float_digits. Drivers that
wanted exact float values, and applications like pg_dump that must
preserve values exactly, set extra_float_digits=3 (or sometimes 2 for
historical reasons, though this isn't enough for float4).
Unfortunately, decimal rounded output is slow enough to become a
noticable bottleneck when dealing with large result sets or COPY of
large tables when many floating-point values are involved.
Floating-point output can be done much faster when the output is not
rounded to a specific decimal length, but rather is chosen as the
shortest decimal representation that is closer to the original float
value than to any other value representable in the same precision. The
recently published Ryu algorithm by Ulf Adams is both relatively
simple and remarkably fast.
Accordingly, change float4out/float8out to output shortest decimal
representations if extra_float_digits is greater than 0, and make that
the new default. Applications that need rounded output can set
extra_float_digits back to 0 or below, and take the resulting
performance hit.
We make one concession to portability for systems with buggy
floating-point input: we do not output decimal values that fall
exactly halfway between adjacent representable binary values (which
would rely on the reader doing round-to-nearest-even correctly). This
is known to be a problem at least for VS2013 on Windows.
Our version of the Ryu code originates from
https://github.com/ulfjack/ryu/ at commit c9c3fb1979, but with the
following (significant) modifications:
- Output format is changed to use fixed-point notation for small
exponents, as printf would, and also to use lowercase 'e', a
minimum of 2 exponent digits, and a mandatory sign on the exponent,
to keep the formatting as close as possible to previous output.
- The output of exact midpoint values is disabled as noted above.
- The integer fast-path code is changed somewhat (since we have
fixed-point output and the upstream did not).
- Our project style has been largely applied to the code with the
exception of C99 declaration-after-statement, which has been
retained as an exception to our present policy.
- Most of upstream's debugging and conditionals are removed, and we
use our own configure tests to determine things like uint128
availability.
Changing the float output format obviously affects a number of
regression tests. This patch uses an explicit setting of
extra_float_digits=0 for test output that is not expected to be
exactly reproducible (e.g. due to numerical instability or differing
algorithms for transcendental functions).
Conversions from floats to numeric are unchanged by this patch. These
may appear in index expressions and it is not yet clear whether any
change should be made, so that can be left for another day.
This patch assumes that the only supported floating point format is
now IEEE format, and the documentation is updated to reflect that.
Code by me, adapting the work of Ulf Adams and other contributors.
References:
https://dl.acm.org/citation.cfm?id=3192369
Reviewed-by: Tom Lane, Andres Freund, Donald Dong
Discussion: https://postgr.es/m/87r2el1bx6.fsf@news-spur.riddles.org.uk
2019-02-13 16:20:33 +01:00
float4
----------
12345.05
2018-03-29 15:33:56 +02:00
(1 row)
select '12345.05'::jsonb::float8;
float8
----------
12345.05
(1 row)
select '12345.05'::jsonb::int2;
int2
-------
12345
(1 row)
select '12345.05'::jsonb::int4;
int4
-------
12345
(1 row)
select '12345.05'::jsonb::int8;
int8
-------
12345
(1 row)
select '12345.0000000000000000000000000000000000000000000005'::jsonb::numeric;
numeric
------------------------------------------------------
12345.0000000000000000000000000000000000000000000005
(1 row)
select '12345.0000000000000000000000000000000000000000000005'::jsonb::float4;
float4
--------
12345
(1 row)
select '12345.0000000000000000000000000000000000000000000005'::jsonb::float8;
float8
--------
12345
(1 row)
select '12345.0000000000000000000000000000000000000000000005'::jsonb::int2;
int2
-------
12345
(1 row)
select '12345.0000000000000000000000000000000000000000000005'::jsonb::int4;
int4
-------
12345
(1 row)
select '12345.0000000000000000000000000000000000000000000005'::jsonb::int8;
int8
-------
12345
(1 row)