diff --git a/src/backend/commands/recipe.c b/src/backend/commands/recipe.c
index bfdfe9d78fd3a96cf101ba84531ed7beeb626a4e..96808a6e3115f8003f2917ddc18a4ebb24ccdb9c 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.17 1998/01/05 16:38:57 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/Attic/recipe.c,v 1.18 1998/01/20 22:10:53 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -494,6 +494,7 @@ tg_replaceNumberedParam(Node *expression,
 							newVar = makeVar(rt_ind,
 											 0, /* the whole tuple */
 										   TypeGet(teeRelName, &defined),
+										     0,
 											 rt_ind,
 											 0);
 							return (Node *) newVar;
@@ -503,6 +504,7 @@ tg_replaceNumberedParam(Node *expression,
 											 1, /* just the first field,
 												 * which is 'result' */
 										   TypeGet(teeRelName, &defined),
+										     0,
 											 rt_ind,
 											 0);
 						return (Node *) newVar;
diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c
index d6cc4cd5470c27a0faeb0f49051b668529e5b017..c3b98a555f51fca284db02a1b93547497104f897 100644
--- a/src/backend/nodes/copyfuncs.c
+++ b/src/backend/nodes/copyfuncs.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.34 1998/01/20 05:03:40 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.35 1998/01/20 22:10:58 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -671,6 +671,7 @@ _copyVar(Var *from)
 	newnode->varno = from->varno;
 	newnode->varattno = from->varattno;
 	newnode->vartype = from->vartype;
+	newnode->varlevelsup = from->varlevelsup;
 
 	newnode->varnoold = from->varnoold;
 	newnode->varoattno = from->varoattno;
diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c
index d569bd471283e43d08a83a1b919e1cf7c47dd29b..bfed02b5e568a30ed1142f22aba46c696142326c 100644
--- a/src/backend/nodes/equalfuncs.c
+++ b/src/backend/nodes/equalfuncs.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.12 1998/01/07 21:03:26 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.13 1998/01/20 22:11:02 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -129,6 +129,8 @@ _equalVar(Var *a, Var *b)
 		return (false);
 	if (a->vartype != b->vartype)
 		return (false);
+	if (a->varlevelsup != b->varlevelsup)
+		return (false);
 	if (a->varnoold != b->varnoold)
 		return (false);
 	if (a->varoattno != b->varoattno)
diff --git a/src/backend/nodes/makefuncs.c b/src/backend/nodes/makefuncs.c
index 95cce161d6675fda28f4a236c141c82c67c9e150..af5003e87732271c0e93c216bafb098493dc2e9d 100644
--- a/src/backend/nodes/makefuncs.c
+++ b/src/backend/nodes/makefuncs.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/nodes/makefuncs.c,v 1.4 1997/09/08 02:23:39 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/nodes/makefuncs.c,v 1.5 1998/01/20 22:11:05 momjian Exp $
  *
  * NOTES
  *	  Creator functions in POSTGRES 4.2 are generated automatically. Most of
@@ -53,6 +53,7 @@ Var		   *
 makeVar(Index varno,
 		AttrNumber varattno,
 		Oid vartype,
+		Index varlevelsup,
 		Index varnoold,
 		AttrNumber varoattno)
 {
@@ -61,6 +62,7 @@ makeVar(Index varno,
 	var->varno = varno;
 	var->varattno = varattno;
 	var->vartype = vartype;
+	var->varlevelsup = varlevelsup;
 	var->varnoold = varnoold;
 	var->varoattno = varoattno;
 
diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c
index d7ede89e65c49dc49d635b45e3f9120aea46c712..6f69c34983ce410b6c9d156c82ebed8927162399 100644
--- a/src/backend/nodes/outfuncs.c
+++ b/src/backend/nodes/outfuncs.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.25 1998/01/20 05:03:49 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.26 1998/01/20 22:11:12 momjian Exp $
  *
  * NOTES
  *	  Every (plan) node in POSTGRES has an associated "out" routine which
@@ -698,6 +698,8 @@ _outVar(StringInfo str, Var *node)
 	appendStringInfo(str, buf);
 	sprintf(buf, " :vartype %u ", node->vartype);
 	appendStringInfo(str, buf);
+	sprintf(buf, " :varlevelsup %u ", node->varlevelsup);
+	appendStringInfo(str, buf);
 	sprintf(buf, " :varnoold %d ", node->varnoold);
 	appendStringInfo(str, buf);
 	sprintf(buf, " :varoattno %d ", node->varoattno);
diff --git a/src/backend/nodes/readfuncs.c b/src/backend/nodes/readfuncs.c
index 2860bad174a6a1945d9d1cf41039f4152b9d59e4..d0bcf13875fed190d5cce4340b219b7620a05835 100644
--- a/src/backend/nodes/readfuncs.c
+++ b/src/backend/nodes/readfuncs.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.21 1998/01/20 05:03:57 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.22 1998/01/20 22:11:15 momjian Exp $
  *
  * NOTES
  *	  Most of the read functions for plan nodes are tested. (In fact, they
@@ -814,6 +814,10 @@ _readVar()
 	token = lsptok(NULL, &length);		/* get vartype */
 	local_node->vartype = (Oid) atol(token);
 
+	token = lsptok(NULL, &length);		/* eat :varlevelsup */
+	token = lsptok(NULL, &length);		/* get varlevelsup */
+	local_node->varlevelsup = (Oid) atol(token);
+
 	token = lsptok(NULL, &length);		/* eat :varnoold */
 	token = lsptok(NULL, &length);		/* get varnoold */
 	local_node->varnoold = (Oid) atol(token);
diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c
index 970a6a5ffb7dd47db93ab44e3c5d16695662f327..2b53f1875fe6d1d76d2ba3e4a323219dfd0a8fa7 100644
--- a/src/backend/optimizer/plan/createplan.c
+++ b/src/backend/optimizer/plan/createplan.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.23 1998/01/15 18:59:37 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.24 1998/01/20 22:11:25 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -701,6 +701,7 @@ fix_indxqual_references(Node *clause, Path *index_path)
 		makeVar((Index) lfirsti(index_path->parent->relids),
 				1,				/* func indices have one key */
 				((Func *) ((Expr *) clause)->oper)->functype,
+				0,
 				(Index) lfirsti(index_path->parent->relids),
 				0);
 
diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c
index d7edd0aaea0cf7137c0e4dfc0de2c8c46b9cefa8..cb0bd085875ac2fdaffdba3bbf955d706252ae83 100644
--- a/src/backend/optimizer/plan/initsplan.c
+++ b/src/backend/optimizer/plan/initsplan.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/optimizer/plan/initsplan.c,v 1.8 1997/09/08 21:45:19 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/optimizer/plan/initsplan.c,v 1.9 1998/01/20 22:11:27 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -116,7 +116,7 @@ add_missing_vars_to_base_rels(Query *root, List *tlist)
 			!rel_member(relids, root->base_relation_list_))
 		{
 
-			var = makeVar(varno, -2, 26, varno, -2);
+			var = makeVar(varno, -2, 26, 0, varno, -2);
 			/* add it to base_relation_list_ */
 			result = get_base_rel(root, varno);
 			add_tl_element(result, var);
diff --git a/src/backend/optimizer/plan/planmain.c b/src/backend/optimizer/plan/planmain.c
index b8b99149ce5a8e0440426b741c21614e2fe0e404..1c59f64a4c84293893cd23f4acc271b7960253dd 100644
--- a/src/backend/optimizer/plan/planmain.c
+++ b/src/backend/optimizer/plan/planmain.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planmain.c,v 1.16 1998/01/15 18:59:44 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planmain.c,v 1.17 1998/01/20 22:11:29 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -464,7 +464,7 @@ make_groupPlan(List **tlist,
 		else
 			te->expr = (Node *) makeVar(1, resdom->resno,
 										resdom->restype,
-										-1, resdom->resno);
+										0, -1, resdom->resno);
 	}
 
 	sortplan = make_sort(sort_tlist,
diff --git a/src/backend/optimizer/plan/setrefs.c b/src/backend/optimizer/plan/setrefs.c
index fe80a658f0a1f08838f3ae33723719178937934a..284ac836f63603b0176b0f4d32503a811266aa3c 100644
--- a/src/backend/optimizer/plan/setrefs.c
+++ b/src/backend/optimizer/plan/setrefs.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/optimizer/plan/setrefs.c,v 1.15 1998/01/15 18:59:50 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/optimizer/plan/setrefs.c,v 1.16 1998/01/20 22:11:32 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -440,6 +440,7 @@ replace_joinvar_refs(Var *var, List *outer_tlist, List *inner_tlist)
 		return (makeVar(OUTER,
 						outer_resdom->resno,
 						var->vartype,
+						0,
 						var->varnoold,
 						var->varoattno));
 	}
@@ -453,6 +454,7 @@ replace_joinvar_refs(Var *var, List *outer_tlist, List *inner_tlist)
 			return (makeVar(INNER,
 							inner_resdom->resno,
 							var->vartype,
+							0,
 							var->varnoold,
 							var->varoattno));
 		}
@@ -497,6 +499,7 @@ tlist_temp_references(Oid tempid,
 					   (Node *) makeVar(tempid,
 										xtl->resdom->resno,
 										xtl->resdom->restype,
+										0,
 										tempid,
 										oattno));
 
diff --git a/src/backend/optimizer/prep/preptlist.c b/src/backend/optimizer/prep/preptlist.c
index e92fbb333220622046f544f20705d2674bac033d..ad2c697db5a4533bed2851e2a21eb8bb1de3f541 100644
--- a/src/backend/optimizer/prep/preptlist.c
+++ b/src/backend/optimizer/prep/preptlist.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/optimizer/prep/preptlist.c,v 1.7 1998/01/16 23:20:09 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/optimizer/prep/preptlist.c,v 1.8 1998/01/20 22:11:34 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -114,7 +114,7 @@ preprocess_targetlist(List *tlist,
 							0,
 							1);
 
-		var = makeVar(result_relation, -1, 27, result_relation, -1);
+		var = makeVar(result_relation, -1, 27, 0, result_relation, -1);
 
 		ctid = makeNode(TargetEntry);
 		ctid->resdom = resdom;
@@ -322,7 +322,7 @@ new_relation_targetlist(Oid relid, Index rt_index, NodeTag node_type)
 					TargetEntry *temp_list = NULL;
 
 					temp_var =
-						makeVar(rt_index, attno, atttype, rt_index, attno);
+						makeVar(rt_index, attno, atttype, 0, rt_index, attno);
 
 					temp_list = MakeTLE(makeResdom(attno,
 												   atttype,
diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c
index eab49abb1f5b12e6dae71c25d077541089f1487e..6f42df8ceb65fb938390088df0f1dbf5bfebbf17 100644
--- a/src/backend/optimizer/util/clauses.c
+++ b/src/backend/optimizer/util/clauses.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.13 1997/12/22 05:42:14 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.14 1998/01/20 22:11:39 momjian Exp $
  *
  * HISTORY
  *	  AUTHOR			DATE			MAJOR EVENT
@@ -377,7 +377,8 @@ clause_relids_vars(Node *clause, List **relids, List **vars)
 			Var		   *in_list = (Var *) lfirst(vi);
 
 			if (in_list->varno == var->varno &&
-				in_list->varattno == var->varattno)
+				in_list->varattno == var->varattno &&
+				in_list->varlevelsup == var->varlevelsup)
 				break;
 		}
 		if (vi == NIL)
diff --git a/src/backend/optimizer/util/tlist.c b/src/backend/optimizer/util/tlist.c
index aa867f4b5a3845ef8194a036ff844072c0f885e8..edac3e8bf4bd0b13acf8ba893cd75a5c37b00752 100644
--- a/src/backend/optimizer/util/tlist.c
+++ b/src/backend/optimizer/util/tlist.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/optimizer/util/tlist.c,v 1.8 1997/11/25 22:00:16 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/optimizer/util/tlist.c,v 1.9 1998/01/20 22:11:41 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -108,6 +108,7 @@ add_tl_element(Rel *rel, Var *var)
 		Var		   *newvar = makeVar(var->varno,
 									 var->varattno,
 									 var->vartype,
+									 var->varlevelsup,
 									 var->varno,
 									 var->varoattno);
 
@@ -287,7 +288,8 @@ match_varid(Var *test_var, List *tlist)
 		 * changed to INNER/OUTER.
 		 */
 		if (tlvar->varnoold == test_var->varnoold &&
-			tlvar->varoattno == test_var->varoattno)
+			tlvar->varoattno == test_var->varoattno &&
+			tlvar->varlevelsup == test_var->varlevelsup)
 		{
 
 			if (tlvar->vartype == type_var)
diff --git a/src/backend/optimizer/util/var.c b/src/backend/optimizer/util/var.c
index 7ba3ce5d97572337ce18144f1be87a2e65580954..e3ed305ed88ebce158a91dc5d6432f7b0c6f61e3 100644
--- a/src/backend/optimizer/util/var.c
+++ b/src/backend/optimizer/util/var.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/optimizer/util/var.c,v 1.7 1997/12/22 05:42:16 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/optimizer/util/var.c,v 1.8 1998/01/20 22:11:43 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -209,6 +209,7 @@ var_equal(Var *var1, Var *var2)
 	if (IsA(var1, Var) &&IsA(var2, Var) &&
 		(((Var *) var1)->varno == ((Var *) var2)->varno) &&
 		(((Var *) var1)->vartype == ((Var *) var2)->vartype) &&
+		(((Var *) var1)->varlevelsup == ((Var *) var2)->varlevelsup) &&
 		(((Var *) var1)->varattno == ((Var *) var2)->varattno))
 	{
 
diff --git a/src/backend/parser/README b/src/backend/parser/README
index 402f193bc6a924f0f8b4fa5a28ea45a80fdf2425..b67e1909d9e1ab11aac1136f5d323ca790db84bb 100644
--- a/src/backend/parser/README
+++ b/src/backend/parser/README
@@ -12,7 +12,7 @@ parse_clause.c	handle clauses like WHERE, ORDER BY, GROUP BY, ...
 parse_expr.c	handle expressions like col, col + 3, x = 3 or x = 4
 parse_oper.c	handle operations in expressions
 parse_agg.c	handle aggregates, like SUM(col1),  AVG(col2), ...
-parse_func.c	handle functions like date_part(col3), trim(col4), ...
+parse_func.c	handle functions, table.column and column identifiers
 
 parse_node.c	create nodes for various structures
 parse_target.c	handle the result list of the query
diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c
index 077215138f71e41f94f732753ae33227eea05646..a494106fd51d21687cd25a40d4c99c3413c2e350 100644
--- a/src/backend/parser/analyze.c
+++ b/src/backend/parser/analyze.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.67 1998/01/20 05:04:05 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.68 1998/01/20 22:11:51 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -219,7 +219,7 @@ transformDeleteStmt(ParseState *pstate, DeleteStmt *stmt)
 	qry->qual = transformWhereClause(pstate, stmt->whereClause);
 
 	qry->rtable = pstate->p_rtable;
-	qry->resultRelation = refnameRangeTablePosn(pstate->p_rtable, stmt->relname);
+	qry->resultRelation = refnameRangeTablePosn(pstate, stmt->relname, NULL);
 
 	qry->hasAggs = pstate->p_hasAggs;
 	if (pstate->p_hasAggs)
@@ -320,7 +320,7 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt)
 
 	/* now the range table will not change */
 	qry->rtable = pstate->p_rtable;
-	qry->resultRelation = refnameRangeTablePosn(pstate->p_rtable, stmt->relname);
+	qry->resultRelation = refnameRangeTablePosn(pstate, stmt->relname, NULL);
 
 	qry->groupClause = transformGroupClause(pstate,
 											stmt->groupClause,
@@ -816,7 +816,7 @@ transformUpdateStmt(ParseState *pstate, UpdateStmt *stmt)
 
 	qry->rtable = pstate->p_rtable;
 
-	qry->resultRelation = refnameRangeTablePosn(pstate->p_rtable, stmt->relname);
+	qry->resultRelation = refnameRangeTablePosn(pstate, stmt->relname, NULL);
 
 	qry->hasAggs = pstate->p_hasAggs;
 	if (pstate->p_hasAggs)
diff --git a/src/backend/parser/parse_clause.c b/src/backend/parser/parse_clause.c
index 115b8c153d79c27b409ebde7f9031e5799937844..8e571af58f9bd30d07e0dc94709811004eefd5e3 100644
--- a/src/backend/parser/parse_clause.c
+++ b/src/backend/parser/parse_clause.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.10 1998/01/20 05:04:12 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.11 1998/01/20 22:11:53 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -39,16 +39,15 @@ void
 makeRangeTable(ParseState *pstate, char *relname, List *frmList)
 {
 	RangeTblEntry *rte;
-
+	
 	parseFromClause(pstate, frmList);
 
 	if (relname == NULL)
 		return;
 
-	if (refnameRangeTablePosn(pstate->p_rtable, relname) < 1)
-		rte = addRangeTableEntry(pstate, relname, relname, FALSE, FALSE);
-	else
-		rte = refnameRangeTableEntry(pstate->p_rtable, relname);
+	Assert(pstate->p_rtable == NULL);
+
+	rte = addRangeTableEntry(pstate, relname, relname, FALSE, FALSE);
 
 	pstate->p_target_rangetblentry = rte;
 	Assert(pstate->p_target_relation == NULL);
@@ -137,8 +136,7 @@ find_targetlist_entry(ParseState *pstate, SortGroupBy *sortgroupby, List *tlist)
 	TargetEntry *target_result = NULL;
 
 	if (sortgroupby->range)
-		real_rtable_pos = refnameRangeTablePosn(pstate->p_rtable,
-												sortgroupby->range);
+		real_rtable_pos = refnameRangeTablePosn(pstate,	sortgroupby->range, NULL);
 
 	foreach(i, tlist)
 	{
diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c
index ef42a61fe29867c10f9d6e01b900ad2709f3be81..485054eac11dec8cf299493ac0a3ee32376ca0fd 100644
--- a/src/backend/parser/parse_expr.c
+++ b/src/backend/parser/parse_expr.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.11 1998/01/20 05:04:14 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.12 1998/01/20 22:11:55 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -304,6 +304,7 @@ transformIdent(ParseState *pstate, Node *expr, int precedence)
 	{
 		Attr	   *att = makeNode(Attr);
 
+		/* we add the relation name for them */
 		att->relname = rte->refname;
 		att->attrs = lcons(makeString(ident->name), NIL);
 		column_result =
@@ -312,7 +313,7 @@ transformIdent(ParseState *pstate, Node *expr, int precedence)
 	}
 
 	/* try to find the ident as a relation */
-	if (refnameRangeTableEntry(pstate->p_rtable, ident->name) != NULL)
+	if (refnameRangeTableEntry(pstate, ident->name) != NULL)
 	{
 		ident->isRel = TRUE;
 		relation_result = (Node *) ident;
diff --git a/src/backend/parser/parse_func.c b/src/backend/parser/parse_func.c
index e8466fa62640a92700c9d9281e5219960a032530..d864dfc1f6d9f26eff7a2e1e262c167950fe6da0 100644
--- a/src/backend/parser/parse_func.c
+++ b/src/backend/parser/parse_func.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.7 1998/01/20 05:04:16 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.8 1998/01/20 22:11:55 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -174,13 +174,12 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
 		{
 			RangeTblEntry *rte;
 			Ident	   *ident = (Ident *) first_arg;
-
 			/*
 			 * first arg is a relation. This could be a projection.
 			 */
 			refname = ident->name;
 
-			rte = refnameRangeTableEntry(pstate->p_rtable, refname);
+			rte = refnameRangeTableEntry(pstate, refname);
 			if (rte == NULL)
 				rte = addRangeTableEntry(pstate, refname, refname, FALSE, FALSE);
 
@@ -196,6 +195,7 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
 				Oid			dummyTypeId;
 
 				return ((Node *) make_var(pstate,
+									   relid,
 									   refname,
 									   funcname,
 									   &dummyTypeId));
@@ -288,19 +288,18 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
 
 		if (nodeTag(pair) == T_Ident && ((Ident *) pair)->isRel)
 		{
-
 			/*
 			 * a relation
 			 */
 			refname = ((Ident *) pair)->name;
 
-			rte = refnameRangeTableEntry(pstate->p_rtable, refname);
+			rte = refnameRangeTableEntry(pstate, refname);
 			if (rte == NULL)
 				rte = addRangeTableEntry(pstate, refname, refname,
 										 FALSE, FALSE);
 			relname = rte->relname;
 
-			vnum = refnameRangeTablePosn(pstate->p_rtable, rte->refname);
+			vnum = refnameRangeTablePosn(pstate, rte->refname, NULL);
 
 			/*
 			 * for func(relname), the param to the function is the tuple
@@ -312,7 +311,7 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
 			toid = typeTypeId(typenameType(relname));
 			/* replace it in the arg list */
 			lfirst(fargs) =
-				makeVar(vnum, 0, toid, vnum, 0);
+				makeVar(vnum, 0, toid, 0, vnum, 0);
 		}
 		else if (!attisset)
 		{						/* set functions don't have parameters */
@@ -1074,7 +1073,7 @@ setup_tlist(char *attname, Oid relid)
 						 0,
 						 (Oid) 0,
 						 0);
-	varnode = makeVar(-1, attno, typeid, -1, attno);
+	varnode = makeVar(-1, attno, typeid, 0, -1, attno);
 
 	tle = makeNode(TargetEntry);
 	tle->resdom = resnode;
@@ -1101,7 +1100,7 @@ setup_base_tlist(Oid typeid)
 						 0,
 						 (Oid) 0,
 						 0);
-	varnode = makeVar(-1, 1, typeid, -1, 1);
+	varnode = makeVar(-1, 1, typeid, 0, -1, 1);
 	tle = makeNode(TargetEntry);
 	tle->resdom = resnode;
 	tle->expr = (Node *) varnode;
diff --git a/src/backend/parser/parse_node.c b/src/backend/parser/parse_node.c
index ffcafcedb11fd00622be340c0272912d9510bf57..02e5108752643947577754a6198f3d3512426d8c 100644
--- a/src/backend/parser/parse_node.c
+++ b/src/backend/parser/parse_node.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/parser/parse_node.c,v 1.9 1998/01/20 05:04:21 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/parser/parse_node.c,v 1.10 1998/01/20 22:11:57 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -239,27 +239,24 @@ make_op(char *opname, Node *ltree, Node *rtree)
 }
 
 Var		   *
-make_var(ParseState *pstate, char *refname, char *attrname, Oid *type_id)
+make_var(ParseState *pstate, Oid relid, char *refname,
+				char *attrname, Oid *type_id)
 {
 	Var		   *varnode;
 	int			vnum,
 				attid;
 	Oid			vartypeid;
-	RangeTblEntry *rte;
+	int			sublevels_up;
 
-	rte = refnameRangeTableEntry(pstate->p_rtable, refname);
-	if (rte == NULL)
-		rte = addRangeTableEntry(pstate, refname, refname, FALSE, FALSE);
+	vnum = refnameRangeTablePosn(pstate, refname, &sublevels_up);
 
-	vnum = refnameRangeTablePosn(pstate->p_rtable, refname);
-
-	attid = get_attnum(rte->relid, attrname);
+	attid = get_attnum(relid, attrname);
 	if (attid == InvalidAttrNumber)
 		elog(ERROR, "Relation %s does not have attribute %s",
-			 rte->relname, attrname);
-	vartypeid = get_atttype(rte->relid, attid);
+			 refname, attrname);
+	vartypeid = get_atttype(relid, attid);
 
-	varnode = makeVar(vnum, attid, vartypeid, vnum, attid);
+	varnode = makeVar(vnum, attid, vartypeid, sublevels_up, vnum, attid);
 	*type_id = vartypeid;
 
 	return varnode;
diff --git a/src/backend/parser/parse_relation.c b/src/backend/parser/parse_relation.c
index 5009b0326bdadffcd96ca01eecd3c609c30d877a..f4078c9dfaf72eb5287d81d31608b90709b9c955 100644
--- a/src/backend/parser/parse_relation.c
+++ b/src/backend/parser/parse_relation.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/parser/parse_relation.c,v 1.7 1998/01/20 05:04:24 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/parser/parse_relation.c,v 1.8 1998/01/20 22:12:01 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -67,35 +67,57 @@ static char *attnum_type[SPECIALS] = {
 
 /* given refname, return a pointer to the range table entry */
 RangeTblEntry *
-refnameRangeTableEntry(List *rtable, char *refname)
+refnameRangeTableEntry(ParseState *pstate, char *refname)
 {
 	List	   *temp;
 
-	foreach(temp, rtable)
+	while (pstate != NULL)
 	{
-		RangeTblEntry *rte = lfirst(temp);
-
-		if (!strcmp(rte->refname, refname))
-			return rte;
+		foreach(temp, pstate->p_rtable)
+		{
+			RangeTblEntry *rte = lfirst(temp);
+	
+			if (!strcmp(rte->refname, refname))
+				return rte;
+		}
+		/* only allow correlated columns in WHERE clause */
+		if (pstate->p_in_where_clause)
+			pstate = pstate->parentParseState;
+		else	break;
 	}
 	return NULL;
 }
 
 /* given refname, return id of variable; position starts with 1 */
 int
-refnameRangeTablePosn(List *rtable, char *refname)
+refnameRangeTablePosn(ParseState *pstate, char *refname, int *sublevels_up)
 {
 	int			index;
 	List	   *temp;
 
-	index = 1;
-	foreach(temp, rtable)
-	{
-		RangeTblEntry *rte = lfirst(temp);
+	
+	if (sublevels_up)
+		*sublevels_up = 0;
 
-		if (!strcmp(rte->refname, refname))
-			return index;
-		index++;
+	while (pstate != NULL)
+	{
+		index = 1;
+		foreach(temp, pstate->p_rtable)
+		{
+			RangeTblEntry *rte = lfirst(temp);
+	
+			if (!strcmp(rte->refname, refname))
+				return index;
+			index++;
+		}
+		/* only allow correlated columns in WHERE clause */
+		if (pstate->p_in_where_clause)
+		{
+			pstate = pstate->parentParseState;
+			if (sublevels_up)
+				(*sublevels_up)++;
+		}
+		else	break;
 	}
 	return 0;
 }
@@ -110,31 +132,38 @@ colnameRangeTableEntry(ParseState *pstate, char *colname)
 	List	   *rtable;
 	RangeTblEntry *rte_result;
 
-	if (pstate->p_is_rule)
-		rtable = lnext(lnext(pstate->p_rtable));
-	else
-		rtable = pstate->p_rtable;
-
 	rte_result = NULL;
-	foreach(et, rtable)
+	while (pstate != NULL)
 	{
-		RangeTblEntry *rte = lfirst(et);
-
-		/* only entries on outer(non-function?) scope */
-		if (!rte->inFromCl && rte != pstate->p_target_rangetblentry)
-			continue;
+		if (pstate->p_is_rule)
+			rtable = lnext(lnext(pstate->p_rtable));
+		else
+			rtable = pstate->p_rtable;
 
-		if (get_attnum(rte->relid, colname) != InvalidAttrNumber)
+		foreach(et, rtable)
 		{
-			if (rte_result != NULL)
+			RangeTblEntry *rte = lfirst(et);
+	
+			/* only entries on outer(non-function?) scope */
+			if (!rte->inFromCl && rte != pstate->p_target_rangetblentry)
+				continue;
+	
+			if (get_attnum(rte->relid, colname) != InvalidAttrNumber)
 			{
-				if (!pstate->p_is_insert ||
-					rte != pstate->p_target_rangetblentry)
-					elog(ERROR, "Column %s is ambiguous", colname);
+				if (rte_result != NULL)
+				{
+					if (!pstate->p_is_insert ||
+						rte != pstate->p_target_rangetblentry)
+						elog(ERROR, "Column %s is ambiguous", colname);
+				}
+				else
+					rte_result = rte;
 			}
-			else
-				rte_result = rte;
 		}
+		/* only allow correlated columns in WHERE clause */
+		if (pstate->p_in_where_clause && rte_result == NULL)
+			pstate = pstate->parentParseState;
+		else	break;
 	}
 	return rte_result;
 }
@@ -152,11 +181,15 @@ addRangeTableEntry(ParseState *pstate,
 {
 	Relation	relation;
 	RangeTblEntry *rte = makeNode(RangeTblEntry);
+	int	sublevels_up;
 
-	if (pstate != NULL &&
-		refnameRangeTableEntry(pstate->p_rtable, refname) != NULL)
-		elog(ERROR, "Table name %s specified more than once", refname);
-
+	if (pstate != NULL)
+	{
+		if (refnameRangeTablePosn(pstate, refname, &sublevels_up) != 0 &&
+		   (!inFromCl || sublevels_up == 0))
+			elog(ERROR, "Table name %s specified more than once", refname);
+	}
+	
 	rte->relname = pstrdup(relname);
 	rte->refname = pstrdup(refname);
 
@@ -191,7 +224,6 @@ addRangeTableEntry(ParseState *pstate,
 /*
  * expandAll -
  *	  makes a list of attributes
- *	  assumes reldesc caching works
  */
 List	   *
 expandAll(ParseState *pstate, char *relname, char *refname, int *this_resno)
@@ -206,7 +238,7 @@ expandAll(ParseState *pstate, char *relname, char *refname, int *this_resno)
 	int			type_len;
 	RangeTblEntry *rte;
 
-	rte = refnameRangeTableEntry(pstate->p_rtable, refname);
+	rte = refnameRangeTableEntry(pstate, refname);
 	if (rte == NULL)
 		rte = addRangeTableEntry(pstate, relname, refname, FALSE, FALSE);
 
@@ -225,7 +257,8 @@ expandAll(ParseState *pstate, char *relname, char *refname, int *this_resno)
 		TargetEntry *te = makeNode(TargetEntry);
 
 		attrname = pstrdup((rdesc->rd_att->attrs[varattno]->attname).data);
-		varnode = (Var *) make_var(pstate, refname, attrname, &type_id);
+		varnode = (Var *) make_var(pstate, rte->relid, refname,
+													attrname, &type_id);
 		type_len = (int) typeLen(typeidType(type_id));
 
 		handleTargetColname(pstate, &resname, refname, attrname);
@@ -381,7 +414,7 @@ checkTargetTypes(ParseState *pstate, char *target_colname,
 		return;
 
 	if (refname != NULL)
-		rte = refnameRangeTableEntry(pstate->p_rtable, refname);
+		rte = refnameRangeTableEntry(pstate, refname);
 	else
 	{
 		rte = colnameRangeTableEntry(pstate, colname);
diff --git a/src/include/nodes/makefuncs.h b/src/include/nodes/makefuncs.h
index 57583f6773be441a923c242514c5fe3f8226ea30..6345b6002496037b3fefa7cdae88cd17b29ecdcc 100644
--- a/src/include/nodes/makefuncs.h
+++ b/src/include/nodes/makefuncs.h
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: makefuncs.h,v 1.5 1997/09/08 02:37:15 momjian Exp $
+ * $Id: makefuncs.h,v 1.6 1998/01/20 22:12:13 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -27,6 +27,7 @@ extern Var *
 makeVar(Index varno,
 		AttrNumber varattno,
 		Oid vartype,
+		Index varlevelsup,
 		Index varnoold,
 		AttrNumber varoattno);
 
diff --git a/src/include/nodes/primnodes.h b/src/include/nodes/primnodes.h
index 92c2ab00f399adc79811f8df07033d89de59a429..af370b893c705debe594334dd98af7553967ce85 100644
--- a/src/include/nodes/primnodes.h
+++ b/src/include/nodes/primnodes.h
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: primnodes.h,v 1.15 1998/01/19 18:11:10 momjian Exp $
+ * $Id: primnodes.h,v 1.16 1998/01/20 22:12:14 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -104,6 +104,7 @@ typedef struct Expr
  *						  (could be INNER or OUTER)
  *		varattno		- attribute number of this var, or zero for all
  *		vartype			- pg_type tuple oid for the type of this var
+ *		varlevelsup		- for subquery variables referencing outer relations
  *		varnoold		- keep varno around in case it got changed to INNER/
  *						  OUTER (see match_varid)
  *		varoattno		- attribute number of this var
@@ -122,6 +123,7 @@ typedef struct Var
 	Index		varno;
 	AttrNumber	varattno;
 	Oid			vartype;
+	Index		varlevelsup;	/* erased by upper optimizer */
 	Index		varnoold;		/* only used by optimizer */
 	AttrNumber	varoattno;		/* only used by optimizer */
 } Var;
diff --git a/src/include/parser/parse_node.h b/src/include/parser/parse_node.h
index f09c7d0f86e50688bad3b0cd09687683d8cd92da..50580f103661d6df33eff7ebd005395b3e03f86a 100644
--- a/src/include/parser/parse_node.h
+++ b/src/include/parser/parse_node.h
@@ -5,7 +5,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: parse_node.h,v 1.6 1998/01/19 05:06:41 momjian Exp $
+ * $Id: parse_node.h,v 1.7 1998/01/20 22:12:16 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -45,7 +45,8 @@ typedef struct ParseState
 
 extern ParseState *make_parsestate(ParseState *parentParseState);
 extern Expr *make_op(char *opname, Node *ltree, Node *rtree);
-extern Var *make_var(ParseState *pstate, char *refname, char *attrname, Oid *type_id);
+extern Var *make_var(ParseState *pstate, Oid relid, char *refname,
+										char *attrname, Oid *type_id);
 extern ArrayRef   *make_array_ref(Node *expr,
 			   List *indirection);
 extern ArrayRef   *make_array_set(Expr *target_expr,
diff --git a/src/include/parser/parse_relation.h b/src/include/parser/parse_relation.h
index eab72589ff57de996303c2fb90a9cf5296badc69..506fdad46b7c5214e1c408965396033f839f9c0d 100644
--- a/src/include/parser/parse_relation.h
+++ b/src/include/parser/parse_relation.h
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: parse_relation.h,v 1.5 1998/01/20 05:04:56 momjian Exp $
+ * $Id: parse_relation.h,v 1.6 1998/01/20 22:12:17 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -20,8 +20,9 @@
 #include <parser/parse_node.h>
 #include <utils/rel.h>
 
-extern RangeTblEntry *refnameRangeTableEntry(List *rtable, char *refname);
-extern int refnameRangeTablePosn(List *rtable, char *refname);
+extern RangeTblEntry *refnameRangeTableEntry(ParseState *pstate, char *refname);
+extern int refnameRangeTablePosn(ParseState *pstate,
+										char *refname, int *sublevels_up);
 extern RangeTblEntry *colnameRangeTableEntry(ParseState *pstate, char *colname);
 extern RangeTblEntry *addRangeTableEntry(ParseState *pstate,
 								   char *relname,