diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c
index 63534050f1c081aaa871046bc77dfe5f619b089b..1b861c96204944ccb93fc8cbb986c2fffff8d21e 100644
--- a/src/backend/commands/explain.c
+++ b/src/backend/commands/explain.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/commands/explain.c,v 1.24 1998/09/01 04:27:53 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/explain.c,v 1.25 1998/10/21 16:21:20 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -26,6 +26,7 @@
 #include <optimizer/planner.h>
 #include <access/xact.h>
 #include <utils/relcache.h>
+#include <rewrite/rewriteHandler.h>
 
 typedef struct ExplainState
 {
@@ -37,6 +38,8 @@ typedef struct ExplainState
 } ExplainState;
 
 static char *Explain_PlanToString(Plan *plan, ExplainState *es);
+static void ExplainOneQuery(Query *query, bool verbose, CommandDest dest);
+
 
 /*
  * ExplainQuery -
@@ -46,11 +49,8 @@ static char *Explain_PlanToString(Plan *plan, ExplainState *es);
 void
 ExplainQuery(Query *query, bool verbose, CommandDest dest)
 {
-	char	   *s = NULL,
-			   *s2;
-	Plan	   *plan;
-	ExplainState *es;
-	int			len;
+	List	*rewritten;
+	List	*l;
 
 	if (IsAbortedTransactionBlockState())
 	{
@@ -64,6 +64,35 @@ ExplainQuery(Query *query, bool verbose, CommandDest dest)
 		return;
 	}
 
+	/* Rewrite through rule system */
+	rewritten = QueryRewrite(query);
+
+	/* In the case of an INSTEAD NOTHING, tell at least that */
+	if (rewritten == NIL)
+	{
+		elog(NOTICE, "query rewrites to nothing");
+		return;
+	}
+
+	/* Explain every plan */
+	foreach(l, rewritten)
+		ExplainOneQuery(lfirst(l), verbose, dest);
+}
+
+/*
+ * ExplainOneQuery -
+ *	  print out the execution plan for one query
+ *
+ */
+static void
+ExplainOneQuery(Query *query, bool verbose, CommandDest dest)
+{
+	char	   *s = NULL,
+			   *s2;
+	Plan	   *plan;
+	ExplainState *es;
+	int			len;
+
 	/* plan the queries (XXX we've ignored rewrite!!) */
 	plan = planner(query);
 
@@ -202,8 +231,13 @@ explain_outNode(StringInfo str, Plan *plan, int indent, ExplainState *es)
 			{
 				RangeTblEntry *rte = nth(((Scan *) plan)->scanrelid - 1, es->rtable);
 
-				sprintf(buf, " on %s", rte->refname);
-				appendStringInfo(str, buf);
+				appendStringInfo(str, " on ");
+				if (strcmp(rte->refname, rte->relname) != 0)
+				{
+					sprintf(buf, "%s ", rte->relname);
+					appendStringInfo(str, buf);
+				}
+				appendStringInfo(str, rte->refname);
 			}
 			break;
 		default:
@@ -232,7 +266,7 @@ explain_outNode(StringInfo str, Plan *plan, int indent, ExplainState *es)
 			for (i = 0; i < indent; i++)
 				appendStringInfo(str, "  ");
 			appendStringInfo(str, "    ->  ");
-			explain_outNode(str, ((SubPlan *) lfirst(lst))->plan, indent + 4, es);
+			explain_outNode(str, ((SubPlan *) lfirst(lst))->plan, indent + 2, es);
 		}
 		es->rtable = saved_rtable;
 	}
diff --git a/src/backend/commands/recipe.c b/src/backend/commands/recipe.c
index f8b7ce15dfc034ee8ea905f7526d9ab6ac9151a3..2d5662aa2604d8813032af3822d33d0fd237766b 100644
--- a/src/backend/commands/recipe.c
+++ b/src/backend/commands/recipe.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/commands/Attic/recipe.c,v 1.24 1998/09/01 04:27:56 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/Attic/recipe.c,v 1.25 1998/10/21 16:21:21 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -350,8 +350,8 @@ tg_rewriteQuery(TgRecipe * r,
 			 * need to offset the var nodes in the qual and targetlist
 			 * because they are indexed off the original rtable
 			 */
-			OffsetVarNodes((Node *) inputQ->qual, rt_length);
-			OffsetVarNodes((Node *) inputQ->targetList, rt_length);
+			OffsetVarNodes((Node *) inputQ->qual, rt_length, 0);
+			OffsetVarNodes((Node *) inputQ->targetList, rt_length, 0);
 
 			/* append the range tables from the children nodes	*/
 			rtable = nconc(rtable, input_rtable);
diff --git a/src/backend/commands/view.c b/src/backend/commands/view.c
index cf81e8be66f4eb2b9ba31701514669d725c4d2a1..fc5755edd7cd5d6ead5ab6c252fcc66b07eac4ee 100644
--- a/src/backend/commands/view.c
+++ b/src/backend/commands/view.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/commands/view.c,v 1.25 1998/09/01 04:28:10 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/view.c,v 1.26 1998/10/21 16:21:22 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -219,10 +219,10 @@ UpdateRangeTableOfViewParse(char *viewName, Query *viewParse)
 	/*
 	 * first offset all var nodes by 2
 	 */
-	OffsetVarNodes((Node *) viewParse->targetList, 2);
-	OffsetVarNodes(viewParse->qual, 2);
+	OffsetVarNodes((Node *) viewParse->targetList, 2, 0);
+	OffsetVarNodes(viewParse->qual, 2, 0);
 
-	OffsetVarNodes(viewParse->havingQual, 2);
+	OffsetVarNodes(viewParse->havingQual, 2, 0);
 
 
 	/*
diff --git a/src/backend/rewrite/rewriteHandler.c b/src/backend/rewrite/rewriteHandler.c
index a0f30698abc6e42b398be087a4f2a585c0e25bf8..8eaa8dbb9417324372db1e822424a9f20fec2920 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.24 1998/10/20 17:21:43 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.25 1998/10/21 16:21:24 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -48,8 +48,6 @@ static RewriteInfo *gatherRewriteMeta(Query *parsetree,
 				  bool *instead_flag);
 static bool rangeTableEntry_used(Node *node, int rt_index, int sublevels_up);
 static bool attribute_used(Node *node, int rt_index, int attno, int sublevels_up);
-static void offset_varnodes(Node *node, int offset, int sublevels_up);
-static void change_varnodes(Node *node, int rt_index, int new_index, int sublevels_up);
 static void modifyAggregUplevel(Node *node);
 static void modifyAggregChangeVarnodes(Node **nodePtr, int rt_index, int new_index, int sublevels_up);
 static void modifyAggregDropQual(Node **nodePtr, Node *orignode, Expr *expr);
@@ -107,9 +105,9 @@ gatherRewriteMeta(Query *parsetree,
 		info->rt = append(info->rt, info->rule_action->rtable);
 
 		info->new_varno = PRS2_NEW_VARNO + rt_length;
-		OffsetVarNodes(info->rule_action->qual, rt_length);
-		OffsetVarNodes((Node *) info->rule_action->targetList, rt_length);
-		OffsetVarNodes(info->rule_qual, rt_length);
+		OffsetVarNodes(info->rule_action->qual, rt_length, 0);
+		OffsetVarNodes((Node *) info->rule_action->targetList, rt_length, 0);
+		OffsetVarNodes(info->rule_qual, rt_length, 0);
 		ChangeVarNodes((Node *) info->rule_action->qual,
 					   PRS2_CURRENT_VARNO + rt_length, rt_index, 0);
 		ChangeVarNodes((Node *) info->rule_action->targetList,
@@ -550,364 +548,6 @@ attribute_used(Node *node, int rt_index, int attno, int sublevels_up)
 }
 
 
-/*
- * offset_varnodes -
- *	We need another version of OffsetVarNodes() when processing
- *	RIR rules
- */
-static void
-offset_varnodes(Node *node, int offset, int sublevels_up)
-{
-	if (node == NULL)
-		return;
-
-	switch(nodeTag(node)) {
-		case T_TargetEntry:
-			{
-				TargetEntry	*tle = (TargetEntry *)node;
-
-				offset_varnodes(
-						(Node *)(tle->expr),
-						offset,
-						sublevels_up);
-			}
-			break;
-
-		case T_Aggreg:
-			{
-				Aggreg	*agg = (Aggreg *)node;
-
-				offset_varnodes(
-						(Node *)(agg->target),
-						offset,
-						sublevels_up);
-			}
-			break;
-
-		case T_GroupClause:
-			{
-				GroupClause	*grp = (GroupClause *)node;
-
-				offset_varnodes(
-						(Node *)(grp->entry),
-						offset,
-						sublevels_up);
-			}
-			break;
-
-		case T_Expr:
-			{
-				Expr	*exp = (Expr *)node;
-
-				offset_varnodes(
-						(Node *)(exp->args),
-						offset,
-						sublevels_up);
-			}
-			break;
-
-		case T_Iter:
-			{
-				Iter	*iter = (Iter *)node;
-
-				offset_varnodes(
-						(Node *)(iter->iterexpr),
-						offset,
-						sublevels_up);
-			}
-			break;
-
-		case T_ArrayRef:
-			{
-				ArrayRef	*ref = (ArrayRef *)node;
-
-				offset_varnodes(
-						(Node *)(ref->refupperindexpr),
-						offset,
-						sublevels_up);
-				offset_varnodes(
-						(Node *)(ref->reflowerindexpr),
-						offset,
-						sublevels_up);
-				offset_varnodes(
-						(Node *)(ref->refexpr),
-						offset,
-						sublevels_up);
-				offset_varnodes(
-						(Node *)(ref->refassgnexpr),
-						offset,
-						sublevels_up);
-			}
-			break;
-
-		case T_Var:
-			{
-				Var	*var = (Var *)node;
-
-				if (var->varlevelsup == sublevels_up) {
-					var->varno += offset;
-					var->varnoold += offset;
-				}
-			}
-			break;
-
-		case T_Param:
-			break;
-
-		case T_Const:
-			break;
-
-		case T_List:
-			{
-				List	*l;
-
-				foreach (l, (List *)node)
-					offset_varnodes(
-							(Node *)lfirst(l),
-							offset,
-							sublevels_up);
-			}
-			break;
-
-		case T_SubLink:
-			{
-				SubLink	*sub = (SubLink *)node;
-
-				offset_varnodes(
-						(Node *)(sub->lefthand),
-						offset,
-						sublevels_up);
-
-				offset_varnodes(
-						(Node *)(sub->subselect),
-						offset,
-						sublevels_up + 1);
-			}
-			break;
-
-		case T_Query:
-			{
-				Query	*qry = (Query *)node;
-
-				offset_varnodes(
-						(Node *)(qry->targetList),
-						offset,
-						sublevels_up);
-
-				offset_varnodes(
-						(Node *)(qry->qual),
-						offset,
-						sublevels_up);
-
-				offset_varnodes(
-						(Node *)(qry->havingQual),
-						offset,
-						sublevels_up);
-
-				offset_varnodes(
-						(Node *)(qry->groupClause),
-						offset,
-						sublevels_up);
-			}
-			break;
-
-		default:
-			elog(NOTICE, "unknown node tag %d in offset_varnodes()", nodeTag(node));
-			elog(NOTICE, "Node is: %s", nodeToString(node));
-			break;
-
-
-	}
-}
-
-
-/*
- * change_varnodes -
- *	and another ChangeVarNodes() too
- */
-static void
-change_varnodes(Node *node, int rt_index, int new_index, int sublevels_up)
-{
-	if (node == NULL)
-		return;
-
-	switch(nodeTag(node)) {
-		case T_TargetEntry:
-			{
-				TargetEntry	*tle = (TargetEntry *)node;
-
-				change_varnodes(
-						(Node *)(tle->expr),
-						rt_index,
-						new_index,
-						sublevels_up);
-			}
-			break;
-
-		case T_Aggreg:
-			{
-				Aggreg	*agg = (Aggreg *)node;
-
-				change_varnodes(
-						(Node *)(agg->target),
-						rt_index,
-						new_index,
-						sublevels_up);
-			}
-			break;
-
-		case T_GroupClause:
-			{
-				GroupClause	*grp = (GroupClause *)node;
-
-				change_varnodes(
-						(Node *)(grp->entry),
-						rt_index,
-						new_index,
-						sublevels_up);
-			}
-			break;
-
-		case T_Expr:
-			{
-				Expr	*exp = (Expr *)node;
-
-				change_varnodes(
-						(Node *)(exp->args),
-						rt_index,
-						new_index,
-						sublevels_up);
-			}
-			break;
-
-		case T_Iter:
-			{
-				Iter	*iter = (Iter *)node;
-
-				change_varnodes(
-						(Node *)(iter->iterexpr),
-						rt_index,
-						new_index,
-						sublevels_up);
-			}
-			break;
-
-		case T_ArrayRef:
-			{
-				ArrayRef	*ref = (ArrayRef *)node;
-
-				change_varnodes(
-						(Node *)(ref->refupperindexpr),
-						rt_index,
-						new_index,
-						sublevels_up);
-				change_varnodes(
-						(Node *)(ref->reflowerindexpr),
-						rt_index,
-						new_index,
-						sublevels_up);
-				change_varnodes(
-						(Node *)(ref->refexpr),
-						rt_index,
-						new_index,
-						sublevels_up);
-				change_varnodes(
-						(Node *)(ref->refassgnexpr),
-						rt_index,
-						new_index,
-						sublevels_up);
-			}
-			break;
-
-		case T_Var:
-			{
-				Var	*var = (Var *)node;
-
-				if (var->varlevelsup == sublevels_up &&
-						var->varno == rt_index) {
-					var->varno = new_index;
-					var->varnoold = new_index;
-				}
-			}
-			break;
-
-		case T_Param:
-			break;
-
-		case T_Const:
-			break;
-
-		case T_List:
-			{
-				List	*l;
-
-				foreach (l, (List *)node)
-					change_varnodes(
-							(Node *)lfirst(l),
-							rt_index,
-							new_index,
-							sublevels_up);
-			}
-			break;
-
-		case T_SubLink:
-			{
-				SubLink	*sub = (SubLink *)node;
-
-				change_varnodes(
-						(Node *)(sub->lefthand),
-						rt_index,
-						new_index,
-						sublevels_up);
-
-				change_varnodes(
-						(Node *)(sub->subselect),
-						rt_index,
-						new_index,
-						sublevels_up + 1);
-			}
-			break;
-
-		case T_Query:
-			{
-				Query	*qry = (Query *)node;
-
-				change_varnodes(
-						(Node *)(qry->targetList),
-						rt_index,
-						new_index,
-						sublevels_up);
-
-				change_varnodes(
-						(Node *)(qry->qual),
-						rt_index,
-						new_index,
-						sublevels_up);
-
-				change_varnodes(
-						(Node *)(qry->havingQual),
-						rt_index,
-						new_index,
-						sublevels_up);
-
-				change_varnodes(
-						(Node *)(qry->groupClause),
-						rt_index,
-						new_index,
-						sublevels_up);
-			}
-			break;
-
-		default:
-			elog(NOTICE, "unknown node tag %d in change_varnodes()", nodeTag(node));
-			elog(NOTICE, "Node is: %s", nodeToString(node));
-			break;
-
-
-	}
-}
-
-
 /*
  * modifyAggregUplevel -
  *	In the newly created sublink for an aggregate column used in
@@ -1655,6 +1295,121 @@ make_null(Oid type)
 }
 
 
+static void 
+apply_RIR_adjust_sublevel(Node *node, int sublevels_up)
+{
+	if (node == NULL)
+		return;
+
+	switch(nodeTag(node)) {
+		case T_TargetEntry:
+			{
+				TargetEntry	*tle = (TargetEntry *)node;
+
+				apply_RIR_adjust_sublevel(
+						(Node *)(tle->expr),
+						sublevels_up);
+			}
+			break;
+
+		case T_Aggreg:
+			{
+				Aggreg	*agg = (Aggreg *)node;
+
+				apply_RIR_adjust_sublevel(
+						(Node *)(agg->target),
+						sublevels_up);
+			}
+			break;
+
+		case T_GroupClause:
+			{
+				GroupClause	*grp = (GroupClause *)node;
+
+				apply_RIR_adjust_sublevel(
+						(Node *)(grp->entry),
+						sublevels_up);
+			}
+			break;
+
+		case T_Expr:
+			{
+				Expr	*exp = (Expr *)node;
+
+				apply_RIR_adjust_sublevel(
+						(Node *)(exp->args),
+						sublevels_up);
+			}
+			break;
+
+		case T_Iter:
+			{
+				Iter	*iter = (Iter *)node;
+
+				apply_RIR_adjust_sublevel(
+						(Node *)(iter->iterexpr),
+						sublevels_up);
+			}
+			break;
+
+		case T_ArrayRef:
+			{
+				ArrayRef	*ref = (ArrayRef *)node;
+
+				apply_RIR_adjust_sublevel(
+						(Node *)(ref->refupperindexpr),
+						sublevels_up);
+
+				apply_RIR_adjust_sublevel(
+						(Node *)(ref->reflowerindexpr),
+						sublevels_up);
+
+				apply_RIR_adjust_sublevel(
+						(Node *)(ref->refexpr),
+						sublevels_up);
+
+				apply_RIR_adjust_sublevel(
+						(Node *)(ref->refassgnexpr),
+						sublevels_up);
+			}
+			break;
+
+		case T_Var:
+			{
+				Var	*var = (Var *)node;
+
+				var->varlevelsup = sublevels_up;
+			}
+			break;
+
+		case T_Param:
+			break;
+
+		case T_Const:
+			break;
+
+		case T_List:
+			{
+				List	*l;
+
+				foreach (l, (List *)node) {
+					apply_RIR_adjust_sublevel(
+							(Node *)lfirst(l),
+							sublevels_up);
+				}
+			}
+			break;
+
+		default:
+			elog(NOTICE, "unknown node tag %d in attribute_used()", nodeTag(node));
+			elog(NOTICE, "Node is: %s", nodeToString(node));
+			break;
+
+
+	}
+}
+
+
 static void
 apply_RIR_view(Node **nodePtr, int rt_index, RangeTblEntry *rte, List *tlist, int *modified, int sublevels_up)
 {
@@ -1790,10 +1545,8 @@ apply_RIR_view(Node **nodePtr, int rt_index, RangeTblEntry *rte, List *tlist, in
 					}
 
 					exp = copyObject(exp);
-					if (var->varlevelsup > 0 &&
-							nodeTag(exp) == T_Var) {
-						((Var *)exp)->varlevelsup = var->varlevelsup;
-					} 
+					if (var->varlevelsup > 0)
+						apply_RIR_adjust_sublevel(exp, var->varlevelsup);
 					*nodePtr = exp;
 					*modified = TRUE;
 				}
@@ -1885,8 +1638,6 @@ apply_RIR_view(Node **nodePtr, int rt_index, RangeTblEntry *rte, List *tlist, in
 			elog(NOTICE, "unknown node tag %d in apply_RIR_view()", nodeTag(node));
 			elog(NOTICE, "Node is: %s", nodeToString(node));
 			break;
-
-
 	}
 }
 
@@ -1938,12 +1689,12 @@ ApplyRetrieveRule(Query *parsetree,
 	parsetree->rtable = rtable;
 
 	rule_action->rtable = rtable;
-	offset_varnodes((Node *) rule_qual,   rt_length, 0);
-	offset_varnodes((Node *) rule_action, rt_length, 0);
+	OffsetVarNodes((Node *) rule_qual,   rt_length, 0);
+	OffsetVarNodes((Node *) rule_action, rt_length, 0);
 
-	change_varnodes((Node *) rule_qual, 
+	ChangeVarNodes((Node *) rule_qual, 
 				   PRS2_CURRENT_VARNO + rt_length, rt_index, 0);
-	change_varnodes((Node *) rule_action,
+	ChangeVarNodes((Node *) rule_action,
 				   PRS2_CURRENT_VARNO + rt_length, rt_index, 0);
 
 	if (relation_level)
@@ -2246,7 +1997,7 @@ CopyAndAddQual(Query *parsetree,
 		rt_length = length(rtable);
 		rtable = append(rtable, listCopy(rule_action->rtable));
 		new_tree->rtable = rtable;
-		OffsetVarNodes(new_qual, rt_length);
+		OffsetVarNodes(new_qual, rt_length, 0);
 		ChangeVarNodes(new_qual, PRS2_CURRENT_VARNO + rt_length, rt_index, 0);
 	}
 	/* XXX -- where current doesn't work for instead nothing.... yet */
@@ -2385,6 +2136,28 @@ fireRules(Query *parsetree,
 			if (rule_action->commandType == CMD_NOTHING)
 				continue;
 
+			/*--------------------------------------------------
+			 * We copy the qualifications of the parsetree
+			 * to the action and vice versa. So force
+			 * hasSubLinks if one of them has it.
+			 *
+			 * As of 6.4 only parsetree qualifications can
+			 * have sublinks. If this changes, we must make
+			 * this a node lookup at the end of rewriting.
+			 *
+			 * Jan
+			 *--------------------------------------------------
+			 */
+			if (parsetree->hasSubLinks && !rule_action->hasSubLinks)
+			{
+				rule_action = copyObject(rule_action);
+				rule_action->hasSubLinks = TRUE;
+			}
+			if (!parsetree->hasSubLinks && rule_action->hasSubLinks)
+			{
+				parsetree->hasSubLinks = TRUE;
+			}
+
 			/*--------------------------------------------------
 			 * Step 1:
 			 *	  Rewrite current.attribute or current to tuple variable
diff --git a/src/backend/rewrite/rewriteManip.c b/src/backend/rewrite/rewriteManip.c
index d589943dc5c6bc2cdc7475d4e0557a529fa1236d..64da8479d150b61a83a195aadcd3ed9b58a73797 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.21 1998/10/20 17:21:44 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteManip.c,v 1.22 1998/10/21 16:21:26 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -32,222 +32,362 @@ static void ResolveNew(RewriteInfo *info, List *targetlist,
 		   Node **node, int sublevels_up);
 
 
-
+/*
+ * OffsetVarnodes -
+ */
 void
-OffsetVarNodes(Node *node, int offset)
+OffsetVarNodes(Node *node, int offset, int sublevels_up)
 {
 	if (node == NULL)
 		return;
-	switch (nodeTag(node))
-	{
+
+	switch(nodeTag(node)) {
 		case T_TargetEntry:
 			{
-				TargetEntry *tle = (TargetEntry *) node;
+				TargetEntry	*tle = (TargetEntry *)node;
 
-				OffsetVarNodes(tle->expr, offset);
+				OffsetVarNodes(
+						(Node *)(tle->expr),
+						offset,
+						sublevels_up);
 			}
 			break;
+
 		case T_Aggreg:
 			{
-				Aggreg	   *agg = (Aggreg *) node;
+				Aggreg	*agg = (Aggreg *)node;
 
-				OffsetVarNodes(agg->target, offset);
+				OffsetVarNodes(
+						(Node *)(agg->target),
+						offset,
+						sublevels_up);
 			}
 			break;
 
-			/*
-			 * This has to be done to make queries using groupclauses work
-			 * on views
-			 */
 		case T_GroupClause:
 			{
-				GroupClause *group = (GroupClause *) node;
+				GroupClause	*grp = (GroupClause *)node;
 
-				OffsetVarNodes((Node *) (group->entry), offset);
+				OffsetVarNodes(
+						(Node *)(grp->entry),
+						offset,
+						sublevels_up);
 			}
 			break;
+
 		case T_Expr:
 			{
-				Expr	   *expr = (Expr *) node;
+				Expr	*exp = (Expr *)node;
 
-				OffsetVarNodes((Node *) expr->args, offset);
+				OffsetVarNodes(
+						(Node *)(exp->args),
+						offset,
+						sublevels_up);
 			}
 			break;
+
 		case T_Iter:
 			{
-				Iter	   *iter = (Iter *) node;
+				Iter	*iter = (Iter *)node;
 
-				OffsetVarNodes((Node *) iter->iterexpr, offset);
+				OffsetVarNodes(
+						(Node *)(iter->iterexpr),
+						offset,
+						sublevels_up);
 			}
 			break;
+
 		case T_ArrayRef:
 			{
-				ArrayRef	   *ref = (ArrayRef *) node;
+				ArrayRef	*ref = (ArrayRef *)node;
 
-				OffsetVarNodes((Node *) ref->refupperindexpr, offset);
-				OffsetVarNodes((Node *) ref->reflowerindexpr, offset);
-				OffsetVarNodes((Node *) ref->refexpr, offset);
-				OffsetVarNodes((Node *) ref->refassgnexpr, offset);
+				OffsetVarNodes(
+						(Node *)(ref->refupperindexpr),
+						offset,
+						sublevels_up);
+				OffsetVarNodes(
+						(Node *)(ref->reflowerindexpr),
+						offset,
+						sublevels_up);
+				OffsetVarNodes(
+						(Node *)(ref->refexpr),
+						offset,
+						sublevels_up);
+				OffsetVarNodes(
+						(Node *)(ref->refassgnexpr),
+						offset,
+						sublevels_up);
 			}
 			break;
+
 		case T_Var:
 			{
-				Var		   *var = (Var *) node;
+				Var	*var = (Var *)node;
 
-				var->varno += offset;
-				var->varnoold += offset;
+				if (var->varlevelsup == sublevels_up) {
+					var->varno += offset;
+					var->varnoold += offset;
+				}
 			}
 			break;
+
+		case T_Param:
+			break;
+
+		case T_Const:
+			break;
+
 		case T_List:
 			{
-				List	   *l;
+				List	*l;
 
-				foreach(l, (List *) node)
-					OffsetVarNodes(lfirst(l), offset);
+				foreach (l, (List *)node)
+					OffsetVarNodes(
+							(Node *)lfirst(l),
+							offset,
+							sublevels_up);
 			}
 			break;
+
 		case T_SubLink:
 			{
-				SubLink    *sublink = (SubLink *) node;
+				SubLink	*sub = (SubLink *)node;
 
-				/*
-				 * We also have to adapt the variables used in
-				 * sublink->lefthand and sublink->oper
-				 */
-				OffsetVarNodes((Node *) (sublink->lefthand), offset);
+				OffsetVarNodes(
+						(Node *)(sub->lefthand),
+						offset,
+						sublevels_up);
 
-				/*
-				 * Make sure the first argument of sublink->oper points to
-				 * the same var as sublink->lefthand does otherwise we
-				 * will run into troubles using aggregates (aggno will not
-				 * be set correctly)
-				 */
-				lfirst(((Expr *) lfirst(sublink->oper))->args) =
-					lfirst(sublink->lefthand);
+				OffsetVarNodes(
+						(Node *)(sub->subselect),
+						offset,
+						sublevels_up + 1);
 			}
 			break;
+
+		case T_Query:
+			{
+				Query	*qry = (Query *)node;
+
+				OffsetVarNodes(
+						(Node *)(qry->targetList),
+						offset,
+						sublevels_up);
+
+				OffsetVarNodes(
+						(Node *)(qry->qual),
+						offset,
+						sublevels_up);
+
+				OffsetVarNodes(
+						(Node *)(qry->havingQual),
+						offset,
+						sublevels_up);
+
+				OffsetVarNodes(
+						(Node *)(qry->groupClause),
+						offset,
+						sublevels_up);
+			}
+			break;
+
 		default:
-			/* ignore the others */
+			elog(NOTICE, "unknown node tag %d in OffsetVarNodes()", nodeTag(node));
+			elog(NOTICE, "Node is: %s", nodeToString(node));
 			break;
+
+
 	}
 }
 
+
+/*
+ * ChangeVarNodes -
+ */
 void
-ChangeVarNodes(Node *node, int old_varno, int new_varno, int sublevels_up)
+ChangeVarNodes(Node *node, int rt_index, int new_index, int sublevels_up)
 {
 	if (node == NULL)
 		return;
-	switch (nodeTag(node))
-	{
+
+	switch(nodeTag(node)) {
 		case T_TargetEntry:
 			{
-				TargetEntry *tle = (TargetEntry *) node;
+				TargetEntry	*tle = (TargetEntry *)node;
 
-				ChangeVarNodes(tle->expr, old_varno, new_varno, sublevels_up);
+				ChangeVarNodes(
+						(Node *)(tle->expr),
+						rt_index,
+						new_index,
+						sublevels_up);
 			}
 			break;
+
 		case T_Aggreg:
 			{
-				Aggreg	   *agg = (Aggreg *) node;
+				Aggreg	*agg = (Aggreg *)node;
 
-				ChangeVarNodes(agg->target, old_varno, new_varno, sublevels_up);
+				ChangeVarNodes(
+						(Node *)(agg->target),
+						rt_index,
+						new_index,
+						sublevels_up);
 			}
 			break;
 
-			/*
-			 * This has to be done to make queries using groupclauses work
-			 * on views
-			 */
 		case T_GroupClause:
 			{
-				GroupClause *group = (GroupClause *) node;
+				GroupClause	*grp = (GroupClause *)node;
 
-				ChangeVarNodes((Node *) (group->entry), old_varno, new_varno,
-							   sublevels_up);
+				ChangeVarNodes(
+						(Node *)(grp->entry),
+						rt_index,
+						new_index,
+						sublevels_up);
 			}
 			break;
 
 		case T_Expr:
 			{
-				Expr	   *expr = (Expr *) node;
+				Expr	*exp = (Expr *)node;
 
-				ChangeVarNodes((Node *) expr->args, old_varno, new_varno, sublevels_up);
+				ChangeVarNodes(
+						(Node *)(exp->args),
+						rt_index,
+						new_index,
+						sublevels_up);
 			}
 			break;
+
 		case T_Iter:
 			{
-				Iter	   *iter = (Iter *) node;
+				Iter	*iter = (Iter *)node;
 
-				ChangeVarNodes((Node *) iter->iterexpr, old_varno, new_varno, sublevels_up);
+				ChangeVarNodes(
+						(Node *)(iter->iterexpr),
+						rt_index,
+						new_index,
+						sublevels_up);
 			}
 			break;
+
 		case T_ArrayRef:
 			{
-				ArrayRef	   *ref = (ArrayRef *) node;
-
-				ChangeVarNodes((Node *) ref->refupperindexpr, old_varno, new_varno, sublevels_up);
-				ChangeVarNodes((Node *) ref->reflowerindexpr, old_varno, new_varno, sublevels_up);
-				ChangeVarNodes((Node *) ref->refexpr, old_varno, new_varno, sublevels_up);
-				ChangeVarNodes((Node *) ref->refassgnexpr, old_varno, new_varno, sublevels_up);
+				ArrayRef	*ref = (ArrayRef *)node;
+
+				ChangeVarNodes(
+						(Node *)(ref->refupperindexpr),
+						rt_index,
+						new_index,
+						sublevels_up);
+				ChangeVarNodes(
+						(Node *)(ref->reflowerindexpr),
+						rt_index,
+						new_index,
+						sublevels_up);
+				ChangeVarNodes(
+						(Node *)(ref->refexpr),
+						rt_index,
+						new_index,
+						sublevels_up);
+				ChangeVarNodes(
+						(Node *)(ref->refassgnexpr),
+						rt_index,
+						new_index,
+						sublevels_up);
 			}
 			break;
+
 		case T_Var:
 			{
-				Var		   *var = (Var *) node;
+				Var	*var = (Var *)node;
 
-				if (var->varno == old_varno &&
-					var->varlevelsup == sublevels_up)
-				{
-					var->varno = new_varno;
-					var->varnoold = new_varno;
+				if (var->varlevelsup == sublevels_up &&
+						var->varno == rt_index) {
+					var->varno = new_index;
+					var->varnoold = new_index;
 				}
-				if (var->varlevelsup > 0)
-					OffsetVarNodes((Node *) var, 3);
-
 			}
 			break;
+
+		case T_Param:
+			break;
+
+		case T_Const:
+			break;
+
 		case T_List:
 			{
-				List	   *l;
+				List	*l;
 
-				foreach(l, (List *) node)
-					ChangeVarNodes(lfirst(l), old_varno, new_varno, sublevels_up);
+				foreach (l, (List *)node)
+					ChangeVarNodes(
+							(Node *)lfirst(l),
+							rt_index,
+							new_index,
+							sublevels_up);
 			}
 			break;
+
 		case T_SubLink:
 			{
-				SubLink    *sublink = (SubLink *) node;
-				Query	   *query = (Query *) sublink->subselect;
+				SubLink	*sub = (SubLink *)node;
 
-				ChangeVarNodes((Node *) query->qual, old_varno, new_varno,
-							   sublevels_up + 1);
+				ChangeVarNodes(
+						(Node *)(sub->lefthand),
+						rt_index,
+						new_index,
+						sublevels_up);
 
-				/*
-				 * We also have to adapt the variables used in
-				 * sublink->lefthand and sublink->oper
-				 */
-				ChangeVarNodes((Node *) (sublink->lefthand), old_varno, new_varno,
-							   sublevels_up);
+				ChangeVarNodes(
+						(Node *)(sub->subselect),
+						rt_index,
+						new_index,
+						sublevels_up + 1);
+			}
+			break;
 
-				/*
-				 * Make sure the first argument of sublink->oper points to
-				 * the same var as sublink->lefthand does otherwise we
-				 * will run into troubles using aggregates (aggno will not
-				 * be set correctly
-				 */
+		case T_Query:
+			{
+				Query	*qry = (Query *)node;
 
-				/*
-				 * lfirst(((Expr *) lfirst(sublink->oper))->args) =
-				 * lfirst(sublink->lefthand);
-				 */
+				ChangeVarNodes(
+						(Node *)(qry->targetList),
+						rt_index,
+						new_index,
+						sublevels_up);
+
+				ChangeVarNodes(
+						(Node *)(qry->qual),
+						rt_index,
+						new_index,
+						sublevels_up);
+
+				ChangeVarNodes(
+						(Node *)(qry->havingQual),
+						rt_index,
+						new_index,
+						sublevels_up);
+
+				ChangeVarNodes(
+						(Node *)(qry->groupClause),
+						rt_index,
+						new_index,
+						sublevels_up);
 			}
 			break;
+
 		default:
-			/* ignore the others */
+			elog(NOTICE, "unknown node tag %d in ChangeVarNodes()", nodeTag(node));
+			elog(NOTICE, "Node is: %s", nodeToString(node));
 			break;
+
+
 	}
 }
 
+
+
 void
 AddQual(Query *parsetree, Node *qual)
 {
diff --git a/src/include/rewrite/rewriteManip.h b/src/include/rewrite/rewriteManip.h
index 7924f931615e1629503360cb5be561db18b1d645..e1b54829bbc97f9269f9a3074b72b416dc360cb3 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.10 1998/10/08 18:30:41 momjian Exp $
+ * $Id: rewriteManip.h,v 1.11 1998/10/21 16:21:29 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -18,7 +18,7 @@
 #include "rewrite/rewriteHandler.h"
 
 /* RewriteManip.c */
-void		OffsetVarNodes(Node *node, int offset);
+void		OffsetVarNodes(Node *node, int offset, int sublevels_up);
 void ChangeVarNodes(Node *node, int old_varno, int new_varno,
 			   int sublevels_up);
 void		AddQual(Query *parsetree, Node *qual);