aboutsummaryrefslogtreecommitdiffstats
path: root/yql/essentials/tests/postgresql/cases/jsonb.out
diff options
context:
space:
mode:
authorMaxim Yurchuk <maxim-yurchuk@ydb.tech>2024-11-20 17:37:57 +0000
committerGitHub <noreply@github.com>2024-11-20 17:37:57 +0000
commitf76323e9b295c15751e51e3443aa47a36bee8023 (patch)
tree4113c8cad473a33e0f746966e0cf087252fa1d7a /yql/essentials/tests/postgresql/cases/jsonb.out
parent753ecb8d410a4cb459c26f3a0082fb2d1724fe63 (diff)
parenta7b9a6afea2a9d7a7bfac4c5eb4c1a8e60adb9e6 (diff)
downloadydb-f76323e9b295c15751e51e3443aa47a36bee8023.tar.gz
Merge pull request #11788 from ydb-platform/mergelibs-241120-1113
Library import 241120-1113
Diffstat (limited to 'yql/essentials/tests/postgresql/cases/jsonb.out')
-rw-r--r--yql/essentials/tests/postgresql/cases/jsonb.out2987
1 files changed, 2987 insertions, 0 deletions
diff --git a/yql/essentials/tests/postgresql/cases/jsonb.out b/yql/essentials/tests/postgresql/cases/jsonb.out
new file mode 100644
index 0000000000..e5f5749055
--- /dev/null
+++ b/yql/essentials/tests/postgresql/cases/jsonb.out
@@ -0,0 +1,2987 @@
+-- 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...
+-- see json_encoding test for input with unicode escapes
+-- 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 '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 '[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...
+-- 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:
+-- 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
+-- 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)
+
+BEGIN;
+SET LOCAL TIME ZONE 10.5;
+SET LOCAL TIME ZONE -8;
+COMMIT;
+-- 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';
+ ?column?
+----------
+
+(1 row)
+
+SELECT test_json -> 'x' FROM test_jsonb WHERE json_type = 'array';
+ ?column?
+----------
+
+(1 row)
+
+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';
+ ?column?
+----------
+
+(1 row)
+
+SELECT test_json ->> 'field2' FROM test_jsonb WHERE json_type = 'array';
+ ?column?
+----------
+
+(1 row)
+
+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';
+ ?column?
+----------
+
+(1 row)
+
+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';
+ ?column?
+----------
+
+(1 row)
+
+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';
+ ?column?
+----------
+
+(1 row)
+
+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';
+ ?column?
+----------
+
+(1 row)
+
+-- 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)
+
+-- 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;
+ ?column?
+----------
+
+(1 row)
+
+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';
+ ?column?
+----------
+
+(1 row)
+
+select '{"a": "c", "b": null}'::jsonb -> 'b';
+ ?column?
+----------
+ null
+(1 row)
+
+select '"foo"'::jsonb -> 1;
+ ?column?
+----------
+
+(1 row)
+
+select '"foo"'::jsonb -> 'z';
+ ?column?
+----------
+
+(1 row)
+
+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;
+ ?column?
+----------
+
+(1 row)
+
+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';
+ ?column?
+----------
+
+(1 row)
+
+select '{"a": "c", "b": null}'::jsonb ->> 'b';
+ ?column?
+----------
+
+(1 row)
+
+select '"foo"'::jsonb ->> 1;
+ ?column?
+----------
+
+(1 row)
+
+select '"foo"'::jsonb ->> 'z';
+ ?column?
+----------
+
+(1 row)
+
+-- 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)
+
+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)
+
+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
+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 * 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)
+
+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
+-- 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)
+
+SELECT jsonb_build_object(r,2) FROM (SELECT 1 AS a, 2 AS b) r;
+ERROR: key value must be scalar, not array, composite, or json
+SELECT jsonb_build_object(json '{"a":1,"b":2}', 3);
+ERROR: key value must be scalar, not array, composite, or json
+SELECT jsonb_build_object('{1,2,3}'::int[], 3);
+ERROR: key value must be scalar, not array, composite, or json
+-- 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
+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_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
+-- jsonb_object
+-- empty object, one dimension
+SELECT jsonb_object('{}');
+ jsonb_object
+--------------
+ {}
+(1 row)
+
+-- empty object, two dimensions
+SELECT jsonb_object('{}', '{}');
+ jsonb_object
+--------------
+ {}
+(1 row)
+
+-- 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)
+
+-- 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)
+
+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 * 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)
+
+-- 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);
+-- 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)
+
+SELECT count(*) FROM testjsonb WHERE j ? 'bar';
+ count
+-------
+ 0
+(1 row)
+
+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)
+
+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)
+
+CREATE INDEX jidx ON testjsonb USING gin (j);
+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)
+
+-- exercise GIN_SEARCH_MODE_ALL
+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)
+
+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)
+
+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)
+
+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)
+
+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)
+
+-- btree
+CREATE INDEX jidx ON testjsonb USING btree (j);
+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)
+
+CREATE INDEX jidx ON testjsonb USING gin (j jsonb_path_ops);
+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)
+
+-- exercise GIN_SEARCH_MODE_ALL
+SELECT count(*) FROM testjsonb WHERE j @> '{}';
+ count
+-------
+ 1012
+(1 row)
+
+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 @? '$.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)
+
+-- 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 '{"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)
+
+-- 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);
+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)
+
+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)
+
+-- 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
+ ?column?
+----------
+
+(1 row)
+
+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?
+----------
+ 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?
+----------
+
+(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)
+
+-- 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)
+
+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)
+
+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)
+
+select '"a"'::jsonb || '{"a":1}';
+ ?column?
+-----------------
+ ["a", {"a": 1}]
+(1 row)
+
+select '{"a":1}' || '"a"'::jsonb;
+ ?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)
+
+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)
+
+select '{"a":1 , "b":2, "c":3}'::jsonb - 'a';
+ ?column?
+------------------
+ {"b": 2, "c": 3}
+(1 row)
+
+select '{"a":null , "b":2, "c":3}'::jsonb - 'a';
+ ?column?
+------------------
+ {"b": 2, "c": 3}
+(1 row)
+
+select '{"a":1 , "b":2, "c":3}'::jsonb - 'b';
+ ?column?
+------------------
+ {"a": 1, "c": 3}
+(1 row)
+
+select '{"a":1 , "b":2, "c":3}'::jsonb - 'c';
+ ?column?
+------------------
+ {"a": 1, "b": 2}
+(1 row)
+
+select '{"a":1 , "b":2, "c":3}'::jsonb - 'd';
+ ?column?
+--------------------------
+ {"a": 1, "b": 2, "c": 3}
+(1 row)
+
+select pg_column_size('{"a":1 , "b":2, "c":3}'::jsonb - 'b') = pg_column_size('{"a":1, "b":2}'::jsonb);
+ ?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)
+
+select jsonb_delete_path('{"n":null, "a":1, "b":[1,2], "c":{"1":2}, "d":{"1":[2,3]}}', '{n}');
+ jsonb_delete_path
+----------------------------------------------------------
+ {"a": 1, "b": [1, 2], "c": {"1": 2}, "d": {"1": [2, 3]}}
+(1 row)
+
+select jsonb_delete_path('{"n":null, "a":1, "b":[1,2], "c":{"1":2}, "d":{"1":[2,3]}}', '{b,-1}');
+ jsonb_delete_path
+------------------------------------------------------------------
+ {"a": 1, "b": [1], "c": {"1": 2}, "d": {"1": [2, 3]}, "n": null}
+(1 row)
+
+select jsonb_delete_path('{"n":null, "a":1, "b":[1,2], "c":{"1":2}, "d":{"1":[2,3]}}', '{d,1,0}');
+ jsonb_delete_path
+------------------------------------------------------------------
+ {"a": 1, "b": [1, 2], "c": {"1": 2}, "d": {"1": [3]}, "n": null}
+(1 row)
+
+select '{"n":null, "a":1, "b":[1,2], "c":{"1":2}, "d":{"1":[2,3]}}'::jsonb #- '{n}';
+ ?column?
+----------------------------------------------------------
+ {"a": 1, "b": [1, 2], "c": {"1": 2}, "d": {"1": [2, 3]}}
+(1 row)
+
+select '{"n":null, "a":1, "b":[1,2], "c":{"1":2}, "d":{"1":[2,3]}}'::jsonb #- '{b,-1}';
+ ?column?
+------------------------------------------------------------------
+ {"a": 1, "b": [1], "c": {"1": 2}, "d": {"1": [2, 3]}, "n": null}
+(1 row)
+
+select '{"n":null, "a":1, "b":[1,2], "c":{"1":2}, "d":{"1":[2,3]}}'::jsonb #- '{b,-1e}'; -- invalid array subscript
+ERROR: path element at position 2 is not an integer: "-1e"
+select '{"n":null, "a":1, "b":[1,2], "c":{"1":2}, "d":{"1":[2,3]}}'::jsonb #- '{d,1,0}';
+ ?column?
+------------------------------------------------------------------
+ {"a": 1, "b": [1, 2], "c": {"1": 2}, "d": {"1": [3]}, "n": null}
+(1 row)
+
+-- 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
+select '{}'::jsonb - 1; -- error
+ERROR: cannot delete from object using integer index
+select '[]'::jsonb - 1;
+ ?column?
+----------
+ []
+(1 row)
+
+select '"a"'::jsonb #- '{a}'; -- error
+ERROR: cannot delete path in scalar
+select '{}'::jsonb #- '{a}';
+ ?column?
+----------
+ {}
+(1 row)
+
+select '[]'::jsonb #- '{a}';
+ ?column?
+----------
+ []
+(1 row)
+
+select jsonb_set('{}','{a}','"b"', false);
+ jsonb_set
+-----------
+ {}
+(1 row)
+
+select jsonb_set('[]','{1}','"b"', false);
+ jsonb_set
+-----------
+ []
+(1 row)
+
+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)
+
+-- jsonb_set_lax
+\pset null NULL
+-- errors
+select jsonb_set_lax('{"a":1,"b":2}', '{b}', null, true, null);
+ERROR: null_value_treatment must be "delete_key", "return_target", "use_json_null", or "raise_exception"
+select jsonb_set_lax('{"a":1,"b":2}', '{b}', null, true, 'no_such_treatment');
+ERROR: null_value_treatment must be "delete_key", "return_target", "use_json_null", or "raise_exception"
+\pset null ''
+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"', true);
+ jsonb_insert
+------------------------------------------------------------
+ {"a": {"b": {"c": [0, 1, "test1", "new_value", "test2"]}}}
+(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"', true);
+ jsonb_insert
+-------------------------------
+ {"a": [0, 1, 2, "new_value"]}
+(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"', true);
+ jsonb_insert
+---------------
+ ["new_value"]
+(1 row)
+
+select jsonb_insert('{"a": []}', '{a, 1}', '"new_value"', true);
+ jsonb_insert
+----------------------
+ {"a": ["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"', true);
+ERROR: cannot replace existing key
+HINT: Try using the function jsonb_set to replace key value.
+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
+-- NULL as jsonb source
+insert into test_jsonb_subscript values (3, NULL);
+insert into test_jsonb_subscript values (1, '[0]');
+insert into test_jsonb_subscript values (1, '[]');
+insert into test_jsonb_subscript values (1, '{}');
+insert into test_jsonb_subscript values (1, '{}');
+insert into test_jsonb_subscript values (1, '{"b": 1}');
+insert into test_jsonb_subscript values (1, '{}');
+insert into test_jsonb_subscript values (1, '[]');
+insert into test_jsonb_subscript values (1, '{}');
+insert into test_jsonb_subscript values (1, '[]');
+insert into test_jsonb_subscript values (1, '{}');
+insert into test_jsonb_subscript values (1, '{"a": {}}');
+insert into test_jsonb_subscript values (1, '{"a": []}');
+insert into test_jsonb_subscript values (1, '{"a": 1}');
+insert into test_jsonb_subscript values (1, 'null');
+-- casts
+select 'true'::jsonb::bool;
+ bool
+------
+ t
+(1 row)
+
+select '[]'::jsonb::bool;
+ERROR: cannot cast jsonb array to type boolean
+select '1.0'::jsonb::float;
+ float8
+--------
+ 1
+(1 row)
+
+select '[1.0]'::jsonb::float;
+ERROR: cannot cast jsonb array to type double precision
+select '12345'::jsonb::int4;
+ int4
+-------
+ 12345
+(1 row)
+
+select '"hello"'::jsonb::int4;
+ERROR: cannot cast jsonb string to type integer
+select '12345'::jsonb::numeric;
+ numeric
+---------
+ 12345
+(1 row)
+
+select '{}'::jsonb::numeric;
+ERROR: cannot cast jsonb object to type numeric
+select '12345.05'::jsonb::numeric;
+ numeric
+----------
+ 12345.05
+(1 row)
+
+select '12345.05'::jsonb::float4;
+ float4
+----------
+ 12345.05
+(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)
+