From 0f413d2dc20111d7d539e2c3eee8ce0ef441ca36 Mon Sep 17 00:00:00 2001
From: Bruce Momjian <bruce@momjian.us>
Date: Wed, 21 Jan 1998 04:24:46 +0000
Subject: [PATCH] Make subqueries rewrite properly.

---
 src/backend/rewrite/locks.c          |  33 +++--
 src/backend/rewrite/rewriteHandler.c | 100 +++++++++++--
 src/backend/rewrite/rewriteManip.c   | 205 ++++++++++++++++-----------
 src/include/rewrite/rewriteManip.h   |   5 +-
 4 files changed, 237 insertions(+), 106 deletions(-)

diff --git a/src/backend/rewrite/locks.c b/src/backend/rewrite/locks.c
index b0557b042e1..56bd8e053b7 100644
--- a/src/backend/rewrite/locks.c
+++ b/src/backend/rewrite/locks.c
@@ -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;
diff --git a/src/backend/rewrite/rewriteHandler.c b/src/backend/rewrite/rewriteHandler.c
index 68f34e6cd5d..415ce6e80f8 100644
--- a/src/backend/rewrite/rewriteHandler.c
+++ b/src/backend/rewrite/rewriteHandler.c
@@ -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 $
  *
  *-------------------------------------------------------------------------
  */
@@ -29,12 +29,12 @@
 #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);
@@ -627,6 +627,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;
 
diff --git a/src/backend/rewrite/rewriteManip.c b/src/backend/rewrite/rewriteManip.c
index cd5f5e16a4d..493e0c4c4ae 100644
--- a/src/backend/rewrite/rewriteManip.c
+++ b/src/backend/rewrite/rewriteManip.c
@@ -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);
 }
diff --git a/src/include/rewrite/rewriteManip.h b/src/include/rewrite/rewriteManip.h
index 175cdd6ca88..c564dbf1d31 100644
--- a/src/include/rewrite/rewriteManip.h
+++ b/src/include/rewrite/rewriteManip.h
@@ -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);
-- 
GitLab