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

Commitef30f6f

Browse files
committed
add jsonb any element
1 parenta4656b3 commitef30f6f

File tree

6 files changed

+236
-25
lines changed

6 files changed

+236
-25
lines changed

‎src/backend/parser/gram.y

Lines changed: 53 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -176,8 +176,8 @@ static void processCASbits(int cas_bits, int location, const char *constrType,
176176
bool *deferrable,bool *initdeferred,bool *not_valid,
177177
bool *no_inherit,core_yyscan_t yyscanner);
178178
static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
179-
static SelectStmt *makeElementSubselect(Node *of,constchar *aliasname,
180-
Node *clause,int location);
179+
static SelectStmt *makeElementSubselect(int kind,bool recursive, Node *of,
180+
constchar *aliasname,Node *clause,int location);
181181

182182
%}
183183

@@ -291,6 +291,7 @@ static SelectStmt * makeElementSubselect(Node *of, const char *aliasname,
291291
%type<boolean>opt_or_replace
292292
opt_grant_grant_optionopt_grant_admin_option
293293
opt_nowaitopt_if_existsopt_with_data
294+
opt_anywhere
294295
%type<ival>opt_nowait_or_skip
295296

296297
%type<list>OptRoleListAlterOptRoleList
@@ -448,6 +449,7 @@ static SelectStmt * makeElementSubselect(Node *of, const char *aliasname,
448449
%type<node>case_exprcase_argwhen_clausecase_default
449450
%type<list>when_clause_list
450451
%type<ival>sub_type
452+
%type<ival>any_or_eachany_or_each_kind
451453
%type<node>ctext_expr
452454
%type<value>NumericOnly
453455
%type<list>NumericOnly_list
@@ -563,7 +565,7 @@ static SelectStmt * makeElementSubselect(Node *of, const char *aliasname,
563565

564566
/* ordinary key words in alphabetical order*/
565567
%token<keyword>ABORT_PABSOLUTE_PACCESSACTIONADD_PADMINAFTER
566-
AGGREGATE ALL ALSO ALTER ALWAYS ANALYSE ANALYZE AND ANY ARRAY AS ASC
568+
AGGREGATE ALL ALSO ALTER ALWAYS ANALYSE ANALYZE AND ANYANYWHEREARRAY AS ASC
567569
ASSERTION ASSIGNMENT ASYMMETRIC AT ATTRIBUTE AUTHORIZATION
568570

569571
BACKWARD BEFORE BEGIN_P BETWEEN BIGINT BINARY BIT
@@ -12058,30 +12060,42 @@ c_expr:columnref{ $$ = $1; }
1205812060
g->location =@1;
1205912061
$$ = (Node *)g;
1206012062
}
12061-
|ANY_ELELEMENTOFb_exprASColIdSATISFIES'('a_expr')'
12063+
|any_or_eachany_or_each_kindopt_anywhereOFb_exprASColIdSATISFIES'('a_expr')'
1206212064
{
1206312065
SubLink*n = makeNode(SubLink);
1206412066

1206512067
n->subLinkType = EXISTS_SUBLINK;
1206612068
n->subLinkId =0;
1206712069
n->testexpr =NULL;
1206812070
n->operName = NIL;
12069-
n->subselect = (Node*)makeElementSubselect($4,$6,$9,@1);
12071+
n->subselect = (Node*)makeElementSubselect(
12072+
$2,$3,
12073+
$5,$7,
12074+
($1 == EACH) ? makeNotExpr($10,@1) :$10,
12075+
@1
12076+
);
1207012077
n->location =@1;
12071-
$$ = (Node *)n;
12078+
if ($1 == EACH)
12079+
$$ = makeNotExpr((Node *)n,@1);
12080+
else
12081+
$$ = (Node *)n;
1207212082
}
12073-
|EACHELEMENTOFb_exprASColIdSATISFIES'('a_expr')'
12074-
{
12075-
SubLink*n = makeNode(SubLink);
12083+
;
1207612084

12077-
n->subLinkType = EXISTS_SUBLINK;
12078-
n->subLinkId =0;
12079-
n->testexpr =NULL;
12080-
n->operName = NIL;
12081-
n->subselect = (Node*)makeElementSubselect($4,$6, makeNotExpr($9,@1),@1);
12082-
n->location =@1;
12083-
$$ = makeNotExpr((Node *)n,@1);;
12084-
}
12085+
any_or_each:
12086+
ANY_EL{$$ = ANY_EL; }
12087+
|EACH{$$ = EACH; }
12088+
;
12089+
12090+
any_or_each_kind:
12091+
ELEMENT{$$ = ELEMENT; }
12092+
|KEY{$$ = KEY; }
12093+
|VALUE_P{$$ = VALUE_P; }
12094+
;
12095+
12096+
opt_anywhere:
12097+
ANYWHERE{$$ =true; }
12098+
|/* empty*/{$$ =false; }
1208512099
;
1208612100

1208712101
func_application:func_name'('')'
@@ -13614,6 +13628,7 @@ unreserved_keyword:
1361413628
| ALSO
1361513629
| ALTER
1361613630
| ALWAYS
13631+
| ANYWHERE
1361713632
| ASSERTION
1361813633
| ASSIGNMENT
1361913634
| AT
@@ -14858,17 +14873,36 @@ makeRecursiveViewSelect(char *relname, List *aliases, Node *query)
1485814873
}
1485914874

1486014875
static SelectStmt *
14861-
makeElementSubselect(Node *of, const char *aliasname, Node *clause, int location)
14876+
makeElementSubselect(int kind, bool recursive, Node *of,
14877+
const char *aliasname, Node *clause, int location)
1486214878
{
1486314879
ResTarget *target = makeNode(ResTarget);
1486414880
FuncCall*func_call;
1486514881
RangeFunction*table_ref = makeNode(RangeFunction);
1486614882
SelectStmt *subselect = makeNode(SelectStmt);
14883+
char*funcname;
1486714884

1486814885
target->val = (Node*)makeIntConst(1, location);
1486914886
target->location = location;
1487014887

14871-
func_call = makeFuncCall(SystemFuncName("unnest"), list_make1(of), location);
14888+
switch(kind)
14889+
{
14890+
case ELEMENT:
14891+
funcname = "unnest_element";
14892+
break;
14893+
case KEY:
14894+
funcname = "unnest_key";
14895+
break;
14896+
case VALUE_P:
14897+
funcname = "unnest_value";
14898+
break;
14899+
default:
14900+
elog(ERROR,"unkown ANY_EL");
14901+
}
14902+
14903+
func_call = makeFuncCall(SystemFuncName(funcname),
14904+
list_make2(of, makeBoolAConst(recursive, location)),
14905+
location);
1487214906

1487314907
table_ref->functions = list_make1(list_make2(func_call, NIL));
1487414908
table_ref->alias = makeAlias(aliasname, NIL);

‎src/backend/parser/parser.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -191,8 +191,15 @@ base_yylex(YYSTYPE *lvalp, YYLTYPE *llocp, core_yyscan_t yyscanner)
191191
}
192192
break;
193193
caseANY:
194-
if (next_token==ELEMENT)
195-
cur_token=ANY_EL;
194+
/* Replace ANY by ANY_EL if it's followed by ELEMENT or KEY or VALUE */
195+
switch (next_token)
196+
{
197+
caseELEMENT:
198+
caseKEY:
199+
caseVALUE_P:
200+
cur_token=ANY_EL;
201+
break;
202+
}
196203
break;
197204
}
198205

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

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3898,3 +3898,156 @@ replacePathArray(JsonbIterator **it, Datum *path_elems, bool *path_nulls,
38983898
}
38993899
}
39003900
}
3901+
3902+
typedefstructUnnestState
3903+
{
3904+
MemoryContextctx;
3905+
Jsonb*jb;
3906+
JsonbIterator*it;
3907+
boolskipNested;
3908+
JsonbIteratorTokentype;
3909+
}
3910+
UnnestState;
3911+
3912+
staticvoidfiniUnnest(UnnestState*state);
3913+
3914+
staticvoid
3915+
initUnnest(FuncCallContext*funcctx,Datumjsonb,boolrecursive,
3916+
JsonbIteratorTokentype)
3917+
{
3918+
MemoryContextoldcontext;
3919+
UnnestState*state;
3920+
JsonbValuev;
3921+
intr;
3922+
3923+
oldcontext=MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
3924+
3925+
state=palloc0(sizeof(*state));
3926+
state->ctx=funcctx->multi_call_memory_ctx;
3927+
state->jb=DatumGetJsonbCopy(jsonb);
3928+
state->it=JsonbIteratorInit(&state->jb->root);
3929+
state->skipNested= !recursive;
3930+
state->type=type;
3931+
3932+
r=JsonbIteratorNext(&state->it,&v, false);
3933+
3934+
if (JB_ROOT_IS_SCALAR(state->jb))
3935+
{
3936+
r=JsonbIteratorNext(&state->it,&v, true);
3937+
r=JsonbIteratorNext(&state->it,&v, true);
3938+
Assert(r==WJB_DONE);
3939+
}
3940+
3941+
MemoryContextSwitchTo(oldcontext);
3942+
3943+
if (r==WJB_DONE)
3944+
{
3945+
finiUnnest(state);
3946+
state=NULL;
3947+
}
3948+
3949+
funcctx->user_fctx= (void*)state;
3950+
}
3951+
3952+
staticJsonb*
3953+
nextUnnest(UnnestState*state)
3954+
{
3955+
MemoryContextoldcontext;
3956+
JsonbValuev;
3957+
intr;
3958+
3959+
/*
3960+
* Iterator should work in long-lived memory context
3961+
*/
3962+
oldcontext=MemoryContextSwitchTo(state->ctx);
3963+
3964+
while((r=JsonbIteratorNext(&state->it,&v,state->skipNested))!=WJB_DONE)
3965+
{
3966+
if (r==state->type)
3967+
break;
3968+
}
3969+
3970+
MemoryContextSwitchTo(oldcontext);
3971+
3972+
return (r==state->type) ?JsonbValueToJsonb(&v) :NULL;
3973+
}
3974+
3975+
staticvoid
3976+
finiUnnest(UnnestState*state)
3977+
{
3978+
if (state)
3979+
{
3980+
pfree(state->jb);
3981+
pfree(state);
3982+
}
3983+
}
3984+
3985+
Datum
3986+
jsonb_unnest_element(PG_FUNCTION_ARGS)
3987+
{
3988+
FuncCallContext*funcctx;
3989+
UnnestState*state;
3990+
Jsonb*r;
3991+
3992+
if (SRF_IS_FIRSTCALL())
3993+
initUnnest(SRF_FIRSTCALL_INIT(),PG_GETARG_DATUM(0),
3994+
PG_GETARG_BOOL(1),WJB_ELEM);
3995+
3996+
funcctx=SRF_PERCALL_SETUP();
3997+
state=funcctx->user_fctx;
3998+
3999+
if (state==NULL|| (r=nextUnnest(state))==NULL)
4000+
{
4001+
finiUnnest(state);
4002+
SRF_RETURN_DONE(funcctx);
4003+
}
4004+
4005+
SRF_RETURN_NEXT(funcctx,JsonbGetDatum(r));
4006+
}
4007+
4008+
Datum
4009+
jsonb_unnest_value(PG_FUNCTION_ARGS)
4010+
{
4011+
FuncCallContext*funcctx;
4012+
UnnestState*state;
4013+
Jsonb*r;
4014+
4015+
if (SRF_IS_FIRSTCALL())
4016+
initUnnest(SRF_FIRSTCALL_INIT(),PG_GETARG_DATUM(0),
4017+
PG_GETARG_BOOL(1),WJB_VALUE);
4018+
4019+
funcctx=SRF_PERCALL_SETUP();
4020+
state=funcctx->user_fctx;
4021+
4022+
if (state==NULL|| (r=nextUnnest(state))==NULL)
4023+
{
4024+
finiUnnest(state);
4025+
SRF_RETURN_DONE(funcctx);
4026+
}
4027+
4028+
SRF_RETURN_NEXT(funcctx,JsonbGetDatum(r));
4029+
}
4030+
4031+
Datum
4032+
jsonb_unnest_key(PG_FUNCTION_ARGS)
4033+
{
4034+
FuncCallContext*funcctx;
4035+
UnnestState*state;
4036+
Jsonb*r;
4037+
4038+
if (SRF_IS_FIRSTCALL())
4039+
initUnnest(SRF_FIRSTCALL_INIT(),PG_GETARG_DATUM(0),
4040+
PG_GETARG_BOOL(1),WJB_KEY);
4041+
4042+
funcctx=SRF_PERCALL_SETUP();
4043+
state=funcctx->user_fctx;
4044+
4045+
if (state==NULL|| (r=nextUnnest(state))==NULL)
4046+
{
4047+
finiUnnest(state);
4048+
SRF_RETURN_DONE(funcctx);
4049+
}
4050+
4051+
SRF_RETURN_NEXT(funcctx,JsonbGetDatum(r));
4052+
}
4053+

‎src/include/catalog/pg_proc.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -924,6 +924,9 @@ DATA(insert OID = 1286 ( array_fill PGNSP PGUID 12 1 0 0 0 f f f f f f i 3 0 22
924924
DESCR("array constructor with value");
925925
DATA(insert OID = 2331 ( unnest PGNSP PGUID 12 1 100 0 0 f f f f t t i 1 0 2283 "2277" _null_ _null_ _null_ _null_ _null_ array_unnest _null_ _null_ _null_ ));
926926
DESCR("expand array to set of rows");
927+
/* just for compatibility with jsonb_unnest* for any/each element clause */
928+
DATA(insert OID = 7644 ( unnest_element PGNSP PGUID 12 1 100 0 0 f f f f t t i 2 0 2283 "2277 16" _null_ _null_ _null_ _null_ _null_ array_unnest _null_ _null_ _null_ ));
929+
DESCR("expand array to set of rows");
927930
DATA(insert OID = 3167 ( array_remove PGNSP PGUID 12 1 0 0 0 f f f f f f i 2 0 2277 "2277 2283" _null_ _null_ _null_ _null_ _null_ array_remove _null_ _null_ _null_ ));
928931
DESCR("remove any occurrences of an element from an array");
929932
DATA(insert OID = 3168 ( array_replace PGNSP PGUID 12 1 0 0 0 f f f f f f i 3 0 2277 "2277 2283 2283" _null_ _null_ _null_ _null_ _null_ array_replace _null_ _null_ _null_ ));
@@ -4863,6 +4866,12 @@ DATA(insert OID = 3305 ( jsonb_replace PGNSP PGUID 12 1 0 0 0 f f f f t f i
48634866
DESCR("Replace part of a jsonb");
48644867
DATA(insert OID = 3306 ( jsonb_pretty PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 25 "3802" _null_ _null_ _null_ _null_ _null_ jsonb_pretty _null_ _null_ _null_ ));
48654868
DESCR("Indented text from jsonb");
4869+
DATA(insert OID = 7645 ( unnest_element PGNSP PGUID 12 1 100 0 0 f f f f t t i 2 0 3802 "3802 16" _null_ _null_ _null_ _null_ _null_ jsonb_unnest_element _null_ _null_ _null_ ));
4870+
DESCR("expand elements from jsonb");
4871+
DATA(insert OID = 7646 ( unnest_value PGNSP PGUID 12 1 100 0 0 f f f f t t i 2 0 3802 "3802 16" _null_ _null_ _null_ _null_ _null_ jsonb_unnest_value _null_ _null_ _null_ ));
4872+
DESCR("expand values from jsonb");
4873+
DATA(insert OID = 7647 ( unnest_key PGNSP PGUID 12 1 100 0 0 f f f f t t i 2 0 3802 "3802 16" _null_ _null_ _null_ _null_ _null_ jsonb_unnest_key _null_ _null_ _null_ ));
4874+
DESCR("expand keys from jsonb");
48664875
/* txid */
48674876
DATA(insert OID = 2939 ( txid_snapshot_inPGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 2970 "2275" _null_ _null_ _null_ _null_ _null_ txid_snapshot_in _null_ _null_ _null_ ));
48684877
DESCR("I/O");

‎src/include/parser/kwlist.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ PG_KEYWORD("analyse", ANALYSE, RESERVED_KEYWORD)/* British spelling */
4242
PG_KEYWORD("analyze",ANALYZE,RESERVED_KEYWORD)
4343
PG_KEYWORD("and",AND,RESERVED_KEYWORD)
4444
PG_KEYWORD("any",ANY,RESERVED_KEYWORD)
45+
PG_KEYWORD("anywhere",ANYWHERE,UNRESERVED_KEYWORD)
4546
PG_KEYWORD("array",ARRAY,RESERVED_KEYWORD)
4647
PG_KEYWORD("as",AS,RESERVED_KEYWORD)
4748
PG_KEYWORD("asc",ASC,RESERVED_KEYWORD)

‎src/include/utils/jsonb.h

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -65,10 +65,12 @@ typedef enum
6565
#defineJGIN_MAXLENGTH125/* max length of text part before hashing */
6666

6767
/* Convenience macros */
68-
#defineDatumGetJsonb(d)((Jsonb *) PG_DETOAST_DATUM(d))
69-
#defineJsonbGetDatum(p)PointerGetDatum(p)
70-
#definePG_GETARG_JSONB(x)DatumGetJsonb(PG_GETARG_DATUM(x))
71-
#definePG_RETURN_JSONB(x)PG_RETURN_POINTER(x)
68+
#defineDatumGetJsonb(d)((Jsonb *) PG_DETOAST_DATUM(d))
69+
#defineDatumGetJsonbCopy(d)((Jsonb *) PG_DETOAST_DATUM_COPY(d))
70+
#defineJsonbGetDatum(p)PointerGetDatum(p)
71+
#definePG_GETARG_JSONB(x)DatumGetJsonb(PG_GETARG_DATUM(x))
72+
#definePG_GETARG_JSONB_COPY(x)DatumGetJsonbCopy(PG_GETARG_DATUM(x))
73+
#definePG_RETURN_JSONB(x)PG_RETURN_POINTER(x)
7274

7375
typedefstructJsonbPairJsonbPair;
7476
typedefstructJsonbValueJsonbValue;
@@ -400,6 +402,11 @@ extern Datum jsonb_pretty(PG_FUNCTION_ARGS);
400402
/* concatenation */
401403
externDatumjsonb_concat(PG_FUNCTION_ARGS);
402404

405+
/* unnesting function */
406+
externDatumjsonb_unnest_element(PG_FUNCTION_ARGS);
407+
externDatumjsonb_unnest_value(PG_FUNCTION_ARGS);
408+
externDatumjsonb_unnest_key(PG_FUNCTION_ARGS);
409+
403410
/* deletion */
404411
Datumjsonb_delete(PG_FUNCTION_ARGS);
405412
Datumjsonb_delete_idx(PG_FUNCTION_ARGS);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp