Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit18fc4ec

Browse files
committed
Process variadic arguments consistently in json functions
json_build_object and json_build_array and the jsonb equivalents did notcorrectly process explicit VARIADIC arguments. They are modified to usethe new extract_variadic_args() utility function which abstracts awaythe details of the call method.Michael Paquier, reviewed by Tom Lane and Dmitry Dolgov.Backpatch to 9.5 for the jsonb fixes and 9.4 for the json fixes, asthat's where they originated.
1 parentf3c6e8a commit18fc4ec

File tree

6 files changed

+306
-132
lines changed

6 files changed

+306
-132
lines changed

‎src/backend/utils/adt/json.c

Lines changed: 24 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include"access/transam.h"
1818
#include"catalog/pg_type.h"
1919
#include"executor/spi.h"
20+
#include"funcapi.h"
2021
#include"lib/stringinfo.h"
2122
#include"libpq/pqformat.h"
2223
#include"mb/pg_wchar.h"
@@ -2111,10 +2112,17 @@ json_build_object(PG_FUNCTION_ARGS)
21112112
{
21122113
intnargs=PG_NARGS();
21132114
inti;
2114-
Datumarg;
21152115
constchar*sep="";
21162116
StringInforesult;
2117-
Oidval_type;
2117+
Datum*args;
2118+
bool*nulls;
2119+
Oid*types;
2120+
2121+
/* fetch argument values to build the object */
2122+
nargs=extract_variadic_args(fcinfo,0, false,&args,&types,&nulls);
2123+
2124+
if (nargs<0)
2125+
PG_RETURN_NULL();
21182126

21192127
if (nargs %2!=0)
21202128
ereport(ERROR,
@@ -2128,52 +2136,22 @@ json_build_object(PG_FUNCTION_ARGS)
21282136

21292137
for (i=0;i<nargs;i+=2)
21302138
{
2131-
/*
2132-
* Note: since json_build_object() is declared as taking type "any",
2133-
* the parser will not do any type conversion on unknown-type literals
2134-
* (that is, undecorated strings or NULLs). Such values will arrive
2135-
* here as type UNKNOWN, which fortunately does not matter to us,
2136-
* since unknownout() works fine.
2137-
*/
21382139
appendStringInfoString(result,sep);
21392140
sep=", ";
21402141

21412142
/* process key */
2142-
val_type=get_fn_expr_argtype(fcinfo->flinfo,i);
2143-
2144-
if (val_type==InvalidOid)
2145-
ereport(ERROR,
2146-
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2147-
errmsg("could not determine data type for argument %d",
2148-
i+1)));
2149-
2150-
if (PG_ARGISNULL(i))
2143+
if (nulls[i])
21512144
ereport(ERROR,
21522145
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
21532146
errmsg("argument %d cannot be null",i+1),
21542147
errhint("Object keys should be text.")));
21552148

2156-
arg=PG_GETARG_DATUM(i);
2157-
2158-
add_json(arg, false,result,val_type, true);
2149+
add_json(args[i], false,result,types[i], true);
21592150

21602151
appendStringInfoString(result," : ");
21612152

21622153
/* process value */
2163-
val_type=get_fn_expr_argtype(fcinfo->flinfo,i+1);
2164-
2165-
if (val_type==InvalidOid)
2166-
ereport(ERROR,
2167-
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2168-
errmsg("could not determine data type for argument %d",
2169-
i+2)));
2170-
2171-
if (PG_ARGISNULL(i+1))
2172-
arg= (Datum)0;
2173-
else
2174-
arg=PG_GETARG_DATUM(i+1);
2175-
2176-
add_json(arg,PG_ARGISNULL(i+1),result,val_type, false);
2154+
add_json(args[i+1],nulls[i+1],result,types[i+1], false);
21772155
}
21782156

21792157
appendStringInfoChar(result,'}');
@@ -2196,43 +2174,29 @@ json_build_object_noargs(PG_FUNCTION_ARGS)
21962174
Datum
21972175
json_build_array(PG_FUNCTION_ARGS)
21982176
{
2199-
intnargs=PG_NARGS();
2177+
intnargs;
22002178
inti;
2201-
Datumarg;
22022179
constchar*sep="";
22032180
StringInforesult;
2204-
Oidval_type;
2181+
Datum*args;
2182+
bool*nulls;
2183+
Oid*types;
2184+
2185+
/* fetch argument values to build the array */
2186+
nargs=extract_variadic_args(fcinfo,0, false,&args,&types,&nulls);
2187+
2188+
if (nargs<0)
2189+
PG_RETURN_NULL();
22052190

22062191
result=makeStringInfo();
22072192

22082193
appendStringInfoChar(result,'[');
22092194

22102195
for (i=0;i<nargs;i++)
22112196
{
2212-
/*
2213-
* Note: since json_build_array() is declared as taking type "any",
2214-
* the parser will not do any type conversion on unknown-type literals
2215-
* (that is, undecorated strings or NULLs). Such values will arrive
2216-
* here as type UNKNOWN, which fortunately does not matter to us,
2217-
* since unknownout() works fine.
2218-
*/
22192197
appendStringInfoString(result,sep);
22202198
sep=", ";
2221-
2222-
val_type=get_fn_expr_argtype(fcinfo->flinfo,i);
2223-
2224-
if (val_type==InvalidOid)
2225-
ereport(ERROR,
2226-
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2227-
errmsg("could not determine data type for argument %d",
2228-
i+1)));
2229-
2230-
if (PG_ARGISNULL(i))
2231-
arg= (Datum)0;
2232-
else
2233-
arg=PG_GETARG_DATUM(i);
2234-
2235-
add_json(arg,PG_ARGISNULL(i),result,val_type, false);
2199+
add_json(args[i],nulls[i],result,types[i], false);
22362200
}
22372201

22382202
appendStringInfoChar(result,']');

‎src/backend/utils/adt/jsonb.c

Lines changed: 28 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* jsonb.c
44
*I/O routines for jsonb type
55
*
6-
*Copyright (c) 2014-2017, PostgreSQL Global Development Group
6+
*COPYRIGHT (c) 2014-2017, PostgreSQL Global Development Group
77
*
88
* IDENTIFICATION
99
* src/backend/utils/adt/jsonb.c
@@ -16,6 +16,7 @@
1616
#include"access/htup_details.h"
1717
#include"access/transam.h"
1818
#include"catalog/pg_type.h"
19+
#include"funcapi.h"
1920
#include"libpq/pqformat.h"
2021
#include"parser/parse_coerce.h"
2122
#include"utils/builtins.h"
@@ -1171,16 +1172,24 @@ to_jsonb(PG_FUNCTION_ARGS)
11711172
Datum
11721173
jsonb_build_object(PG_FUNCTION_ARGS)
11731174
{
1174-
intnargs=PG_NARGS();
1175+
intnargs;
11751176
inti;
1176-
Datumarg;
1177-
Oidval_type;
11781177
JsonbInStateresult;
1178+
Datum*args;
1179+
bool*nulls;
1180+
Oid*types;
1181+
1182+
/* build argument values to build the object */
1183+
nargs=extract_variadic_args(fcinfo,0, true,&args,&types,&nulls);
1184+
1185+
if (nargs<0)
1186+
PG_RETURN_NULL();
11791187

11801188
if (nargs %2!=0)
11811189
ereport(ERROR,
11821190
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1183-
errmsg("invalid number of arguments: object must be matched key value pairs")));
1191+
errmsg("argument list must have even number of elements"),
1192+
errhint("The arguments of jsonb_build_object() must consist of alternating keys and values.")));
11841193

11851194
memset(&result,0,sizeof(JsonbInState));
11861195

@@ -1189,54 +1198,15 @@ jsonb_build_object(PG_FUNCTION_ARGS)
11891198
for (i=0;i<nargs;i+=2)
11901199
{
11911200
/* process key */
1192-
1193-
if (PG_ARGISNULL(i))
1201+
if (nulls[i])
11941202
ereport(ERROR,
11951203
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
11961204
errmsg("argument %d: key must not be null",i+1)));
1197-
val_type=get_fn_expr_argtype(fcinfo->flinfo,i);
1198-
1199-
/*
1200-
* turn a constant (more or less literal) value that's of unknown type
1201-
* into text. Unknowns come in as a cstring pointer.
1202-
*/
1203-
if (val_type==UNKNOWNOID&&get_fn_expr_arg_stable(fcinfo->flinfo,i))
1204-
{
1205-
val_type=TEXTOID;
1206-
arg=CStringGetTextDatum(PG_GETARG_POINTER(i));
1207-
}
1208-
else
1209-
{
1210-
arg=PG_GETARG_DATUM(i);
1211-
}
1212-
if (val_type==InvalidOid||val_type==UNKNOWNOID)
1213-
ereport(ERROR,
1214-
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1215-
errmsg("could not determine data type for argument %d",i+1)));
12161205

1217-
add_jsonb(arg, false,&result,val_type, true);
1206+
add_jsonb(args[i], false,&result,types[i], true);
12181207

12191208
/* process value */
1220-
1221-
val_type=get_fn_expr_argtype(fcinfo->flinfo,i+1);
1222-
/* see comments above */
1223-
if (val_type==UNKNOWNOID&&get_fn_expr_arg_stable(fcinfo->flinfo,i+1))
1224-
{
1225-
val_type=TEXTOID;
1226-
if (PG_ARGISNULL(i+1))
1227-
arg= (Datum)0;
1228-
else
1229-
arg=CStringGetTextDatum(PG_GETARG_POINTER(i+1));
1230-
}
1231-
else
1232-
{
1233-
arg=PG_GETARG_DATUM(i+1);
1234-
}
1235-
if (val_type==InvalidOid||val_type==UNKNOWNOID)
1236-
ereport(ERROR,
1237-
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1238-
errmsg("could not determine data type for argument %d",i+2)));
1239-
add_jsonb(arg,PG_ARGISNULL(i+1),&result,val_type, false);
1209+
add_jsonb(args[i+1],nulls[i+1],&result,types[i+1], false);
12401210
}
12411211

12421212
result.res=pushJsonbValue(&result.parseState,WJB_END_OBJECT,NULL);
@@ -1266,38 +1236,25 @@ jsonb_build_object_noargs(PG_FUNCTION_ARGS)
12661236
Datum
12671237
jsonb_build_array(PG_FUNCTION_ARGS)
12681238
{
1269-
intnargs=PG_NARGS();
1239+
intnargs;
12701240
inti;
1271-
Datumarg;
1272-
Oidval_type;
12731241
JsonbInStateresult;
1242+
Datum*args;
1243+
bool*nulls;
1244+
Oid*types;
1245+
1246+
/* build argument values to build the array */
1247+
nargs=extract_variadic_args(fcinfo,0, true,&args,&types,&nulls);
1248+
1249+
if (nargs<0)
1250+
PG_RETURN_NULL();
12741251

12751252
memset(&result,0,sizeof(JsonbInState));
12761253

12771254
result.res=pushJsonbValue(&result.parseState,WJB_BEGIN_ARRAY,NULL);
12781255

12791256
for (i=0;i<nargs;i++)
1280-
{
1281-
val_type=get_fn_expr_argtype(fcinfo->flinfo,i);
1282-
/* see comments in jsonb_build_object above */
1283-
if (val_type==UNKNOWNOID&&get_fn_expr_arg_stable(fcinfo->flinfo,i))
1284-
{
1285-
val_type=TEXTOID;
1286-
if (PG_ARGISNULL(i))
1287-
arg= (Datum)0;
1288-
else
1289-
arg=CStringGetTextDatum(PG_GETARG_POINTER(i));
1290-
}
1291-
else
1292-
{
1293-
arg=PG_GETARG_DATUM(i);
1294-
}
1295-
if (val_type==InvalidOid||val_type==UNKNOWNOID)
1296-
ereport(ERROR,
1297-
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1298-
errmsg("could not determine data type for argument %d",i+1)));
1299-
add_jsonb(arg,PG_ARGISNULL(i),&result,val_type, false);
1300-
}
1257+
add_jsonb(args[i],nulls[i],&result,types[i], false);
13011258

13021259
result.res=pushJsonbValue(&result.parseState,WJB_END_ARRAY,NULL);
13031260

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp