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

Commit33a3776

Browse files
committed
IS JSON predicate
This patch intrdocuces the SQL standard IS JSON predicate. It operateson text and bytea values representing JSON as well as on the json andjsonb types. Each test has an IS and IS NOT variant. The tests are:IS JSON [VALUE]IS JSON ARRAYIS JSON OBJECTIS JSON SCALARIS JSON WITH | WITHOUT UNIQUE KEYSThese are mostly self-explanatory, but note that IS JSON WITHOUT UNIQUEKEYS is true whenever IS JSON is true, and IS JSON WITH UNIQUE KEYS istrue whenever IS JSON is true except it IS JSON OBJECT is true and thereare duplicate keys (which is never the case when applied to jsonb values).Nikita GlukhovReviewers have included (in no particular order) Andres Freund, AlexanderKorotkov, Pavel Stehule, Andrew Alsup, Erik Rijkers, Zihong Yu,Himanshu Upadhyaya, Daniel Gustafsson, Justin Pryzby.Discussion:https://postgr.es/m/cd0bb935-0158-78a7-08b5-904886deac4b@postgrespro.ru
1 parent6198420 commit33a3776

25 files changed

+856
-17
lines changed

‎src/backend/executor/execExpr.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2513,6 +2513,19 @@ ExecInitExprRec(Expr *node, ExprState *state,
25132513
}
25142514
break;
25152515

2516+
caseT_JsonIsPredicate:
2517+
{
2518+
JsonIsPredicate*pred= (JsonIsPredicate*)node;
2519+
2520+
ExecInitExprRec((Expr*)pred->expr,state,resv,resnull);
2521+
2522+
scratch.opcode=EEOP_IS_JSON;
2523+
scratch.d.is_json.pred=pred;
2524+
2525+
ExprEvalPushStep(state,&scratch);
2526+
break;
2527+
}
2528+
25162529
default:
25172530
elog(ERROR,"unrecognized node type: %d",
25182531
(int)nodeTag(node));

‎src/backend/executor/execExprInterp.c

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@
7373
#include"utils/expandedrecord.h"
7474
#include"utils/json.h"
7575
#include"utils/jsonb.h"
76+
#include"utils/jsonfuncs.h"
7677
#include"utils/lsyscache.h"
7778
#include"utils/memutils.h"
7879
#include"utils/timestamp.h"
@@ -480,6 +481,7 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
480481
&&CASE_EEOP_WINDOW_FUNC,
481482
&&CASE_EEOP_SUBPLAN,
482483
&&CASE_EEOP_JSON_CONSTRUCTOR,
484+
&&CASE_EEOP_IS_JSON,
483485
&&CASE_EEOP_AGG_STRICT_DESERIALIZE,
484486
&&CASE_EEOP_AGG_DESERIALIZE,
485487
&&CASE_EEOP_AGG_STRICT_INPUT_CHECK_ARGS,
@@ -1799,6 +1801,14 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
17991801
EEO_NEXT();
18001802
}
18011803

1804+
EEO_CASE(EEOP_IS_JSON)
1805+
{
1806+
/* too complex for an inline implementation */
1807+
ExecEvalJsonIsPredicate(state,op);
1808+
1809+
EEO_NEXT();
1810+
}
1811+
18021812
EEO_CASE(EEOP_LAST)
18031813
{
18041814
/* unreachable */
@@ -3909,6 +3919,91 @@ ExecEvalXmlExpr(ExprState *state, ExprEvalStep *op)
39093919
}
39103920
}
39113921

3922+
void
3923+
ExecEvalJsonIsPredicate(ExprState*state,ExprEvalStep*op)
3924+
{
3925+
JsonIsPredicate*pred=op->d.is_json.pred;
3926+
Datumjs=*op->resvalue;
3927+
Oidexprtype;
3928+
boolres;
3929+
3930+
if (*op->resnull)
3931+
{
3932+
*op->resvalue=BoolGetDatum(false);
3933+
return;
3934+
}
3935+
3936+
exprtype=exprType(pred->expr);
3937+
3938+
if (exprtype==TEXTOID||exprtype==JSONOID)
3939+
{
3940+
text*json=DatumGetTextP(js);
3941+
3942+
if (pred->value_type==JS_TYPE_ANY)
3943+
res= true;
3944+
else
3945+
{
3946+
switch (json_get_first_token(json, false))
3947+
{
3948+
caseJSON_TOKEN_OBJECT_START:
3949+
res=pred->value_type==JS_TYPE_OBJECT;
3950+
break;
3951+
caseJSON_TOKEN_ARRAY_START:
3952+
res=pred->value_type==JS_TYPE_ARRAY;
3953+
break;
3954+
caseJSON_TOKEN_STRING:
3955+
caseJSON_TOKEN_NUMBER:
3956+
caseJSON_TOKEN_TRUE:
3957+
caseJSON_TOKEN_FALSE:
3958+
caseJSON_TOKEN_NULL:
3959+
res=pred->value_type==JS_TYPE_SCALAR;
3960+
break;
3961+
default:
3962+
res= false;
3963+
break;
3964+
}
3965+
}
3966+
3967+
/*
3968+
* Do full parsing pass only for uniqueness check or for
3969+
* JSON text validation.
3970+
*/
3971+
if (res&& (pred->unique_keys||exprtype==TEXTOID))
3972+
res=json_validate(json,pred->unique_keys);
3973+
}
3974+
elseif (exprtype==JSONBOID)
3975+
{
3976+
if (pred->value_type==JS_TYPE_ANY)
3977+
res= true;
3978+
else
3979+
{
3980+
Jsonb*jb=DatumGetJsonbP(js);
3981+
3982+
switch (pred->value_type)
3983+
{
3984+
caseJS_TYPE_OBJECT:
3985+
res=JB_ROOT_IS_OBJECT(jb);
3986+
break;
3987+
caseJS_TYPE_ARRAY:
3988+
res=JB_ROOT_IS_ARRAY(jb)&& !JB_ROOT_IS_SCALAR(jb);
3989+
break;
3990+
caseJS_TYPE_SCALAR:
3991+
res=JB_ROOT_IS_ARRAY(jb)&&JB_ROOT_IS_SCALAR(jb);
3992+
break;
3993+
default:
3994+
res= false;
3995+
break;
3996+
}
3997+
}
3998+
3999+
/* Key uniqueness check is redundant for jsonb */
4000+
}
4001+
else
4002+
res= false;
4003+
4004+
*op->resvalue=BoolGetDatum(res);
4005+
}
4006+
39124007
/*
39134008
* ExecEvalGroupingFunc
39144009
*

‎src/backend/jit/llvm/llvmjit_expr.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2354,6 +2354,12 @@ llvm_compile_expr(ExprState *state)
23542354
LLVMBuildBr(b,opblocks[opno+1]);
23552355
break;
23562356

2357+
caseEEOP_IS_JSON:
2358+
build_EvalXFunc(b,mod,"ExecEvalJsonIsPredicate",
2359+
v_state,op);
2360+
LLVMBuildBr(b,opblocks[opno+1]);
2361+
break;
2362+
23572363
caseEEOP_LAST:
23582364
Assert(false);
23592365
break;

‎src/backend/jit/llvm/llvmjit_types.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ void *referenced_functions[] =
132132
ExecEvalWholeRowVar,
133133
ExecEvalXmlExpr,
134134
ExecEvalJsonConstructor,
135+
ExecEvalJsonIsPredicate,
135136
MakeExpandedObjectReadOnlyInternal,
136137
slot_getmissingattrs,
137138
slot_getsomeattrs_int,

‎src/backend/nodes/copyfuncs.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2491,6 +2491,23 @@ _copyJsonArrayQueryConstructor(const JsonArrayQueryConstructor *from)
24912491
returnnewnode;
24922492
}
24932493

2494+
/*
2495+
* _copyJsonIsPredicate
2496+
*/
2497+
staticJsonIsPredicate*
2498+
_copyJsonIsPredicate(constJsonIsPredicate*from)
2499+
{
2500+
JsonIsPredicate*newnode=makeNode(JsonIsPredicate);
2501+
2502+
COPY_NODE_FIELD(expr);
2503+
COPY_SCALAR_FIELD(format);
2504+
COPY_SCALAR_FIELD(value_type);
2505+
COPY_SCALAR_FIELD(unique_keys);
2506+
COPY_LOCATION_FIELD(location);
2507+
2508+
returnnewnode;
2509+
}
2510+
24942511
/* ****************************************************************
24952512
*pathnodes.h copy functions
24962513
*
@@ -5625,6 +5642,9 @@ copyObjectImpl(const void *from)
56255642
caseT_JsonArrayAgg:
56265643
retval=_copyJsonArrayAgg(from);
56275644
break;
5645+
caseT_JsonIsPredicate:
5646+
retval=_copyJsonIsPredicate(from);
5647+
break;
56285648

56295649
/*
56305650
* RELATION NODES

‎src/backend/nodes/equalfuncs.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -976,6 +976,18 @@ _equalJsonArrayQueryConstructor(const JsonArrayQueryConstructor *a,
976976
return true;
977977
}
978978

979+
staticbool
980+
_equalJsonIsPredicate(constJsonIsPredicate*a,
981+
constJsonIsPredicate*b)
982+
{
983+
COMPARE_NODE_FIELD(expr);
984+
COMPARE_SCALAR_FIELD(value_type);
985+
COMPARE_SCALAR_FIELD(unique_keys);
986+
COMPARE_LOCATION_FIELD(location);
987+
988+
return true;
989+
}
990+
979991
/*
980992
* Stuff from pathnodes.h
981993
*/
@@ -3546,6 +3558,9 @@ equal(const void *a, const void *b)
35463558
caseT_JsonConstructorExpr:
35473559
retval=_equalJsonConstructorExpr(a,b);
35483560
break;
3561+
caseT_JsonIsPredicate:
3562+
retval=_equalJsonIsPredicate(a,b);
3563+
break;
35493564

35503565
/*
35513566
* RELATION NODES

‎src/backend/nodes/makefuncs.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -887,3 +887,22 @@ makeJsonKeyValue(Node *key, Node *value)
887887

888888
return (Node*)n;
889889
}
890+
891+
/*
892+
* makeJsonIsPredicate -
893+
* creates a JsonIsPredicate node
894+
*/
895+
Node*
896+
makeJsonIsPredicate(Node*expr,JsonFormat*format,JsonValueTypevalue_type,
897+
boolunique_keys,intlocation)
898+
{
899+
JsonIsPredicate*n=makeNode(JsonIsPredicate);
900+
901+
n->expr=expr;
902+
n->format=format;
903+
n->value_type=value_type;
904+
n->unique_keys=unique_keys;
905+
n->location=location;
906+
907+
return (Node*)n;
908+
}

‎src/backend/nodes/nodeFuncs.c

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,9 @@ exprType(const Node *expr)
260260
caseT_JsonConstructorExpr:
261261
type= ((constJsonConstructorExpr*)expr)->returning->typid;
262262
break;
263+
caseT_JsonIsPredicate:
264+
type=BOOLOID;
265+
break;
263266
default:
264267
elog(ERROR,"unrecognized node type: %d", (int)nodeTag(expr));
265268
type=InvalidOid;/* keep compiler quiet */
@@ -985,6 +988,9 @@ exprCollation(const Node *expr)
985988
coll=InvalidOid;
986989
}
987990
break;
991+
caseT_JsonIsPredicate:
992+
coll=InvalidOid;/* result is always an boolean type */
993+
break;
988994
default:
989995
elog(ERROR,"unrecognized node type: %d", (int)nodeTag(expr));
990996
coll=InvalidOid;/* keep compiler quiet */
@@ -1211,6 +1217,9 @@ exprSetCollation(Node *expr, Oid collation)
12111217
Assert(!OidIsValid(collation));/* result is always a json[b] type */
12121218
}
12131219
break;
1220+
caseT_JsonIsPredicate:
1221+
Assert(!OidIsValid(collation));/* result is always boolean */
1222+
break;
12141223
default:
12151224
elog(ERROR,"unrecognized node type: %d", (int)nodeTag(expr));
12161225
break;
@@ -1663,6 +1672,9 @@ exprLocation(const Node *expr)
16631672
caseT_JsonConstructorExpr:
16641673
loc= ((constJsonConstructorExpr*)expr)->location;
16651674
break;
1675+
caseT_JsonIsPredicate:
1676+
loc= ((constJsonIsPredicate*)expr)->location;
1677+
break;
16661678
default:
16671679
/* for any other node type it's just unknown... */
16681680
loc=-1;
@@ -2429,6 +2441,8 @@ expression_tree_walker(Node *node,
24292441
return true;
24302442
}
24312443
break;
2444+
caseT_JsonIsPredicate:
2445+
returnwalker(((JsonIsPredicate*)node)->expr,context);
24322446
default:
24332447
elog(ERROR,"unrecognized node type: %d",
24342448
(int)nodeTag(node));
@@ -3438,6 +3452,16 @@ expression_tree_mutator(Node *node,
34383452
MUTATE(newnode->coercion,jve->coercion,Expr*);
34393453
MUTATE(newnode->returning,jve->returning,JsonReturning*);
34403454

3455+
return (Node*)newnode;
3456+
}
3457+
caseT_JsonIsPredicate:
3458+
{
3459+
JsonIsPredicate*pred= (JsonIsPredicate*)node;
3460+
JsonIsPredicate*newnode;
3461+
3462+
FLATCOPY(newnode,pred,JsonIsPredicate);
3463+
MUTATE(newnode->expr,pred->expr,Node*);
3464+
34413465
return (Node*)newnode;
34423466
}
34433467
default:
@@ -4290,6 +4314,8 @@ raw_expression_tree_walker(Node *node,
42904314
return true;
42914315
}
42924316
break;
4317+
caseT_JsonIsPredicate:
4318+
returnwalker(((JsonIsPredicate*)node)->expr,context);
42934319
default:
42944320
elog(ERROR,"unrecognized node type: %d",
42954321
(int)nodeTag(node));

‎src/backend/nodes/outfuncs.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1797,6 +1797,17 @@ _outJsonConstructorExpr(StringInfo str, const JsonConstructorExpr *node)
17971797
WRITE_LOCATION_FIELD(location);
17981798
}
17991799

1800+
staticvoid
1801+
_outJsonIsPredicate(StringInfostr,constJsonIsPredicate*node)
1802+
{
1803+
WRITE_NODE_TYPE("JSONISPREDICATE");
1804+
1805+
WRITE_NODE_FIELD(expr);
1806+
WRITE_ENUM_FIELD(value_type,JsonValueType);
1807+
WRITE_BOOL_FIELD(unique_keys);
1808+
WRITE_LOCATION_FIELD(location);
1809+
}
1810+
18001811
/*****************************************************************************
18011812
*
18021813
*Stuff from pathnodes.h.
@@ -4630,6 +4641,9 @@ outNode(StringInfo str, const void *obj)
46304641
caseT_JsonConstructorExpr:
46314642
_outJsonConstructorExpr(str,obj);
46324643
break;
4644+
caseT_JsonIsPredicate:
4645+
_outJsonIsPredicate(str,obj);
4646+
break;
46334647

46344648
default:
46354649

‎src/backend/nodes/readfuncs.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1492,6 +1492,22 @@ _readJsonConstructorExpr(void)
14921492
READ_DONE();
14931493
}
14941494

1495+
/*
1496+
* _readJsonIsPredicate
1497+
*/
1498+
staticJsonIsPredicate*
1499+
_readJsonIsPredicate()
1500+
{
1501+
READ_LOCALS(JsonIsPredicate);
1502+
1503+
READ_NODE_FIELD(expr);
1504+
READ_ENUM_FIELD(value_type,JsonValueType);
1505+
READ_BOOL_FIELD(unique_keys);
1506+
READ_LOCATION_FIELD(location);
1507+
1508+
READ_DONE();
1509+
}
1510+
14951511
/*
14961512
*Stuff from pathnodes.h.
14971513
*
@@ -3090,6 +3106,8 @@ parseNodeString(void)
30903106
return_value=_readJsonValueExpr();
30913107
elseif (MATCH("JSONCTOREXPR",12))
30923108
return_value=_readJsonConstructorExpr();
3109+
elseif (MATCH("JSONISPREDICATE",15))
3110+
return_value=_readJsonIsPredicate();
30933111
else
30943112
{
30953113
elog(ERROR,"badly formatted node string \"%.32s\"...",token);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp