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

Commit5070aad

Browse files
author
Nikita Glukhov
committed
Add JSON_QUERY support for row, array and domain types
1 parent3287f38 commit5070aad

File tree

7 files changed

+125
-3
lines changed

7 files changed

+125
-3
lines changed

‎src/backend/executor/execExpr.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2272,6 +2272,8 @@ ExecInitExprRec(Expr *node, ExprState *state,
22722272
lappend(scratch.d.jsonexpr.args,var);
22732273
}
22742274

2275+
scratch.d.jsonexpr.cache=NULL;
2276+
22752277
if (jexpr->coercions)
22762278
{
22772279
JsonCoercion**coercion;

‎src/backend/executor/execExprInterp.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4563,6 +4563,13 @@ ExecEvalJsonExprCoercion(ExprEvalStep *op, ExprContext *econtext,
45634563
elseif (op->d.jsonexpr.result_expr)
45644564
res=ExecEvalExprPassingCaseValue(op->d.jsonexpr.result_expr,econtext,
45654565
isNull,res,*isNull);
4566+
elseif (coercion&&coercion->via_populate)
4567+
res=json_populate_type(res,JSONBOID,
4568+
jexpr->returning->typid,
4569+
jexpr->returning->typmod,
4570+
&op->d.jsonexpr.cache,
4571+
econtext->ecxt_per_query_memory,
4572+
isNull);
45664573
/* else no coercion, simply return item */
45674574

45684575
returnres;

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

Lines changed: 47 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2628,11 +2628,11 @@ populate_array_dim_jsonb(PopulateArrayContext *ctx, /* context */
26282628

26292629
check_stack_depth();
26302630

2631-
if (jbv->type!=jbvBinary|| !JsonContainerIsArray(jbc))
2631+
if (jbv->type!=jbvBinary||
2632+
!JsonContainerIsArray(jbc)||
2633+
JsonContainerIsScalar(jbc))
26322634
populate_array_report_expected_array(ctx,ndim-1);
26332635

2634-
Assert(!JsonContainerIsScalar(jbc));
2635-
26362636
it=JsonbIteratorInit(jbc);
26372637

26382638
tok=JsonbIteratorNext(&it,&val, true);
@@ -3104,6 +3104,50 @@ populate_record_field(ColumnIOData *col,
31043104
}
31053105
}
31063106

3107+
/* recursively populate specified type from a json/jsonb value */
3108+
Datum
3109+
json_populate_type(Datumjson_val,Oidjson_type,Oidtypid,int32typmod,
3110+
void**cache,MemoryContextmcxt,bool*isnull)
3111+
{
3112+
JsValuejsv= {0 };
3113+
JsonbValuejbv;
3114+
3115+
jsv.is_json=json_type==JSONOID;
3116+
3117+
if (*isnull)
3118+
{
3119+
if (jsv.is_json)
3120+
jsv.val.json.str=NULL;
3121+
else
3122+
jsv.val.jsonb=NULL;
3123+
}
3124+
elseif (jsv.is_json)
3125+
{
3126+
text*json=DatumGetTextPP(json_val);
3127+
3128+
jsv.val.json.str=VARDATA_ANY(json);
3129+
jsv.val.json.len=VARSIZE_ANY_EXHDR(json);
3130+
jsv.val.json.type=JSON_TOKEN_INVALID;/* not used in populate_composite() */
3131+
}
3132+
else
3133+
{
3134+
Jsonb*jsonb=DatumGetJsonbP(json_val);
3135+
3136+
jsv.val.jsonb=&jbv;
3137+
3138+
/* fill binary jsonb value pointing to jb */
3139+
jbv.type=jbvBinary;
3140+
jbv.val.binary.data=&jsonb->root;
3141+
jbv.val.binary.len=VARSIZE(jsonb)-VARHDRSZ;
3142+
}
3143+
3144+
if (!*cache)
3145+
*cache=MemoryContextAllocZero(mcxt,sizeof(ColumnIOData));
3146+
3147+
returnpopulate_record_field(*cache ,typid,typmod,NULL,mcxt,
3148+
PointerGetDatum(NULL),&jsv,isnull);
3149+
}
3150+
31073151
staticRecordIOData*
31083152
allocate_record_info(MemoryContextmcxt,intncolumns)
31093153
{

‎src/include/executor/execExpr.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -684,6 +684,8 @@ typedef struct ExprEvalStep
684684
ExprState*default_on_error;/* ON ERROR DEFAULT expression */
685685
List*args;/* passing arguments */
686686

687+
void*cache;/* cache for json_populate_type() */
688+
687689
structJsonCoercionsState
688690
{
689691
structJsonCoercionState

‎src/include/utils/jsonfuncs.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,4 +58,8 @@ extern Jsonb *transform_jsonb_string_values(Jsonb *jsonb, void *action_state,
5858
externtext*transform_json_string_values(text*json,void*action_state,
5959
JsonTransformStringValuesActiontransform_action);
6060

61+
externDatumjson_populate_type(Datumjson_val,Oidjson_type,
62+
Oidtypid,int32typmod,
63+
void**cache,MemoryContextmcxt,bool*isnull);
64+
6165
#endif

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

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -758,6 +758,53 @@ FROM
758758
4 | 4 | [4]
759759
(25 rows)
760760

761+
-- Extension: record types returning
762+
CREATE TYPE sqljsonb_rec AS (a int, t text, js json, jb jsonb, jsa json[]);
763+
CREATE TYPE sqljsonb_reca AS (reca sqljsonb_rec[]);
764+
SELECT JSON_QUERY(jsonb '[{"a": 1, "b": "foo", "t": "aaa", "js": [1, "2", {}], "jb": {"x": [1, "2", {}]}}, {"a": 2}]', '$[0]' RETURNING sqljsonb_rec);
765+
json_query
766+
-----------------------------------------------------
767+
(1,aaa,"[1, ""2"", {}]","{""x"": [1, ""2"", {}]}",)
768+
(1 row)
769+
770+
SELECT * FROM unnest((JSON_QUERY(jsonb '{"jsa": [{"a": 1, "b": ["foo"]}, {"a": 2, "c": {}}, 123]}', '$' RETURNING sqljsonb_rec)).jsa);
771+
unnest
772+
------------------------
773+
{"a": 1, "b": ["foo"]}
774+
{"a": 2, "c": {}}
775+
123
776+
(3 rows)
777+
778+
SELECT * FROM unnest((JSON_QUERY(jsonb '{"reca": [{"a": 1, "t": ["foo", []]}, {"a": 2, "jb": [{}, true]}]}', '$' RETURNING sqljsonb_reca)).reca);
779+
a | t | js | jb | jsa
780+
---+-------------+----+------------+-----
781+
1 | ["foo", []] | | |
782+
2 | | | [{}, true] |
783+
(2 rows)
784+
785+
-- Extension: array types returning
786+
SELECT JSON_QUERY(jsonb '[1,2,null,"3"]', '$[*]' RETURNING int[] WITH WRAPPER);
787+
json_query
788+
--------------
789+
{1,2,NULL,3}
790+
(1 row)
791+
792+
SELECT * FROM unnest(JSON_QUERY(jsonb '[{"a": 1, "t": ["foo", []]}, {"a": 2, "jb": [{}, true]}]', '$' RETURNING sqljsonb_rec[]));
793+
a | t | js | jb | jsa
794+
---+-------------+----+------------+-----
795+
1 | ["foo", []] | | |
796+
2 | | | [{}, true] |
797+
(2 rows)
798+
799+
-- Extension: domain types returning
800+
SELECT JSON_QUERY(jsonb '{"a": 1}', '$.a' RETURNING sqljsonb_int_not_null);
801+
json_query
802+
------------
803+
1
804+
(1 row)
805+
806+
SELECT JSON_QUERY(jsonb '{"a": 1}', '$.b' RETURNING sqljsonb_int_not_null);
807+
ERROR: domain sqljsonb_int_not_null does not allow null values
761808
-- Test constraints
762809
CREATE TABLE test_jsonb_constraints (
763810
js text,

‎src/test/regress/sql/jsonb_sqljson.sql

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,22 @@ FROM
214214
generate_series(0,4) x,
215215
generate_series(0,4) y;
216216

217+
-- Extension: record types returning
218+
CREATETYPEsqljsonb_recAS (aint, ttext, js json, jb jsonb, jsa json[]);
219+
CREATETYPEsqljsonb_recaAS (reca sqljsonb_rec[]);
220+
221+
SELECT JSON_QUERY(jsonb'[{"a": 1, "b": "foo", "t": "aaa", "js": [1, "2", {}], "jb": {"x": [1, "2", {}]}}, {"a": 2}]','$[0]' RETURNING sqljsonb_rec);
222+
SELECT*FROM unnest((JSON_QUERY(jsonb'{"jsa": [{"a": 1, "b": ["foo"]}, {"a": 2, "c": {}}, 123]}','$' RETURNING sqljsonb_rec)).jsa);
223+
SELECT*FROM unnest((JSON_QUERY(jsonb'{"reca": [{"a": 1, "t": ["foo", []]}, {"a": 2, "jb": [{}, true]}]}','$' RETURNING sqljsonb_reca)).reca);
224+
225+
-- Extension: array types returning
226+
SELECT JSON_QUERY(jsonb'[1,2,null,"3"]','$[*]' RETURNINGint[] WITH WRAPPER);
227+
SELECT*FROM unnest(JSON_QUERY(jsonb'[{"a": 1, "t": ["foo", []]}, {"a": 2, "jb": [{}, true]}]','$' RETURNING sqljsonb_rec[]));
228+
229+
-- Extension: domain types returning
230+
SELECT JSON_QUERY(jsonb'{"a": 1}','$.a' RETURNING sqljsonb_int_not_null);
231+
SELECT JSON_QUERY(jsonb'{"a": 1}','$.b' RETURNING sqljsonb_int_not_null);
232+
217233
-- Test constraints
218234

219235
CREATETABLEtest_jsonb_constraints (

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp