]> granicus.if.org Git - postgresql/commitdiff
Restore the former RestrictInfo field valid_everywhere (but invert the flag
authorTom Lane <tgl@sss.pgh.pa.us>
Mon, 14 Nov 2005 23:54:23 +0000 (23:54 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Mon, 14 Nov 2005 23:54:23 +0000 (23:54 +0000)
sense and rename to "outerjoin_delayed" to more clearly reflect what it
means).  I had decided that it was redundant in 8.1, but the folly of this
is exposed by a bug report from Sebastian Böck.  The place where it's
needed is to prevent orindxpath.c from cherry-picking arms of an outer-join
OR clause to form a relation restriction that isn't actually legal to push
down to the relation scan level.  There may be some legal cases that this
forbids optimizing, but we'd need much closer analysis to determine it.

src/backend/nodes/copyfuncs.c
src/backend/nodes/equalfuncs.c
src/backend/nodes/outfuncs.c
src/backend/optimizer/path/indxpath.c
src/backend/optimizer/path/orindxpath.c
src/backend/optimizer/plan/initsplan.c
src/backend/optimizer/util/restrictinfo.c
src/include/nodes/relation.h
src/include/optimizer/restrictinfo.h

index 4a90b10b277dbf512b738db90643c394a49e99fd..a5efda5a30b413f4aac18b58368657bbdb271446 100644 (file)
@@ -15,7 +15,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.316 2005/10/15 02:49:18 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.317 2005/11/14 23:54:12 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1249,6 +1249,7 @@ _copyRestrictInfo(RestrictInfo *from)
 
        COPY_NODE_FIELD(clause);
        COPY_SCALAR_FIELD(is_pushed_down);
+       COPY_SCALAR_FIELD(outerjoin_delayed);
        COPY_SCALAR_FIELD(can_join);
        COPY_BITMAPSET_FIELD(clause_relids);
        COPY_BITMAPSET_FIELD(required_relids);
index 9baa79dd9358af25579fa321858d771f196637a1..dbebe8d4e874f3eee91a0aa4db298f98793cf45f 100644 (file)
@@ -18,7 +18,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.253 2005/10/15 02:49:18 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.254 2005/11/14 23:54:15 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -602,6 +602,7 @@ _equalRestrictInfo(RestrictInfo *a, RestrictInfo *b)
 {
        COMPARE_NODE_FIELD(clause);
        COMPARE_SCALAR_FIELD(is_pushed_down);
+       COMPARE_SCALAR_FIELD(outerjoin_delayed);
        COMPARE_BITMAPSET_FIELD(required_relids);
 
        /*
index 19306b3e53dbcdc99433f7fa9870abae46069c8d..16acd5d72140d48e5bde33f0dccec58938e943d1 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.261 2005/10/15 02:49:18 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.262 2005/11/14 23:54:15 tgl Exp $
  *
  * NOTES
  *       Every node type that can appear in stored rules' parsetrees *must*
@@ -1241,6 +1241,7 @@ _outRestrictInfo(StringInfo str, RestrictInfo *node)
        /* NB: this isn't a complete set of fields */
        WRITE_NODE_FIELD(clause);
        WRITE_BOOL_FIELD(is_pushed_down);
+       WRITE_BOOL_FIELD(outerjoin_delayed);
        WRITE_BOOL_FIELD(can_join);
        WRITE_BITMAPSET_FIELD(clause_relids);
        WRITE_BITMAPSET_FIELD(required_relids);
index 1790cc5266be85454c92358e039ae5088f0b1fea..0033b98d57afcb81d2fb2e7799cc33d1ddaa1ec4 100644 (file)
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/optimizer/path/indxpath.c,v 1.191 2005/10/15 02:49:19 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/optimizer/path/indxpath.c,v 1.192 2005/11/14 23:54:17 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1917,6 +1917,7 @@ expand_indexqual_conditions(IndexOptInfo *index, List *clausegroups)
                                        resultquals = lappend(resultquals,
                                                                                  make_restrictinfo(boolqual,
                                                                                                                        true,
+                                                                                                                       false,
                                                                                                                        NULL));
                                        continue;
                                }
@@ -2166,7 +2167,7 @@ prefix_quals(Node *leftop, Oid opclass,
                        elog(ERROR, "no = operator for opclass %u", opclass);
                expr = make_opclause(oproid, BOOLOID, false,
                                                         (Expr *) leftop, (Expr *) prefix_const);
-               result = list_make1(make_restrictinfo(expr, true, NULL));
+               result = list_make1(make_restrictinfo(expr, true, false, NULL));
                return result;
        }
 
@@ -2181,7 +2182,7 @@ prefix_quals(Node *leftop, Oid opclass,
                elog(ERROR, "no >= operator for opclass %u", opclass);
        expr = make_opclause(oproid, BOOLOID, false,
                                                 (Expr *) leftop, (Expr *) prefix_const);
-       result = list_make1(make_restrictinfo(expr, true, NULL));
+       result = list_make1(make_restrictinfo(expr, true, false, NULL));
 
        /*-------
         * If we can create a string larger than the prefix, we can say
@@ -2197,7 +2198,7 @@ prefix_quals(Node *leftop, Oid opclass,
                        elog(ERROR, "no < operator for opclass %u", opclass);
                expr = make_opclause(oproid, BOOLOID, false,
                                                         (Expr *) leftop, (Expr *) greaterstr);
-               result = lappend(result, make_restrictinfo(expr, true, NULL));
+               result = lappend(result, make_restrictinfo(expr, true, false, NULL));
        }
 
        return result;
@@ -2268,7 +2269,7 @@ network_prefix_quals(Node *leftop, Oid expr_op, Oid opclass, Datum rightop)
                                                 (Expr *) leftop,
                                                 (Expr *) makeConst(datatype, -1, opr1right,
                                                                                        false, false));
-       result = list_make1(make_restrictinfo(expr, true, NULL));
+       result = list_make1(make_restrictinfo(expr, true, false, NULL));
 
        /* create clause "key <= network_scan_last( rightop )" */
 
@@ -2283,7 +2284,7 @@ network_prefix_quals(Node *leftop, Oid expr_op, Oid opclass, Datum rightop)
                                                 (Expr *) leftop,
                                                 (Expr *) makeConst(datatype, -1, opr2right,
                                                                                        false, false));
-       result = lappend(result, make_restrictinfo(expr, true, NULL));
+       result = lappend(result, make_restrictinfo(expr, true, false, NULL));
 
        return result;
 }
index be5a0c3434fc49f23dfcd7374a7c0c70e71151bd..10b12890dae35a91cdf95e8ef4d842c82e256ac6 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/optimizer/path/orindxpath.c,v 1.75 2005/10/15 02:49:20 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/optimizer/path/orindxpath.c,v 1.76 2005/11/14 23:54:18 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -90,13 +90,19 @@ create_or_index_quals(PlannerInfo *root, RelOptInfo *rel)
        ListCell   *i;
 
        /*
-        * Find potentially interesting OR joinclauses.
+        * Find potentially interesting OR joinclauses.  Note we must ignore any
+        * joinclauses that are marked outerjoin_delayed, because they cannot
+        * be pushed down to the per-relation level due to outer-join rules.
+        * (XXX in some cases it might be possible to allow this, but it would
+        * require substantially more bookkeeping about where the clause came
+        * from.)
         */
        foreach(i, rel->joininfo)
        {
                RestrictInfo *rinfo = (RestrictInfo *) lfirst(i);
 
-               if (restriction_is_or_clause(rinfo))
+               if (restriction_is_or_clause(rinfo) &&
+                       !rinfo->outerjoin_delayed)
                {
                        /*
                         * Use the generate_bitmap_or_paths() machinery to estimate the
index dd8fc4fa2d7ba076e617bab03e1aaf8611902575..fd1ddedbfd2a8f320db7e7ef9706bf90cda8e0a4 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/optimizer/plan/initsplan.c,v 1.110 2005/10/15 02:49:20 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/optimizer/plan/initsplan.c,v 1.111 2005/11/14 23:54:18 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -409,6 +409,7 @@ distribute_qual_to_rels(PlannerInfo *root, Node *clause,
                                                Relids qualscope)
 {
        Relids          relids;
+       bool            outerjoin_delayed;
        bool            maybe_equijoin;
        bool            maybe_outer_join;
        RestrictInfo *restrictinfo;
@@ -451,6 +452,7 @@ distribute_qual_to_rels(PlannerInfo *root, Node *clause,
                 */
                Assert(bms_equal(relids, qualscope));
                /* Needn't feed it back for more deductions */
+               outerjoin_delayed = false;
                maybe_equijoin = false;
                maybe_outer_join = false;
        }
@@ -470,6 +472,7 @@ distribute_qual_to_rels(PlannerInfo *root, Node *clause,
                 * except for not setting maybe_equijoin (see below).
                 */
                relids = qualscope;
+               outerjoin_delayed = true;
 
                /*
                 * We can't use such a clause to deduce equijoin (the left and right
@@ -499,13 +502,17 @@ distribute_qual_to_rels(PlannerInfo *root, Node *clause,
                Relids          tmprelids;
                int                     relno;
 
+               outerjoin_delayed = false;
                tmprelids = bms_copy(relids);
                while ((relno = bms_first_member(tmprelids)) >= 0)
                {
                        RelOptInfo *rel = find_base_rel(root, relno);
 
                        if (rel->outerjoinset != NULL)
+                       {
                                addrelids = bms_add_members(addrelids, rel->outerjoinset);
+                               outerjoin_delayed = true;
+                       }
                }
                bms_free(tmprelids);
 
@@ -555,6 +562,7 @@ distribute_qual_to_rels(PlannerInfo *root, Node *clause,
         */
        restrictinfo = make_restrictinfo((Expr *) clause,
                                                                         is_pushed_down,
+                                                                        outerjoin_delayed,
                                                                         relids);
 
        /*
index d277cac735123d9b79936162d45a3c2d94e10be9..96c207c9350267928e23dff0f361560b2cb1caca 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/optimizer/util/restrictinfo.c,v 1.41 2005/10/15 02:49:21 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/optimizer/util/restrictinfo.c,v 1.42 2005/11/14 23:54:22 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 static RestrictInfo *make_restrictinfo_internal(Expr *clause,
                                                   Expr *orclause,
                                                   bool is_pushed_down,
+                                                  bool outerjoin_delayed,
                                                   Relids required_relids);
 static Expr *make_sub_restrictinfos(Expr *clause,
-                                          bool is_pushed_down);
+                                          bool is_pushed_down,
+                                          bool outerjoin_delayed);
 static RestrictInfo *join_clause_is_redundant(PlannerInfo *root,
                                                 RestrictInfo *rinfo,
                                                 List *reference_list,
@@ -39,8 +41,8 @@ static RestrictInfo *join_clause_is_redundant(PlannerInfo *root,
  *
  * Build a RestrictInfo node containing the given subexpression.
  *
- * The is_pushed_down flag must be supplied by the caller.
- * required_relids can be NULL, in which case it defaults to the
+ * 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).
  *
  * We initialize fields that depend only on the given subexpression, leaving
@@ -48,19 +50,25 @@ static RestrictInfo *join_clause_is_redundant(PlannerInfo *root,
  * later.
  */
 RestrictInfo *
-make_restrictinfo(Expr *clause, bool is_pushed_down, Relids required_relids)
+make_restrictinfo(Expr *clause,
+                                 bool is_pushed_down,
+                                 bool outerjoin_delayed,
+                                 Relids required_relids)
 {
        /*
         * If it's an OR clause, build a modified copy with RestrictInfos inserted
         * above each subclause of the top-level AND/OR structure.
         */
        if (or_clause((Node *) clause))
-               return (RestrictInfo *) make_sub_restrictinfos(clause, is_pushed_down);
+               return (RestrictInfo *) make_sub_restrictinfos(clause,
+                                                                                                          is_pushed_down,
+                                                                                                          outerjoin_delayed);
 
        /* 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,
+       return make_restrictinfo_internal(clause, NULL,
+                                                                         is_pushed_down, outerjoin_delayed,
                                                                          required_relids);
 }
 
@@ -74,6 +82,9 @@ make_restrictinfo(Expr *clause, bool is_pushed_down, Relids required_relids)
  * The result is a List (effectively, implicit-AND representation) of
  * RestrictInfos.
  *
+ * The caller must pass is_pushed_down, but we assume outerjoin_delayed
+ * is 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
  * that might be weaker than the actual scan represents.
@@ -169,6 +180,7 @@ make_restrictinfo_from_bitmapqual(Path *bitmapqual,
                                list_make1(make_restrictinfo_internal(make_orclause(withoutris),
                                                                                                          make_orclause(withris),
                                                                                                          is_pushed_down,
+                                                                                                         false,
                                                                                                          NULL));
                }
        }
@@ -193,6 +205,7 @@ make_restrictinfo_from_bitmapqual(Path *bitmapqual,
                                        result = lappend(result,
                                                                         make_restrictinfo(pred,
                                                                                                           is_pushed_down,
+                                                                                                          false,
                                                                                                           NULL));
                        }
                }
@@ -213,13 +226,15 @@ make_restrictinfo_from_bitmapqual(Path *bitmapqual,
  */
 static RestrictInfo *
 make_restrictinfo_internal(Expr *clause, Expr *orclause,
-                                                  bool is_pushed_down, Relids required_relids)
+                                                  bool is_pushed_down, bool outerjoin_delayed,
+                                                  Relids required_relids)
 {
        RestrictInfo *restrictinfo = makeNode(RestrictInfo);
 
        restrictinfo->clause = clause;
        restrictinfo->orclause = orclause;
        restrictinfo->is_pushed_down = is_pushed_down;
+       restrictinfo->outerjoin_delayed = outerjoin_delayed;
        restrictinfo->can_join = false;         /* may get set below */
 
        /*
@@ -299,7 +314,8 @@ make_restrictinfo_internal(Expr *clause, Expr *orclause,
  * simple clauses are valid RestrictInfos.
  */
 static Expr *
-make_sub_restrictinfos(Expr *clause, bool is_pushed_down)
+make_sub_restrictinfos(Expr *clause,
+                                          bool is_pushed_down, bool outerjoin_delayed)
 {
        if (or_clause((Node *) clause))
        {
@@ -309,10 +325,12 @@ make_sub_restrictinfos(Expr *clause, bool is_pushed_down)
                foreach(temp, ((BoolExpr *) clause)->args)
                        orlist = lappend(orlist,
                                                         make_sub_restrictinfos(lfirst(temp),
-                                                                                                       is_pushed_down));
+                                                                                                       is_pushed_down,
+                                                                                                       outerjoin_delayed));
                return (Expr *) make_restrictinfo_internal(clause,
                                                                                                   make_orclause(orlist),
                                                                                                   is_pushed_down,
+                                                                                                  outerjoin_delayed,
                                                                                                   NULL);
        }
        else if (and_clause((Node *) clause))
@@ -323,13 +341,15 @@ make_sub_restrictinfos(Expr *clause, bool is_pushed_down)
                foreach(temp, ((BoolExpr *) clause)->args)
                        andlist = lappend(andlist,
                                                          make_sub_restrictinfos(lfirst(temp),
-                                                                                                        is_pushed_down));
+                                                                                                        is_pushed_down,
+                                                                                                        outerjoin_delayed));
                return make_andclause(andlist);
        }
        else
                return (Expr *) make_restrictinfo_internal(clause,
                                                                                                   NULL,
                                                                                                   is_pushed_down,
+                                                                                                  outerjoin_delayed,
                                                                                                   NULL);
 }
 
index 01aa96d717154ccd2ec39cf750f22cf305e742fc..15d5647282cb563d626fd93b2977480e1021f887 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/nodes/relation.h,v 1.119 2005/10/15 02:49:45 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/nodes/relation.h,v 1.120 2005/11/14 23:54:23 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -714,6 +714,11 @@ typedef struct HashPath
  * joined, will also have is_pushed_down set because it will get attached to
  * some lower joinrel.
  *
+ * When application of a qual must be delayed by outer join, we also mark it
+ * with outerjoin_delayed = true.  This isn't redundant with required_relids
+ * because that might equal clause_relids whether or not it's an outer-join
+ * clause.
+ *
  * In general, the referenced clause might be arbitrarily complex.     The
  * kinds of clauses we can handle as indexscan quals, mergejoin clauses,
  * or hashjoin clauses are fairly limited --- the code for each kind of
@@ -740,6 +745,8 @@ typedef struct RestrictInfo
 
        bool            is_pushed_down; /* TRUE if clause was pushed down in level */
 
+       bool            outerjoin_delayed;              /* TRUE if delayed by outer join */
+
        /*
         * This flag is set true if the clause looks potentially useful as a merge
         * or hash join clause, that is if it is a binary opclause with
index 0715df59d68685c009da8f7a53eb7bedf72b796c..4ca5c87bae82674562267d80d217458af0a8c1b2 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/optimizer/restrictinfo.h,v 1.34 2005/10/15 02:49:45 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/optimizer/restrictinfo.h,v 1.35 2005/11/14 23:54:23 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -19,6 +19,7 @@
 
 extern RestrictInfo *make_restrictinfo(Expr *clause,
                                  bool is_pushed_down,
+                                 bool outerjoin_delayed,
                                  Relids required_relids);
 extern List *make_restrictinfo_from_bitmapqual(Path *bitmapqual,
                                                                  bool is_pushed_down,