@@ -139,8 +139,10 @@ static JsonbValue *findJsonbValueFromContainerLen(JsonbContainer *container,
139
139
/* functions supporting jsonb_delete, jsonb_set and jsonb_concat */
140
140
static JsonbValue * IteratorConcat (JsonbIterator * * it1 , JsonbIterator * * it2 ,
141
141
JsonbParseState * * state );
142
- static Datum jsonb_set_element (Datum datum , text * * path , int path_len , Datum sourceData , Oid source_type );
143
- static Datum jsonb_get_element (Datum datum , text * * path , int path_len , bool * isNull );
142
+ static Datum jsonb_set_element (Datum datum , Datum * path , int path_len ,
143
+ Datum sourceData , Oid source_type );
144
+ static Datum jsonb_get_element (Jsonb * jb , Datum * path , int npath ,
145
+ bool * isnull , bool as_text );
144
146
static JsonbValue * setPath (JsonbIterator * * it , Datum * path_elems ,
145
147
bool * path_nulls , int path_len ,
146
148
JsonbParseState * * st , int level , JsonbValue * newval , int op_type );
@@ -1175,16 +1177,11 @@ get_jsonb_path_all(FunctionCallInfo fcinfo, bool as_text)
1175
1177
{
1176
1178
Jsonb * jb = PG_GETARG_JSONB (0 );
1177
1179
ArrayType * path = PG_GETARG_ARRAYTYPE_P (1 );
1178
- Jsonb * res ;
1179
1180
Datum * pathtext ;
1180
1181
bool * pathnulls ;
1182
+ bool isnull ;
1181
1183
int npath ;
1182
- int i ;
1183
- bool have_object = false,
1184
- have_array = false;
1185
- JsonbValue * jbvp = NULL ;
1186
- JsonbValue tv ;
1187
- JsonbContainer * container ;
1184
+ Datum res ;
1188
1185
1189
1186
/*
1190
1187
* If the array contains any null elements, return NULL, on the grounds
@@ -1199,9 +1196,28 @@ get_jsonb_path_all(FunctionCallInfo fcinfo, bool as_text)
1199
1196
deconstruct_array (path , TEXTOID , -1 , false, 'i' ,
1200
1197
& pathtext , & pathnulls , & npath );
1201
1198
1202
- /* Identify whether we have object, array, or scalar at top-level */
1203
- container = & jb -> root ;
1199
+ res = jsonb_get_element (jb , pathtext , npath , & isnull , as_text );
1200
+
1201
+ if (isnull )
1202
+ PG_RETURN_NULL ();
1203
+ else
1204
+ PG_RETURN_DATUM (res );
1205
+ }
1204
1206
1207
+ static Datum
1208
+ jsonb_get_element (Jsonb * jb , Datum * path , int npath , bool * isnull , bool as_text )
1209
+ {
1210
+ Jsonb * res ;
1211
+ JsonbContainer * container = & jb -> root ;
1212
+ JsonbValue * jbvp = NULL ;
1213
+ JsonbValue tv ;
1214
+ int i ;
1215
+ bool have_object = false,
1216
+ have_array = false;
1217
+
1218
+ * isnull = false;
1219
+
1220
+ /* Identify whether we have object, array, or scalar at top-level */
1205
1221
if (JB_ROOT_IS_OBJECT (jb ))
1206
1222
have_object = true;
1207
1223
else if (JB_ROOT_IS_ARRAY (jb ) && !JB_ROOT_IS_SCALAR (jb ))
@@ -1226,14 +1242,14 @@ get_jsonb_path_all(FunctionCallInfo fcinfo, bool as_text)
1226
1242
{
1227
1243
if (as_text )
1228
1244
{
1229
- PG_RETURN_TEXT_P (cstring_to_text (JsonbToCString (NULL ,
1245
+ return PointerGetDatum (cstring_to_text (JsonbToCString (NULL ,
1230
1246
container ,
1231
1247
VARSIZE (jb ))));
1232
1248
}
1233
1249
else
1234
1250
{
1235
1251
/* not text mode - just hand back the jsonb */
1236
- PG_RETURN_JSONB (jb );
1252
+ return JsonbGetDatum (jb );
1237
1253
}
1238
1254
}
1239
1255
@@ -1243,21 +1259,24 @@ get_jsonb_path_all(FunctionCallInfo fcinfo, bool as_text)
1243
1259
{
1244
1260
jbvp = findJsonbValueFromContainerLen (container ,
1245
1261
JB_FOBJECT ,
1246
- VARDATA_ANY (pathtext [i ]),
1247
- VARSIZE_ANY_EXHDR (pathtext [i ]));
1262
+ VARDATA_ANY (path [i ]),
1263
+ VARSIZE_ANY_EXHDR (path [i ]));
1248
1264
}
1249
1265
else if (have_array )
1250
1266
{
1251
1267
long lindex ;
1252
1268
uint32 index ;
1253
- char * indextext = TextDatumGetCString (pathtext [i ]);
1269
+ char * indextext = TextDatumGetCString (path [i ]);
1254
1270
char * endptr ;
1255
1271
1256
1272
errno = 0 ;
1257
1273
lindex = strtol (indextext , & endptr , 10 );
1258
1274
if (endptr == indextext || * endptr != '\0' || errno != 0 ||
1259
1275
lindex > INT_MAX || lindex < INT_MIN )
1260
- PG_RETURN_NULL ();
1276
+ {
1277
+ * isnull = true;
1278
+ return PointerGetDatum (NULL );
1279
+ }
1261
1280
1262
1281
if (lindex >= 0 )
1263
1282
{
@@ -1275,7 +1294,10 @@ get_jsonb_path_all(FunctionCallInfo fcinfo, bool as_text)
1275
1294
nelements = container -> header & JB_CMASK ;
1276
1295
1277
1296
if (- lindex > nelements )
1278
- PG_RETURN_NULL ();
1297
+ {
1298
+ * isnull = true;
1299
+ return PointerGetDatum (NULL );
1300
+ }
1279
1301
else
1280
1302
index = nelements + lindex ;
1281
1303
}
@@ -1285,11 +1307,15 @@ get_jsonb_path_all(FunctionCallInfo fcinfo, bool as_text)
1285
1307
else
1286
1308
{
1287
1309
/* scalar, extraction yields a null */
1288
- PG_RETURN_NULL ();
1310
+ * isnull = true;
1311
+ return PointerGetDatum (NULL );
1289
1312
}
1290
1313
1291
1314
if (jbvp == NULL )
1292
- PG_RETURN_NULL ();
1315
+ {
1316
+ * isnull = true;
1317
+ return PointerGetDatum (NULL );
1318
+ }
1293
1319
else if (i == npath - 1 )
1294
1320
break ;
1295
1321
@@ -1314,24 +1340,28 @@ get_jsonb_path_all(FunctionCallInfo fcinfo, bool as_text)
1314
1340
{
1315
1341
/* special-case outputs for string and null values */
1316
1342
if (jbvp -> type == jbvString )
1317
- PG_RETURN_TEXT_P (cstring_to_text_with_len (jbvp -> val .string .val ,
1318
- jbvp -> val .string .len ));
1343
+ return PointerGetDatum (
1344
+ cstring_to_text_with_len (jbvp -> val .string .val ,
1345
+ jbvp -> val .string .len ));
1319
1346
if (jbvp -> type == jbvNull )
1320
- PG_RETURN_NULL ();
1347
+ {
1348
+ * isnull = true;
1349
+ return PointerGetDatum (NULL );
1350
+ }
1321
1351
}
1322
1352
1323
1353
res = JsonbValueToJsonb (jbvp );
1324
1354
1325
1355
if (as_text )
1326
1356
{
1327
- PG_RETURN_TEXT_P (cstring_to_text (JsonbToCString (NULL ,
1357
+ return PointerGetDatum (cstring_to_text (JsonbToCString (NULL ,
1328
1358
& res -> root ,
1329
1359
VARSIZE (res ))));
1330
1360
}
1331
1361
else
1332
1362
{
1333
1363
/* not text mode - just hand back the jsonb */
1334
- PG_RETURN_JSONB (res );
1364
+ return JsonbGetDatum (res );
1335
1365
}
1336
1366
}
1337
1367
@@ -4009,29 +4039,6 @@ setPathArray(JsonbIterator **it, Datum *path_elems, bool *path_nulls,
4009
4039
}
4010
4040
}
4011
4041
4012
- Datum
4013
- jsonb_get_element (Datum jsonbdatum , text * * path , int path_len , bool * is_null )
4014
- {
4015
- Jsonb * jb = DatumGetJsonb (jsonbdatum );
4016
- JsonbValue vbuf ;
4017
- JsonbValue * v = JsonbToJsonbValue (jb , & vbuf );
4018
- int level ;
4019
-
4020
- for (level = 0 ; level < path_len ; level ++ )
4021
- {
4022
- if (v -> type != jbvBinary ||
4023
- !(v = findJsonbValueFromContainerLen (v -> val .binary .data , JB_FOBJECT ,
4024
- VARDATA_ANY (path [level ]),
4025
- VARSIZE_ANY_EXHDR (path [level ]))))
4026
- {
4027
- * is_null = true;
4028
- return (Datum ) 0 ;
4029
- }
4030
- }
4031
-
4032
- PG_RETURN_JSONB (JsonbValueToJsonb (v ));
4033
- }
4034
-
4035
4042
Datum
4036
4043
jsonb_subscription_evaluate (PG_FUNCTION_ARGS )
4037
4044
{
@@ -4040,12 +4047,6 @@ jsonb_subscription_evaluate(PG_FUNCTION_ARGS)
4040
4047
SubscriptionRef * jsonb_ref = (SubscriptionRef * ) sbstate -> xprstate .expr ;
4041
4048
bool * is_null = sbsdata -> isNull ;
4042
4049
bool is_assignment = (jsonb_ref -> refassgnexpr != NULL );
4043
- text * * path ;
4044
- int i = 0 ;
4045
-
4046
- path = (text * * ) palloc (sbsdata -> indexprNumber * sizeof (text * ));
4047
- for (i = 0 ; i < sbsdata -> indexprNumber ; i ++ )
4048
- path [i ] = DatumGetTextP (sbsdata -> upper [i ]);
4049
4050
4050
4051
if (is_assignment )
4051
4052
{
@@ -4105,14 +4106,18 @@ jsonb_subscription_evaluate(PG_FUNCTION_ARGS)
4105
4106
* is_null = false;
4106
4107
}
4107
4108
4108
- return jsonb_set_element (sbsdata -> containerSource , path ,
4109
+ return jsonb_set_element (sbsdata -> containerSource ,
4110
+ sbsdata -> upper ,
4109
4111
sbsdata -> indexprNumber ,
4110
4112
sourceData ,
4111
4113
jsonb_ref -> refelemtype );
4112
4114
}
4113
4115
else
4114
- return jsonb_get_element (sbsdata -> containerSource , path ,
4115
- sbsdata -> indexprNumber , is_null );
4116
+ return jsonb_get_element (DatumGetJsonb (sbsdata -> containerSource ),
4117
+ sbsdata -> upper ,
4118
+ sbsdata -> indexprNumber ,
4119
+ is_null ,
4120
+ false);
4116
4121
}
4117
4122
4118
4123
Datum
@@ -4180,7 +4185,7 @@ jsonb_subscription(PG_FUNCTION_ARGS)
4180
4185
}
4181
4186
4182
4187
Datum
4183
- jsonb_set_element (Datum jsonbdatum , text * * path , int path_len ,
4188
+ jsonb_set_element (Datum jsonbdatum , Datum * path , int path_len ,
4184
4189
Datum sourceData , Oid source_type )
4185
4190
{
4186
4191
Jsonb * jb = DatumGetJsonb (jsonbdatum );
@@ -4197,7 +4202,7 @@ jsonb_set_element(Datum jsonbdatum, text **path, int path_len,
4197
4202
4198
4203
it = JsonbIteratorInit (& jb -> root );
4199
4204
4200
- res = setPath (& it , ( Datum * ) path , path_nulls , path_len , & state , 0 ,
4205
+ res = setPath (& it , path , path_nulls , path_len , & state , 0 ,
4201
4206
newval , JB_PATH_CREATE );
4202
4207
4203
4208
pfree (path_nulls );
0 commit comments