-- directory paths are passed to us in environment variables
\getenv abs_srcdir PG_ABS_SRCDIR
CREATETABLE testjsonb (
j jsonb
);
\set filename :abs_srcdir '/data/jsonb.data'
COPY testjsonb FROM :'filename';
-- Strings. SELECT'""'::jsonb; -- OK. SELECT $$''$$::jsonb; -- ERROR, single quotes are not allowed SELECT'"abc"'::jsonb; -- OK SELECT'"abc'::jsonb; -- ERROR, quotes not closed SELECT'"abc
def"'::jsonb; -- ERROR, unescaped newline in string constant SELECT'"\n\"\\"'::jsonb; -- OK, legal escapes SELECT'"\v"'::jsonb; -- ERROR, not a valid JSON escape -- see json_encoding test for input with unicode escapes
-- Numbers. SELECT'1'::jsonb; -- OK SELECT'0'::jsonb; -- OK SELECT'01'::jsonb; -- ERROR, not valid according to JSON spec SELECT'0.1'::jsonb; -- OK SELECT'9223372036854775808'::jsonb; -- OK, even though it's too large for int8 SELECT'1e100'::jsonb; -- OK SELECT'1.3e100'::jsonb; -- OK SELECT'1f2'::jsonb; -- ERROR SELECT'0.x1'::jsonb; -- ERROR SELECT'1.3ex100'::jsonb; -- ERROR
-- Arrays. SELECT'[]'::jsonb; -- OK SELECT'[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]'::jsonb; -- OK SELECT'[1,2]'::jsonb; -- OK SELECT'[1,2,]'::jsonb; -- ERROR, trailing comma SELECT'[1,2'::jsonb; -- ERROR, no closing bracket SELECT'[1,[2]'::jsonb; -- ERROR, no closing bracket
-- Objects. SELECT'{}'::jsonb; -- OK SELECT'{"abc"}'::jsonb; -- ERROR, no value SELECT'{"abc":1}'::jsonb; -- OK SELECT'{1:"abc"}'::jsonb; -- ERROR, keys must be strings SELECT'{"abc",1}'::jsonb; -- ERROR, wrong separator SELECT'{"abc"=1}'::jsonb; -- ERROR, totally wrong separator SELECT'{"abc"::1}'::jsonb; -- ERROR, another wrong separator SELECT'{"abc":1,"def":2,"ghi":[3,4],"hij":{"klm":5,"nop":[6]}}'::jsonb; -- OK SELECT'{"abc":1:2}'::jsonb; -- ERROR, colon in wrong spot SELECT'{"abc":1,3}'::jsonb; -- ERROR, no value
-- Miscellaneous stuff. SELECT'true'::jsonb; -- OK SELECT'false'::jsonb; -- OK SELECT'null'::jsonb; -- OK SELECT' true '::jsonb; -- OK, even with extra whitespace SELECT'true false'::jsonb; -- ERROR, too many values SELECT'true, false'::jsonb; -- ERROR, too many values SELECT'truf'::jsonb; -- ERROR, not a keyword SELECT'trues'::jsonb; -- ERROR, not a keyword SELECT''::jsonb; -- ERROR, no value SELECT' '::jsonb; -- ERROR, no value
-- Multi-line JSON input to check ERROR reporting SELECT'{ "one": 1, "two":"two", "three": true}'::jsonb; -- OK SELECT'{ "one": 1, "two":,"two", -- ERROR extraneous comma before field "two" "three": true}'::jsonb; SELECT'{ "one": 1, "two":"two", "averyveryveryveryveryveryveryveryveryverylongfieldname":}'::jsonb; -- ERROR missing value for last field
-- test non-error-throwing input select pg_input_is_valid('{"a":true}', 'jsonb'); select pg_input_is_valid('{"a":true', 'jsonb'); select * from pg_input_error_info('{"a":true', 'jsonb'); select * from pg_input_error_info('{"a":1e1000000}', 'jsonb');
-- make sure jsonb is passed through json generators without being escaped SELECT array_to_json(ARRAY [jsonb '{"a":1}', jsonb '{"b":[2,3]}']);
-- anyarray column
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 from pg_stats where tablename = 'rows'and
schemaname = pg_my_temp_schema()::regnamespace::text orderby1;
BEGIN; SET LOCAL TIME ZONE 10.5; select to_jsonb(timestamptz '2014-05-28 12:22:35.614298-04'); SET LOCAL TIME ZONE -8; select to_jsonb(timestamptz '2014-05-28 12:22:35.614298-04'); COMMIT;
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;
SELECT jsonb_agg(q ORDERBY x, y) FROM rows q;
UPDATE rows SET x = NULLWHERE x = 1;
SELECT jsonb_agg(q ORDERBY x NULLS FIRST, y) FROM rows q;
SELECT test_json -> 'x'FROM test_jsonb WHERE json_type = 'scalar'; SELECT test_json -> 'x'FROM test_jsonb WHERE json_type = 'array'; SELECT test_json -> 'x'FROM test_jsonb WHERE json_type = 'object'; SELECT test_json -> 'field2'FROM test_jsonb WHERE json_type = 'object';
SELECT test_json ->> 'field2'FROM test_jsonb WHERE json_type = 'scalar'; SELECT test_json ->> 'field2'FROM test_jsonb WHERE json_type = 'array'; SELECT test_json ->> 'field2'FROM test_jsonb WHERE json_type = 'object';
SELECT test_json -> 2FROM test_jsonb WHERE json_type = 'scalar'; SELECT test_json -> 2FROM test_jsonb WHERE json_type = 'array'; SELECT test_json -> 9FROM test_jsonb WHERE json_type = 'array'; SELECT test_json -> 2FROM test_jsonb WHERE json_type = 'object';
SELECT test_json ->> 6FROM test_jsonb WHERE json_type = 'array'; SELECT test_json ->> 7FROM test_jsonb WHERE json_type = 'array';
SELECT test_json ->> 'field4'FROM test_jsonb WHERE json_type = 'object'; SELECT test_json ->> 'field5'FROM test_jsonb WHERE json_type = 'object'; SELECT test_json ->> 'field6'FROM test_jsonb WHERE json_type = 'object';
SELECT test_json ->> 2FROM test_jsonb WHERE json_type = 'scalar'; SELECT test_json ->> 2FROM test_jsonb WHERE json_type = 'array'; SELECT test_json ->> 2FROM test_jsonb WHERE json_type = 'object';
SELECT jsonb_object_keys(test_json) FROM test_jsonb WHERE json_type = 'scalar'; SELECT jsonb_object_keys(test_json) FROM test_jsonb WHERE json_type = 'array'; SELECT jsonb_object_keys(test_json) FROM test_jsonb WHERE json_type = 'object';
-- nulls SELECT (test_json->'field3') ISNULLAS expect_false FROM test_jsonb WHERE json_type = 'object'; SELECT (test_json->>'field3') ISNULLAS expect_true FROM test_jsonb WHERE json_type = 'object'; SELECT (test_json->3) ISNULLAS expect_false FROM test_jsonb WHERE json_type = 'array'; SELECT (test_json->>3) ISNULLAS expect_true FROM test_jsonb WHERE json_type = 'array';
-- each SELECT jsonb_each('{"f1":[1,2,3],"f2":{"f3":1},"f4":null}'); SELECT jsonb_each('{"a":{"b":"c","c":"b","1":"first"},"b":[1,2],"c":"cc","1":"first","n":null}'::jsonb) AS q; SELECT * FROM jsonb_each('{"f1":[1,2,3],"f2":{"f3":1},"f4":null,"f5":99,"f6":"stringy"}') q; SELECT * FROM jsonb_each('{"a":{"b":"c","c":"b","1":"first"},"b":[1,2],"c":"cc","1":"first","n":null}'::jsonb) AS q;
SELECT jsonb_each_text('{"f1":[1,2,3],"f2":{"f3":1},"f4":null,"f5":"null"}'); SELECT jsonb_each_text('{"a":{"b":"c","c":"b","1":"first"},"b":[1,2],"c":"cc","1":"first","n":null}'::jsonb) AS q; SELECT * FROM jsonb_each_text('{"f1":[1,2,3],"f2":{"f3":1},"f4":null,"f5":99,"f6":"stringy"}') q; SELECT * FROM jsonb_each_text('{"a":{"b":"c","c":"b","1":"first"},"b":[1,2],"c":"cc","1":"first","n":null}'::jsonb) AS q;
-- exists SELECT jsonb_exists('{"a":null, "b":"qq"}', 'a'); SELECT jsonb_exists('{"a":null, "b":"qq"}', 'b'); SELECT jsonb_exists('{"a":null, "b":"qq"}', 'c'); SELECT jsonb_exists('{"a":"null", "b":"qq"}', 'a'); SELECT jsonb '{"a":null, "b":"qq"}' ? 'a'; SELECT jsonb '{"a":null, "b":"qq"}' ? 'b'; SELECT jsonb '{"a":null, "b":"qq"}' ? 'c'; SELECT jsonb '{"a":"null", "b":"qq"}' ? 'a'; -- array exists - array elements should behave as keys SELECT count(*) from testjsonb WHERE j->'array' ? 'bar'; -- 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; -- However, a raw scalar is *contained* within the array SELECT count(*) from testjsonb WHERE j->'array' @> '5'::jsonb;
-- typeof SELECT jsonb_typeof('{}') AS object; SELECT jsonb_typeof('{"c":3,"p":"o"}') AS object; SELECT jsonb_typeof('[]') AS array; SELECT jsonb_typeof('["a", 1]') AS array; SELECT jsonb_typeof('null') AS"null"; SELECT jsonb_typeof('1') AS number; SELECT jsonb_typeof('-1') AS number; SELECT jsonb_typeof('1.0') AS number; SELECT jsonb_typeof('1e2') AS number; SELECT jsonb_typeof('-1.0') AS number; SELECT jsonb_typeof('true') AS boolean; SELECT jsonb_typeof('false') AS boolean; SELECT jsonb_typeof('"hello"') AS string; SELECT jsonb_typeof('"true"') AS string; SELECT jsonb_typeof('"1.0"') AS string;
create type jb_unordered_pair as (x int, y int); create domain jb_ordered_pair as jb_unordered_pair check((value).x <= (value).y);
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
);
SELECT * FROM jsonb_populate_record(NULL::jbpop,'{"a":"blurfl","x":43.2}') q; SELECT * FROM jsonb_populate_record(row('x',3,'2012-12-31 15:30:56')::jbpop,'{"a":"blurfl","x":43.2}') q;
SELECT * FROM jsonb_populate_record(NULL::jbpop,'{"a":"blurfl","x":43.2}') q; SELECT * FROM jsonb_populate_record(row('x',3,'2012-12-31 15:30:56')::jbpop,'{"a":"blurfl","x":43.2}') q;
SELECT * FROM jsonb_populate_record(NULL::jbpop,'{"a":[100,200,false],"x":43.2}') q; SELECT * FROM jsonb_populate_record(row('x',3,'2012-12-31 15:30:56')::jbpop,'{"a":[100,200,false],"x":43.2}') q; SELECT * FROM jsonb_populate_record(row('x',3,'2012-12-31 15:30:56')::jbpop,'{"c":[100,200,false],"x":43.2}') q;
SELECT * FROM jsonb_populate_record(row('x',3,'2012-12-31 15:30:56')::jbpop, '{}') q;
SELECT i FROM jsonb_populate_record(NULL::jsbrec_i_not_null, '{"x": 43.2}') q; SELECT i FROM jsonb_populate_record(NULL::jsbrec_i_not_null, '{"i": null}') q; SELECT i FROM jsonb_populate_record(NULL::jsbrec_i_not_null, '{"i": 12345}') q;
SELECT ia FROM jsonb_populate_record(NULL::jsbrec, '{"ia": null}') q; SELECT ia FROM jsonb_populate_record(NULL::jsbrec, '{"ia": 123}') q; SELECT ia FROM jsonb_populate_record(NULL::jsbrec, '{"ia": [1, "2", null, 4]}') q; SELECT ia FROM jsonb_populate_record(NULL::jsbrec, '{"ia": [[1, 2], [3, 4]]}') q; SELECT ia FROM jsonb_populate_record(NULL::jsbrec, '{"ia": [[1], 2]}') q; SELECT ia FROM jsonb_populate_record(NULL::jsbrec, '{"ia": [[1], [2, 3]]}') q; SELECT ia FROM jsonb_populate_record(NULL::jsbrec, '{"ia": "{1,2,3}"}') q;
SELECT ia1 FROM jsonb_populate_record(NULL::jsbrec, '{"ia1": null}') q; SELECT ia1 FROM jsonb_populate_record(NULL::jsbrec, '{"ia1": 123}') q; SELECT ia1 FROM jsonb_populate_record(NULL::jsbrec, '{"ia1": [1, "2", null, 4]}') q; SELECT ia1 FROM jsonb_populate_record(NULL::jsbrec, '{"ia1": [[1, 2, 3]]}') q;
SELECT ia1d FROM jsonb_populate_record(NULL::jsbrec, '{"ia1d": null}') q; SELECT ia1d FROM jsonb_populate_record(NULL::jsbrec, '{"ia1d": 123}') q; SELECT ia1d FROM jsonb_populate_record(NULL::jsbrec, '{"ia1d": [1, "2", null, 4]}') q; SELECT ia1d FROM jsonb_populate_record(NULL::jsbrec, '{"ia1d": [1, "2", null]}') q;
SELECT ia2 FROM jsonb_populate_record(NULL::jsbrec, '{"ia2": [1, "2", null, 4]}') q; SELECT ia2 FROM jsonb_populate_record(NULL::jsbrec, '{"ia2": [[1, 2], [null, 4]]}') q; SELECT ia2 FROM jsonb_populate_record(NULL::jsbrec, '{"ia2": [[], []]}') q; SELECT ia2 FROM jsonb_populate_record(NULL::jsbrec, '{"ia2": [[1, 2], [3]]}') q; SELECT ia2 FROM jsonb_populate_record(NULL::jsbrec, '{"ia2": [[1, 2], 3, 4]}') q;
SELECT ta FROM jsonb_populate_record(NULL::jsbrec, '{"ta": null}') q; SELECT ta FROM jsonb_populate_record(NULL::jsbrec, '{"ta": 123}') q; SELECT ta FROM jsonb_populate_record(NULL::jsbrec, '{"ta": [1, "2", null, 4]}') q; SELECT ta FROM jsonb_populate_record(NULL::jsbrec, '{"ta": [[1, 2, 3], {"k": "v"}]}') q;
SELECT c FROM jsonb_populate_record(NULL::jsbrec, '{"c": null}') q; SELECT c FROM jsonb_populate_record(NULL::jsbrec, '{"c": "aaa"}') q; SELECT c FROM jsonb_populate_record(NULL::jsbrec, '{"c": "aaaaaaaaaa"}') q; SELECT c FROM jsonb_populate_record(NULL::jsbrec, '{"c": "aaaaaaaaaaaaa"}') q;
SELECT ca FROM jsonb_populate_record(NULL::jsbrec, '{"ca": null}') q; SELECT ca FROM jsonb_populate_record(NULL::jsbrec, '{"ca": 123}') q; SELECT ca FROM jsonb_populate_record(NULL::jsbrec, '{"ca": [1, "2", null, 4]}') q; SELECT ca FROM jsonb_populate_record(NULL::jsbrec, '{"ca": ["aaaaaaaaaaaaaaaa"]}') q; SELECT ca FROM jsonb_populate_record(NULL::jsbrec, '{"ca": [[1, 2, 3], {"k": "v"}]}') q;
SELECT js FROM jsonb_populate_record(NULL::jsbrec, '{"js": null}') q; SELECT js FROM jsonb_populate_record(NULL::jsbrec, '{"js": true}') q; SELECT js FROM jsonb_populate_record(NULL::jsbrec, '{"js": 123.45}') q; SELECT js FROM jsonb_populate_record(NULL::jsbrec, '{"js": "123.45"}') q; SELECT js FROM jsonb_populate_record(NULL::jsbrec, '{"js": "abc"}') q; SELECT js FROM jsonb_populate_record(NULL::jsbrec, '{"js": [123, "123", null, {"key": "value"}]}') q; SELECT js FROM jsonb_populate_record(NULL::jsbrec, '{"js": {"a": "bbb", "b": null, "c": 123.45}}') q;
SELECT jsb FROM jsonb_populate_record(NULL::jsbrec, '{"jsb": null}') q; SELECT jsb FROM jsonb_populate_record(NULL::jsbrec, '{"jsb": true}') q; SELECT jsb FROM jsonb_populate_record(NULL::jsbrec, '{"jsb": 123.45}') q; SELECT jsb FROM jsonb_populate_record(NULL::jsbrec, '{"jsb": "123.45"}') q; SELECT jsb FROM jsonb_populate_record(NULL::jsbrec, '{"jsb": "abc"}') q; SELECT jsb FROM jsonb_populate_record(NULL::jsbrec, '{"jsb": [123, "123", null, {"key": "value"}]}') q; SELECT jsb FROM jsonb_populate_record(NULL::jsbrec, '{"jsb": {"a": "bbb", "b": null, "c": 123.45}}') q;
-- populate_recordset SELECT * FROM jsonb_populate_recordset(NULL::jbpop,'[{"a":"blurfl","x":43.2},{"b":3,"c":"2012-01-20 10:42:53"}]') q; 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; SELECT * FROM jsonb_populate_recordset(NULL::jbpop,'[{"a":"blurfl","x":43.2},{"b":3,"c":"2012-01-20 10:42:53"}]') q; 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; 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; 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;
SELECT * FROM jsonb_populate_recordset(NULL::jbpop,'[{"a":"blurfl","x":43.2},{"b":3,"c":"2012-01-20 10:42:53"}]') q; 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; 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;
-- anonymous record type SELECT jsonb_populate_recordset(null::record, '[{"x": 0, "y": 1}]'); SELECT jsonb_populate_recordset(row(1,2), '[{"f1": 0, "f2": 1}]'); SELECT i, jsonb_populate_recordset(row(i,50), '[{"f1":"42"},{"f2":"43"}]') FROM (VALUES (1),(2)) v(i); SELECT * FROM
jsonb_populate_recordset(null::record, '[{"x": 776}]') AS (x int, y int);
-- empty array is a corner case SELECT jsonb_populate_recordset(null::record, '[]'); SELECT jsonb_populate_recordset(row(1,2), '[]'); SELECT * FROM jsonb_populate_recordset(NULL::jbpop,'[]') q; SELECT * FROM
jsonb_populate_recordset(null::record, '[]') AS (x int, y int);
-- 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); select * from jsonb_populate_recordset(row(0::int,0::int),'[{"a":"1","b":"2"},{"a":"3"}]') q (a text, b text); select * from jsonb_populate_recordset(row(0::int,0::int,0::int),'[{"a":"1","b":"2"},{"a":"3"}]') q (a text, b text); select * from jsonb_populate_recordset(row(1000000000::int,50::int),'[{"b":"2"},{"a":"3"}]') q (a text, b text);
-- jsonb_to_record and jsonb_to_recordset
select * from jsonb_to_record('{"a":1,"b":"foo","c":"bar"}') as x(a int, b text, d text);
select * from jsonb_to_recordset('[{"a":1,"b":"foo","d":false},{"a":2,"b":"bar","c":true}]') as x(a int, b text, c boolean);
select *, c isnullas c_is_null 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);
select *, c isnullas 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);
select * from jsonb_to_record('{"ia": null}') as x(ia _int4); select * from jsonb_to_record('{"ia": 123}') as x(ia _int4); select * from jsonb_to_record('{"ia": [1, "2", null, 4]}') as x(ia _int4); select * from jsonb_to_record('{"ia": [[1, 2], [3, 4]]}') as x(ia _int4); select * from jsonb_to_record('{"ia": [[1], 2]}') as x(ia _int4); select * from jsonb_to_record('{"ia": [[1], [2, 3]]}') as x(ia _int4);
select * from jsonb_to_record('{"ia2": [1, 2, 3]}') as x(ia2 int[][]); select * from jsonb_to_record('{"ia2": [[1, 2], [3, 4]]}') as x(ia2 int4[][]); select * from jsonb_to_record('{"ia2": [[[1], [2], [3]]]}') as x(ia2 int4[][]);
select * from jsonb_to_record('{"out": {"key": 1}}') as x(out json); select * from jsonb_to_record('{"out": [{"key": 1}]}') as x(out json); select * from jsonb_to_record('{"out": "{\"key\": 1}"}') as x(out json); select * from jsonb_to_record('{"out": {"key": 1}}') as x(out jsonb); select * from jsonb_to_record('{"out": [{"key": 1}]}') as x(out jsonb); select * from jsonb_to_record('{"out": "{\"key\": 1}"}') as x(out jsonb);
-- test type info caching in jsonb_populate_record() CREATE TEMP TABLE jsbpoptest (js jsonb);
SELECT (jsonb_populate_record(NULL::jsbrec, js)).* FROM jsbpoptest;
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; DROP DOMAIN jb_ordered_pair; DROP TYPE jb_unordered_pair;
-- indexing SELECT count(*) FROM testjsonb WHERE j @> '{"wait":null}'; SELECT count(*) FROM testjsonb WHERE j @> '{"wait":"CC"}'; SELECT count(*) FROM testjsonb WHERE j @> '{"wait":"CC", "public":true}'; SELECT count(*) FROM testjsonb WHERE j @> '{"age":25}'; SELECT count(*) FROM testjsonb WHERE j @> '{"age":25.0}'; SELECT count(*) FROM testjsonb WHERE j ? 'public'; SELECT count(*) FROM testjsonb WHERE j ? 'bar'; SELECT count(*) FROM testjsonb WHERE j ?| ARRAY['public','disabled']; SELECT count(*) FROM testjsonb WHERE j ?& ARRAY['public','disabled']; SELECT count(*) FROM testjsonb WHERE j @@ '$.wait == null'; SELECT count(*) FROM testjsonb WHERE j @@ '"CC" == $.wait'; SELECT count(*) FROM testjsonb WHERE j @@ '$.wait == "CC" && true == $.public'; SELECT count(*) FROM testjsonb WHERE j @@ '$.age == 25'; SELECT count(*) FROM testjsonb WHERE j @@ '$.age == 25.0'; SELECT count(*) FROM testjsonb WHERE j @@ 'exists($)'; SELECT count(*) FROM testjsonb WHERE j @@ 'exists($.public)'; SELECT count(*) FROM testjsonb WHERE j @@ 'exists($.bar)'; SELECT count(*) FROM testjsonb WHERE j @@ 'exists($.public) || exists($.disabled)'; SELECT count(*) FROM testjsonb WHERE j @@ 'exists($.public) && exists($.disabled)'; SELECT count(*) FROM testjsonb WHERE j @? '$.wait ? (@ == null)'; SELECT count(*) FROM testjsonb WHERE j @? '$.wait ? ("CC" == @)'; SELECT count(*) FROM testjsonb WHERE j @? '$ ? (@.wait == "CC" && true == @.public)'; SELECT count(*) FROM testjsonb WHERE j @? '$.age ? (@ == 25)'; SELECT count(*) FROM testjsonb WHERE j @? '$ ? (@.age == 25.0)'; SELECT count(*) FROM testjsonb WHERE j @? '$'; SELECT count(*) FROM testjsonb WHERE j @? '$.public'; SELECT count(*) FROM testjsonb WHERE j @? '$.bar';
ALTERTABLE testjsonb SET (parallel_workers = 2); CREATEINDEX jidx ON testjsonb USING gin (j); SET enable_seqscan = off;
SELECT count(*) FROM testjsonb WHERE j @> '{"wait":null}'; SELECT count(*) FROM testjsonb WHERE j @> '{"wait":"CC"}'; SELECT count(*) FROM testjsonb WHERE j @> '{"wait":"CC", "public":true}'; SELECT count(*) FROM testjsonb WHERE j @> '{"age":25}'; SELECT count(*) FROM testjsonb WHERE j @> '{"age":25.0}'; SELECT count(*) FROM testjsonb WHERE j @> '{"array":["foo"]}'; SELECT count(*) FROM testjsonb WHERE j @> '{"array":["bar"]}'; -- exercise GIN_SEARCH_MODE_ALL SELECT count(*) FROM testjsonb WHERE j @> '{}'; SELECT count(*) FROM testjsonb WHERE j ? 'public'; SELECT count(*) FROM testjsonb WHERE j ? 'bar'; SELECT count(*) FROM testjsonb WHERE j ?| ARRAY['public','disabled']; SELECT count(*) FROM testjsonb WHERE j ?& ARRAY['public','disabled'];
EXPLAIN (COSTS OFF) SELECT count(*) FROM testjsonb WHERE j @@ '$.wait == null'; SELECT count(*) FROM testjsonb WHERE j @@ '$.wait == null'; SELECT count(*) FROM testjsonb WHERE j @@ 'exists($ ? (@.wait == null))'; SELECT count(*) FROM testjsonb WHERE j @@ 'exists($.wait ? (@ == null))'; SELECT count(*) FROM testjsonb WHERE j @@ '"CC" == $.wait'; SELECT count(*) FROM testjsonb WHERE j @@ '$.wait == "CC" && true == $.public'; SELECT count(*) FROM testjsonb WHERE j @@ '$.age == 25'; SELECT count(*) FROM testjsonb WHERE j @@ '$.age == 25.0'; SELECT count(*) FROM testjsonb WHERE j @@ '$.array[*] == "foo"'; SELECT count(*) FROM testjsonb WHERE j @@ '$.array[*] == "bar"'; SELECT count(*) FROM testjsonb WHERE j @@ 'exists($ ? (@.array[*] == "bar"))'; SELECT count(*) FROM testjsonb WHERE j @@ 'exists($.array ? (@[*] == "bar"))'; SELECT count(*) FROM testjsonb WHERE j @@ 'exists($.array[*] ? (@ == "bar"))'; SELECT count(*) FROM testjsonb WHERE j @@ 'exists($)'; SELECT count(*) FROM testjsonb WHERE j @@ 'exists($.public)'; SELECT count(*) FROM testjsonb WHERE j @@ 'exists($.bar)'; SELECT count(*) FROM testjsonb WHERE j @@ 'exists($.public) || exists($.disabled)'; SELECT count(*) FROM testjsonb WHERE j @@ 'exists($.public) && exists($.disabled)'; EXPLAIN (COSTS OFF) SELECT count(*) FROM testjsonb WHERE j @? '$.wait ? (@ == null)'; SELECT count(*) FROM testjsonb WHERE j @? '$.wait ? (@ == null)'; SELECT count(*) FROM testjsonb WHERE j @? '$.wait ? ("CC" == @)'; SELECT count(*) FROM testjsonb WHERE j @? '$ ? (@.wait == "CC" && true == @.public)'; SELECT count(*) FROM testjsonb WHERE j @? '$.age ? (@ == 25)'; SELECT count(*) FROM testjsonb WHERE j @? '$ ? (@.age == 25.0)'; SELECT count(*) FROM testjsonb WHERE j @? '$ ? (@.array[*] == "bar")'; SELECT count(*) FROM testjsonb WHERE j @? '$.array ? (@[*] == "bar")'; SELECT count(*) FROM testjsonb WHERE j @? '$.array[*] ? (@ == "bar")'; SELECT count(*) FROM testjsonb WHERE j @? '$'; SELECT count(*) FROM testjsonb WHERE j @? '$.public'; SELECT count(*) FROM testjsonb WHERE j @? '$.bar';
-- array exists - array elements should behave as keys (for GIN index scans too) CREATEINDEX jidx_array ON testjsonb USING gin((j->'array')); SELECT count(*) from testjsonb WHERE j->'array' ? 'bar'; -- 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; -- However, a raw scalar is *contained* within the array SELECT count(*) from testjsonb WHERE j->'array' @> '5'::jsonb;
RESET enable_seqscan;
SELECT count(*) FROM (SELECT (jsonb_each(j)).keyFROM testjsonb) AS wow; SELECTkey, count(*) FROM (SELECT (jsonb_each(j)).keyFROM testjsonb) AS wow GROUPBYkeyORDERBY count DESC, key;
-- sort/hash SELECT count(distinct j) FROM testjsonb; SET enable_hashagg = off; SELECT count(*) FROM (SELECT j FROM (SELECT * FROM testjsonb UNIONALLSELECT * FROM testjsonb) js GROUPBY j) js2; SET enable_hashagg = on; SET enable_sort = off; SELECT count(*) FROM (SELECT j FROM (SELECT * FROM testjsonb UNIONALLSELECT * FROM testjsonb) js GROUPBY j) js2; SELECTdistinct * FROM (values (jsonb '{}' || ''::text),('{}')) v(j); SET enable_sort = on;
RESET enable_hashagg;
RESET enable_sort;
DROPINDEX jidx; DROPINDEX jidx_array; -- btree CREATEINDEX jidx ON testjsonb USING btree (j); SET enable_seqscan = off;
SELECT count(*) FROM testjsonb WHERE j > '{"p":1}'; SELECT count(*) FROM testjsonb WHERE j = '{"pos":98, "line":371, "node":"CBA", "indexed":true}';
--gin path opclass DROPINDEX jidx; CREATEINDEX CONCURRENTLY jidx ON testjsonb USING gin (j jsonb_path_ops); SET enable_seqscan = off;
SELECT count(*) FROM testjsonb WHERE j @> '{"wait":null}'; SELECT count(*) FROM testjsonb WHERE j @> '{"wait":"CC"}'; SELECT count(*) FROM testjsonb WHERE j @> '{"wait":"CC", "public":true}'; SELECT count(*) FROM testjsonb WHERE j @> '{"age":25}'; SELECT count(*) FROM testjsonb WHERE j @> '{"age":25.0}'; -- exercise GIN_SEARCH_MODE_ALL SELECT count(*) FROM testjsonb WHERE j @> '{}';
SELECT count(*) FROM testjsonb WHERE j @@ '$.wait == null'; SELECT count(*) FROM testjsonb WHERE j @@ 'exists($ ? (@.wait == null))'; SELECT count(*) FROM testjsonb WHERE j @@ 'exists($.wait ? (@ == null))'; SELECT count(*) FROM testjsonb WHERE j @@ '"CC" == $.wait'; SELECT count(*) FROM testjsonb WHERE j @@ '$.wait == "CC" && true == $.public'; SELECT count(*) FROM testjsonb WHERE j @@ '$.age == 25'; SELECT count(*) FROM testjsonb WHERE j @@ '$.age == 25.0'; SELECT count(*) FROM testjsonb WHERE j @@ '$.array[*] == "foo"'; SELECT count(*) FROM testjsonb WHERE j @@ '$.array[*] == "bar"'; SELECT count(*) FROM testjsonb WHERE j @@ 'exists($ ? (@.array[*] == "bar"))'; SELECT count(*) FROM testjsonb WHERE j @@ 'exists($.array ? (@[*] == "bar"))'; SELECT count(*) FROM testjsonb WHERE j @@ 'exists($.array[*] ? (@ == "bar"))'; SELECT count(*) FROM testjsonb WHERE j @@ 'exists($)';
EXPLAIN (COSTS OFF) SELECT count(*) FROM testjsonb WHERE j @? '$.wait ? (@ == null)'; SELECT count(*) FROM testjsonb WHERE j @? '$.wait ? (@ == null)'; SELECT count(*) FROM testjsonb WHERE j @? '$.wait ? ("CC" == @)'; SELECT count(*) FROM testjsonb WHERE j @? '$ ? (@.wait == "CC" && true == @.public)'; SELECT count(*) FROM testjsonb WHERE j @? '$.age ? (@ == 25)'; SELECT count(*) FROM testjsonb WHERE j @? '$ ? (@.age == 25.0)'; SELECT count(*) FROM testjsonb WHERE j @? '$ ? (@.array[*] == "bar")'; SELECT count(*) FROM testjsonb WHERE j @? '$.array ? (@[*] == "bar")'; SELECT count(*) FROM testjsonb WHERE j @? '$.array[*] ? (@ == "bar")'; SELECT count(*) FROM testjsonb WHERE j @? '$'; SELECT count(*) FROM testjsonb WHERE j @? '$.public'; SELECT count(*) FROM testjsonb WHERE j @? '$.bar';
set enable_seqscan = on; set enable_bitmapscan = off; select * from nestjsonb where j @> '{"a":[[{"x":2}]]}'::jsonb; select * from nestjsonb where j @> '{"c":3}'; select * from nestjsonb where j @> '[[14]]'; set enable_seqscan = off; set enable_bitmapscan = on; select * from nestjsonb where j @> '{"a":[[{"x":2}]]}'::jsonb; select * from nestjsonb where j @> '{"c":3}'; select * from nestjsonb where j @> '[[14]]';
reset enable_seqscan;
reset enable_bitmapscan;
-- 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"'); select jsonb_insert('{"a": {"b": "value"}}', '{a, c}', '"new_value"', true);
create TEMP TABLE test_jsonb_subscript (
id int,
test_json jsonb
);
insertinto 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;
-- update jsonb with some data update test_jsonb_subscript set test_json['a'] = '1'where id = 2; select * from test_jsonb_subscript;
-- replace jsonb update test_jsonb_subscript set test_json['a'] = '"test"'; select * from test_jsonb_subscript;
-- replace by object update test_jsonb_subscript set test_json['a'] = '{"b": 1}'::jsonb; select * from test_jsonb_subscript;
-- replace by array update test_jsonb_subscript set test_json['a'] = '[1, 2, 3]'::jsonb; select * from test_jsonb_subscript;
-- use jsonb subscription in where clause select * from test_jsonb_subscript where test_json['key'] = '"value"'; select * from test_jsonb_subscript where test_json['key_doesnt_exists'] = '"value"'; select * from test_jsonb_subscript where test_json['key'] = '"wrong_value"';
-- NULL update test_jsonb_subscript set test_json[NULL] = '1'; update test_jsonb_subscript set test_json['another_key'] = NULL; select * from test_jsonb_subscript;
-- NULL as jsonb source insertinto test_jsonb_subscript values (3, NULL); update test_jsonb_subscript set test_json['a'] = '1'where id = 3; select * from test_jsonb_subscript;
update test_jsonb_subscript set test_json = NULLwhere id = 3; update test_jsonb_subscript set test_json[0] = '1'; select * from test_jsonb_subscript;
-- Fill the gaps logic deletefrom test_jsonb_subscript; insertinto test_jsonb_subscript values (1, '[0]');
update test_jsonb_subscript set test_json[5] = '1'; select * from test_jsonb_subscript;
update test_jsonb_subscript set test_json[-4] = '1'; select * from test_jsonb_subscript;
update test_jsonb_subscript set test_json[-8] = '1'; select * from test_jsonb_subscript;
update test_jsonb_subscript set test_json[5] = '1'; select * from test_jsonb_subscript;
-- create the whole path deletefrom test_jsonb_subscript; insertinto test_jsonb_subscript values (1, '{}'); update test_jsonb_subscript set test_json['a'][0]['b'][0]['c'] = '1'; select * from test_jsonb_subscript;
deletefrom test_jsonb_subscript; insertinto test_jsonb_subscript values (1, '{}'); update test_jsonb_subscript set test_json['a'][2]['b'][2]['c'][2] = '1'; select * from test_jsonb_subscript;
-- create the whole path with already existing keys deletefrom test_jsonb_subscript; insertinto test_jsonb_subscript values (1, '{"b": 1}'); update test_jsonb_subscript set test_json['a'][0] = '2'; select * from test_jsonb_subscript;
-- the start jsonb is an object, first subscript is treated as a key deletefrom test_jsonb_subscript; insertinto test_jsonb_subscript values (1, '{}'); update test_jsonb_subscript set test_json[0]['a'] = '1'; select * from test_jsonb_subscript;
-- the start jsonb is an array deletefrom test_jsonb_subscript; insertinto 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;
-- overwriting an existing path deletefrom test_jsonb_subscript; insertinto 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;
deletefrom test_jsonb_subscript; insertinto 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;
deletefrom test_jsonb_subscript; insertinto 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;
-- an empty sub element
deletefrom test_jsonb_subscript; insertinto test_jsonb_subscript values (1, '{"a": {}}'); update test_jsonb_subscript set test_json['a']['b']['c'][2] = '1'; select * from test_jsonb_subscript;
deletefrom test_jsonb_subscript; insertinto test_jsonb_subscript values (1, '{"a": []}'); update test_jsonb_subscript set test_json['a'][1]['c'][2] = '1'; select * from test_jsonb_subscript;
-- trying replace assuming a composite object, but it's an element or a value
deletefrom test_jsonb_subscript; insertinto test_jsonb_subscript values (1, '{"a": 1}'); update test_jsonb_subscript set test_json['a']['b'] = '1'; update test_jsonb_subscript set test_json['a']['b']['c'] = '1'; update test_jsonb_subscript set test_json['a'][0] = '1'; update test_jsonb_subscript set test_json['a'][0]['c'] = '1'; update test_jsonb_subscript set test_json['a'][0][0] = '1';
-- trying replace assuming a composite object, but it's a raw scalar
deletefrom test_jsonb_subscript; insertinto test_jsonb_subscript values (1, 'null'); update test_jsonb_subscript set test_json[0] = '1'; update test_jsonb_subscript set test_json[0][0] = '1';
-- try some things with short-header and toasted subscript values
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.