OSDN Git Service

Make subqueries rewrite properly.
authorBruce Momjian <bruce@momjian.us>
Wed, 21 Jan 1998 04:24:46 +0000 (04:24 +0000)
committerBruce Momjian <bruce@momjian.us>
Wed, 21 Jan 1998 04:24:46 +0000 (04:24 +0000)
src/backend/rewrite/locks.c
src/backend/rewrite/rewriteHandler.c
src/backend/rewrite/rewriteManip.c
src/include/rewrite/rewriteManip.h

index b0557b0..56bd8e0 100644 (file)
@@ -6,7 +6,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/rewrite/Attic/locks.c,v 1.7 1998/01/15 19:00:06 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/rewrite/Attic/locks.c,v 1.8 1998/01/21 04:24:34 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -27,7 +27,8 @@
  * otherwise, we return false
  */
 static bool
-nodeThisLockWasTriggered(Node *node, int varno, AttrNumber attnum)
+nodeThisLockWasTriggered(Node *node, int varno, AttrNumber attnum,
+                       int sublevels_up)
 {
        if (node == NULL)
                return FALSE;
@@ -46,24 +47,24 @@ nodeThisLockWasTriggered(Node *node, int varno, AttrNumber attnum)
                        {
                                Expr       *expr = (Expr *) node;
 
-                               return
-                                       nodeThisLockWasTriggered((Node *) expr->args, varno, attnum);
+                               return nodeThisLockWasTriggered((Node *) expr->args, varno,
+                                               attnum, sublevels_up);
                        }
                        break;
                case T_TargetEntry:
                        {
                                TargetEntry *tle = (TargetEntry *) node;
 
-                               return
-                                       nodeThisLockWasTriggered(tle->expr, varno, attnum);
+                               return nodeThisLockWasTriggered(tle->expr, varno, attnum,
+                                                                       sublevels_up);
                        }
                        break;
                case T_Aggreg:
                        {
                                Aggreg *agg = (Aggreg *) node;
 
-                               return
-                                       nodeThisLockWasTriggered(agg->target, varno, attnum);
+                               return nodeThisLockWasTriggered(agg->target, varno, attnum,
+                                                               sublevels_up);
                        }
                        break;
                case T_List:
@@ -72,12 +73,22 @@ nodeThisLockWasTriggered(Node *node, int varno, AttrNumber attnum)
 
                                foreach(l, (List *) node)
                                {
-                                       if (nodeThisLockWasTriggered(lfirst(l), varno, attnum))
+                                       if (nodeThisLockWasTriggered(lfirst(l), varno, attnum,
+                                                               sublevels_up))
                                                return TRUE;
                                }
                                return FALSE;
                        }
                        break;
+               case T_SubLink:
+                       {
+                               SubLink            *sublink = (SubLink *) node;
+                               Query              *query = (Query *)sublink->subselect;
+
+                               return nodeThisLockWasTriggered(query->qual, varno, attnum,
+                                                                       sublevels_up + 1);
+                       }
+                       break;
                default:
                        break;
        }
@@ -96,10 +107,10 @@ thisLockWasTriggered(int varno,
                                         Query *parsetree)
 {
        
-       if (nodeThisLockWasTriggered(parsetree->qual, varno, attnum))
+       if (nodeThisLockWasTriggered(parsetree->qual, varno, attnum, 0))
                return true;
 
-       if (nodeThisLockWasTriggered((Node *) parsetree->targetList, varno, attnum))
+       if (nodeThisLockWasTriggered((Node *) parsetree->targetList, varno, attnum, 0))
                return true;
 
        return false;
index 68f34e6..415ce6e 100644 (file)
@@ -6,7 +6,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.10 1998/01/09 05:48:17 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.11 1998/01/21 04:24:36 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
 #include "commands/creatinh.h"
 #include "access/heapam.h"
 
-static void
-ApplyRetrieveRule(Query *parsetree, RewriteRule *rule,
+static void ApplyRetrieveRule(Query *parsetree, RewriteRule *rule,
                                  int rt_index, int relation_level, int *modified);
-static List *
-fireRules(Query *parsetree, int rt_index, CmdType event,
+static List *fireRules(Query *parsetree, int rt_index, CmdType event,
                  bool *instead_flag, List *locks, List **qual_products);
+static void QueryRewriteSubLink(Node *node);
+static List       *QueryRewriteOne(Query *parsetree);
 static List *deepRewriteQuery(Query *parsetree);
 
 /*
@@ -77,11 +77,11 @@ gatherRewriteMeta(Query *parsetree,
                OffsetVarNodes((Node *) info->rule_action->targetList, rt_length);
                OffsetVarNodes(info->rule_qual, rt_length);
                ChangeVarNodes((Node *) info->rule_action->qual,
-                                          PRS2_CURRENT_VARNO + rt_length, rt_index);
+                                          PRS2_CURRENT_VARNO + rt_length, rt_index, 0);
                ChangeVarNodes((Node *) info->rule_action->targetList,
-                                          PRS2_CURRENT_VARNO + rt_length, rt_index);
+                                          PRS2_CURRENT_VARNO + rt_length, rt_index, 0);
                ChangeVarNodes(info->rule_qual,
-                                          PRS2_CURRENT_VARNO + rt_length, rt_index);
+                                          PRS2_CURRENT_VARNO + rt_length, rt_index, 0);
 
                /*
                 * bug here about replace CURRENT  -- sort of replace current is
@@ -292,10 +292,10 @@ ApplyRetrieveRule(Query *parsetree,
        OffsetVarNodes((Node *) rule_action->targetList, rt_length);
        OffsetVarNodes(rule_qual, rt_length);
        ChangeVarNodes(rule_action->qual,
-                                  PRS2_CURRENT_VARNO + rt_length, rt_index);
+                                  PRS2_CURRENT_VARNO + rt_length, rt_index, 0);
        ChangeVarNodes((Node *) rule_action->targetList,
-                                  PRS2_CURRENT_VARNO + rt_length, rt_index);
-       ChangeVarNodes(rule_qual, PRS2_CURRENT_VARNO + rt_length, rt_index);
+                                  PRS2_CURRENT_VARNO + rt_length, rt_index, 0);
+       ChangeVarNodes(rule_qual, PRS2_CURRENT_VARNO + rt_length, rt_index, 0);
        if (relation_level)
        {
                HandleViewRule(parsetree, rtable, rule_action->targetList, rt_index,
@@ -402,7 +402,7 @@ CopyAndAddQual(Query *parsetree,
                rtable = append(rtable, listCopy(rule_action->rtable));
                new_tree->rtable = rtable;
                OffsetVarNodes(new_qual, rt_length);
-               ChangeVarNodes(new_qual, PRS2_CURRENT_VARNO + rt_length, rt_index);
+               ChangeVarNodes(new_qual, PRS2_CURRENT_VARNO + rt_length, rt_index, 0);
        }
        /* XXX -- where current doesn't work for instead nothing.... yet */
        AddNotQual(new_tree, new_qual);
@@ -628,6 +628,82 @@ static int numQueryRewriteInvoked = 0;
 List      *
 QueryRewrite(Query *parsetree)
 {
+
+       QueryRewriteSubLink(parsetree->qual);
+       return QueryRewriteOne(parsetree);
+}
+
+/*
+ *     QueryRewriteSubLink
+ *
+ *     This rewrites the SubLink subqueries first, doing the lowest ones first.
+ *     We already have code in the main rewrite loops to process correlated
+ *     variables from upper queries that exist in subqueries.
+ */
+static void
+QueryRewriteSubLink(Node *node)
+{
+       if (node == NULL)
+               return;
+
+       switch (nodeTag(node))
+       {
+               case T_TargetEntry:
+                       break;
+               case T_Aggreg:
+                       break;
+               case T_Expr:
+                       {
+                               Expr       *expr = (Expr *) node;
+
+                               QueryRewriteSubLink((Node *)expr->args);
+                       }
+                       break;
+               case T_Var:
+                       break;
+               case T_List:
+                       {
+                               List       *l;
+
+                               foreach(l, (List *) node)
+                                       QueryRewriteSubLink(lfirst(l));
+                       }
+                       break;
+               case T_SubLink:
+                       {
+                               SubLink            *sublink = (SubLink *) node;
+                               Query              *query = (Query *)sublink->subselect;
+                               List               *ret;
+
+                               /*
+                                *      Nest down first.  We do this so if a rewrite adds a
+                                *      SubLink we don't process it as part of this loop.
+                                */
+                               QueryRewriteSubLink((Node *)query->qual);
+
+                               ret = QueryRewriteOne(query);
+                               if (!ret)
+                                       sublink->subselect = NULL;
+                               else if (lnext(ret) == NIL)
+                                       sublink->subselect = lfirst(ret);
+                               else
+                                       elog(ERROR,"Don't know how to process subquery that rewrites to multiple queries.");
+                       }
+                       break;
+               default:
+                       /* ignore the others */
+                       break;
+       }
+       return;
+}
+
+/*
+ * QueryOneRewrite -
+ *       rewrite one query
+ */
+static List       *
+QueryRewriteOne(Query *parsetree)
+{
        numQueryRewriteInvoked = 0;
 
        /*
index cd5f5e1..493e0c4 100644 (file)
@@ -6,7 +6,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteManip.c,v 1.10 1998/01/15 19:00:07 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteManip.c,v 1.11 1998/01/21 04:24:39 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -28,7 +28,8 @@
 #include "nodes/plannodes.h"
 #include "optimizer/clauses.h"
 
-static void ResolveNew(RewriteInfo *info, List *targetlist, Node **node);
+static void ResolveNew(RewriteInfo *info, List *targetlist,
+                                       Node **node, int sublevels_up);
 
 
 
@@ -85,7 +86,7 @@ OffsetVarNodes(Node *node, int offset)
 }
 
 void
-ChangeVarNodes(Node *node, int old_varno, int new_varno)
+ChangeVarNodes(Node *node, int old_varno, int new_varno, int sublevels_up)
 {
        if (node == NULL)
                return;
@@ -95,28 +96,29 @@ ChangeVarNodes(Node *node, int old_varno, int new_varno)
                        {
                                TargetEntry *tle = (TargetEntry *) node;
 
-                               ChangeVarNodes(tle->expr, old_varno, new_varno);
+                               ChangeVarNodes(tle->expr, old_varno, new_varno, sublevels_up);
                        }
                        break;
                case T_Aggreg:
                        {
                                Aggreg *agg = (Aggreg *) node;
 
-                               ChangeVarNodes(agg->target, old_varno, new_varno);
+                               ChangeVarNodes(agg->target, old_varno, new_varno, sublevels_up);
                        }
                        break;
                case T_Expr:
                        {
                                Expr       *expr = (Expr *) node;
 
-                               ChangeVarNodes((Node *) expr->args, old_varno, new_varno);
+                               ChangeVarNodes((Node *) expr->args, old_varno, new_varno, sublevels_up);
                        }
                        break;
                case T_Var:
                        {
                                Var                *var = (Var *) node;
 
-                               if (var->varno == old_varno)
+                               if (var->varno == old_varno &&
+                                       var->varlevelsup == sublevels_up)
                                {
                                        var->varno = new_varno;
                                        var->varnoold = new_varno;
@@ -128,9 +130,16 @@ ChangeVarNodes(Node *node, int old_varno, int new_varno)
                                List       *l;
 
                                foreach(l, (List *) node)
-                               {
-                                       ChangeVarNodes(lfirst(l), old_varno, new_varno);
-                               }
+                                       ChangeVarNodes(lfirst(l), old_varno, new_varno, sublevels_up);
+                       }
+                       break;
+               case T_SubLink:
+                       {
+                               SubLink            *sublink = (SubLink *) node;
+                               Query              *query = (Query *)sublink->subselect;
+
+                               ChangeVarNodes((Node *)query->qual, old_varno, new_varno,
+                                                                               sublevels_up + 1);
                        }
                        break;
                default:
@@ -237,7 +246,8 @@ FindMatchingTLEntry(List *tlist, char *e_attname)
 }
 
 static void
-ResolveNew(RewriteInfo *info, List *targetlist, Node **nodePtr)
+ResolveNew(RewriteInfo *info, List *targetlist, Node **nodePtr,
+                                                                       int sublevels_up)
 {
        Node       *node = *nodePtr;
 
@@ -247,20 +257,25 @@ ResolveNew(RewriteInfo *info, List *targetlist, Node **nodePtr)
        switch (nodeTag(node))
        {
                case T_TargetEntry:
-                       ResolveNew(info, targetlist, &((TargetEntry *) node)->expr);
+                       ResolveNew(info, targetlist, &((TargetEntry *) node)->expr,
+                                                                                                       sublevels_up);
                        break;
                case T_Aggreg:
-                       ResolveNew(info, targetlist, &((Aggreg *) node)->target);
+                       ResolveNew(info, targetlist, &((Aggreg *) node)->target,
+                                                                                                       sublevels_up);
                        break;
                case T_Expr:
-                       ResolveNew(info, targetlist, (Node **) (&(((Expr *) node)->args)));
+                       ResolveNew(info, targetlist, (Node **) (&(((Expr *) node)->args)),
+                                                                                                       sublevels_up);
                        break;
                case T_Var:
                        {
-                               int                     this_varno = (int) ((Var *) node)->varno;
-                               Node       *n;
+                               int             this_varno = (int) ((Var *) node)->varno;
+                               int             this_varlevelsup = (int) ((Var *) node)->varlevelsup;
+                               Node   *n;
 
-                               if (this_varno == info->new_varno)
+                               if (this_varno == info->new_varno &&
+                                       this_varlevelsup == sublevels_up)
                                {
                                        n = FindMatchingNew(targetlist,
                                                                                ((Var *) node)->varattno);
@@ -288,11 +303,18 @@ ResolveNew(RewriteInfo *info, List *targetlist, Node **nodePtr)
                                List       *l;
 
                                foreach(l, (List *) node)
-                               {
-                                       ResolveNew(info, targetlist, (Node **) &(lfirst(l)));
-                               }
+                                       ResolveNew(info, targetlist, (Node **) &(lfirst(l)),
+                                                                                                       sublevels_up);
                                break;
                        }
+               case T_SubLink:
+                       {
+                               SubLink            *sublink = (SubLink *) node;
+                               Query              *query = (Query *)sublink->subselect;
+
+                               ResolveNew(info, targetlist, (Node **)&(query->qual), sublevels_up + 1);
+                       }
+                       break;
                default:
                        /* ignore the others */
                        break;
@@ -303,8 +325,8 @@ void
 FixNew(RewriteInfo *info, Query *parsetree)
 {
        ResolveNew(info, parsetree->targetList,
-                          (Node **) &(info->rule_action->targetList));
-       ResolveNew(info, parsetree->targetList, &info->rule_action->qual);
+                          (Node **) &(info->rule_action->targetList), 0);
+       ResolveNew(info, parsetree->targetList, &info->rule_action->qual, 0);
 }
 
 static void
@@ -314,7 +336,8 @@ nodeHandleRIRAttributeRule(Node **nodePtr,
                                                   int rt_index,
                                                   int attr_num,
                                                   int *modified,
-                                                  int *badsql)
+                                                  int *badsql,
+                                                  int sublevels_up)
 {
        Node       *node = *nodePtr;
 
@@ -322,24 +345,13 @@ nodeHandleRIRAttributeRule(Node **nodePtr,
                return;
        switch (nodeTag(node))
        {
-               case T_List:
-                       {
-                               List       *i;
-
-                               foreach(i, (List *) node)
-                               {
-                                       nodeHandleRIRAttributeRule((Node **) (&(lfirst(i))), rtable,
-                                                                                 targetlist, rt_index, attr_num,
-                                                                                          modified, badsql);
-                               }
-                       }
-                       break;
                case T_TargetEntry:
                        {
                                TargetEntry *tle = (TargetEntry *) node;
 
                                nodeHandleRIRAttributeRule(&tle->expr, rtable, targetlist,
-                                                                  rt_index, attr_num, modified, badsql);
+                                                                  rt_index, attr_num, modified, badsql,
+                                                                  sublevels_up);
                        }
                        break;
                case T_Aggreg:
@@ -347,7 +359,8 @@ nodeHandleRIRAttributeRule(Node **nodePtr,
                                Aggreg *agg = (Aggreg *) node;
 
                                nodeHandleRIRAttributeRule(&agg->target, rtable, targetlist,
-                                                                  rt_index, attr_num, modified, badsql);
+                                                                  rt_index, attr_num, modified, badsql,
+                                                                  sublevels_up);
                        }
                        break;
                case T_Expr:
@@ -356,18 +369,19 @@ nodeHandleRIRAttributeRule(Node **nodePtr,
 
                                nodeHandleRIRAttributeRule((Node **) (&(expr->args)), rtable,
                                                                                   targetlist, rt_index, attr_num,
-                                                                                  modified, badsql);
+                                                                                  modified, badsql,
+                                                                                  sublevels_up);
                        }
                        break;
                case T_Var:
                        {
-                               int                     this_varno = (int) ((Var *) node)->varno;
-                               NameData        name_to_look_for;
-
-                               MemSet(name_to_look_for.data, 0, NAMEDATALEN);
+                               int                     this_varno = ((Var *) node)->varno;
+                               int                     this_varattno = ((Var *) node)->varattno;
+                               int                     this_varlevelsup = ((Var *) node)->varlevelsup;
 
                                if (this_varno == rt_index &&
-                                       ((Var *) node)->varattno == attr_num)
+                                       this_varattno == attr_num &&
+                                       this_varlevelsup == sublevels_up)
                                {
                                        if (((Var *) node)->vartype == 32)
                                        {                       /* HACK */
@@ -378,29 +392,50 @@ nodeHandleRIRAttributeRule(Node **nodePtr,
                                        }
                                        else
                                        {
+                                               NameData        name_to_look_for;
+
+                                               name_to_look_for.data[0] = '\0';
                                                namestrcpy(&name_to_look_for,
                                                                (char *) get_attname(getrelid(this_varno,
                                                                                                                          rtable),
                                                                                                         attr_num));
+                                               if (name_to_look_for.data[0])
+                                               {
+                                                       Node       *n;
+               
+                                                       n = FindMatchingTLEntry(targetlist, (char *) &name_to_look_for);
+                                                       if (n == NULL)
+                                                               *nodePtr = make_null(((Var *) node)->vartype);
+                                                       else
+                                                               *nodePtr = n;
+                                                       *modified = TRUE;
+                                               }
                                        }
                                }
-                               if (name_to_look_for.data[0])
-                               {
-                                       Node       *n;
+                       }
+                       break;
+               case T_List:
+                       {
+                               List       *i;
 
-                                       n = FindMatchingTLEntry(targetlist, (char *) &name_to_look_for);
-                                       if (n == NULL)
-                                       {
-                                               *nodePtr = make_null(((Var *) node)->vartype);
-                                       }
-                                       else
-                                       {
-                                               *nodePtr = n;
-                                       }
-                                       *modified = TRUE;
+                               foreach(i, (List *) node)
+                               {
+                                       nodeHandleRIRAttributeRule((Node **) (&(lfirst(i))), rtable,
+                                                                                 targetlist, rt_index, attr_num,
+                                                                                          modified, badsql, sublevels_up);
                                }
                        }
                        break;
+               case T_SubLink:
+                       {
+                               SubLink            *sublink = (SubLink *) node;
+                               Query              *query = (Query *)sublink->subselect;
+
+                               nodeHandleRIRAttributeRule((Node **)&(query->qual), rtable, targetlist,
+                                                                  rt_index, attr_num, modified, badsql,
+                                                                  sublevels_up + 1);
+                       }
+                       break;
                default:
                        /* ignore the others */
                        break;
@@ -423,9 +458,9 @@ HandleRIRAttributeRule(Query *parsetree,
        
        nodeHandleRIRAttributeRule((Node **) (&(parsetree->targetList)), rtable,
                                                           targetlist, rt_index, attr_num,
-                                                          modified, badsql);
+                                                          modified, badsql, 0);
        nodeHandleRIRAttributeRule(&parsetree->qual, rtable, targetlist,
-                                                          rt_index, attr_num, modified, badsql);
+                                                          rt_index, attr_num, modified, badsql, 0);
 }
 
 
@@ -434,7 +469,8 @@ nodeHandleViewRule(Node **nodePtr,
                                   List *rtable,
                                   List *targetlist,
                                   int rt_index,
-                                  int *modified)
+                                  int *modified,
+                                       int sublevels_up)
 {
        Node       *node = *nodePtr;
 
@@ -443,24 +479,12 @@ nodeHandleViewRule(Node **nodePtr,
 
        switch (nodeTag(node))
        {
-               case T_List:
-                       {
-                               List       *l;
-
-                               foreach(l, (List *) node)
-                               {
-                                       nodeHandleViewRule((Node **) (&(lfirst(l))),
-                                                                          rtable, targetlist,
-                                                                          rt_index, modified);
-                               }
-                       }
-                       break;
                case T_TargetEntry:
                        {
                                TargetEntry *tle = (TargetEntry *) node;
 
                                nodeHandleViewRule(&(tle->expr), rtable, targetlist,
-                                                                  rt_index, modified);
+                                                                  rt_index, modified, sublevels_up);
                        }
                        break;
                case T_Aggreg:
@@ -468,7 +492,7 @@ nodeHandleViewRule(Node **nodePtr,
                                Aggreg *agg = (Aggreg *) node;
 
                                nodeHandleViewRule(&(agg->target), rtable, targetlist,
-                                                                  rt_index, modified);
+                                                                  rt_index, modified, sublevels_up);
                        }
                        break;
                case T_Expr:
@@ -477,33 +501,52 @@ nodeHandleViewRule(Node **nodePtr,
 
                                nodeHandleViewRule((Node **) (&(expr->args)),
                                                                   rtable, targetlist,
-                                                                  rt_index, modified);
+                                                                  rt_index, modified, sublevels_up);
                        }
                        break;
                case T_Var:
                        {
                                Var                *var = (Var *) node;
                                int                     this_varno = var->varno;
+                               int                     this_varlevelsup = var->varlevelsup;
                                Node       *n;
 
-                               if (this_varno == rt_index)
+                               if (this_varno == rt_index &&
+                                   this_varlevelsup == sublevels_up)
                                {
                                        n = FindMatchingTLEntry(targetlist,
                                                                                 get_attname(getrelid(this_varno,
                                                                                                                          rtable),
                                                                                                         var->varattno));
                                        if (n == NULL)
-                                       {
                                                *nodePtr = make_null(((Var *) node)->vartype);
-                                       }
                                        else
-                                       {
                                                *nodePtr = n;
-                                       }
                                        *modified = TRUE;
                                }
                                break;
                        }
+               case T_List:
+                       {
+                               List       *l;
+
+                               foreach(l, (List *) node)
+                               {
+                                       nodeHandleViewRule((Node **) (&(lfirst(l))),
+                                                                          rtable, targetlist,
+                                                                          rt_index, modified, sublevels_up);
+                               }
+                       }
+                       break;
+               case T_SubLink:
+                       {
+                               SubLink            *sublink = (SubLink *) node;
+                               Query              *query = (Query *)sublink->subselect;
+
+                               nodeHandleViewRule((Node **)&(query->qual), rtable, targetlist,
+                                                                  rt_index, modified, sublevels_up + 1);
+                       }
+                       break;
                default:
                        /* ignore the others */
                        break;
@@ -519,7 +562,7 @@ HandleViewRule(Query *parsetree,
 {
 
        nodeHandleViewRule(&parsetree->qual, rtable, targetlist, rt_index,
-                                          modified);
+                                          modified, 0);
        nodeHandleViewRule((Node **) (&(parsetree->targetList)), rtable, targetlist,
-                                          rt_index, modified);
+                                          rt_index, modified, 0);
 }
index 175cdd6..c564dbf 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: rewriteManip.h,v 1.5 1997/11/26 01:14:25 momjian Exp $
+ * $Id: rewriteManip.h,v 1.6 1998/01/21 04:24:46 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -19,7 +19,8 @@
 
 /* RewriteManip.c */
 void           OffsetVarNodes(Node *node, int offset);
-void           ChangeVarNodes(Node *node, int old_varno, int new_varno);
+void           ChangeVarNodes(Node *node, int old_varno, int new_varno,
+                                                       int sublevels_up);
 void           AddQual(Query *parsetree, Node *qual);
 void           AddNotQual(Query *parsetree, Node *qual);
 void           FixResdomTypes(List *user_tlist);