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

Commit6c13c76

Browse files
author
Nikita Glukhov
committed
Add IS JSON predicate transformation
1 parent3578661 commit6c13c76

File tree

17 files changed

+730
-4
lines changed

17 files changed

+730
-4
lines changed

‎contrib/pg_stat_statements/pg_stat_statements.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3124,6 +3124,16 @@ JumbleExpr(pgssJumbleState *jstate, Node *node)
31243124
APP_JUMB(ctor->absent_on_null);
31253125
}
31263126
break;
3127+
caseT_JsonIsPredicate:
3128+
{
3129+
JsonIsPredicate*pred= (JsonIsPredicate*)node;
3130+
3131+
JumbleExpr(jstate, (Node*)pred->expr);
3132+
JumbleExpr(jstate, (Node*)pred->format);
3133+
APP_JUMB(pred->unique_keys);
3134+
APP_JUMB(pred->value_type);
3135+
}
3136+
break;
31273137
caseT_List:
31283138
foreach(temp, (List*)node)
31293139
{

‎src/backend/executor/execExpr.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2193,6 +2193,11 @@ ExecInitExprRec(Expr *node, ExprState *state,
21932193
}
21942194
break;
21952195

2196+
caseT_JsonIsPredicate:
2197+
ExecInitExprRec((Expr*) ((JsonIsPredicate*)node)->expr,state,resv,
2198+
resnull);
2199+
break;
2200+
21962201
default:
21972202
elog(ERROR,"unrecognized node type: %d",
21982203
(int)nodeTag(node));

‎src/backend/nodes/copyfuncs.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2440,6 +2440,23 @@ _copyJsonArrayQueryConstructor(const JsonArrayQueryConstructor *from)
24402440
returnnewnode;
24412441
}
24422442

2443+
/*
2444+
* _copyJsonIsPredicate
2445+
*/
2446+
staticJsonIsPredicate*
2447+
_copyJsonIsPredicate(constJsonIsPredicate*from)
2448+
{
2449+
JsonIsPredicate*newnode=makeNode(JsonIsPredicate);
2450+
2451+
COPY_NODE_FIELD(expr);
2452+
COPY_SCALAR_FIELD(format);
2453+
COPY_SCALAR_FIELD(value_type);
2454+
COPY_SCALAR_FIELD(unique_keys);
2455+
COPY_LOCATION_FIELD(location);
2456+
2457+
returnnewnode;
2458+
}
2459+
24432460
/* ****************************************************************
24442461
*pathnodes.h copy functions
24452462
*
@@ -5373,6 +5390,9 @@ copyObjectImpl(const void *from)
53735390
caseT_JsonArrayAgg:
53745391
retval=_copyJsonArrayAgg(from);
53755392
break;
5393+
caseT_JsonIsPredicate:
5394+
retval=_copyJsonIsPredicate(from);
5395+
break;
53765396

53775397
/*
53785398
* RELATION NODES

‎src/backend/nodes/equalfuncs.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -953,6 +953,18 @@ _equalJsonArrayQueryConstructor(const JsonArrayQueryConstructor *a,
953953
return true;
954954
}
955955

956+
staticbool
957+
_equalJsonIsPredicate(constJsonIsPredicate*a,
958+
constJsonIsPredicate*b)
959+
{
960+
COMPARE_NODE_FIELD(expr);
961+
COMPARE_SCALAR_FIELD(value_type);
962+
COMPARE_SCALAR_FIELD(unique_keys);
963+
COMPARE_LOCATION_FIELD(location);
964+
965+
return true;
966+
}
967+
956968
/*
957969
* Stuff from pathnodes.h
958970
*/
@@ -3357,6 +3369,9 @@ equal(const void *a, const void *b)
33573369
caseT_JsonConstructorExpr:
33583370
retval=_equalJsonConstructorExpr(a,b);
33593371
break;
3372+
caseT_JsonIsPredicate:
3373+
retval=_equalJsonIsPredicate(a,b);
3374+
break;
33603375

33613376
/*
33623377
* RELATION NODES

‎src/backend/nodes/nodeFuncs.c

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,9 @@ exprType(const Node *expr)
268268
caseT_JsonConstructorExpr:
269269
type= ((constJsonConstructorExpr*)expr)->returning->typid;
270270
break;
271+
caseT_JsonIsPredicate:
272+
type=BOOLOID;
273+
break;
271274
default:
272275
elog(ERROR,"unrecognized node type: %d", (int)nodeTag(expr));
273276
type=InvalidOid;/* keep compiler quiet */
@@ -933,6 +936,9 @@ exprCollation(const Node *expr)
933936
coll=InvalidOid;
934937
}
935938
break;
939+
caseT_JsonIsPredicate:
940+
coll=InvalidOid;/* result is always an boolean type */
941+
break;
936942
default:
937943
elog(ERROR,"unrecognized node type: %d", (int)nodeTag(expr));
938944
coll=InvalidOid;/* keep compiler quiet */
@@ -1150,6 +1156,9 @@ exprSetCollation(Node *expr, Oid collation)
11501156
Assert(!OidIsValid(collation));/* result is always an json[b] type */
11511157
}
11521158
break;
1159+
caseT_JsonIsPredicate:
1160+
Assert(!OidIsValid(collation));/* result is always boolean */
1161+
break;
11531162
default:
11541163
elog(ERROR,"unrecognized node type: %d", (int)nodeTag(expr));
11551164
break;
@@ -1596,6 +1605,9 @@ exprLocation(const Node *expr)
15961605
caseT_JsonConstructorExpr:
15971606
loc= ((constJsonConstructorExpr*)expr)->location;
15981607
break;
1608+
caseT_JsonIsPredicate:
1609+
loc= ((constJsonIsPredicate*)expr)->location;
1610+
break;
15991611
default:
16001612
/* for any other node type it's just unknown... */
16011613
loc=-1;
@@ -2315,6 +2327,8 @@ expression_tree_walker(Node *node,
23152327
return true;
23162328
}
23172329
break;
2330+
caseT_JsonIsPredicate:
2331+
returnwalker(((JsonIsPredicate*)node)->expr,context);
23182332
default:
23192333
elog(ERROR,"unrecognized node type: %d",
23202334
(int)nodeTag(node));
@@ -3272,6 +3286,16 @@ expression_tree_mutator(Node *node,
32723286
MUTATE(newnode->coercion,jve->coercion,Expr*);
32733287
MUTATE(newnode->returning,jve->returning,JsonReturning*);
32743288

3289+
return (Node*)newnode;
3290+
}
3291+
caseT_JsonIsPredicate:
3292+
{
3293+
JsonIsPredicate*pred= (JsonIsPredicate*)node;
3294+
JsonIsPredicate*newnode;
3295+
3296+
FLATCOPY(newnode,pred,JsonIsPredicate);
3297+
MUTATE(newnode->expr,pred->expr,Node*);
3298+
32753299
return (Node*)newnode;
32763300
}
32773301
default:
@@ -4081,6 +4105,8 @@ raw_expression_tree_walker(Node *node,
40814105
return true;
40824106
}
40834107
break;
4108+
caseT_JsonIsPredicate:
4109+
returnwalker(((JsonIsPredicate*)node)->expr,context);
40844110
default:
40854111
elog(ERROR,"unrecognized node type: %d",
40864112
(int)nodeTag(node));

‎src/backend/nodes/outfuncs.c

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

1757+
staticvoid
1758+
_outJsonIsPredicate(StringInfostr,constJsonIsPredicate*node)
1759+
{
1760+
WRITE_NODE_TYPE("JSONISPREDICATE");
1761+
1762+
WRITE_NODE_FIELD(expr);
1763+
WRITE_ENUM_FIELD(value_type,JsonValueType);
1764+
WRITE_BOOL_FIELD(unique_keys);
1765+
WRITE_LOCATION_FIELD(location);
1766+
}
1767+
17571768
/*****************************************************************************
17581769
*
17591770
*Stuff from pathnodes.h.
@@ -4394,6 +4405,9 @@ outNode(StringInfo str, const void *obj)
43944405
caseT_JsonConstructorExpr:
43954406
_outJsonConstructorExpr(str,obj);
43964407
break;
4408+
caseT_JsonIsPredicate:
4409+
_outJsonIsPredicate(str,obj);
4410+
break;
43974411

43984412
default:
43994413

‎src/backend/nodes/readfuncs.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1408,6 +1408,22 @@ _readJsonConstructorExpr(void)
14081408
READ_DONE();
14091409
}
14101410

1411+
/*
1412+
* _readJsonIsPredicate
1413+
*/
1414+
staticJsonIsPredicate*
1415+
_readJsonIsPredicate()
1416+
{
1417+
READ_LOCALS(JsonIsPredicate);
1418+
1419+
READ_NODE_FIELD(expr);
1420+
READ_ENUM_FIELD(value_type,JsonValueType);
1421+
READ_BOOL_FIELD(unique_keys);
1422+
READ_LOCATION_FIELD(location);
1423+
1424+
READ_DONE();
1425+
}
1426+
14111427
/*
14121428
*Stuff from pathnodes.h.
14131429
*
@@ -2953,6 +2969,8 @@ parseNodeString(void)
29532969
return_value=_readJsonValueExpr();
29542970
elseif (MATCH("JSONCTOREXPR",12))
29552971
return_value=_readJsonConstructorExpr();
2972+
elseif (MATCH("JSONISPREDICATE",15))
2973+
return_value=_readJsonIsPredicate();
29562974
else
29572975
{
29582976
elog(ERROR,"badly formatted node string \"%.32s\"...",token);

‎src/backend/parser/parse_expr.c

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ static Node *transformJsonArrayQueryConstructor(ParseState *pstate,
131131
JsonArrayQueryConstructor*ctor);
132132
staticNode*transformJsonObjectAgg(ParseState*pstate,JsonObjectAgg*agg);
133133
staticNode*transformJsonArrayAgg(ParseState*pstate,JsonArrayAgg*agg);
134+
staticNode*transformJsonIsPredicate(ParseState*pstate,JsonIsPredicate*p);
134135
staticNode*make_row_comparison_op(ParseState*pstate,List*opname,
135136
List*largs,List*rargs,intlocation);
136137
staticNode*make_row_distinct_op(ParseState*pstate,List*opname,
@@ -399,6 +400,10 @@ transformExprRecurse(ParseState *pstate, Node *expr)
399400
result=transformJsonArrayAgg(pstate, (JsonArrayAgg*)expr);
400401
break;
401402

403+
caseT_JsonIsPredicate:
404+
result=transformJsonIsPredicate(pstate, (JsonIsPredicate*)expr);
405+
break;
406+
402407
default:
403408
/* should not reach here */
404409
elog(ERROR,"unrecognized node type: %d", (int)nodeTag(expr));
@@ -4340,3 +4345,101 @@ transformJsonArrayConstructor(ParseState *pstate, JsonArrayConstructor *ctor)
43404345
returning, false,ctor->absent_on_null,
43414346
ctor->location);
43424347
}
4348+
4349+
staticconstchar*
4350+
JsonValueTypeStrings[]=
4351+
{
4352+
"any",
4353+
"object",
4354+
"array",
4355+
"scalar",
4356+
};
4357+
4358+
staticConst*
4359+
makeJsonValueTypeConst(JsonValueTypetype)
4360+
{
4361+
returnmakeConst(TEXTOID,-1,InvalidOid,-1,
4362+
PointerGetDatum(cstring_to_text(
4363+
JsonValueTypeStrings[(int)type])),
4364+
false, false);
4365+
}
4366+
4367+
/*
4368+
* Transform IS JSON predicate into
4369+
* json[b]_is_valid(json, value_type [, check_key_uniqueness]) call.
4370+
*/
4371+
staticNode*
4372+
transformJsonIsPredicate(ParseState*pstate,JsonIsPredicate*pred)
4373+
{
4374+
Node*expr=transformExprRecurse(pstate,pred->expr);
4375+
Oidexprtype=exprType(expr);
4376+
FuncExpr*fexpr;
4377+
4378+
/* prepare input document */
4379+
if (exprtype==BYTEAOID)
4380+
{
4381+
expr=makeJsonByteaToTextConversion(expr,pred->format,
4382+
exprLocation(expr));
4383+
exprtype=TEXTOID;
4384+
}
4385+
else
4386+
{
4387+
chartypcategory;
4388+
booltypispreferred;
4389+
4390+
get_type_category_preferred(exprtype,&typcategory,&typispreferred);
4391+
4392+
if (exprtype==UNKNOWNOID||typcategory==TYPCATEGORY_STRING)
4393+
{
4394+
expr=coerce_to_target_type(pstate, (Node*)expr,exprtype,
4395+
TEXTOID,-1,
4396+
COERCION_IMPLICIT,
4397+
COERCE_IMPLICIT_CAST,-1);
4398+
exprtype=TEXTOID;
4399+
}
4400+
4401+
if (pred->format->encoding!=JS_ENC_DEFAULT)
4402+
ereport(ERROR,
4403+
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4404+
parser_errposition(pstate,pred->format->location),
4405+
errmsg("cannot use JSON FORMAT ENCODING clause for non-bytea input types")));
4406+
}
4407+
4408+
expr= (Node*)makeJsonValueExpr((Expr*)expr,pred->format);
4409+
4410+
/* make resulting expression */
4411+
if (exprtype==TEXTOID||exprtype==JSONOID)
4412+
{
4413+
fexpr=makeFuncExpr(F_JSON_IS_VALID,BOOLOID,
4414+
list_make3(expr,
4415+
makeJsonValueTypeConst(pred->value_type),
4416+
makeBoolConst(pred->unique_keys, false)),
4417+
InvalidOid,InvalidOid,COERCE_EXPLICIT_CALL);
4418+
4419+
fexpr->location=pred->location;
4420+
}
4421+
elseif (exprtype==JSONBOID)
4422+
{
4423+
/* XXX the following expressions also can be used here:
4424+
* jsonb_type(jsonb) = 'type' (for object and array checks)
4425+
* CASE jsonb_type(jsonb) WHEN ... END (for scalars checks)
4426+
*/
4427+
fexpr=makeFuncExpr(F_JSONB_IS_VALID,BOOLOID,
4428+
list_make2(expr,
4429+
makeJsonValueTypeConst(pred->value_type)),
4430+
InvalidOid,InvalidOid,COERCE_EXPLICIT_CALL);
4431+
4432+
fexpr->location=pred->location;
4433+
}
4434+
else
4435+
{
4436+
ereport(ERROR,
4437+
(errcode(ERRCODE_DATATYPE_MISMATCH),
4438+
errmsg("cannot use type %s in IS JSON predicate",
4439+
format_type_be(exprtype))));
4440+
returnNULL;
4441+
}
4442+
4443+
returnmakeJsonIsPredicate((Node*)fexpr,NULL,pred->value_type,
4444+
pred->unique_keys);
4445+
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp