index 71179f655182bdfab0e56c215f6660ce79db1b6c..f303860fdbb98948cb0663fda7dfd7cd0590d636 100644 (file)
@@ -2075,8 +2075,10 @@ populate_record_worker(FunctionCallInfo fcinfo, bool have_record_arg)
* with domain nulls.
*/
if (hash_get_num_entries(json_hash) == 0 && rec)
+ {
+ hash_destroy(json_hash);
PG_RETURN_POINTER(rec);
-
+ }
}
else
{
@@ -2250,6 +2252,9 @@ populate_record_worker(FunctionCallInfo fcinfo, bool have_record_arg)
ReleaseTupleDesc(tupdesc);
+ if (json_hash)
+ hash_destroy(json_hash);
+
PG_RETURN_DATUM(HeapTupleGetDatum(rettuple));
}
int lex_level = _state->lex->lex_level;
HASHCTL ctl;
+ /* Reject object at top level: we must have an array at level 0 */
if (lex_level == 0)
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("cannot call json_populate_recordset on an object")));
- else if (lex_level > 1 && !_state->use_json_as_text)
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("cannot call json_populate_recordset with nested objects")));
- /* set up a new hash for this entry */
+ /* Nested objects, if allowed, require no special processing */
+ if (lex_level > 1)
+ {
+ if (!_state->use_json_as_text)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("cannot call json_populate_recordset with nested objects")));
+ return;
+ }
+
+ /* Object at level 1: set up a new hash table for this object */
memset(&ctl, 0, sizeof(ctl));
ctl.keysize = NAMEDATALEN;
ctl.entrysize = sizeof(JsonHashEntry);
HeapTupleHeader rec = _state->rec;
HeapTuple rettuple;
+ /* Nested objects require no special processing */
if (_state->lex->lex_level > 1)
return;
+ /* Otherwise, construct and return a tuple based on this level-1 object */
values = (Datum *) palloc(ncolumns * sizeof(Datum));
nulls = (bool *) palloc(ncolumns * sizeof(bool));
tuplestore_puttuple(_state->tuple_store, rettuple);
+ /* Done with hash for this object */
hash_destroy(json_hash);
+ _state->json_hash = NULL;
}
static void
index 8b8556b2e04cc89b29c84d3d8a64f0b3d41aa435..d1e32a19a52891dee8e2f5aaf500b40006fc11b2 100644 (file)
@@ -1007,6 +1007,13 @@ select * from json_populate_recordset(row('def',99,null)::jpop,'[{"a":[100,200,3
select * from json_populate_recordset(row('def',99,null)::jpop,'[{"c":[100,200,300],"x":43.2},{"a":{"z":true},"b":3,"c":"2012年01月20日 10:42:53"}]',true) q;
ERROR: invalid input syntax for type timestamp: "[100,200,300]"
+create type jpop2 as (a int, b json, c int, d int);
+select * from json_populate_recordset(null::jpop2, '[{"a":2,"c":3,"b":{"z":4},"d":6}]',true) q;
+ a | b | c | d
+---+---------+---+---
+ 2 | {"z":4} | 3 | 6
+(1 row)
+
-- using the default use_json_as_text argument
select * from json_populate_recordset(null::jpop,'[{"a":"blurfl","x":43.2},{"b":3,"c":"2012年01月20日 10:42:53"}]') q;
a | b | c
@@ -1223,3 +1230,11 @@ select * from json_to_recordset('[{"a":1,"b":"foo","d":false},{"a":2,"b":"bar","
2 | bar | t
(2 rows)
+select * from json_to_recordset('[{"a":1,"b":{"d":"foo"},"c":true},{"a":2,"c":false,"b":{"d":"bar"}}]', true)
+ as x(a int, b json, c boolean);
+ a | b | c
+---+-------------+---
+ 1 | {"d":"foo"} | t
+ 2 | {"d":"bar"} | f
+(2 rows)
+
index b32c3ed09f37586f5ab005c1032bfd03a4313d3a..93cb693b2fbdec2bab654fbfdaf0e26d50cde51e 100644 (file)
@@ -1007,6 +1007,13 @@ select * from json_populate_recordset(row('def',99,null)::jpop,'[{"a":[100,200,3
select * from json_populate_recordset(row('def',99,null)::jpop,'[{"c":[100,200,300],"x":43.2},{"a":{"z":true},"b":3,"c":"2012年01月20日 10:42:53"}]',true) q;
ERROR: invalid input syntax for type timestamp: "[100,200,300]"
+create type jpop2 as (a int, b json, c int, d int);
+select * from json_populate_recordset(null::jpop2, '[{"a":2,"c":3,"b":{"z":4},"d":6}]',true) q;
+ a | b | c | d
+---+---------+---+---
+ 2 | {"z":4} | 3 | 6
+(1 row)
+
-- using the default use_json_as_text argument
select * from json_populate_recordset(null::jpop,'[{"a":"blurfl","x":43.2},{"b":3,"c":"2012年01月20日 10:42:53"}]') q;
a | b | c
@@ -1219,3 +1226,11 @@ select * from json_to_recordset('[{"a":1,"b":"foo","d":false},{"a":2,"b":"bar","
2 | bar | t
(2 rows)
+select * from json_to_recordset('[{"a":1,"b":{"d":"foo"},"c":true},{"a":2,"c":false,"b":{"d":"bar"}}]', true)
+ as x(a int, b json, c boolean);
+ a | b | c
+---+-------------+---
+ 1 | {"d":"foo"} | t
+ 2 | {"d":"bar"} | f
+(2 rows)
+
index 3d5ed50126e83bd28defb25f0748cafc26a1ff3b..bc8bb62978155f672b5ab4fafd69d7cbd74869e1 100644 (file)
@@ -325,6 +325,9 @@ select * from json_populate_recordset(row('def',99,null)::jpop,'[{"a":"blurfl","
select * from json_populate_recordset(row('def',99,null)::jpop,'[{"a":[100,200,300],"x":43.2},{"a":{"z":true},"b":3,"c":"2012年01月20日 10:42:53"}]',true) q;
select * from json_populate_recordset(row('def',99,null)::jpop,'[{"c":[100,200,300],"x":43.2},{"a":{"z":true},"b":3,"c":"2012年01月20日 10:42:53"}]',true) q;
+create type jpop2 as (a int, b json, c int, d int);
+select * from json_populate_recordset(null::jpop2, '[{"a":2,"c":3,"b":{"z":4},"d":6}]',true) q;
+
-- using the default use_json_as_text argument
select * from json_populate_recordset(null::jpop,'[{"a":"blurfl","x":43.2},{"b":3,"c":"2012年01月20日 10:42:53"}]') q;
@@ -447,3 +450,6 @@ select * from json_to_record('{"a":1,"b":"foo","c":"bar"}',true)
select * from json_to_recordset('[{"a":1,"b":"foo","d":false},{"a":2,"b":"bar","c":true}]',false)
as x(a int, b text, c boolean);
+
+select * from json_to_recordset('[{"a":1,"b":{"d":"foo"},"c":true},{"a":2,"c":false,"b":{"d":"bar"}}]', true)
+ as x(a int, b json, c boolean);