<!--
-$PostgreSQL: pgsql/doc/src/sgml/config.sgml,v 1.45 2006/01/23 18:16:41 tgl Exp $
+$PostgreSQL: pgsql/doc/src/sgml/config.sgml,v 1.46 2006/02/04 23:03:19 tgl Exp $
-->
<chapter Id="runtime-config">
<title>Server Configuration</title>
When this parameter is <literal>on</>, the planner compares
query conditions with table <literal>CHECK</> constraints, and
omits scanning tables for which the conditions contradict the
- constraints. (Presently this is done only for child tables of
- inheritance scans.) For example:
+ constraints. For example:
<programlisting>
CREATE TABLE parent(key integer, ...);
-<!-- $PostgreSQL: pgsql/doc/src/sgml/ddl.sgml,v 1.51 2005/12/23 00:38:03 momjian Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/ddl.sgml,v 1.52 2006/02/04 23:03:19 tgl Exp $ -->
<chapter id="ddl">
<title>Data Definition</title>
<para>
<productname>PostgreSQL</productname> supports basic table
- partitioning. This section describes why and how you can implement
+ partitioning. This section describes why and how to implement
partitioning as part of your database design.
</para>
table of a single parent table. The parent table itself is normally
empty; it exists just to represent the entire data set. You should be
familiar with inheritance (see <xref linkend="ddl-inherit">) before
- attempting to implement partitioning.
+ attempting to set up partitioning.
</para>
<para>
UNION ALL SELECT * FROM measurement_yy06mm01;
</programlisting>
- However, constraint exclusion is currently not supported for
- partitioned tables defined in this manner. Also, the need to
+ However, the need to
recreate the view adds an extra step to adding and dropping
individual partitions of the dataset.
</para>
optimized, since the planner cannot know what partitions the
parameter value might select at runtime. For the same reason,
<quote>stable</> functions such as <function>CURRENT_DATE</function>
- must be avoided. Joining the partition key to a column of another
- table will not be optimized, either.
+ must be avoided.
</para>
</listitem>
</para>
</listitem>
- <listitem>
- <para>
- <command>UPDATE</command> and <command>DELETE</command> commands
- against the master table do not currently perform constraint exclusion.
- </para>
- </listitem>
-
<listitem>
<para>
All constraints on all partitions of the master table are considered for
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/path/allpaths.c,v 1.141 2006/02/03 21:08:49 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/path/allpaths.c,v 1.142 2006/02/04 23:03:20 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "optimizer/paths.h"
#include "optimizer/plancat.h"
#include "optimizer/planner.h"
-#include "optimizer/predtest.h"
#include "optimizer/prep.h"
#include "optimizer/var.h"
#include "parser/parsetree.h"
/* These parameters are set by GUC */
-bool constraint_exclusion = false;
bool enable_geqo = false; /* just in case GUC doesn't set it */
int geqo_threshold;
static void set_base_rel_pathlists(PlannerInfo *root);
-static void set_rel_pathlist(PlannerInfo *root, RelOptInfo *rel,
- Index rti, RangeTblEntry *rte);
+static void set_rel_pathlist(PlannerInfo *root, RelOptInfo *rel, Index rti);
static void set_plain_rel_pathlist(PlannerInfo *root, RelOptInfo *rel,
RangeTblEntry *rte);
static void set_append_rel_pathlist(PlannerInfo *root, RelOptInfo *rel,
if (rel->reloptkind != RELOPT_BASEREL)
continue;
- set_rel_pathlist(root, rel, rti,
- rt_fetch(rti, root->parse->rtable));
+ set_rel_pathlist(root, rel, rti);
}
}
* Build access paths for a base relation
*/
static void
-set_rel_pathlist(PlannerInfo *root, RelOptInfo *rel,
- Index rti, RangeTblEntry *rte)
+set_rel_pathlist(PlannerInfo *root, RelOptInfo *rel, Index rti)
{
+ RangeTblEntry *rte = rt_fetch(rti, root->parse->rtable);
+
if (rte->inh)
{
/* It's an "append relation", process accordingly */
if (create_or_index_quals(root, rel))
set_baserel_size_estimates(root, rel);
+ /*
+ * If we can prove we don't need to scan the rel via constraint exclusion,
+ * set up a single dummy path for it. (Rather than inventing a special
+ * "dummy" path type, we represent this as an AppendPath with no members.)
+ */
+ if (relation_excluded_by_constraints(rel, rte))
+ {
+ /* Reset output-rows estimate to 0 */
+ rel->rows = 0;
+
+ add_path(rel, (Path *) create_append_path(rel, NIL));
+
+ /* Select cheapest path (pretty easy in this case...) */
+ set_cheapest(rel);
+
+ return;
+ }
+
/*
* Generate paths and add them to the rel's pathlist.
*
AppendRelInfo *appinfo = (AppendRelInfo *) lfirst(l);
int childRTindex;
RelOptInfo *childrel;
- RangeTblEntry *childrte;
Path *childpath;
ListCell *parentvars;
ListCell *childvars;
childrel->max_attr);
/*
- * If we can prove we don't need to scan this child via constraint
- * exclusion, just ignore it. (We have to have converted the
- * baserestrictinfo Vars before we can make the test.)
- *
- * XXX it'd probably be better to give the child some kind of dummy
- * cheapest path, or otherwise explicitly mark it as ignorable.
- * Currently there is an ugly check in join_before_append() to handle
- * excluded children.
- */
- childrte = rt_fetch(childRTindex, root->parse->rtable);
- if (constraint_exclusion &&
- childrte->rtekind == RTE_RELATION)
- {
- List *constraint_pred;
-
- constraint_pred = get_relation_constraints(childrte->relid,
- childrel);
-
- /*
- * 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))
- {
- /*
- * 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,
- childrel->baserestrictinfo))
- continue;
- }
- }
-
- /*
- * Compute the child's access paths, and save the cheapest.
+ * Compute the child's access paths, and add the cheapest one
+ * to the Append path we are constructing for the parent.
*
* It's possible that the child is itself an appendrel, in which
* case we can "cut out the middleman" and just add its child
* paths to our own list. (We don't try to do this earlier because
* we need to apply both levels of transformation to the quals.)
+ * This test also handles the case where the child rel need not
+ * be scanned because of constraint exclusion: it'll have an
+ * Append path with no subpaths, and will vanish from our list.
*/
- set_rel_pathlist(root, childrel, childRTindex, childrte);
+ set_rel_pathlist(root, childrel, childRTindex);
childpath = childrel->cheapest_total_path;
if (IsA(childpath, AppendPath))
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/path/joinpath.c,v 1.100 2006/02/03 21:08:49 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/path/joinpath.c,v 1.101 2006/02/04 23:03:20 tgl Exp $
*
*-------------------------------------------------------------------------
*/
Assert(childrel->reloptkind == RELOPT_OTHER_MEMBER_REL);
/*
- * If the child has no cheapest_total_path, assume it was deemed
- * excludable by constraint exclusion (see set_append_rel_pathlist).
+ * Check to see if child was rejected by constraint exclusion.
+ * If so, it will have a cheapest_total_path that's an Append path
+ * with no members (see set_plain_rel_pathlist).
*/
- if (childrel->cheapest_total_path == NULL)
- {
- Assert(constraint_exclusion);
- continue;
- }
+ if (IsA(childrel->cheapest_total_path, AppendPath) &&
+ ((AppendPath *) childrel->cheapest_total_path)->subpaths == NIL)
+ continue; /* OK, we can ignore it */
/*
* Get the best innerjoin indexpath (if any) for this outer rel.
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
#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"
#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);
/*
* 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;
}
+/*
+ * 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
*
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/optimizer/plancat.h,v 1.37 2005/07/23 21:05:48 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/optimizer/plancat.h,v 1.38 2006/02/04 23:03:20 tgl Exp $
*
*-------------------------------------------------------------------------
*/
extern void get_relation_info(Oid relationObjectId, RelOptInfo *rel);
-extern List *get_relation_constraints(Oid relationObjectId, RelOptInfo *rel);
+extern bool relation_excluded_by_constraints(RelOptInfo *rel,
+ RangeTblEntry *rte);
extern List *build_physical_tlist(PlannerInfo *root, RelOptInfo *rel);