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

Commitdfea49f

Browse files
author
Nikita Glukhov
committed
Add json array subscription support for expressions
1 parentf5d96c5 commitdfea49f

File tree

3 files changed

+178
-61
lines changed

3 files changed

+178
-61
lines changed

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

Lines changed: 64 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -139,8 +139,10 @@ static JsonbValue *findJsonbValueFromContainerLen(JsonbContainer *container,
139139
/* functions supporting jsonb_delete, jsonb_set and jsonb_concat */
140140
staticJsonbValue*IteratorConcat(JsonbIterator**it1,JsonbIterator**it2,
141141
JsonbParseState**state);
142-
staticDatumjsonb_set_element(Datumdatum,text**path,intpath_len,DatumsourceData,Oidsource_type);
143-
staticDatumjsonb_get_element(Datumdatum,text**path,intpath_len,bool*isNull);
142+
staticDatumjsonb_set_element(Datumdatum,Datum*path,intpath_len,
143+
DatumsourceData,Oidsource_type);
144+
staticDatumjsonb_get_element(Jsonb*jb,Datum*path,intnpath,
145+
bool*isnull,boolas_text);
144146
staticJsonbValue*setPath(JsonbIterator**it,Datum*path_elems,
145147
bool*path_nulls,intpath_len,
146148
JsonbParseState**st,intlevel,JsonbValue*newval,intop_type);
@@ -1175,16 +1177,11 @@ get_jsonb_path_all(FunctionCallInfo fcinfo, bool as_text)
11751177
{
11761178
Jsonb*jb=PG_GETARG_JSONB(0);
11771179
ArrayType*path=PG_GETARG_ARRAYTYPE_P(1);
1178-
Jsonb*res;
11791180
Datum*pathtext;
11801181
bool*pathnulls;
1182+
boolisnull;
11811183
intnpath;
1182-
inti;
1183-
boolhave_object= false,
1184-
have_array= false;
1185-
JsonbValue*jbvp=NULL;
1186-
JsonbValuetv;
1187-
JsonbContainer*container;
1184+
Datumres;
11881185

11891186
/*
11901187
* 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)
11991196
deconstruct_array(path,TEXTOID,-1, false,'i',
12001197
&pathtext,&pathnulls,&npath);
12011198

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+
}
12041206

1207+
staticDatum
1208+
jsonb_get_element(Jsonb*jb,Datum*path,intnpath,bool*isnull,boolas_text)
1209+
{
1210+
Jsonb*res;
1211+
JsonbContainer*container=&jb->root;
1212+
JsonbValue*jbvp=NULL;
1213+
JsonbValuetv;
1214+
inti;
1215+
boolhave_object= false,
1216+
have_array= false;
1217+
1218+
*isnull= false;
1219+
1220+
/* Identify whether we have object, array, or scalar at top-level */
12051221
if (JB_ROOT_IS_OBJECT(jb))
12061222
have_object= true;
12071223
elseif (JB_ROOT_IS_ARRAY(jb)&& !JB_ROOT_IS_SCALAR(jb))
@@ -1226,14 +1242,14 @@ get_jsonb_path_all(FunctionCallInfo fcinfo, bool as_text)
12261242
{
12271243
if (as_text)
12281244
{
1229-
PG_RETURN_TEXT_P(cstring_to_text(JsonbToCString(NULL,
1245+
returnPointerGetDatum(cstring_to_text(JsonbToCString(NULL,
12301246
container,
12311247
VARSIZE(jb))));
12321248
}
12331249
else
12341250
{
12351251
/* not text mode - just hand back the jsonb */
1236-
PG_RETURN_JSONB(jb);
1252+
returnJsonbGetDatum(jb);
12371253
}
12381254
}
12391255

@@ -1243,21 +1259,24 @@ get_jsonb_path_all(FunctionCallInfo fcinfo, bool as_text)
12431259
{
12441260
jbvp=findJsonbValueFromContainerLen(container,
12451261
JB_FOBJECT,
1246-
VARDATA_ANY(pathtext[i]),
1247-
VARSIZE_ANY_EXHDR(pathtext[i]));
1262+
VARDATA_ANY(path[i]),
1263+
VARSIZE_ANY_EXHDR(path[i]));
12481264
}
12491265
elseif (have_array)
12501266
{
12511267
longlindex;
12521268
uint32index;
1253-
char*indextext=TextDatumGetCString(pathtext[i]);
1269+
char*indextext=TextDatumGetCString(path[i]);
12541270
char*endptr;
12551271

12561272
errno=0;
12571273
lindex=strtol(indextext,&endptr,10);
12581274
if (endptr==indextext||*endptr!='\0'||errno!=0||
12591275
lindex>INT_MAX||lindex<INT_MIN)
1260-
PG_RETURN_NULL();
1276+
{
1277+
*isnull= true;
1278+
returnPointerGetDatum(NULL);
1279+
}
12611280

12621281
if (lindex >=0)
12631282
{
@@ -1275,7 +1294,10 @@ get_jsonb_path_all(FunctionCallInfo fcinfo, bool as_text)
12751294
nelements=container->header&JB_CMASK;
12761295

12771296
if (-lindex>nelements)
1278-
PG_RETURN_NULL();
1297+
{
1298+
*isnull= true;
1299+
returnPointerGetDatum(NULL);
1300+
}
12791301
else
12801302
index=nelements+lindex;
12811303
}
@@ -1285,11 +1307,15 @@ get_jsonb_path_all(FunctionCallInfo fcinfo, bool as_text)
12851307
else
12861308
{
12871309
/* scalar, extraction yields a null */
1288-
PG_RETURN_NULL();
1310+
*isnull= true;
1311+
returnPointerGetDatum(NULL);
12891312
}
12901313

12911314
if (jbvp==NULL)
1292-
PG_RETURN_NULL();
1315+
{
1316+
*isnull= true;
1317+
returnPointerGetDatum(NULL);
1318+
}
12931319
elseif (i==npath-1)
12941320
break;
12951321

@@ -1314,24 +1340,28 @@ get_jsonb_path_all(FunctionCallInfo fcinfo, bool as_text)
13141340
{
13151341
/* special-case outputs for string and null values */
13161342
if (jbvp->type==jbvString)
1317-
PG_RETURN_TEXT_P(cstring_to_text_with_len(jbvp->val.string.val,
1318-
jbvp->val.string.len));
1343+
returnPointerGetDatum(
1344+
cstring_to_text_with_len(jbvp->val.string.val,
1345+
jbvp->val.string.len));
13191346
if (jbvp->type==jbvNull)
1320-
PG_RETURN_NULL();
1347+
{
1348+
*isnull= true;
1349+
returnPointerGetDatum(NULL);
1350+
}
13211351
}
13221352

13231353
res=JsonbValueToJsonb(jbvp);
13241354

13251355
if (as_text)
13261356
{
1327-
PG_RETURN_TEXT_P(cstring_to_text(JsonbToCString(NULL,
1357+
returnPointerGetDatum(cstring_to_text(JsonbToCString(NULL,
13281358
&res->root,
13291359
VARSIZE(res))));
13301360
}
13311361
else
13321362
{
13331363
/* not text mode - just hand back the jsonb */
1334-
PG_RETURN_JSONB(res);
1364+
returnJsonbGetDatum(res);
13351365
}
13361366
}
13371367

@@ -4009,29 +4039,6 @@ setPathArray(JsonbIterator **it, Datum *path_elems, bool *path_nulls,
40094039
}
40104040
}
40114041

4012-
Datum
4013-
jsonb_get_element(Datumjsonbdatum,text**path,intpath_len,bool*is_null)
4014-
{
4015-
Jsonb*jb=DatumGetJsonb(jsonbdatum);
4016-
JsonbValuevbuf;
4017-
JsonbValue*v=JsonbToJsonbValue(jb,&vbuf);
4018-
intlevel;
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-
40354042
Datum
40364043
jsonb_subscription_evaluate(PG_FUNCTION_ARGS)
40374044
{
@@ -4040,12 +4047,6 @@ jsonb_subscription_evaluate(PG_FUNCTION_ARGS)
40404047
SubscriptionRef*jsonb_ref= (SubscriptionRef*)sbstate->xprstate.expr;
40414048
bool*is_null=sbsdata->isNull;
40424049
boolis_assignment= (jsonb_ref->refassgnexpr!=NULL);
4043-
text**path;
4044-
inti=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]);
40494050

40504051
if (is_assignment)
40514052
{
@@ -4105,14 +4106,18 @@ jsonb_subscription_evaluate(PG_FUNCTION_ARGS)
41054106
*is_null= false;
41064107
}
41074108

4108-
returnjsonb_set_element(sbsdata->containerSource,path,
4109+
returnjsonb_set_element(sbsdata->containerSource,
4110+
sbsdata->upper,
41094111
sbsdata->indexprNumber,
41104112
sourceData,
41114113
jsonb_ref->refelemtype);
41124114
}
41134115
else
4114-
returnjsonb_get_element(sbsdata->containerSource,path,
4115-
sbsdata->indexprNumber,is_null);
4116+
returnjsonb_get_element(DatumGetJsonb(sbsdata->containerSource),
4117+
sbsdata->upper,
4118+
sbsdata->indexprNumber,
4119+
is_null,
4120+
false);
41164121
}
41174122

41184123
Datum
@@ -4180,7 +4185,7 @@ jsonb_subscription(PG_FUNCTION_ARGS)
41804185
}
41814186

41824187
Datum
4183-
jsonb_set_element(Datumjsonbdatum,text**path,intpath_len,
4188+
jsonb_set_element(Datumjsonbdatum,Datum*path,intpath_len,
41844189
DatumsourceData,Oidsource_type)
41854190
{
41864191
Jsonb*jb=DatumGetJsonb(jsonbdatum);
@@ -4197,7 +4202,7 @@ jsonb_set_element(Datum jsonbdatum, text **path, int path_len,
41974202

41984203
it=JsonbIteratorInit(&jb->root);
41994204

4200-
res=setPath(&it,(Datum*)path,path_nulls,path_len,&state,0,
4205+
res=setPath(&it,path,path_nulls,path_len,&state,0,
42014206
newval,JB_PATH_CREATE);
42024207

42034208
pfree(path_nulls);

‎src/test/regress/expected/jsonb.out‎

Lines changed: 97 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3442,12 +3442,90 @@ select jsonb_insert('{"a": {"b": "value"}}', '{a, b}', '"new_value"', true);
34423442
ERROR: cannot replace existing key
34433443
HINT: Try using the function jsonb_set to replace key value.
34443444
-- jsonb subscript
3445+
select ('123'::jsonb)['a'];
3446+
jsonb
3447+
-------
3448+
3449+
(1 row)
3450+
3451+
select ('123'::jsonb)[0];
3452+
jsonb
3453+
-------
3454+
3455+
(1 row)
3456+
34453457
select ('{"a": 1}'::jsonb)['a'];
34463458
jsonb
34473459
-------
34483460
1
34493461
(1 row)
34503462

3463+
select ('{"a": 1}'::jsonb)[0];
3464+
jsonb
3465+
-------
3466+
3467+
(1 row)
3468+
3469+
select ('{"a": 1}'::jsonb)['not_exist'];
3470+
jsonb
3471+
-------
3472+
3473+
(1 row)
3474+
3475+
select ('[1, "2", null]'::jsonb)['a'];
3476+
jsonb
3477+
-------
3478+
3479+
(1 row)
3480+
3481+
select ('[1, "2", null]'::jsonb)[0];
3482+
jsonb
3483+
-------
3484+
1
3485+
(1 row)
3486+
3487+
select ('[1, "2", null]'::jsonb)['1'];
3488+
jsonb
3489+
-------
3490+
"2"
3491+
(1 row)
3492+
3493+
select ('[1, "2", null]'::jsonb)[1.0];
3494+
jsonb
3495+
-------
3496+
3497+
(1 row)
3498+
3499+
select ('[1, "2", null]'::jsonb)[2];
3500+
jsonb
3501+
-------
3502+
null
3503+
(1 row)
3504+
3505+
select ('[1, "2", null]'::jsonb)[3];
3506+
jsonb
3507+
-------
3508+
3509+
(1 row)
3510+
3511+
select ('[1, "2", null]'::jsonb)[-2];
3512+
jsonb
3513+
-------
3514+
"2"
3515+
(1 row)
3516+
3517+
select ('[1, "2", null]'::jsonb)[1]['a'];
3518+
jsonb
3519+
-------
3520+
3521+
(1 row)
3522+
3523+
select ('[1, "2", null]'::jsonb)[1][0];
3524+
jsonb
3525+
-------
3526+
3527+
(1 row)
3528+
34513529
select ('{"a": 1, "b": "c", "d": [1, 2, 3]}'::jsonb)['b'];
34523530
jsonb
34533531
-------
@@ -3460,7 +3538,13 @@ select ('{"a": 1, "b": "c", "d": [1, 2, 3]}'::jsonb)['d'];
34603538
[1, 2, 3]
34613539
(1 row)
34623540

3463-
select ('{"a": 1}'::jsonb)['not_exist'];
3541+
select ('{"a": 1, "b": "c", "d": [1, 2, 3]}'::jsonb)['d'][1];
3542+
jsonb
3543+
-------
3544+
2
3545+
(1 row)
3546+
3547+
select ('{"a": 1, "b": "c", "d": [1, 2, 3]}'::jsonb)['d']['a'];
34643548
jsonb
34653549
-------
34663550

@@ -3484,6 +3568,18 @@ select ('{"a": {"a1": {"a2": "aaa"}}, "b": "bbb", "c": "ccc"}'::jsonb)['a']['a1'
34843568

34853569
(1 row)
34863570

3571+
select ('{"a": ["a1", {"b1": ["aaa", "bbb", "ccc"]}], "b": "bb"}'::jsonb)['a'][1]['b1'];
3572+
jsonb
3573+
-----------------------
3574+
["aaa", "bbb", "ccc"]
3575+
(1 row)
3576+
3577+
select ('{"a": ["a1", {"b1": ["aaa", "bbb", "ccc"]}], "b": "bb"}'::jsonb)['a'][1]['b1'][2];
3578+
jsonb
3579+
-------
3580+
"ccc"
3581+
(1 row)
3582+
34873583
create TEMP TABLE test_jsonb_subscript (
34883584
id int,
34893585
test_json jsonb

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp