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

Commite8b6ae2

Browse files
committed
Fix handling of opclauses in extended statistics
We expect opclauses to have exactly one Var and one Const, but the codewas checking the Const by calling is_pseudo_constant_clause() which isincorrect - we need a proper constant.Fixed by using plain IsA(x,Const) to check type of the node. We need todo these checks in two places, so move it into a separate function thatcan be called in both places.Reported by Andreas Seltenreich, based on crash reported by sqlsmith.Backpatch to v12, where this code was introduced.Discussion:https://postgr.es/m/8736jdhbhc.fsf%40ansel.ydns.euBackpatch-to: 12
1 parenta4303a0 commite8b6ae2

File tree

3 files changed

+73
-32
lines changed

3 files changed

+73
-32
lines changed

‎src/backend/statistics/extended_stats.c

Lines changed: 64 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -796,21 +796,13 @@ statext_is_compatible_clause_internal(PlannerInfo *root, Node *clause,
796796
RangeTblEntry*rte=root->simple_rte_array[relid];
797797
OpExpr*expr= (OpExpr*)clause;
798798
Var*var;
799-
boolvaronleft= true;
800-
boolok;
801799

802800
/* Only expressions with two arguments are considered compatible. */
803801
if (list_length(expr->args)!=2)
804802
return false;
805803

806-
/* see if it actually has the right shape (one Var, one Const) */
807-
ok= (NumRelids((Node*)expr)==1)&&
808-
(is_pseudo_constant_clause(lsecond(expr->args))||
809-
(varonleft= false,
810-
is_pseudo_constant_clause(linitial(expr->args))));
811-
812-
/* unsupported structure (two variables or so) */
813-
if (!ok)
804+
/* Check if the expression the right shape (one Var, one Const) */
805+
if (!examine_opclause_expression(expr,&var,NULL,NULL))
814806
return false;
815807

816808
/*
@@ -850,8 +842,6 @@ statext_is_compatible_clause_internal(PlannerInfo *root, Node *clause,
850842
!get_func_leakproof(get_opcode(expr->opno)))
851843
return false;
852844

853-
var= (varonleft) ?linitial(expr->args) :lsecond(expr->args);
854-
855845
returnstatext_is_compatible_clause_internal(root, (Node*)var,
856846
relid,attnums);
857847
}
@@ -1196,3 +1186,65 @@ statext_clauselist_selectivity(PlannerInfo *root, List *clauses, int varRelid,
11961186

11971187
returnsel;
11981188
}
1189+
1190+
/*
1191+
* examine_operator_expression
1192+
*Split expression into Var and Const parts.
1193+
*
1194+
* Attempts to match the arguments to either (Var op Const) or (Const op Var),
1195+
* possibly with a RelabelType on top. When the expression matches this form,
1196+
* returns true, otherwise returns false.
1197+
*
1198+
* Optionally returns pointers to the extracted Var/Const nodes, when passed
1199+
* non-null pointers (varp, cstp and isgtp). The isgt flag specifies whether
1200+
* the Var node is on the left (false) or right (true) side of the operator.
1201+
*/
1202+
bool
1203+
examine_opclause_expression(OpExpr*expr,Var**varp,Const**cstp,bool*isgtp)
1204+
{
1205+
Var*var;
1206+
Const*cst;
1207+
boolisgt;
1208+
Node*leftop,
1209+
*rightop;
1210+
1211+
/* enforced by statext_is_compatible_clause_internal */
1212+
Assert(list_length(expr->args)==2);
1213+
1214+
leftop=linitial(expr->args);
1215+
rightop=lsecond(expr->args);
1216+
1217+
/* strip RelabelType from either side of the expression */
1218+
if (IsA(leftop,RelabelType))
1219+
leftop= (Node*) ((RelabelType*)leftop)->arg;
1220+
1221+
if (IsA(rightop,RelabelType))
1222+
rightop= (Node*) ((RelabelType*)rightop)->arg;
1223+
1224+
if (IsA(leftop,Var)&&IsA(rightop,Const))
1225+
{
1226+
var= (Var*)leftop;
1227+
cst= (Const*)rightop;
1228+
isgt= false;
1229+
}
1230+
elseif (IsA(leftop,Const)&&IsA(rightop,Var))
1231+
{
1232+
var= (Var*)rightop;
1233+
cst= (Const*)leftop;
1234+
isgt= true;
1235+
}
1236+
else
1237+
return false;
1238+
1239+
/* return pointers to the extracted parts if requested */
1240+
if (varp)
1241+
*varp=var;
1242+
1243+
if (cstp)
1244+
*cstp=cst;
1245+
1246+
if (isgtp)
1247+
*isgtp=isgt;
1248+
1249+
return true;
1250+
}

‎src/backend/statistics/mcv.c

Lines changed: 7 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1561,36 +1561,23 @@ mcv_get_match_bitmap(PlannerInfo *root, List *clauses,
15611561
if (is_opclause(clause))
15621562
{
15631563
OpExpr*expr= (OpExpr*)clause;
1564-
boolvaronleft= true;
1565-
boolok;
15661564
FmgrInfoopproc;
15671565

15681566
/* get procedure computing operator selectivity */
15691567
RegProcedureoprrest=get_oprrest(expr->opno);
15701568

1571-
fmgr_info(get_opcode(expr->opno),&opproc);
1569+
/* valid only after examine_opclause_expression returns true */
1570+
Var*var;
1571+
Const*cst;
1572+
boolisgt;
15721573

1573-
ok= (NumRelids(clause)==1)&&
1574-
(is_pseudo_constant_clause(lsecond(expr->args))||
1575-
(varonleft= false,
1576-
is_pseudo_constant_clause(linitial(expr->args))));
1574+
fmgr_info(get_opcode(expr->opno),&opproc);
15771575

1578-
if (ok)
1576+
/* extract the var and const from the expression */
1577+
if (examine_opclause_expression(expr,&var,&cst,&isgt))
15791578
{
1580-
Var*var;
1581-
Const*cst;
1582-
boolisgt;
15831579
intidx;
15841580

1585-
/* extract the var and const from the expression */
1586-
var= (varonleft) ?linitial(expr->args) :lsecond(expr->args);
1587-
cst= (varonleft) ?lsecond(expr->args) :linitial(expr->args);
1588-
isgt= (!varonleft);
1589-
1590-
/* strip binary-compatible relabeling */
1591-
if (IsA(var,RelabelType))
1592-
var= (Var*) ((RelabelType*)var)->arg;
1593-
15941581
/* match the attribute to a dimension of the statistic */
15951582
idx=bms_member_index(keys,var->varattno);
15961583

‎src/include/statistics/extended_stats_internal.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,8 @@ extern SortItem *build_sorted_items(int numrows, int *nitems, HeapTuple *rows,
9797
TupleDesctdesc,MultiSortSupportmss,
9898
intnumattrs,AttrNumber*attnums);
9999

100+
externboolexamine_opclause_expression(OpExpr*expr,Var**varp,
101+
Const**cstp,bool*isgtp);
100102

101103
externSelectivitymcv_clauselist_selectivity(PlannerInfo*root,
102104
StatisticExtInfo*stat,

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp