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

Commit3be04dc

Browse files
akorotkovNikita Glukhov
authored and
Nikita Glukhov
committed
Improve mutability check for SQL/JSON query functions
1 parent2c5b48a commit3be04dc

File tree

8 files changed

+378
-103
lines changed

8 files changed

+378
-103
lines changed

‎src/backend/optimizer/util/clauses.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
#include"utils/fmgroids.h"
5252
#include"utils/json.h"
5353
#include"utils/jsonb.h"
54+
#include"utils/jsonpath.h"
5455
#include"utils/lsyscache.h"
5556
#include"utils/memutils.h"
5657
#include"utils/syscache.h"
@@ -689,6 +690,27 @@ contain_mutable_functions_walker(Node *node, void *context)
689690
/* Check all subnodes */
690691
}
691692

693+
if (IsA(node,JsonExpr))
694+
{
695+
JsonExpr*jexpr=castNode(JsonExpr,node);
696+
697+
if (IsA(jexpr->path_spec,Const))
698+
{
699+
Const*c=castNode(Const,jexpr->path_spec);
700+
701+
Assert(c->consttype==JSONPATHOID);
702+
if (c->constisnull)
703+
return false;
704+
705+
returnjspIsMutable(DatumGetJsonPathP(c->constvalue),
706+
jexpr->passing_names,jexpr->passing_values);
707+
}
708+
else
709+
{
710+
return true;
711+
}
712+
}
713+
692714
if (IsA(node,SQLValueFunction))
693715
{
694716
/* all variants of SQLValueFunction are stable */

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

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1018,11 +1018,6 @@ typedef struct NUMProc
10181018
*L_currency_symbol;
10191019
}NUMProc;
10201020

1021-
/* Return flags for DCH_from_char() */
1022-
#defineDCH_DATED0x01
1023-
#defineDCH_TIMED0x02
1024-
#defineDCH_ZONED0x04
1025-
10261021
/* ----------
10271022
* Functions
10281023
* ----------
@@ -6624,3 +6619,43 @@ float8_to_char(PG_FUNCTION_ARGS)
66246619
NUM_TOCHAR_finish;
66256620
PG_RETURN_TEXT_P(result);
66266621
}
6622+
6623+
int
6624+
datetime_format_flags(constchar*fmt_str,bool*have_error)
6625+
{
6626+
boolincache;
6627+
intfmt_len=strlen(fmt_str);
6628+
intresult;
6629+
FormatNode*format;
6630+
6631+
if (fmt_len>DCH_CACHE_SIZE)
6632+
{
6633+
/*
6634+
* Allocate new memory if format picture is bigger than static cache
6635+
* and do not use cache (call parser always)
6636+
*/
6637+
incache= false;
6638+
6639+
format= (FormatNode*)palloc((fmt_len+1)*sizeof(FormatNode));
6640+
6641+
parse_format(format,fmt_str,DCH_keywords,
6642+
DCH_suff,DCH_index,DCH_FLAG,NULL);
6643+
}
6644+
else
6645+
{
6646+
/*
6647+
* Use cache buffers
6648+
*/
6649+
DCHCacheEntry*ent=DCH_cache_fetch(fmt_str, false);
6650+
6651+
incache= true;
6652+
format=ent->format;
6653+
}
6654+
6655+
result=DCH_datetime_type(format,have_error);
6656+
6657+
if (!incache)
6658+
pfree(format);
6659+
6660+
returnresult;
6661+
}

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

Lines changed: 259 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,9 @@
6767
#include"lib/stringinfo.h"
6868
#include"libpq/pqformat.h"
6969
#include"miscadmin.h"
70+
#include"nodes/nodeFuncs.h"
7071
#include"utils/builtins.h"
72+
#include"utils/formatting.h"
7173
#include"utils/json.h"
7274
#include"utils/jsonpath.h"
7375

@@ -1073,3 +1075,260 @@ jspGetArraySubscript(JsonPathItem *v, JsonPathItem *from, JsonPathItem *to,
10731075

10741076
return true;
10751077
}
1078+
1079+
/* SQL/JSON datatype status: */
1080+
typedefenumJsonPathDatatypeStatus
1081+
{
1082+
jpdsNonDateTime,/* null, bool, numeric, string, array, object */
1083+
jpdsDateTime,/* unknown datetime type */
1084+
jpdsDateTimeZoned,/* timetz, timestamptz */
1085+
jpdsDateTimeNonZoned/* time, timestamp, date */
1086+
}JsonPathDatatypeStatus;
1087+
1088+
/* Context for jspIsMutableWalker() */
1089+
typedefstructJsonPathMutableContext
1090+
{
1091+
List*varnames;/* list of variable names */
1092+
List*varexprs;/* list of variable expressions */
1093+
JsonPathDatatypeStatuscurrent;/* status of @ item */
1094+
boollax;/* jsonpath is lax or strict */
1095+
boolmutable;/* resulting mutability status */
1096+
}JsonPathMutableContext;
1097+
1098+
/*
1099+
* Recursive walker for jspIsMutable()
1100+
*/
1101+
staticJsonPathDatatypeStatus
1102+
jspIsMutableWalker(JsonPathItem*jpi,JsonPathMutableContext*cxt)
1103+
{
1104+
JsonPathItemnext;
1105+
JsonPathDatatypeStatusstatus=jpdsNonDateTime;
1106+
1107+
while (!cxt->mutable)
1108+
{
1109+
JsonPathItemarg;
1110+
JsonPathDatatypeStatusleftStatus;
1111+
JsonPathDatatypeStatusrightStatus;
1112+
1113+
switch (jpi->type)
1114+
{
1115+
casejpiRoot:
1116+
Assert(status==jpdsNonDateTime);
1117+
break;
1118+
1119+
casejpiCurrent:
1120+
Assert(status==jpdsNonDateTime);
1121+
status=cxt->current;
1122+
break;
1123+
1124+
casejpiFilter:
1125+
{
1126+
JsonPathDatatypeStatusprevStatus=cxt->current;
1127+
1128+
cxt->current=status;
1129+
jspGetArg(jpi,&arg);
1130+
jspIsMutableWalker(&arg,cxt);
1131+
1132+
cxt->current=prevStatus;
1133+
break;
1134+
}
1135+
1136+
casejpiVariable:
1137+
{
1138+
int32len;
1139+
constchar*name=jspGetString(jpi,&len);
1140+
ListCell*lc1;
1141+
ListCell*lc2;
1142+
1143+
Assert(status==jpdsNonDateTime);
1144+
1145+
forboth(lc1,cxt->varnames,lc2,cxt->varexprs)
1146+
{
1147+
Value*varname=lfirst(lc1);
1148+
Node*varexpr=lfirst(lc2);
1149+
1150+
Assert(IsA(varname,String));
1151+
1152+
if (strncmp(varname->val.str,name,len))
1153+
continue;
1154+
1155+
switch (exprType(varexpr))
1156+
{
1157+
caseDATEOID:
1158+
caseTIMEOID:
1159+
caseTIMESTAMPOID:
1160+
status=jpdsDateTimeNonZoned;
1161+
break;
1162+
1163+
caseTIMETZOID:
1164+
caseTIMESTAMPTZOID:
1165+
status=jpdsDateTimeZoned;
1166+
break;
1167+
1168+
default:
1169+
status=jpdsNonDateTime;
1170+
break;
1171+
}
1172+
1173+
break;
1174+
}
1175+
break;
1176+
}
1177+
1178+
casejpiEqual:
1179+
casejpiNotEqual:
1180+
casejpiLess:
1181+
casejpiGreater:
1182+
casejpiLessOrEqual:
1183+
casejpiGreaterOrEqual:
1184+
Assert(status==jpdsNonDateTime);
1185+
jspGetLeftArg(jpi,&arg);
1186+
leftStatus=jspIsMutableWalker(&arg,cxt);
1187+
1188+
jspGetRightArg(jpi,&arg);
1189+
rightStatus=jspIsMutableWalker(&arg,cxt);
1190+
1191+
/*
1192+
* Comparison of datetime type with different timezone status
1193+
* is mutable.
1194+
*/
1195+
if (leftStatus!=jpdsNonDateTime&&
1196+
rightStatus!=jpdsNonDateTime&&
1197+
(leftStatus==jpdsDateTime||
1198+
rightStatus==jpdsDateTime||
1199+
leftStatus!=rightStatus))
1200+
cxt->mutable= true;
1201+
break;
1202+
1203+
casejpiNot:
1204+
casejpiIsUnknown:
1205+
casejpiExists:
1206+
casejpiPlus:
1207+
casejpiMinus:
1208+
Assert(status==jpdsNonDateTime);
1209+
jspGetArg(jpi,&arg);
1210+
jspIsMutableWalker(&arg,cxt);
1211+
break;
1212+
1213+
casejpiAnd:
1214+
casejpiOr:
1215+
casejpiAdd:
1216+
casejpiSub:
1217+
casejpiMul:
1218+
casejpiDiv:
1219+
casejpiMod:
1220+
casejpiStartsWith:
1221+
Assert(status==jpdsNonDateTime);
1222+
jspGetLeftArg(jpi,&arg);
1223+
jspIsMutableWalker(&arg,cxt);
1224+
jspGetRightArg(jpi,&arg);
1225+
jspIsMutableWalker(&arg,cxt);
1226+
break;
1227+
1228+
casejpiIndexArray:
1229+
for (inti=0;i<jpi->content.array.nelems;i++)
1230+
{
1231+
JsonPathItemfrom;
1232+
JsonPathItemto;
1233+
1234+
if (jspGetArraySubscript(jpi,&from,&to,i))
1235+
jspIsMutableWalker(&to,cxt);
1236+
1237+
jspIsMutableWalker(&from,cxt);
1238+
}
1239+
/* FALLTHROUGH */
1240+
1241+
casejpiAnyArray:
1242+
if (!cxt->lax)
1243+
status=jpdsNonDateTime;
1244+
break;
1245+
1246+
casejpiAny:
1247+
if (jpi->content.anybounds.first>0)
1248+
status=jpdsNonDateTime;
1249+
break;
1250+
1251+
casejpiDatetime:
1252+
if (jpi->content.arg)
1253+
{
1254+
char*template;
1255+
intflags;
1256+
1257+
jspGetArg(jpi,&arg);
1258+
if (arg.type!=jpiString)
1259+
{
1260+
status=jpdsNonDateTime;
1261+
break;/* there will be runtime error */
1262+
}
1263+
1264+
template=jspGetString(&arg,NULL);
1265+
flags=datetime_format_flags(template,NULL);
1266+
if (flags&DCH_ZONED)
1267+
status=jpdsDateTimeZoned;
1268+
else
1269+
status=jpdsDateTimeNonZoned;
1270+
}
1271+
else
1272+
{
1273+
status=jpdsDateTime;
1274+
}
1275+
break;
1276+
1277+
casejpiLikeRegex:
1278+
Assert(status==jpdsNonDateTime);
1279+
jspInitByBuffer(&arg,jpi->base,jpi->content.like_regex.expr);
1280+
jspIsMutableWalker(&arg,cxt);
1281+
break;
1282+
1283+
/* literals */
1284+
casejpiNull:
1285+
casejpiString:
1286+
casejpiNumeric:
1287+
casejpiBool:
1288+
/* accessors */
1289+
casejpiKey:
1290+
casejpiAnyKey:
1291+
/* special items */
1292+
casejpiSubscript:
1293+
casejpiLast:
1294+
/* item methods */
1295+
casejpiType:
1296+
casejpiSize:
1297+
casejpiAbs:
1298+
casejpiFloor:
1299+
casejpiCeiling:
1300+
casejpiDouble:
1301+
casejpiKeyValue:
1302+
status=jpdsNonDateTime;
1303+
break;
1304+
}
1305+
1306+
if (!jspGetNext(jpi,&next))
1307+
break;
1308+
1309+
jpi=&next;
1310+
}
1311+
1312+
returnstatus;
1313+
}
1314+
1315+
/*
1316+
* Check whether jsonpath expression is immutable or not.
1317+
*/
1318+
bool
1319+
jspIsMutable(JsonPath*path,List*varnames,List*varexprs)
1320+
{
1321+
JsonPathMutableContextcxt;
1322+
JsonPathItemjpi;
1323+
1324+
cxt.varnames=varnames;
1325+
cxt.varexprs=varexprs;
1326+
cxt.current=jpdsNonDateTime;
1327+
cxt.lax= (path->header&JSONPATH_LAX)!=0;
1328+
cxt.mutable= false;
1329+
1330+
jspInit(&jpi,path);
1331+
jspIsMutableWalker(&jpi,&cxt);
1332+
1333+
returncxt.mutable;
1334+
}

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2890,7 +2890,7 @@ JsonPathExists(Datum jb, JsonPath *jp, List *vars, bool *error)
28902890
{
28912891
JsonPathExecResultres=executeJsonPath(jp,vars,EvalJsonPathVar,
28922892
DatumGetJsonbP(jb), !error,NULL,
2893-
false/* XXX */);
2893+
true);
28942894

28952895
Assert(error|| !jperIsError(res));
28962896

@@ -2911,7 +2911,7 @@ JsonPathQuery(Datum jb, JsonPath *jp, JsonWrapper wrapper, bool *empty,
29112911
intcount;
29122912

29132913
res=executeJsonPath(jp,vars,EvalJsonPathVar,DatumGetJsonbP(jb), !error,
2914-
&found,false/* XXX */);
2914+
&found,true);
29152915

29162916
Assert(error|| !jperIsError(res));
29172917

@@ -2978,7 +2978,7 @@ JsonPathValue(Datum jb, JsonPath *jp, bool *empty, bool *error, List *vars)
29782978
intcount;
29792979

29802980
jper=executeJsonPath(jp,vars,EvalJsonPathVar,DatumGetJsonbP(jb), !error,
2981-
&found,false/* XXX */);
2981+
&found,true);
29822982

29832983
Assert(error|| !jperIsError(jper));
29842984

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp