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:
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user