mirror of
https://github.com/postgres/postgres.git
synced 2025-11-12 05:01:15 +03:00
Clean up the usage of canonicalize_qual(): in particular, be consistent
about whether it is applied before or after eval_const_expressions(). I believe there were some corner cases where the system would fail to recognize that a partial index is applicable because of the previous inconsistency. Store normal rather than 'implicit AND' representations of constraints and index predicates in the catalogs. initdb forced due to representation change of constraints/predicates.
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
* back to source text
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.160 2003/11/29 19:51:59 pgsql Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.161 2003/12/28 21:57:37 tgl Exp $
|
||||
*
|
||||
* This software is copyrighted by Jan Wieck - Hamburg.
|
||||
*
|
||||
@@ -810,13 +810,6 @@ pg_get_indexdef_worker(Oid indexrelid, int colno, int prettyFlags)
|
||||
node = (Node *) stringToNode(predString);
|
||||
pfree(predString);
|
||||
|
||||
/*
|
||||
* If top level is a List, assume it is an implicit-AND
|
||||
* structure, and convert to explicit AND. This is needed for
|
||||
* partial index predicates.
|
||||
*/
|
||||
if (node && IsA(node, List))
|
||||
node = (Node *) make_ands_explicit((List *) node);
|
||||
/* Deparse */
|
||||
str = deparse_expression_pretty(node, context, false, false,
|
||||
prettyFlags, 0);
|
||||
@@ -1060,14 +1053,6 @@ pg_get_constraintdef_worker(Oid constraintId, int prettyFlags)
|
||||
conbin = DatumGetCString(DirectFunctionCall1(textout, val));
|
||||
expr = stringToNode(conbin);
|
||||
|
||||
/*
|
||||
* If top level is a List, assume it is an implicit-AND
|
||||
* structure, and convert to explicit AND. This is needed
|
||||
* for partial index predicates.
|
||||
*/
|
||||
if (expr && IsA(expr, List))
|
||||
expr = (Node *) make_ands_explicit((List *) expr);
|
||||
|
||||
/* Set up deparsing context for Var nodes in constraint */
|
||||
if (conForm->conrelid != InvalidOid)
|
||||
{
|
||||
@@ -1212,14 +1197,6 @@ pg_get_expr_worker(text *expr, Oid relid, char *relname, int prettyFlags)
|
||||
/* Convert expression to node tree */
|
||||
node = (Node *) stringToNode(exprstr);
|
||||
|
||||
/*
|
||||
* If top level is a List, assume it is an implicit-AND structure, and
|
||||
* convert to explicit AND. This is needed for partial index
|
||||
* predicates.
|
||||
*/
|
||||
if (node && IsA(node, List))
|
||||
node = (Node *) make_ands_explicit((List *) node);
|
||||
|
||||
/* Deparse */
|
||||
context = deparse_context_for(relname, relid);
|
||||
str = deparse_expression_pretty(node, context, false, false,
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/selfuncs.c,v 1.150 2003/12/07 04:14:10 joe Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/selfuncs.c,v 1.151 2003/12/28 21:57:37 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -3902,12 +3902,12 @@ genericcostestimate(Query *root, RelOptInfo *rel,
|
||||
* If the index is partial, AND the index predicate with the
|
||||
* explicitly given indexquals to produce a more accurate idea of the
|
||||
* index restriction. This may produce redundant clauses, which we
|
||||
* hope that cnfify and clauselist_selectivity will deal with
|
||||
* hope that canonicalize_qual and clauselist_selectivity will deal with
|
||||
* intelligently.
|
||||
*
|
||||
* Note that index->indpred and indexQuals are both in implicit-AND form
|
||||
* to start with, which we have to make explicit to hand to
|
||||
* canonicalize_qual, and then we get back implicit-AND form again.
|
||||
* canonicalize_qual, and then we convert back to implicit-AND form.
|
||||
*/
|
||||
if (index->indpred != NIL)
|
||||
{
|
||||
@@ -3915,7 +3915,8 @@ genericcostestimate(Query *root, RelOptInfo *rel,
|
||||
|
||||
andedQuals = make_ands_explicit(nconc(listCopy(index->indpred),
|
||||
indexQuals));
|
||||
selectivityQuals = canonicalize_qual(andedQuals, true);
|
||||
andedQuals = canonicalize_qual(andedQuals);
|
||||
selectivityQuals = make_ands_implicit(andedQuals);
|
||||
}
|
||||
|
||||
/* Estimate the fraction of main-table tuples that will be visited */
|
||||
|
||||
29
src/backend/utils/cache/relcache.c
vendored
29
src/backend/utils/cache/relcache.c
vendored
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/utils/cache/relcache.c,v 1.193 2003/11/29 19:52:00 pgsql Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/utils/cache/relcache.c,v 1.194 2003/12/28 21:57:37 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -53,6 +53,7 @@
|
||||
#include "miscadmin.h"
|
||||
#include "optimizer/clauses.h"
|
||||
#include "optimizer/planmain.h"
|
||||
#include "optimizer/prep.h"
|
||||
#include "storage/smgr.h"
|
||||
#include "utils/builtins.h"
|
||||
#include "utils/catcache.h"
|
||||
@@ -2770,11 +2771,13 @@ RelationGetIndexExpressions(Relation relation)
|
||||
pfree(exprsString);
|
||||
|
||||
/*
|
||||
* Run the expressions through eval_const_expressions. This is not
|
||||
* just an optimization, but is necessary, because the planner will be
|
||||
* comparing them to const-folded qual clauses, and may fail to detect
|
||||
* valid matches without this.
|
||||
* Run the expressions through flatten_andors and eval_const_expressions.
|
||||
* This is not just an optimization, but is necessary, because the planner
|
||||
* will be comparing them to similarly-processed qual clauses, and may
|
||||
* fail to detect valid matches without this.
|
||||
*/
|
||||
result = (List *) flatten_andors((Node *) result);
|
||||
|
||||
result = (List *) eval_const_expressions((Node *) result);
|
||||
|
||||
/* May as well fix opfuncids too */
|
||||
@@ -2791,7 +2794,8 @@ RelationGetIndexExpressions(Relation relation)
|
||||
/*
|
||||
* RelationGetIndexPredicate -- get the index predicate for an index
|
||||
*
|
||||
* We cache the result of transforming pg_index.indpred into a node tree.
|
||||
* We cache the result of transforming pg_index.indpred into an implicit-AND
|
||||
* node tree (suitable for ExecQual).
|
||||
* If the rel is not an index or has no predicate, we return NIL.
|
||||
* Otherwise, the returned tree is copied into the caller's memory context.
|
||||
* (We don't want to return a pointer to the relcache copy, since it could
|
||||
@@ -2835,13 +2839,18 @@ RelationGetIndexPredicate(Relation relation)
|
||||
pfree(predString);
|
||||
|
||||
/*
|
||||
* Run the expression through eval_const_expressions. This is not
|
||||
* just an optimization, but is necessary, because the planner will be
|
||||
* comparing it to const-folded qual clauses, and may fail to detect
|
||||
* valid matches without this.
|
||||
* Run the expression through canonicalize_qual and eval_const_expressions.
|
||||
* This is not just an optimization, but is necessary, because the planner
|
||||
* will be comparing it to similarly-processed qual clauses, and may fail
|
||||
* to detect valid matches without this.
|
||||
*/
|
||||
result = (List *) canonicalize_qual((Expr *) result);
|
||||
|
||||
result = (List *) eval_const_expressions((Node *) result);
|
||||
|
||||
/* Also convert to implicit-AND format */
|
||||
result = make_ands_implicit((Expr *) result);
|
||||
|
||||
/* May as well fix opfuncids too */
|
||||
fix_opfuncids((Node *) result);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user