aboutsummaryrefslogtreecommitdiff
path: root/src/backend/optimizer/util
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/optimizer/util')
-rw-r--r--src/backend/optimizer/util/clauses.c43
-rw-r--r--src/backend/optimizer/util/pathnode.c39
-rw-r--r--src/backend/optimizer/util/restrictinfo.c118
3 files changed, 118 insertions, 82 deletions
diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c
index 4da9f47dec5..bde0966f4ae 100644
--- a/src/backend/optimizer/util/clauses.c
+++ b/src/backend/optimizer/util/clauses.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.212 2006/06/16 18:42:22 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.213 2006/07/01 18:38:33 tgl Exp $
*
* HISTORY
* AUTHOR DATE MAJOR EVENT
@@ -1052,14 +1052,13 @@ is_strict_saop(ScalarArrayOpExpr *expr, bool falseOK)
/*
* is_pseudo_constant_clause
- * Detect whether a clause is "constant", ie, it contains no variables
- * of the current query level and no uses of volatile functions.
- * Such a clause is not necessarily a true constant: it can still contain
+ * Detect whether an expression is "pseudo constant", ie, it contains no
+ * variables of the current query level and no uses of volatile functions.
+ * Such an expr is not necessarily a true constant: it can still contain
* Params and outer-level Vars, not to mention functions whose results
- * may vary from one statement to the next. However, the clause's value
+ * may vary from one statement to the next. However, the expr's value
* will be constant over any one scan of the current query, so it can be
- * used as an indexscan key or (if a top-level qual) can be pushed up to
- * become a gating qual.
+ * used as, eg, an indexscan key.
*/
bool
is_pseudo_constant_clause(Node *clause)
@@ -1079,7 +1078,7 @@ is_pseudo_constant_clause(Node *clause)
/*
* is_pseudo_constant_clause_relids
* Same as above, except caller already has available the var membership
- * of the clause; this lets us avoid the contain_var_clause() scan.
+ * of the expression; this lets us avoid the contain_var_clause() scan.
*/
bool
is_pseudo_constant_clause_relids(Node *clause, Relids relids)
@@ -1090,34 +1089,6 @@ is_pseudo_constant_clause_relids(Node *clause, Relids relids)
return false;
}
-/*
- * pull_constant_clauses
- * Scan through a list of qualifications and separate "constant" quals
- * from those that are not.
- *
- * Returns a list of the pseudo-constant clauses in constantQual and the
- * remaining quals as the return value.
- */
-List *
-pull_constant_clauses(List *quals, List **constantQual)
-{
- List *constqual = NIL,
- *restqual = NIL;
- ListCell *q;
-
- foreach(q, quals)
- {
- Node *qual = (Node *) lfirst(q);
-
- if (is_pseudo_constant_clause(qual))
- constqual = lappend(constqual, qual);
- else
- restqual = lappend(restqual, qual);
- }
- *constantQual = constqual;
- return restqual;
-}
-
/*****************************************************************************
* Tests on clauses of queries
diff --git a/src/backend/optimizer/util/pathnode.c b/src/backend/optimizer/util/pathnode.c
index f8270074142..c0363d2405d 100644
--- a/src/backend/optimizer/util/pathnode.c
+++ b/src/backend/optimizer/util/pathnode.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/util/pathnode.c,v 1.128 2006/06/06 17:59:57 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/util/pathnode.c,v 1.129 2006/07/01 18:38:33 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -667,36 +667,29 @@ create_append_path(RelOptInfo *rel, List *subpaths)
/*
* create_result_path
- * Creates a path corresponding to a Result plan, returning the
- * pathnode.
+ * Creates a path representing a Result-and-nothing-else plan.
+ * This is only used for the case of a query with an empty jointree.
*/
ResultPath *
-create_result_path(RelOptInfo *rel, Path *subpath, List *constantqual)
+create_result_path(List *quals)
{
ResultPath *pathnode = makeNode(ResultPath);
pathnode->path.pathtype = T_Result;
- pathnode->path.parent = rel; /* may be NULL */
-
- if (subpath)
- pathnode->path.pathkeys = subpath->pathkeys;
- else
- pathnode->path.pathkeys = NIL;
-
- pathnode->subpath = subpath;
- pathnode->constantqual = constantqual;
+ pathnode->path.parent = NULL;
+ pathnode->path.pathkeys = NIL;
+ pathnode->quals = quals;
/* Ideally should define cost_result(), but I'm too lazy */
- if (subpath)
- {
- pathnode->path.startup_cost = subpath->startup_cost;
- pathnode->path.total_cost = subpath->total_cost;
- }
- else
- {
- pathnode->path.startup_cost = 0;
- pathnode->path.total_cost = cpu_tuple_cost;
- }
+ pathnode->path.startup_cost = 0;
+ pathnode->path.total_cost = cpu_tuple_cost;
+ /*
+ * In theory we should include the qual eval cost as well, but
+ * at present that doesn't accomplish much except duplicate work that
+ * will be done again in make_result; since this is only used for
+ * degenerate cases, nothing interesting will be done with the path
+ * cost values...
+ */
return pathnode;
}
diff --git a/src/backend/optimizer/util/restrictinfo.c b/src/backend/optimizer/util/restrictinfo.c
index 606f77bf900..ec43ee39f0e 100644
--- a/src/backend/optimizer/util/restrictinfo.c
+++ b/src/backend/optimizer/util/restrictinfo.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/util/restrictinfo.c,v 1.47 2006/04/07 17:05:39 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/util/restrictinfo.c,v 1.48 2006/07/01 18:38:33 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -26,10 +26,12 @@ static RestrictInfo *make_restrictinfo_internal(Expr *clause,
Expr *orclause,
bool is_pushed_down,
bool outerjoin_delayed,
+ bool pseudoconstant,
Relids required_relids);
static Expr *make_sub_restrictinfos(Expr *clause,
bool is_pushed_down,
bool outerjoin_delayed,
+ bool pseudoconstant,
Relids required_relids);
static RestrictInfo *join_clause_is_redundant(PlannerInfo *root,
RestrictInfo *rinfo,
@@ -42,9 +44,10 @@ static RestrictInfo *join_clause_is_redundant(PlannerInfo *root,
*
* Build a RestrictInfo node containing the given subexpression.
*
- * The is_pushed_down and outerjoin_delayed flags must be supplied by the
- * caller. required_relids can be NULL, in which case it defaults to the
- * actual clause contents (i.e., clause_relids).
+ * The is_pushed_down, outerjoin_delayed, and pseudoconstant flags for the
+ * RestrictInfo must be supplied by the caller. required_relids can be NULL,
+ * in which case it defaults to the actual clause contents (i.e.,
+ * clause_relids).
*
* We initialize fields that depend only on the given subexpression, leaving
* others that depend on context (or may never be needed at all) to be filled
@@ -54,6 +57,7 @@ RestrictInfo *
make_restrictinfo(Expr *clause,
bool is_pushed_down,
bool outerjoin_delayed,
+ bool pseudoconstant,
Relids required_relids)
{
/*
@@ -64,13 +68,17 @@ make_restrictinfo(Expr *clause,
return (RestrictInfo *) make_sub_restrictinfos(clause,
is_pushed_down,
outerjoin_delayed,
+ pseudoconstant,
required_relids);
/* Shouldn't be an AND clause, else AND/OR flattening messed up */
Assert(!and_clause((Node *) clause));
- return make_restrictinfo_internal(clause, NULL,
- is_pushed_down, outerjoin_delayed,
+ return make_restrictinfo_internal(clause,
+ NULL,
+ is_pushed_down,
+ outerjoin_delayed,
+ pseudoconstant,
required_relids);
}
@@ -85,7 +93,8 @@ make_restrictinfo(Expr *clause,
* RestrictInfos.
*
* The caller must pass is_pushed_down, but we assume outerjoin_delayed
- * is false (no such qual should ever get into a bitmapqual).
+ * and pseudoconstant are false (no such qual should ever get into a
+ * bitmapqual).
*
* If include_predicates is true, we add any partial index predicates to
* the explicit index quals. When this is not true, we return a condition
@@ -214,6 +223,7 @@ make_restrictinfo_from_bitmapqual(Path *bitmapqual,
make_orclause(withris),
is_pushed_down,
false,
+ false,
NULL));
}
}
@@ -239,6 +249,7 @@ make_restrictinfo_from_bitmapqual(Path *bitmapqual,
make_restrictinfo(pred,
is_pushed_down,
false,
+ false,
NULL));
}
}
@@ -258,8 +269,11 @@ make_restrictinfo_from_bitmapqual(Path *bitmapqual,
* Common code for the main entry points and the recursive cases.
*/
static RestrictInfo *
-make_restrictinfo_internal(Expr *clause, Expr *orclause,
- bool is_pushed_down, bool outerjoin_delayed,
+make_restrictinfo_internal(Expr *clause,
+ Expr *orclause,
+ bool is_pushed_down,
+ bool outerjoin_delayed,
+ bool pseudoconstant,
Relids required_relids)
{
RestrictInfo *restrictinfo = makeNode(RestrictInfo);
@@ -268,6 +282,7 @@ make_restrictinfo_internal(Expr *clause, Expr *orclause,
restrictinfo->orclause = orclause;
restrictinfo->is_pushed_down = is_pushed_down;
restrictinfo->outerjoin_delayed = outerjoin_delayed;
+ restrictinfo->pseudoconstant = pseudoconstant;
restrictinfo->can_join = false; /* may get set below */
/*
@@ -292,7 +307,11 @@ make_restrictinfo_internal(Expr *clause, Expr *orclause,
!bms_is_empty(restrictinfo->right_relids) &&
!bms_overlap(restrictinfo->left_relids,
restrictinfo->right_relids))
+ {
restrictinfo->can_join = true;
+ /* pseudoconstant should certainly not be true */
+ Assert(!restrictinfo->pseudoconstant);
+ }
}
else
{
@@ -346,13 +365,18 @@ make_restrictinfo_internal(Expr *clause, Expr *orclause,
* implicit-AND lists at top level of RestrictInfo lists. Only ORs and
* simple clauses are valid RestrictInfos.
*
+ * The same is_pushed_down, outerjoin_delayed, and pseudoconstant flag
+ * values can be applied to all RestrictInfo nodes in the result.
+ *
* The given required_relids are attached to our top-level output,
* but any OR-clause constituents are allowed to default to just the
* contained rels.
*/
static Expr *
make_sub_restrictinfos(Expr *clause,
- bool is_pushed_down, bool outerjoin_delayed,
+ bool is_pushed_down,
+ bool outerjoin_delayed,
+ bool pseudoconstant,
Relids required_relids)
{
if (or_clause((Node *) clause))
@@ -365,11 +389,13 @@ make_sub_restrictinfos(Expr *clause,
make_sub_restrictinfos(lfirst(temp),
is_pushed_down,
outerjoin_delayed,
+ pseudoconstant,
NULL));
return (Expr *) make_restrictinfo_internal(clause,
make_orclause(orlist),
is_pushed_down,
outerjoin_delayed,
+ pseudoconstant,
required_relids);
}
else if (and_clause((Node *) clause))
@@ -382,6 +408,7 @@ make_sub_restrictinfos(Expr *clause,
make_sub_restrictinfos(lfirst(temp),
is_pushed_down,
outerjoin_delayed,
+ pseudoconstant,
required_relids));
return make_andclause(andlist);
}
@@ -390,6 +417,7 @@ make_sub_restrictinfos(Expr *clause,
NULL,
is_pushed_down,
outerjoin_delayed,
+ pseudoconstant,
required_relids);
}
@@ -411,47 +439,91 @@ restriction_is_or_clause(RestrictInfo *restrictinfo)
* get_actual_clauses
*
* Returns a list containing the bare clauses from 'restrictinfo_list'.
+ *
+ * This is only to be used in cases where none of the RestrictInfos can
+ * be pseudoconstant clauses (for instance, it's OK on indexqual lists).
*/
List *
get_actual_clauses(List *restrictinfo_list)
{
List *result = NIL;
- ListCell *temp;
+ ListCell *l;
- foreach(temp, restrictinfo_list)
+ foreach(l, restrictinfo_list)
{
- RestrictInfo *rinfo = (RestrictInfo *) lfirst(temp);
+ RestrictInfo *rinfo = (RestrictInfo *) lfirst(l);
Assert(IsA(rinfo, RestrictInfo));
+ Assert(!rinfo->pseudoconstant);
+
result = lappend(result, rinfo->clause);
}
return result;
}
/*
- * get_actual_join_clauses
+ * extract_actual_clauses
*
- * Extract clauses from 'restrictinfo_list', separating those that
+ * Extract bare clauses from 'restrictinfo_list', returning either the
+ * regular ones or the pseudoconstant ones per 'pseudoconstant'.
+ */
+List *
+extract_actual_clauses(List *restrictinfo_list,
+ bool pseudoconstant)
+{
+ List *result = NIL;
+ ListCell *l;
+
+ foreach(l, restrictinfo_list)
+ {
+ RestrictInfo *rinfo = (RestrictInfo *) lfirst(l);
+
+ Assert(IsA(rinfo, RestrictInfo));
+
+ if (rinfo->pseudoconstant == pseudoconstant)
+ result = lappend(result, rinfo->clause);
+ }
+ return result;
+}
+
+/*
+ * extract_actual_join_clauses
+ *
+ * Extract bare clauses from 'restrictinfo_list', separating those that
* syntactically match the join level from those that were pushed down.
+ * Pseudoconstant clauses are excluded from the results.
+ *
+ * This is only used at outer joins, since for plain joins we don't care
+ * about pushed-down-ness.
*/
void
-get_actual_join_clauses(List *restrictinfo_list,
- List **joinquals, List **otherquals)
+extract_actual_join_clauses(List *restrictinfo_list,
+ List **joinquals,
+ List **otherquals)
{
- ListCell *temp;
+ ListCell *l;
*joinquals = NIL;
*otherquals = NIL;
- foreach(temp, restrictinfo_list)
+ foreach(l, restrictinfo_list)
{
- RestrictInfo *clause = (RestrictInfo *) lfirst(temp);
+ RestrictInfo *rinfo = (RestrictInfo *) lfirst(l);
+
+ Assert(IsA(rinfo, RestrictInfo));
- if (clause->is_pushed_down)
- *otherquals = lappend(*otherquals, clause->clause);
+ if (rinfo->is_pushed_down)
+ {
+ if (!rinfo->pseudoconstant)
+ *otherquals = lappend(*otherquals, rinfo->clause);
+ }
else
- *joinquals = lappend(*joinquals, clause->clause);
+ {
+ /* joinquals shouldn't have been marked pseudoconstant */
+ Assert(!rinfo->pseudoconstant);
+ *joinquals = lappend(*joinquals, rinfo->clause);
+ }
}
}