parent = stack;
stack = (PathHashStack *) palloc(sizeof(PathHashStack));
- if (parent->parent)
- {
- /*
- * We pass forward hashes from previous container nesting
- * levels so that nested arrays with an outermost nested
- * object will have element hashes mixed with the
- * outermost key. It's also somewhat useful to have
- * nested objects' innermost values have hashes that are a
- * function of not just their own key, but outer keys too.
- *
- * Nesting an array within another array will not alter
- * innermost scalar element hash values, but that seems
- * inconsequential.
- */
- stack->hash = parent->hash;
- }
- else
- {
- /*
- * At the outermost level, initialize hash with container
- * type proxy value. Note that this makes JB_FARRAY and
- * JB_FOBJECT part of the on-disk representation, but they
- * are that in the base jsonb object storage already.
- */
- stack->hash = (r == WJB_BEGIN_ARRAY) ? JB_FARRAY : JB_FOBJECT;
- }
+ /*
+ * We pass forward hashes from outer nesting levels so that
+ * the hashes for nested values will include outer keys as
+ * well as their own keys.
+ *
+ * Nesting an array within another array will not alter
+ * innermost scalar element hash values, but that seems
+ * inconsequential.
+ */
+ stack->hash = parent->hash;
stack->parent = parent;
break;
case WJB_KEY:
- /* initialize hash from parent */
- stack->hash = stack->parent->hash;
- /* and mix in this key */
+ /* mix this key into the current outer hash */
JsonbHashScalarValue(&v, &stack->hash);
/* hash is now ready to incorporate the value */
break;
case WJB_ELEM:
- /* array elements use parent hash mixed with element's hash */
- stack->hash = stack->parent->hash;
- /* FALL THRU */
case WJB_VALUE:
/* mix the element or value's hash into the prepared hash */
JsonbHashScalarValue(&v, &stack->hash);
/* and emit an index entry */
entries[i++] = UInt32GetDatum(stack->hash);
- /* Note: we assume we'll see KEY before another VALUE */
+ /* reset hash for next key, value, or sub-object */
+ stack->hash = stack->parent->hash;
break;
case WJB_END_ARRAY:
case WJB_END_OBJECT:
parent = stack->parent;
pfree(stack);
stack = parent;
+ /* reset hash for next key, value, or sub-object */
+ if (stack->parent)
+ stack->hash = stack->parent->hash;
+ else
+ stack->hash = 0;
break;
default:
elog(ERROR, "invalid JsonbIteratorNext rc: %d", (int) r);
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);
+set enable_seqscan = on;
+set enable_bitmapscan = off;
+select * from nestjsonb where j @> '{"a":[[{"x":2}]]}'::jsonb;
+ j
+---------------------------------------------------
+ {"a": [["b", {"x": 1}], ["b", {"x": 2}]], "c": 3}
+(1 row)
+
+select * from nestjsonb where j @> '{"c":3}';
+ j
+---------------------------------------------------
+ {"a": [["b", {"x": 1}], ["b", {"x": 2}]], "c": 3}
+(1 row)
+
+select * from nestjsonb where j @> '[[14]]';
+ j
+-----------------
+ [[14, 2, 3]]
+ [1, [14, 2, 3]]
+(2 rows)
+
+set enable_seqscan = off;
+set enable_bitmapscan = on;
+select * from nestjsonb where j @> '{"a":[[{"x":2}]]}'::jsonb;
+ j
+---------------------------------------------------
+ {"a": [["b", {"x": 1}], ["b", {"x": 2}]], "c": 3}
+(1 row)
+
+select * from nestjsonb where j @> '{"c":3}';
+ j
+---------------------------------------------------
+ {"a": [["b", {"x": 1}], ["b", {"x": 2}]], "c": 3}
+(1 row)
+
+select * from nestjsonb where j @> '[[14]]';
+ j
+-----------------
+ [[14, 2, 3]]
+ [1, [14, 2, 3]]
+(2 rows)
+
+reset enable_seqscan;
+reset enable_bitmapscan;
-- nested object field / array index lookup
SELECT '{"n":null,"a":1,"b":[1,2],"c":{"1":2},"d":{"1":[2,3]}}'::jsonb -> 'n';
?column?
SELECT '{"a":[1,2,{"c":3,"x":4}],"c":"b"}'::jsonb @> '{"a":[{"x":4},3]}';
SELECT '{"a":[1,2,{"c":3,"x":4}],"c":"b"}'::jsonb @> '{"a":[{"x":4},1]}';
+-- check some corner cases for indexed nested containment (bug #13756)
+create temp table nestjsonb (j jsonb);
+insert into nestjsonb (j) values ('{"a":[["b",{"x":1}],["b",{"x":2}]],"c":3}');
+insert into nestjsonb (j) values ('[[14,2,3]]');
+insert into nestjsonb (j) values ('[1,[14,2,3]]');
+create index on nestjsonb using gin(j jsonb_path_ops);
+
+set enable_seqscan = on;
+set enable_bitmapscan = off;
+select * from nestjsonb where j @> '{"a":[[{"x":2}]]}'::jsonb;
+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;
+
-- nested object field / array index lookup
SELECT '{"n":null,"a":1,"b":[1,2],"c":{"1":2},"d":{"1":[2,3]}}'::jsonb -> 'n';
SELECT '{"n":null,"a":1,"b":[1,2],"c":{"1":2},"d":{"1":[2,3]}}'::jsonb -> 'a';