Adjust the definition of RestrictInfo's left_relids and right_relids
authorTom Lane <tgl@sss.pgh.pa.us>
Tue, 30 Dec 2003 23:53:15 +0000 (23:53 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Tue, 30 Dec 2003 23:53:15 +0000 (23:53 +0000)
fields: now they are valid whenever the clause is a binary opclause,
not only when it is a potential join clause (there is a new boolean
field canjoin to signal the latter condition).  This lets us avoid
recomputing the relid sets over and over while examining indexes.
Still more work to do to make this as useful as it could be, because
there are places that could use the info but don't have access to the
RestrictInfo node.

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/joinpath.c
src/backend/optimizer/plan/initsplan.c
src/backend/optimizer/util/clauses.c
src/backend/optimizer/util/restrictinfo.c
src/include/nodes/relation.h
src/include/optimizer/clauses.h

index ef4f0421e93bdc7ba7eaf78be71be1be2c062fac..8b96f77a7316f2b327e7209bb9c7aab4d0748b2e 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.269 2003/11/29 19:51:49 pgsql Exp $
+ *   $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.270 2003/12/30 23:53:14 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1169,11 +1169,12 @@ _copyRestrictInfo(RestrictInfo *from)
 
    COPY_NODE_FIELD(clause);
    COPY_SCALAR_FIELD(ispusheddown);
+   COPY_SCALAR_FIELD(canjoin);
+   COPY_BITMAPSET_FIELD(left_relids);
+   COPY_BITMAPSET_FIELD(right_relids);
    COPY_NODE_FIELD(subclauseindices);  /* XXX probably bad */
    COPY_SCALAR_FIELD(eval_cost);
    COPY_SCALAR_FIELD(this_selec);
-   COPY_BITMAPSET_FIELD(left_relids);
-   COPY_BITMAPSET_FIELD(right_relids);
    COPY_SCALAR_FIELD(mergejoinoperator);
    COPY_SCALAR_FIELD(left_sortop);
    COPY_SCALAR_FIELD(right_sortop);
index f4fd1d774326d6784ab12dad0bea23e48448e5ad..5c7e53844022743eea617cff8e2d6cec65a1a7f5 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.210 2003/11/29 19:51:49 pgsql Exp $
+ *   $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.211 2003/12/30 23:53:14 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -563,16 +563,9 @@ _equalRestrictInfo(RestrictInfo *a, RestrictInfo *b)
    COMPARE_SCALAR_FIELD(ispusheddown);
 
    /*
-    * We ignore subclauseindices, eval_cost, this_selec,
-    * left/right_relids, left/right_pathkey, and left/right_bucketsize,
-    * since they may not be set yet, and should be derivable from the
-    * clause anyway.  Probably it's not really necessary to compare any
-    * of these remaining fields ...
+    * We ignore all the remaining fields, since they may not be set yet,
+    * and should be derivable from the clause anyway.
     */
-   COMPARE_SCALAR_FIELD(mergejoinoperator);
-   COMPARE_SCALAR_FIELD(left_sortop);
-   COMPARE_SCALAR_FIELD(right_sortop);
-   COMPARE_SCALAR_FIELD(hashjoinoperator);
 
    return true;
 }
index 0946cbc9eb7e5ddb2311f76be18d73c0a71fd598..6b8a8a4a8748439e90a85ca41f05fed07138a4c6 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.222 2003/11/29 19:51:49 pgsql Exp $
+ *   $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.223 2003/12/30 23:53:14 tgl Exp $
  *
  * NOTES
  *   Every node type that can appear in stored rules' parsetrees *must*
@@ -1074,9 +1074,10 @@ _outRestrictInfo(StringInfo str, RestrictInfo *node)
    /* NB: this isn't a complete set of fields */
    WRITE_NODE_FIELD(clause);
    WRITE_BOOL_FIELD(ispusheddown);
-   WRITE_NODE_FIELD(subclauseindices);
+   WRITE_BOOL_FIELD(canjoin);
    WRITE_BITMAPSET_FIELD(left_relids);
    WRITE_BITMAPSET_FIELD(right_relids);
+   WRITE_NODE_FIELD(subclauseindices);
    WRITE_OID_FIELD(mergejoinoperator);
    WRITE_OID_FIELD(left_sortop);
    WRITE_OID_FIELD(right_sortop);
index b9ccc770a431c923b1fe4e510bb7de9ebc1bc215..c2fe837db65a71df189acb8fbce8050fb65d61a1 100644 (file)
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/optimizer/path/indxpath.c,v 1.150 2003/12/18 00:22:12 tgl Exp $
+ *   $PostgreSQL: pgsql/src/backend/optimizer/path/indxpath.c,v 1.151 2003/12/30 23:53:14 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -64,9 +64,11 @@ static List *group_clauses_by_indexkey_for_join(Query *root,
                                   Relids outer_relids,
                                   JoinType jointype, bool isouterjoin);
 static bool match_clause_to_indexcol(RelOptInfo *rel, IndexOptInfo *index,
-                        int indexcol, Oid opclass, Expr *clause);
+                                    int indexcol, Oid opclass,
+                                    Expr *clause, RestrictInfo *rinfo);
 static bool match_join_clause_to_indexcol(RelOptInfo *rel, IndexOptInfo *index,
-                             int indexcol, Oid opclass, Expr *clause);
+                                         int indexcol, Oid opclass,
+                                         RestrictInfo *rinfo);
 static Oid indexable_operator(Expr *clause, Oid opclass,
                   bool indexkey_on_left);
 static bool pred_test(List *predicate_list, List *restrictinfo_list,
@@ -374,14 +376,14 @@ match_or_subclause_to_indexkey(RelOptInfo *rel,
        foreach(item, ((BoolExpr *) clause)->args)
        {
            if (match_clause_to_indexcol(rel, index, 0, opclass,
-                                        lfirst(item)))
+                                        lfirst(item), NULL))
                return true;
        }
        return false;
    }
    else
        return match_clause_to_indexcol(rel, index, 0, opclass,
-                                       clause);
+                                       clause, NULL);
 }
 
 /*----------
@@ -445,7 +447,7 @@ extract_or_indexqual_conditions(RelOptInfo *rel,
 
                if (match_clause_to_indexcol(rel, index,
                                             indexcol, curClass,
-                                            subsubclause))
+                                            subsubclause, NULL))
                    FastConc(&clausegroup,
                             expand_indexqual_condition(subsubclause,
                                                        curClass));
@@ -453,7 +455,7 @@ extract_or_indexqual_conditions(RelOptInfo *rel,
        }
        else if (match_clause_to_indexcol(rel, index,
                                          indexcol, curClass,
-                                         orsubclause))
+                                         orsubclause, NULL))
            FastConc(&clausegroup,
                     expand_indexqual_condition(orsubclause,
                                                curClass));
@@ -470,7 +472,7 @@ extract_or_indexqual_conditions(RelOptInfo *rel,
 
                if (match_clause_to_indexcol(rel, index,
                                             indexcol, curClass,
-                                            rinfo->clause))
+                                            rinfo->clause, rinfo))
                    FastConc(&clausegroup,
                             expand_indexqual_condition(rinfo->clause,
                                                        curClass));
@@ -550,7 +552,8 @@ group_clauses_by_indexkey(RelOptInfo *rel, IndexOptInfo *index)
                                         index,
                                         indexcol,
                                         curClass,
-                                        rinfo->clause))
+                                        rinfo->clause,
+                                        rinfo))
                FastAppend(&clausegroup, rinfo);
        }
 
@@ -625,7 +628,8 @@ group_clauses_by_indexkey_for_join(Query *root,
                                         index,
                                         indexcol,
                                         curClass,
-                                        rinfo->clause))
+                                        rinfo->clause,
+                                        rinfo))
                FastAppend(&clausegroup, rinfo);
        }
 
@@ -654,7 +658,7 @@ group_clauses_by_indexkey_for_join(Query *root,
                                                  index,
                                                  indexcol,
                                                  curClass,
-                                                 rinfo->clause))
+                                                 rinfo))
                {
                    FastAppend(&clausegroup, rinfo);
                    if (!jfoundhere)
@@ -726,6 +730,7 @@ group_clauses_by_indexkey_for_join(Query *root,
  * 'indexcol' is a column number of 'index' (counting from 0).
  * 'opclass' is the corresponding operator class.
  * 'clause' is the clause to be tested.
+ * 'rinfo' is the clause's RestrictInfo, if available (NULL if not).
  *
  * Returns true if the clause can be used with this index key.
  *
@@ -737,7 +742,8 @@ match_clause_to_indexcol(RelOptInfo *rel,
                         IndexOptInfo *index,
                         int indexcol,
                         Oid opclass,
-                        Expr *clause)
+                        Expr *clause,
+                        RestrictInfo *rinfo)
 {
    Node       *leftop,
               *rightop;
@@ -754,9 +760,13 @@ match_clause_to_indexcol(RelOptInfo *rel,
     * Check for clauses of the form: (indexkey operator constant) or
     * (constant operator indexkey). Anything that is a "pseudo constant"
     * expression will do.
+    *
+    * If we have the RestrictInfo available, we can make a more efficient
+    * test for pseudo-constness.
     */
    if (match_index_to_operand(leftop, indexcol, rel, index) &&
-       is_pseudo_constant_clause(rightop))
+       (rinfo ? is_pseudo_constant_clause_relids(rightop, rinfo->right_relids)
+        : is_pseudo_constant_clause(rightop)))
    {
        if (is_indexable_operator(clause, opclass, true))
            return true;
@@ -771,7 +781,8 @@ match_clause_to_indexcol(RelOptInfo *rel,
    }
 
    if (match_index_to_operand(rightop, indexcol, rel, index) &&
-       is_pseudo_constant_clause(leftop))
+       (rinfo ? is_pseudo_constant_clause_relids(leftop, rinfo->left_relids)
+        : is_pseudo_constant_clause(leftop)))
    {
        if (is_indexable_operator(clause, opclass, false))
            return true;
@@ -813,7 +824,7 @@ match_clause_to_indexcol(RelOptInfo *rel,
  * 'index' is an index on 'rel'.
  * 'indexcol' is a column number of 'index' (counting from 0).
  * 'opclass' is the corresponding operator class.
- * 'clause' is the clause to be tested.
+ * 'rinfo' is the clause to be tested (as a RestrictInfo node).
  *
  * Returns true if the clause can be used with this index key.
  *
@@ -825,8 +836,9 @@ match_join_clause_to_indexcol(RelOptInfo *rel,
                              IndexOptInfo *index,
                              int indexcol,
                              Oid opclass,
-                             Expr *clause)
+                             RestrictInfo *rinfo)
 {
+   Expr       *clause = rinfo->clause;
    Node       *leftop,
               *rightop;
 
@@ -846,27 +858,25 @@ match_join_clause_to_indexcol(RelOptInfo *rel,
     */
    if (match_index_to_operand(leftop, indexcol, rel, index))
    {
-       Relids      othervarnos = pull_varnos(rightop);
+       Relids      othervarnos = rinfo->right_relids;
        bool        isIndexable;
 
        isIndexable =
            !bms_overlap(rel->relids, othervarnos) &&
            !contain_volatile_functions(rightop) &&
            is_indexable_operator(clause, opclass, true);
-       bms_free(othervarnos);
        return isIndexable;
    }
 
    if (match_index_to_operand(rightop, indexcol, rel, index))
    {
-       Relids      othervarnos = pull_varnos(leftop);
+       Relids      othervarnos = rinfo->left_relids;
        bool        isIndexable;
 
        isIndexable =
            !bms_overlap(rel->relids, othervarnos) &&
            !contain_volatile_functions(leftop) &&
            is_indexable_operator(clause, opclass, false);
-       bms_free(othervarnos);
        return isIndexable;
    }
 
@@ -1351,7 +1361,6 @@ indexable_outerrelids(RelOptInfo *rel, IndexOptInfo *index)
        foreach(j, joininfo->jinfo_restrictinfo)
        {
            RestrictInfo *rinfo = (RestrictInfo *) lfirst(j);
-           Expr       *clause = rinfo->clause;
            int         indexcol = 0;
            Oid        *classes = index->classlist;
 
@@ -1363,7 +1372,7 @@ indexable_outerrelids(RelOptInfo *rel, IndexOptInfo *index)
                                                  index,
                                                  indexcol,
                                                  curClass,
-                                                 clause))
+                                                 rinfo))
                {
                    match_found = true;
                    break;
index 5b95ec7c4dd9df39b72d544d771ade6320fdac22..91cd0ab22a5f45dbdabd8025a22ce4459d7004e9 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/optimizer/path/joinpath.c,v 1.83 2003/11/29 19:51:50 pgsql Exp $
+ *   $PostgreSQL: pgsql/src/backend/optimizer/path/joinpath.c,v 1.84 2003/12/30 23:53:14 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -690,7 +690,7 @@ hash_inner_and_outer(Query *root,
    {
        RestrictInfo *restrictinfo = (RestrictInfo *) lfirst(i);
 
-       if (restrictinfo->left_relids == NULL ||
+       if (!restrictinfo->canjoin ||
            restrictinfo->hashjoinoperator == InvalidOid)
            continue;           /* not hashjoinable */
 
@@ -809,12 +809,12 @@ select_mergejoin_clauses(RelOptInfo *joinrel,
            switch (jointype)
            {
                case JOIN_RIGHT:
-                   if (restrictinfo->left_relids == NULL ||
+                   if (!restrictinfo->canjoin ||
                        restrictinfo->mergejoinoperator == InvalidOid)
                        return NIL;     /* not mergejoinable */
                    break;
                case JOIN_FULL:
-                   if (restrictinfo->left_relids == NULL ||
+                   if (!restrictinfo->canjoin ||
                        restrictinfo->mergejoinoperator == InvalidOid)
                        ereport(ERROR,
                                (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
@@ -826,7 +826,7 @@ select_mergejoin_clauses(RelOptInfo *joinrel,
            }
        }
 
-       if (restrictinfo->left_relids == NULL ||
+       if (!restrictinfo->canjoin ||
            restrictinfo->mergejoinoperator == InvalidOid)
            continue;           /* not mergejoinable */
 
index 5612430a390fe6d0b1b79d0d4d9e0a3cae02e5b6..3da001e997a0167eb6a2f873b32d3c9dd11baecc 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/optimizer/plan/initsplan.c,v 1.93 2003/11/29 19:51:50 pgsql Exp $
+ *   $PostgreSQL: pgsql/src/backend/optimizer/plan/initsplan.c,v 1.94 2003/12/30 23:53:14 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -380,12 +380,13 @@ distribute_qual_to_rels(Query *root, Node *clause,
    bool        can_be_equijoin;
 
    restrictinfo->clause = (Expr *) clause;
+   restrictinfo->canjoin = false;      /* set below, if join clause */
+   restrictinfo->left_relids = NULL;
+   restrictinfo->right_relids = NULL;
    restrictinfo->subclauseindices = NIL;
    restrictinfo->eval_cost.startup = -1;       /* not computed until
                                                 * needed */
    restrictinfo->this_selec = -1;      /* not computed until needed */
-   restrictinfo->left_relids = NULL;   /* set below, if join clause */
-   restrictinfo->right_relids = NULL;
    restrictinfo->mergejoinoperator = InvalidOid;
    restrictinfo->left_sortop = InvalidOid;
    restrictinfo->right_sortop = InvalidOid;
@@ -510,6 +511,15 @@ distribute_qual_to_rels(Query *root, Node *clause,
    restrictinfo->ispusheddown = ispusheddown || !bms_equal(relids,
                                                            qualscope);
 
+   /*
+    * 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((Expr *) clause));
+       restrictinfo->right_relids = pull_varnos(get_rightop((Expr *) clause));
+   }
+
    switch (bms_membership(relids))
    {
        case BMS_SINGLETON:
@@ -562,18 +572,11 @@ distribute_qual_to_rels(Query *root, Node *clause,
             */
            if (is_opclause(clause) && length(((OpExpr *) clause)->args) == 2)
            {
-               Relids      left_relids;
-               Relids      right_relids;
-
-               left_relids = pull_varnos(get_leftop((Expr *) clause));
-               right_relids = pull_varnos(get_rightop((Expr *) clause));
-               if (!bms_is_empty(left_relids) &&
-                   !bms_is_empty(right_relids) &&
-                   !bms_overlap(left_relids, right_relids))
-               {
-                   restrictinfo->left_relids = left_relids;
-                   restrictinfo->right_relids = right_relids;
-               }
+               if (!bms_is_empty(restrictinfo->left_relids) &&
+                   !bms_is_empty(restrictinfo->right_relids) &&
+                   !bms_overlap(restrictinfo->left_relids,
+                                restrictinfo->right_relids))
+                   restrictinfo->canjoin = true;
            }
 
            /*
@@ -814,13 +817,14 @@ qual_is_redundant(Query *root,
    List       *equalexprs;
    bool        someadded;
 
-   newleft = get_leftop(restrictinfo->clause);
-   newright = get_rightop(restrictinfo->clause);
-
    /* Never redundant unless vars appear on both sides */
-   if (!contain_var_clause(newleft) || !contain_var_clause(newright))
+   if (bms_is_empty(restrictinfo->left_relids) ||
+       bms_is_empty(restrictinfo->right_relids))
        return false;
 
+   newleft = get_leftop(restrictinfo->clause);
+   newright = get_rightop(restrictinfo->clause);
+
    /*
     * Set cached pathkeys.  NB: it is okay to do this now because this
     * routine is only invoked while we are generating implied equalities.
index d6f0bb3ad2eff317545f20465432b4180a2d8410..35efa6bc63074fa14758c90b2c402cf24d288853 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.157 2003/12/28 21:57:37 tgl Exp $
+ *   $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.158 2003/12/30 23:53:15 tgl Exp $
  *
  * HISTORY
  *   AUTHOR            DATE            MAJOR EVENT
@@ -811,6 +811,20 @@ is_pseudo_constant_clause(Node *clause)
    return false;
 }
 
+/*
+ * 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.
+ */
+bool
+is_pseudo_constant_clause_relids(Node *clause, Relids relids)
+{
+   if (bms_is_empty(relids) &&
+       !contain_volatile_functions(clause))
+       return true;
+   return false;
+}
+
 /*
  * pull_constant_clauses
  *     Scan through a list of qualifications and separate "constant" quals
index 2ae122e92a904e8b0df4669ba2eb0b7aa1566154..f77966a22623d54952064f9dcc6f52b3c4efb7ef 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/optimizer/util/restrictinfo.c,v 1.20 2003/11/29 19:51:51 pgsql Exp $
+ *   $PostgreSQL: pgsql/src/backend/optimizer/util/restrictinfo.c,v 1.21 2003/12/30 23:53:15 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -227,15 +227,9 @@ join_clause_is_redundant(Query *root,
 
        if (redundant)
        {
-           /*
-            * It looks redundant, now check for "var = const" case. If
-            * left_relids/right_relids are set, then there are definitely
-            * vars on both sides; else we must check the hard way.
-            */
-           if (rinfo->left_relids)
-               return true;    /* var = var, so redundant */
-           if (contain_var_clause(get_leftop(rinfo->clause)) &&
-               contain_var_clause(get_rightop(rinfo->clause)))
+           /* It looks redundant, but check for "var = const" case */
+           if (!bms_is_empty(rinfo->left_relids) &&
+               !bms_is_empty(rinfo->right_relids))
                return true;    /* var = var, so redundant */
            /* else var = const, not redundant */
        }
index 6b205b20da5a2de1dcd05701e8a8be1f0a4eda9d..0d129f38ea1375d2793c756f0873a8c0bada3c53 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/nodes/relation.h,v 1.87 2003/12/28 21:57:37 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/nodes/relation.h,v 1.88 2003/12/30 23:53:15 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -596,6 +596,19 @@ typedef struct RestrictInfo
 
    bool        ispusheddown;   /* TRUE if clause was pushed down in level */
 
+   /*
+    * 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
+    * nonoverlapping sets of relids referenced in the left and right sides.
+    * (Whether the operator is actually merge or hash joinable isn't
+    * checked, however.)
+    */
+   bool        canjoin;
+
+   /* These fields are set for any binary opclause: */
+   Relids      left_relids;    /* relids in left side of clause */
+   Relids      right_relids;   /* relids in right side of clause */
+
    /* only used if clause is an OR clause: */
    List       *subclauseindices;       /* indexes matching subclauses */
    /* subclauseindices is a List of Lists of IndexOptInfos */
@@ -604,15 +617,6 @@ typedef struct RestrictInfo
    QualCost    eval_cost;      /* eval cost of clause; -1 if not yet set */
    Selectivity this_selec;     /* selectivity; -1 if not yet set */
 
-   /*
-    * If the clause looks useful for joining --- that is, it is a binary
-    * opclause with nonoverlapping sets of relids referenced in the left
-    * and right sides --- then these two fields are set to sets of the
-    * referenced relids.  Otherwise they are both NULL.
-    */
-   Relids      left_relids;    /* relids in left side of join clause */
-   Relids      right_relids;   /* relids in right side of join clause */
-
    /* valid if clause is mergejoinable, else InvalidOid: */
    Oid         mergejoinoperator;      /* copy of clause operator */
    Oid         left_sortop;    /* leftside sortop needed for mergejoin */
index 7fb60b548e48af3a25e946c1c86381e78dad14c8..3e089256a51fb5d2c910b7c1c3e63e937b53514a 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/optimizer/clauses.h,v 1.69 2003/11/29 22:41:07 pgsql Exp $
+ * $PostgreSQL: pgsql/src/include/optimizer/clauses.h,v 1.70 2003/12/30 23:53:15 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -54,6 +54,7 @@ extern bool contain_volatile_functions(Node *clause);
 extern bool contain_nonstrict_functions(Node *clause);
 
 extern bool is_pseudo_constant_clause(Node *clause);
+extern bool is_pseudo_constant_clause_relids(Node *clause, Relids relids);
 extern List *pull_constant_clauses(List *quals, List **constantQual);
 
 extern bool has_distinct_on_clause(Query *query);