diff options
author | Tomas Vondra <tomas.vondra@postgresql.org> | 2019-07-13 00:12:16 +0200 |
---|---|---|
committer | Tomas Vondra <tomas.vondra@postgresql.org> | 2019-07-18 11:29:38 +0200 |
commit | e8b6ae2130e3a95bb776708a9a7c9cb21fe8ac87 (patch) | |
tree | a4da53b2d8031d5d667f443a9ee294cab28e8129 /src/backend/statistics/mcv.c | |
parent | a4303a078c661ebafe8c8c2167b2ad9bf16b32ce (diff) | |
download | postgresql-e8b6ae2130e3a95bb776708a9a7c9cb21fe8ac87.tar.gz postgresql-e8b6ae2130e3a95bb776708a9a7c9cb21fe8ac87.zip |
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
Diffstat (limited to 'src/backend/statistics/mcv.c')
-rw-r--r-- | src/backend/statistics/mcv.c | 27 |
1 files changed, 7 insertions, 20 deletions
diff --git a/src/backend/statistics/mcv.c b/src/backend/statistics/mcv.c index e62421dfa88..a708a8f6740 100644 --- a/src/backend/statistics/mcv.c +++ b/src/backend/statistics/mcv.c @@ -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); - fmgr_info(get_opcode(expr->opno), &opproc); + /* valid only after examine_opclause_expression returns true */ + Var *var; + Const *cst; + bool isgt; - ok = (NumRelids(clause) == 1) && - (is_pseudo_constant_clause(lsecond(expr->args)) || - (varonleft = false, - is_pseudo_constant_clause(linitial(expr->args)))); + fmgr_info(get_opcode(expr->opno), &opproc); - 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); |