Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit a749a23

Browse files
committed
Remove use_json_as_text options from json_to_record/json_populate_record.
The "false" case was really quite useless since all it did was to throw an error; a definition not helped in the least by making it the default. Instead let's just have the "true" case, which emits nested objects and arrays in JSON syntax. We might later want to provide the ability to emit sub-objects in Postgres record or array syntax, but we'd be best off to drive that off a check of the target field datatype, not a separate argument. For the functions newly added in 9.4, we can just remove the flag arguments outright. We can't do that for json_populate_record[set], which already existed in 9.3, but we can ignore the argument and always behave as if it were "true". It helps that the flag arguments were optional and not documented in any useful fashion anyway.
1 parent 51adcaa commit a749a23

File tree

11 files changed

+136
-205
lines changed

11 files changed

+136
-205
lines changed

doc/src/sgml/func.sgml

+12-14
Original file line numberDiff line numberDiff line change
@@ -10562,8 +10562,8 @@ table2-mapping
1056210562
</entry>
1056310563
</row>
1056410564
<row>
10565-
<entry><para><literal>json_populate_record(base anyelement, from_json json, [, use_json_as_text bool=false])</literal>
10566-
</para><para><literal>jsonb_populate_record(base anyelement, from_json jsonb, [, use_json_as_text bool=false])</literal>
10565+
<entry><para><literal>json_populate_record(base anyelement, from_json json)</literal>
10566+
</para><para><literal>jsonb_populate_record(base anyelement, from_json jsonb)</literal>
1056710567
</para></entry>
1056810568
<entry><type>anyelement</type></entry>
1056910569
<entry>
@@ -10581,8 +10581,8 @@ table2-mapping
1058110581
</entry>
1058210582
</row>
1058310583
<row>
10584-
<entry><para><literal>json_populate_recordset(base anyelement, from_json json, [, use_json_as_text bool=false])</literal>
10585-
</para><para><literal>jsonb_populate_recordset(base anyelement, from_json jsonb, [, use_json_as_text bool=false])</literal>
10584+
<entry><para><literal>json_populate_recordset(base anyelement, from_json json)</literal>
10585+
</para><para><literal>jsonb_populate_recordset(base anyelement, from_json jsonb)</literal>
1058610586
</para></entry>
1058710587
<entry><type>setof anyelement</type></entry>
1058810588
<entry>
@@ -10655,18 +10655,17 @@ table2-mapping
1065510655
<entry><literal>number</literal></entry>
1065610656
</row>
1065710657
<row>
10658-
<entry><para><literal>json_to_record(json [, nested_as_text bool=false])</literal>
10659-
</para><para><literal>jsonb_to_record(jsonb [, nested_as_text bool=false])</literal>
10658+
<entry><para><literal>json_to_record(json)</literal>
10659+
</para><para><literal>jsonb_to_record(jsonb)</literal>
1066010660
</para></entry>
1066110661
<entry><type>record</type></entry>
1066210662
<entry>
1066310663
Builds an arbitrary record from a JSON object (see note below). As
1066410664
with all functions returning <type>record</>, the caller must
1066510665
explicitly define the structure of the record with an <literal>AS</>
10666-
clause. If <replaceable>nested_as_text</> is true, the function
10667-
coerces nested complex elements to text.
10666+
clause.
1066810667
</entry>
10669-
<entry><literal>select * from json_to_record('{"a":1,"b":[1,2,3],"c":"bar"}',true) as x(a int, b text, d text) </literal></entry>
10668+
<entry><literal>select * from json_to_record('{"a":1,"b":[1,2,3],"c":"bar"}') as x(a int, b text, d text) </literal></entry>
1067010669
<entry>
1067110670
<programlisting>
1067210671
a | b | d
@@ -10676,18 +10675,17 @@ table2-mapping
1067610675
</entry>
1067710676
</row>
1067810677
<row>
10679-
<entry><para><literal>json_to_recordset(json [, nested_as_text bool=false])</literal>
10680-
</para><para><literal>jsonb_to_recordset(jsonb [, nested_as_text bool=false])</literal>
10678+
<entry><para><literal>json_to_recordset(json)</literal>
10679+
</para><para><literal>jsonb_to_recordset(jsonb)</literal>
1068110680
</para></entry>
1068210681
<entry><type>setof record</type></entry>
1068310682
<entry>
1068410683
Builds an arbitrary set of records from a JSON array of objects (see
1068510684
note below). As with all functions returning <type>record</>, the
1068610685
caller must explicitly define the structure of the record with
10687-
an <literal>AS</> clause. <replaceable>nested_as_text</> works as
10688-
with <function>json_to_record</>.
10686+
an <literal>AS</> clause.
1068910687
</entry>
10690-
<entry><literal>select * from json_to_recordset('[{"a":1,"b":"foo"},{"a":"2","c":"bar"}]',true) as x(a int, b text);</literal></entry>
10688+
<entry><literal>select * from json_to_recordset('[{"a":1,"b":"foo"},{"a":"2","c":"bar"}]') as x(a int, b text);</literal></entry>
1069110689
<entry>
1069210690
<programlisting>
1069310691
a | b

src/backend/catalog/system_views.sql

+2-24
Original file line numberDiff line numberDiff line change
@@ -817,38 +817,16 @@ CREATE OR REPLACE FUNCTION
817817
pg_start_backup(label text, fast boolean DEFAULT false)
818818
RETURNS pg_lsn STRICT VOLATILE LANGUAGE internal AS 'pg_start_backup';
819819

820+
-- legacy definition for compatibility with 9.3
820821
CREATE OR REPLACE FUNCTION
821822
json_populate_record(base anyelement, from_json json, use_json_as_text boolean DEFAULT false)
822823
RETURNS anyelement LANGUAGE internal STABLE AS 'json_populate_record';
823824

825+
-- legacy definition for compatibility with 9.3
824826
CREATE OR REPLACE FUNCTION
825827
json_populate_recordset(base anyelement, from_json json, use_json_as_text boolean DEFAULT false)
826828
RETURNS SETOF anyelement LANGUAGE internal STABLE ROWS 100 AS 'json_populate_recordset';
827829

828-
CREATE OR REPLACE FUNCTION
829-
jsonb_populate_record(base anyelement, from_json jsonb, use_json_as_text boolean DEFAULT false)
830-
RETURNS anyelement LANGUAGE internal STABLE AS 'jsonb_populate_record';
831-
832-
CREATE OR REPLACE FUNCTION
833-
jsonb_populate_recordset(base anyelement, from_json jsonb, use_json_as_text boolean DEFAULT false)
834-
RETURNS SETOF anyelement LANGUAGE internal STABLE ROWS 100 AS 'jsonb_populate_recordset';
835-
836-
CREATE OR REPLACE FUNCTION
837-
json_to_record(from_json json, nested_as_text boolean DEFAULT false)
838-
RETURNS record LANGUAGE internal STABLE AS 'json_to_record';
839-
840-
CREATE OR REPLACE FUNCTION
841-
json_to_recordset(from_json json, nested_as_text boolean DEFAULT false)
842-
RETURNS SETOF record LANGUAGE internal STABLE ROWS 100 AS 'json_to_recordset';
843-
844-
CREATE OR REPLACE FUNCTION
845-
jsonb_to_record(from_json jsonb, nested_as_text boolean DEFAULT false)
846-
RETURNS record LANGUAGE internal STABLE AS 'jsonb_to_record';
847-
848-
CREATE OR REPLACE FUNCTION
849-
jsonb_to_recordset(from_json jsonb, nested_as_text boolean DEFAULT false)
850-
RETURNS SETOF record LANGUAGE internal STABLE ROWS 100 AS 'jsonb_to_recordset';
851-
852830
CREATE OR REPLACE FUNCTION pg_logical_slot_get_changes(
853831
IN slot_name name, IN upto_lsn pg_lsn, IN upto_nchanges int, VARIADIC options text[] DEFAULT '{}',
854832
OUT location pg_lsn, OUT xid xid, OUT data text)

src/backend/utils/adt/jsonfuncs.c

+6-54
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,7 @@ static void elements_array_element_end(void *state, bool isnull);
8585
static void elements_scalar(void *state, char *token, JsonTokenType tokentype);
8686

8787
/* turn a json object into a hash table */
88-
static HTAB *get_json_object_as_hash(text *json, const char *funcname,
89-
bool use_json_as_text);
88+
static HTAB *get_json_object_as_hash(text *json, const char *funcname);
9089

9190
/* common worker for populate_record and to_record */
9291
static Datum populate_record_worker(FunctionCallInfo fcinfo, const char *funcname,
@@ -198,7 +197,6 @@ typedef struct JhashState
198197
HTAB *hash;
199198
char *saved_scalar;
200199
char *save_json_start;
201-
bool use_json_as_text;
202200
} JHashState;
203201

204202
/* hashtable element */
@@ -235,7 +233,6 @@ typedef struct PopulateRecordsetState
235233
HTAB *json_hash;
236234
char *saved_scalar;
237235
char *save_json_start;
238-
bool use_json_as_text;
239236
Tuplestorestate *tuple_store;
240237
TupleDesc ret_tdesc;
241238
HeapTupleHeader rec;
@@ -1989,7 +1986,6 @@ populate_record_worker(FunctionCallInfo fcinfo, const char *funcname,
19891986
Oid jtype = get_fn_expr_argtype(fcinfo->flinfo, json_arg_num);
19901987
text *json;
19911988
Jsonb *jb = NULL;
1992-
bool use_json_as_text;
19931989
HTAB *json_hash = NULL;
19941990
HeapTupleHeader rec = NULL;
19951991
Oid tupType = InvalidOid;
@@ -2005,9 +2001,6 @@ populate_record_worker(FunctionCallInfo fcinfo, const char *funcname,
20052001

20062002
Assert(jtype == JSONOID || jtype == JSONBOID);
20072003

2008-
use_json_as_text = PG_ARGISNULL(json_arg_num + 1) ? false :
2009-
PG_GETARG_BOOL(json_arg_num + 1);
2010-
20112004
if (have_record_arg)
20122005
{
20132006
Oid argtype = get_fn_expr_argtype(fcinfo->flinfo, 0);
@@ -2065,7 +2058,7 @@ populate_record_worker(FunctionCallInfo fcinfo, const char *funcname,
20652058
/* just get the text */
20662059
json = PG_GETARG_TEXT_P(json_arg_num);
20672060

2068-
json_hash = get_json_object_as_hash(json, funcname, use_json_as_text);
2061+
json_hash = get_json_object_as_hash(json, funcname);
20692062

20702063
/*
20712064
* if the input json is empty, we can only skip the rest if we were
@@ -2227,10 +2220,6 @@ populate_record_worker(FunctionCallInfo fcinfo, const char *funcname,
22272220
else if (v->type == jbvNumeric)
22282221
s = DatumGetCString(DirectFunctionCall1(numeric_out,
22292222
PointerGetDatum(v->val.numeric)));
2230-
else if (!use_json_as_text)
2231-
ereport(ERROR,
2232-
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2233-
errmsg("cannot populate with a nested object unless use_json_as_text is true")));
22342223
else if (v->type == jbvBinary)
22352224
s = JsonbToCString(NULL, (JsonbContainer *) v->val.binary.data, v->val.binary.len);
22362225
else
@@ -2258,15 +2247,9 @@ populate_record_worker(FunctionCallInfo fcinfo, const char *funcname,
22582247
* get_json_object_as_hash
22592248
*
22602249
* decompose a json object into a hash table.
2261-
*
2262-
* Currently doesn't allow anything but a flat object. Should this
2263-
* change?
2264-
*
2265-
* funcname argument allows caller to pass in its name for use in
2266-
* error messages.
22672250
*/
22682251
static HTAB *
2269-
get_json_object_as_hash(text *json, const char *funcname, bool use_json_as_text)
2252+
get_json_object_as_hash(text *json, const char *funcname)
22702253
{
22712254
HASHCTL ctl;
22722255
HTAB *tab;
@@ -2289,7 +2272,6 @@ get_json_object_as_hash(text *json, const char *funcname, bool use_json_as_text)
22892272
state->function_name = funcname;
22902273
state->hash = tab;
22912274
state->lex = lex;
2292-
state->use_json_as_text = use_json_as_text;
22932275

22942276
sem->semstate = (void *) state;
22952277
sem->array_start = hash_array_start;
@@ -2313,11 +2295,7 @@ hash_object_field_start(void *state, char *fname, bool isnull)
23132295
if (_state->lex->token_type == JSON_TOKEN_ARRAY_START ||
23142296
_state->lex->token_type == JSON_TOKEN_OBJECT_START)
23152297
{
2316-
if (!_state->use_json_as_text)
2317-
ereport(ERROR,
2318-
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2319-
errmsg("cannot call %s on a nested object",
2320-
_state->function_name)));
2298+
/* remember start position of the whole text of the subobject */
23212299
_state->save_json_start = _state->lex->token_start;
23222300
}
23232301
else
@@ -2535,10 +2513,6 @@ make_row_from_rec_and_jsonb(Jsonb *element, PopulateRecordsetState *state)
25352513
else if (v->type == jbvNumeric)
25362514
s = DatumGetCString(DirectFunctionCall1(numeric_out,
25372515
PointerGetDatum(v->val.numeric)));
2538-
else if (!state->use_json_as_text)
2539-
ereport(ERROR,
2540-
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2541-
errmsg("cannot populate with a nested object unless use_json_as_text is true")));
25422516
else if (v->type == jbvBinary)
25432517
s = JsonbToCString(NULL, (JsonbContainer *) v->val.binary.data, v->val.binary.len);
25442518
else
@@ -2565,7 +2539,6 @@ populate_recordset_worker(FunctionCallInfo fcinfo, const char *funcname,
25652539
{
25662540
int json_arg_num = have_record_arg ? 1 : 0;
25672541
Oid jtype = get_fn_expr_argtype(fcinfo->flinfo, json_arg_num);
2568-
bool use_json_as_text;
25692542
ReturnSetInfo *rsi;
25702543
MemoryContext old_cxt;
25712544
Oid tupType;
@@ -2576,8 +2549,6 @@ populate_recordset_worker(FunctionCallInfo fcinfo, const char *funcname,
25762549
int ncolumns;
25772550
PopulateRecordsetState *state;
25782551

2579-
use_json_as_text = PG_ARGISNULL(json_arg_num + 1) ? false : PG_GETARG_BOOL(json_arg_num + 1);
2580-
25812552
if (have_record_arg)
25822553
{
25832554
Oid argtype = get_fn_expr_argtype(fcinfo->flinfo, 0);
@@ -2667,7 +2638,6 @@ populate_recordset_worker(FunctionCallInfo fcinfo, const char *funcname,
26672638
state->function_name = funcname;
26682639
state->my_extra = my_extra;
26692640
state->rec = rec;
2670-
state->use_json_as_text = use_json_as_text;
26712641
state->fn_mcxt = fcinfo->flinfo->fn_mcxt;
26722642

26732643
if (jtype == JSONOID)
@@ -2749,16 +2719,9 @@ populate_recordset_object_start(void *state)
27492719
errmsg("cannot call %s on an object",
27502720
_state->function_name)));
27512721

2752-
/* Nested objects, if allowed, require no special processing */
2722+
/* Nested objects require no special processing */
27532723
if (lex_level > 1)
2754-
{
2755-
if (!_state->use_json_as_text)
2756-
ereport(ERROR,
2757-
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2758-
errmsg("cannot call %s with nested objects",
2759-
_state->function_name)));
27602724
return;
2761-
}
27622725

27632726
/* Object at level 1: set up a new hash table for this object */
27642727
memset(&ctl, 0, sizeof(ctl));
@@ -2903,13 +2866,7 @@ populate_recordset_array_element_start(void *state, bool isnull)
29032866
static void
29042867
populate_recordset_array_start(void *state)
29052868
{
2906-
PopulateRecordsetState *_state = (PopulateRecordsetState *) state;
2907-
2908-
if (_state->lex->lex_level != 0 && !_state->use_json_as_text)
2909-
ereport(ERROR,
2910-
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2911-
errmsg("cannot call %s with nested arrays",
2912-
_state->function_name)));
2869+
/* nothing to do */
29132870
}
29142871

29152872
static void
@@ -2938,11 +2895,6 @@ populate_recordset_object_field_start(void *state, char *fname, bool isnull)
29382895
if (_state->lex->token_type == JSON_TOKEN_ARRAY_START ||
29392896
_state->lex->token_type == JSON_TOKEN_OBJECT_START)
29402897
{
2941-
if (!_state->use_json_as_text)
2942-
ereport(ERROR,
2943-
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2944-
errmsg("cannot call %s on a nested object",
2945-
_state->function_name)));
29462898
_state->save_json_start = _state->lex->token_start;
29472899
}
29482900
else

src/include/catalog/catversion.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,6 @@
5353
*/
5454

5555
/* yyyymmddN */
56-
#define CATALOG_VERSION_NO 201406262
56+
#define CATALOG_VERSION_NO 201406292
5757

5858
#endif

src/include/catalog/pg_proc.h

+7-7
Original file line numberDiff line numberDiff line change
@@ -1061,7 +1061,7 @@ DESCR("truncate large object");
10611061
DATA(insert OID = 3172 ( lo_truncate64 PGNSP PGUID 12 1 0 0 0 f f f f t f v 2 0 23 "23 20" _null_ _null_ _null_ _null_ lo_truncate64 _null_ _null_ _null_ ));
10621062
DESCR("truncate large object (64 bit)");
10631063

1064-
DATA(insert OID = 3457 ( lo_from_bytea PGNSP PGUID 12 1 0 0 0 f f f f t f v 2 0 26 "26 17" _null_ _null_ _null_ _null_ lo_from_bytea _null_ _null_ _null_ ));
1064+
DATA(insert OID = 3457 ( lo_from_bytea PGNSP PGUID 12 1 0 0 0 f f f f t f v 2 0 26 "26 17" _null_ _null_ _null_ _null_ lo_from_bytea _null_ _null_ _null_ ));
10651065
DESCR("create new large object with given content");
10661066
DATA(insert OID = 3458 ( lo_get PGNSP PGUID 12 1 0 0 0 f f f f t f v 1 0 17 "26" _null_ _null_ _null_ _null_ lo_get _null_ _null_ _null_ ));
10671067
DESCR("read entire large object");
@@ -4248,9 +4248,9 @@ DATA(insert OID = 3960 ( json_populate_record PGNSP PGUID 12 1 0 0 0 f f f f
42484248
DESCR("get record fields from a json object");
42494249
DATA(insert OID = 3961 ( json_populate_recordset PGNSP PGUID 12 1 100 0 0 f f f f f t s 3 0 2283 "2283 114 16" _null_ _null_ _null_ _null_ json_populate_recordset _null_ _null_ _null_ ));
42504250
DESCR("get set of records with fields from a json array of objects");
4251-
DATA(insert OID = 3204 ( json_to_record PGNSP PGUID 12 1 0 0 0 f f f f f f s 2 0 2249 "114 16" _null_ _null_ _null_ _null_ json_to_record _null_ _null_ _null_ ));
4251+
DATA(insert OID = 3204 ( json_to_record PGNSP PGUID 12 1 0 0 0 f f f f t f s 1 0 2249 "114" _null_ _null_ _null_ _null_ json_to_record _null_ _null_ _null_ ));
42524252
DESCR("get record fields from a json object");
4253-
DATA(insert OID = 3205 ( json_to_recordset PGNSP PGUID 12 1 100 0 0 f f f f f t s 2 0 2249 "114 16" _null_ _null_ _null_ _null_ json_to_recordset _null_ _null_ _null_ ));
4253+
DATA(insert OID = 3205 ( json_to_recordset PGNSP PGUID 12 1 100 0 0 f f f f f t s 1 0 2249 "114" _null_ _null_ _null_ _null_ json_to_recordset _null_ _null_ _null_ ));
42544254
DESCR("get set of records with fields from a json array of objects");
42554255
DATA(insert OID = 3968 ( json_typeof PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 25 "114" _null_ _null_ _null_ _null_ json_typeof _null_ _null_ _null_ ));
42564256
DESCR("get the type of a json value");
@@ -4605,13 +4605,13 @@ DATA(insert OID = 3208 ( jsonb_each PGNSP PGUID 12 1 100 0 0 f f f f t t
46054605
DESCR("key value pairs of a jsonb object");
46064606
DATA(insert OID = 3932 ( jsonb_each_text PGNSP PGUID 12 1 100 0 0 f f f f t t i 1 0 2249 "3802" "{3802,25,25}" "{i,o,o}" "{from_json,key,value}" _null_ jsonb_each_text _null_ _null_ _null_ ));
46074607
DESCR("key value pairs of a jsonb object");
4608-
DATA(insert OID = 3209 ( jsonb_populate_record PGNSP PGUID 12 1 0 0 0 f f f f f f s 3 0 2283 "2283 3802 16" _null_ _null_ _null_ _null_ jsonb_populate_record _null_ _null_ _null_ ));
4608+
DATA(insert OID = 3209 ( jsonb_populate_record PGNSP PGUID 12 1 0 0 0 f f f f f f s 2 0 2283 "2283 3802" _null_ _null_ _null_ _null_ jsonb_populate_record _null_ _null_ _null_ ));
46094609
DESCR("get record fields from a jsonb object");
4610-
DATA(insert OID = 3475 ( jsonb_populate_recordset PGNSP PGUID 12 1 100 0 0 f f f f f t s 3 0 2283 "2283 3802 16" _null_ _null_ _null_ _null_ jsonb_populate_recordset _null_ _null_ _null_ ));
4610+
DATA(insert OID = 3475 ( jsonb_populate_recordset PGNSP PGUID 12 1 100 0 0 f f f f f t s 2 0 2283 "2283 3802" _null_ _null_ _null_ _null_ jsonb_populate_recordset _null_ _null_ _null_ ));
46114611
DESCR("get set of records with fields from a jsonb array of objects");
4612-
DATA(insert OID = 3490 ( jsonb_to_record PGNSP PGUID 12 1 0 0 0 f f f f f f s 2 0 2249 "3802 16" _null_ _null_ _null_ _null_ jsonb_to_record _null_ _null_ _null_ ));
4612+
DATA(insert OID = 3490 ( jsonb_to_record PGNSP PGUID 12 1 0 0 0 f f f f t f s 1 0 2249 "3802" _null_ _null_ _null_ _null_ jsonb_to_record _null_ _null_ _null_ ));
46134613
DESCR("get record fields from a json object");
4614-
DATA(insert OID = 3491 ( jsonb_to_recordset PGNSP PGUID 12 1 100 0 0 f f f f f t s 2 0 2249 "3802 16" _null_ _null_ _null_ _null_ jsonb_to_recordset _null_ _null_ _null_ ));
4614+
DATA(insert OID = 3491 ( jsonb_to_recordset PGNSP PGUID 12 1 100 0 0 f f f f f t s 1 0 2249 "3802" _null_ _null_ _null_ _null_ jsonb_to_recordset _null_ _null_ _null_ ));
46154615
DESCR("get set of records with fields from a json array of objects");
46164616
DATA(insert OID = 3210 ( jsonb_typeof PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 25 "3802" _null_ _null_ _null_ _null_ jsonb_typeof _null_ _null_ _null_ ));
46174617
DESCR("get the type of a jsonb value");

0 commit comments

Comments
 (0)