1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-19 13:42:17 +03:00

Fix handling of opclauses in extended statistics

We expect opclauses to have exactly one Var and one Const, but the code
was checking the Const by calling is_pseudo_constant_clause() which is
incorrect - we need a proper constant.

Fixed by using plain IsA(x,Const) to check type of the node. We need to
do these checks in two places, so move it into a separate function that
can 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.eu
Backpatch-to: 12
This commit is contained in:
Tomas Vondra
2019-07-13 00:12:16 +02:00
parent a4303a078c
commit e8b6ae2130
3 changed files with 73 additions and 32 deletions

View File

@@ -1561,36 +1561,23 @@ mcv_get_match_bitmap(PlannerInfo *root, List *clauses,
if (is_opclause(clause))
{
OpExpr *expr = (OpExpr *) clause;
bool varonleft = true;
bool ok;
FmgrInfo opproc;
/* get procedure computing operator selectivity */
RegProcedure oprrest = get_oprrest(expr->opno);
/* valid only after examine_opclause_expression returns true */
Var *var;
Const *cst;
bool isgt;
fmgr_info(get_opcode(expr->opno), &opproc);
ok = (NumRelids(clause) == 1) &&
(is_pseudo_constant_clause(lsecond(expr->args)) ||
(varonleft = false,
is_pseudo_constant_clause(linitial(expr->args))));
if (ok)
/* extract the var and const from the expression */
if (examine_opclause_expression(expr, &var, &cst, &isgt))
{
Var *var;
Const *cst;
bool isgt;
int idx;
/* extract the var and const from the expression */
var = (varonleft) ? linitial(expr->args) : lsecond(expr->args);
cst = (varonleft) ? lsecond(expr->args) : linitial(expr->args);
isgt = (!varonleft);
/* strip binary-compatible relabeling */
if (IsA(var, RelabelType))
var = (Var *) ((RelabelType *) var)->arg;
/* match the attribute to a dimension of the statistic */
idx = bms_member_index(keys, var->varattno);