aboutsummaryrefslogtreecommitdiff
path: root/src/backend/optimizer/util/restrictinfo.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2004-01-04 00:07:32 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2004-01-04 00:07:32 +0000
commit6cb1c0238b2503f485e3491902bfc294b7beeed1 (patch)
tree0cb4104e7027805adb1420ed182e4ff908fd0b0e /src/backend/optimizer/util/restrictinfo.c
parent037e2fcf8fb4f5af00a5eceb26f4a2170e99b343 (diff)
downloadpostgresql-6cb1c0238b2503f485e3491902bfc294b7beeed1.tar.gz
postgresql-6cb1c0238b2503f485e3491902bfc294b7beeed1.zip
Rewrite OR indexscan processing to be more flexible. We can now for the
first time generate an OR indexscan for a two-column index when the WHERE condition is like 'col1 = foo AND (col2 = bar OR col2 = baz)' --- before, the OR had to be on the first column of the index or we'd not notice the possibility of using it. Some progress towards extracting OR indexscans from subclauses of an OR that references multiple relations, too, although this code is #ifdef'd out because it needs more work.
Diffstat (limited to 'src/backend/optimizer/util/restrictinfo.c')
-rw-r--r--src/backend/optimizer/util/restrictinfo.c127
1 files changed, 124 insertions, 3 deletions
diff --git a/src/backend/optimizer/util/restrictinfo.c b/src/backend/optimizer/util/restrictinfo.c
index f77966a2262..a7c9ec85f72 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.21 2003/12/30 23:53:15 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/util/restrictinfo.c,v 1.22 2004/01/04 00:07:32 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -20,6 +20,7 @@
#include "optimizer/var.h"
+static Expr *make_sub_restrictinfos(Expr *clause, bool ispusheddown);
static bool join_clause_is_redundant(Query *root,
RestrictInfo *rinfo,
List *reference_list,
@@ -27,6 +28,127 @@ static bool join_clause_is_redundant(Query *root,
/*
+ * make_restrictinfo
+ *
+ * Build a RestrictInfo node containing the given subexpression.
+ *
+ * The ispusheddown flag must be supplied by the caller. 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 later.
+ */
+RestrictInfo *
+make_restrictinfo(Expr *clause, bool ispusheddown)
+{
+ RestrictInfo *restrictinfo = makeNode(RestrictInfo);
+
+ restrictinfo->clause = clause;
+ restrictinfo->ispusheddown = ispusheddown;
+ restrictinfo->canjoin = false; /* may get set below */
+
+ /*
+ * If it's a binary opclause, set up left/right relids info.
+ */
+ if (is_opclause(clause) && length(((OpExpr *) clause)->args) == 2)
+ {
+ restrictinfo->left_relids = pull_varnos(get_leftop(clause));
+ restrictinfo->right_relids = pull_varnos(get_rightop(clause));
+
+ /*
+ * Does it look like a normal join clause, i.e., a binary operator
+ * relating expressions that come from distinct relations? If so
+ * we might be able to use it in a join algorithm. Note that this
+ * is a purely syntactic test that is made regardless of context.
+ */
+ if (!bms_is_empty(restrictinfo->left_relids) &&
+ !bms_is_empty(restrictinfo->right_relids) &&
+ !bms_overlap(restrictinfo->left_relids,
+ restrictinfo->right_relids))
+ restrictinfo->canjoin = true;
+ }
+ else
+ {
+ /* Not a binary opclause, so mark both relid sets as empty */
+ restrictinfo->left_relids = NULL;
+ restrictinfo->right_relids = NULL;
+ }
+
+ /*
+ * If it's an OR clause, set up a modified copy with RestrictInfos
+ * inserted above each subclause of the top-level AND/OR structure.
+ */
+ if (or_clause((Node *) clause))
+ {
+ restrictinfo->orclause = make_sub_restrictinfos(clause, ispusheddown);
+ }
+ else
+ {
+ /* Shouldn't be an AND clause, else flatten_andors messed up */
+ Assert(!and_clause((Node *) clause));
+
+ restrictinfo->orclause = NULL;
+ }
+
+ /*
+ * Fill in all the cacheable fields with "not yet set" markers.
+ * None of these will be computed until/unless needed. Note in
+ * particular that we don't mark a binary opclause as mergejoinable
+ * or hashjoinable here; that happens only if it appears in the right
+ * context (top level of a joinclause list).
+ */
+ restrictinfo->eval_cost.startup = -1;
+ restrictinfo->this_selec = -1;
+
+ restrictinfo->mergejoinoperator = InvalidOid;
+ restrictinfo->left_sortop = InvalidOid;
+ restrictinfo->right_sortop = InvalidOid;
+
+ restrictinfo->left_pathkey = NIL;
+ restrictinfo->right_pathkey = NIL;
+
+ restrictinfo->left_mergescansel = -1;
+ restrictinfo->right_mergescansel = -1;
+
+ restrictinfo->hashjoinoperator = InvalidOid;
+
+ restrictinfo->left_bucketsize = -1;
+ restrictinfo->right_bucketsize = -1;
+
+ return restrictinfo;
+}
+
+/*
+ * Recursively insert sub-RestrictInfo nodes into a boolean expression.
+ */
+static Expr *
+make_sub_restrictinfos(Expr *clause, bool ispusheddown)
+{
+ if (or_clause((Node *) clause))
+ {
+ List *orlist = NIL;
+ List *temp;
+
+ foreach(temp, ((BoolExpr *) clause)->args)
+ orlist = lappend(orlist,
+ make_sub_restrictinfos(lfirst(temp),
+ ispusheddown));
+ return make_orclause(orlist);
+ }
+ else if (and_clause((Node *) clause))
+ {
+ List *andlist = NIL;
+ List *temp;
+
+ foreach(temp, ((BoolExpr *) clause)->args)
+ andlist = lappend(andlist,
+ make_sub_restrictinfos(lfirst(temp),
+ ispusheddown));
+ return make_andclause(andlist);
+ }
+ else
+ return (Expr *) make_restrictinfo(clause, ispusheddown);
+}
+
+/*
* restriction_is_or_clause
*
* Returns t iff the restrictinfo node contains an 'or' clause.
@@ -34,8 +156,7 @@ static bool join_clause_is_redundant(Query *root,
bool
restriction_is_or_clause(RestrictInfo *restrictinfo)
{
- if (restrictinfo != NULL &&
- or_clause((Node *) restrictinfo->clause))
+ if (restrictinfo->orclause != NULL)
return true;
else
return false;