summaryrefslogtreecommitdiff
path: root/src/backend/optimizer/util/plancat.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2006-02-04 23:03:20 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2006-02-04 23:03:20 +0000
commit3893127431b41a3341ac5ff9611c7ea0215b9110 (patch)
tree7d15367f9f19df8f39b1b5c00b4c33aaed1025d7 /src/backend/optimizer/util/plancat.c
parent48d9ad372251d188bcb0a733e875018a5f1f3503 (diff)
Fix constraint exclusion to work in inherited UPDATE/DELETE queries
... in fact, it will be applied now in any query whatsoever. I'm still a bit concerned about the cycles that might be expended in failed proof attempts, but given that CE is turned off by default, it's the user's choice whether to expend those cycles or not. (Possibly we should change the simple bool constraint_exclusion parameter to something more fine-grained?)
Diffstat (limited to 'src/backend/optimizer/util/plancat.c')
-rw-r--r--src/backend/optimizer/util/plancat.c52
1 files changed, 50 insertions, 2 deletions
diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c
index c926ae5d488..b6dcfa144f2 100644
--- a/src/backend/optimizer/util/plancat.c
+++ b/src/backend/optimizer/util/plancat.c
@@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/util/plancat.c,v 1.117 2006/01/31 21:39:24 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/util/plancat.c,v 1.118 2006/02/04 23:03:20 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -25,6 +25,7 @@
#include "nodes/makefuncs.h"
#include "optimizer/clauses.h"
#include "optimizer/plancat.h"
+#include "optimizer/predtest.h"
#include "optimizer/prep.h"
#include "optimizer/tlist.h"
#include "parser/parsetree.h"
@@ -40,8 +41,13 @@
#include "miscadmin.h"
+/* GUC parameter */
+bool constraint_exclusion = false;
+
+
static void estimate_rel_size(Relation rel, int32 *attr_widths,
BlockNumber *pages, double *tuples);
+static List *get_relation_constraints(Oid relationObjectId, RelOptInfo *rel);
/*
@@ -360,7 +366,7 @@ estimate_rel_size(Relation rel, int32 *attr_widths,
* run, and in many cases it won't be invoked at all, so there seems no
* point in caching the data in RelOptInfo.
*/
-List *
+static List *
get_relation_constraints(Oid relationObjectId, RelOptInfo *rel)
{
List *result = NIL;
@@ -425,6 +431,48 @@ get_relation_constraints(Oid relationObjectId, RelOptInfo *rel)
/*
+ * relation_excluded_by_constraints
+ *
+ * Detect whether the relation need not be scanned because it has CHECK
+ * constraints that conflict with the query's WHERE clause.
+ */
+bool
+relation_excluded_by_constraints(RelOptInfo *rel, RangeTblEntry *rte)
+{
+ List *constraint_pred;
+
+ /* Skip the test if constraint exclusion is disabled */
+ if (!constraint_exclusion)
+ return false;
+
+ /* Only plain relations have constraints */
+ if (rte->rtekind != RTE_RELATION || rte->inh)
+ return false;
+
+ /* OK to fetch the constraint expressions */
+ constraint_pred = get_relation_constraints(rte->relid, rel);
+
+ /*
+ * We do not currently enforce that CHECK constraints contain only
+ * immutable functions, so it's necessary to check here. We daren't draw
+ * conclusions from plan-time evaluation of non-immutable functions.
+ */
+ if (contain_mutable_functions((Node *) constraint_pred))
+ return false;
+
+ /*
+ * The constraints are effectively ANDed together, so we can just try to
+ * refute the entire collection at once. This may allow us to make proofs
+ * that would fail if we took them individually.
+ */
+ if (predicate_refuted_by(constraint_pred, rel->baserestrictinfo))
+ return true;
+
+ return false;
+}
+
+
+/*
* build_physical_tlist
*
* Build a targetlist consisting of exactly the relation's user attributes,