diff --git a/src/backend/access/common/tupdesc.c b/src/backend/access/common/tupdesc.c
index 04622a1362a112f65748820e5554676a8c0c295d..1a8d2975cc4ccb8618e3d2244b1f553a01b67565 100644
--- a/src/backend/access/common/tupdesc.c
+++ b/src/backend/access/common/tupdesc.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/access/common/tupdesc.c,v 1.28 1997/11/24 05:07:42 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/access/common/tupdesc.c,v 1.29 1997/11/25 21:58:35 momjian Exp $
  *
  * NOTES
  *	  some of the executor utility code such as "ExecTypeFromTL" should be
@@ -20,8 +20,9 @@
 
 #include <postgres.h>
 
-#include <parser/catalog_utils.h>
+#include <catalog/pg_type.h>
 #include <nodes/parsenodes.h>
+#include <parser/parse_type.h>
 #include <utils/builtins.h>
 #include <utils/fcache.h>
 #include <utils/syscache.h>
@@ -377,10 +378,10 @@ TupleDescInitEntry(TupleDesc desc,
 	   */
 	if (attisset)
 	{
-		Type		t = type("oid");
+		Type		t = typeidType(OIDOID);
 
-		att->attlen = tlen(t);
-		att->attbyval = tbyval(t);
+		att->attlen = typeLen(t);
+		att->attbyval = typeByVal(t);
 	}
 	else
 	{
@@ -410,12 +411,12 @@ TupleDescMakeSelfReference(TupleDesc desc,
 						   char *relname)
 {
 	AttributeTupleForm att;
-	Type		t = type("oid");
+	Type		t = typeidType(OIDOID);
 
 	att = desc->attrs[attnum - 1];
 	att->atttypid = TypeShellMake(relname);
-	att->attlen = tlen(t);
-	att->attbyval = tbyval(t);
+	att->attlen = typeLen(t);
+	att->attbyval = typeByVal(t);
 	att->attnelems = 0;
 }
 
diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c
index 6a150a01b22a411038eaf09a80c2a8f684c4ad8b..512e2a0fe31b2500d7895b10e73a99865224aede 100644
--- a/src/backend/catalog/heap.c
+++ b/src/backend/catalog/heap.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.33 1997/11/24 05:08:07 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.34 1997/11/25 21:58:40 momjian Exp $
  *
  * INTERFACE ROUTINES
  *		heap_creatr()			- Create an uncataloged heap relation
@@ -42,11 +42,12 @@
 #include <catalog/pg_attrdef.h>
 #include <catalog/pg_relcheck.h>
 #include <commands/trigger.h>
+#include <parser/parse_expr.h>
+#include <parser/parse_node.h>
+#include <parser/parse_type.h>
 #include <storage/bufmgr.h>
 #include <storage/lmgr.h>
 #include <storage/smgr.h>
-#include <parser/catalog_utils.h>
-#include <parser/parse_query.h>
 #include <rewrite/rewriteRemove.h>
 #include <utils/builtins.h>
 #include <utils/mcxt.h>
@@ -722,8 +723,8 @@ addNewRelationType(char *typeName, Oid new_rel_oid)
 	 */
 	new_type_oid = TypeCreate(typeName, /* type name */
 							  new_rel_oid,		/* relation oid */
-							  tlen(type("oid")),		/* internal size */
-							  tlen(type("oid")),		/* external size */
+							  typeLen(typeidType(OIDOID)),	/* internal size */
+							  typeLen(typeidType(OIDOID)),	/* external size */
 							  'c',		/* type-type (catalog) */
 							  ',',		/* default array delimiter */
 							  "int4in", /* input procedure */
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index 418123a0aa5979e9ad4907b4b6fc056f7b3ced7e..deb908e24f80b1f2d1fd8b93ced5930db332e061 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.29 1997/11/24 05:08:11 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.30 1997/11/25 21:58:43 momjian Exp $
  *
  *
  * INTERFACE ROUTINES
@@ -30,26 +30,27 @@
 #include <fmgr.h>
 #include <access/genam.h>
 #include <access/heapam.h>
-#include <storage/lmgr.h>
-#include <miscadmin.h>
+#include <access/istrat.h>
 #include <access/xact.h>
-#include <parser/catalog_utils.h>
-#include <storage/smgr.h>
-#include <utils/builtins.h>
-#include <utils/mcxt.h>
-#include <utils/relcache.h>
-#include <utils/syscache.h>
-#include <utils/tqual.h>
 #include <bootstrap/bootstrap.h>
 #include <catalog/catname.h>
 #include <catalog/catalog.h>
 #include <catalog/indexing.h>
 #include <catalog/heap.h>
 #include <catalog/index.h>
+#include <catalog/pg_type.h>
 #include <executor/executor.h>
+#include <miscadmin.h>
 #include <optimizer/clauses.h>
 #include <optimizer/prep.h>
-#include <access/istrat.h>
+#include <parser/parse_func.h>
+#include <storage/lmgr.h>
+#include <storage/smgr.h>
+#include <utils/builtins.h>
+#include <utils/mcxt.h>
+#include <utils/relcache.h>
+#include <utils/syscache.h>
+#include <utils/tqual.h>
 
 #ifndef HAVE_MEMMOVE
 #include <regex/utils.h>
diff --git a/src/backend/catalog/pg_operator.c b/src/backend/catalog/pg_operator.c
index a4b4919417e3b689bb5e3b39937fa8d30a6e02b7..bbdd23701ade6e0d21b32c46e6a6f6dd0843c2f5 100644
--- a/src/backend/catalog/pg_operator.c
+++ b/src/backend/catalog/pg_operator.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/catalog/pg_operator.c,v 1.16 1997/11/24 05:08:15 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/catalog/pg_operator.c,v 1.17 1997/11/25 21:58:46 momjian Exp $
  *
  * NOTES
  *	  these routines moved here from commands/define.c and somewhat cleaned up.
@@ -20,9 +20,10 @@
 #include <utils/syscache.h>
 #include <utils/tqual.h>
 #include <access/heapam.h>
-#include <parser/catalog_utils.h>
 #include <catalog/catname.h>
 #include <catalog/pg_operator.h>
+#include <catalog/pg_type.h>
+#include <parser/parse_oper.h>
 #include <storage/bufmgr.h>
 #include <fmgr.h>
 #include <miscadmin.h>
diff --git a/src/backend/catalog/pg_proc.c b/src/backend/catalog/pg_proc.c
index 9cbf4e3d7c7aa6c620e8e1361631bd1136b93214..e08bb549c61bd326468c28b6aa8e2a954461d9aa 100644
--- a/src/backend/catalog/pg_proc.c
+++ b/src/backend/catalog/pg_proc.c
@@ -7,28 +7,28 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.9 1997/09/18 20:20:18 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.10 1997/11/25 21:58:48 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
 #include <postgres.h>
 
+#include <fmgr.h>
+#include <miscadmin.h>
 #include <utils/syscache.h>
 #include <catalog/pg_proc.h>
 #include <access/heapam.h>
 #include <access/relscan.h>
-#include <fmgr.h>
-#include <utils/builtins.h>
-#include <utils/sets.h>
 #include <catalog/catname.h>
 #include <catalog/indexing.h>
-#include <parser/parse_query.h>
+#include <catalog/pg_type.h>
+#include <parser/parse_node.h>
 #include <tcop/tcopprot.h>
-#include <parser/catalog_utils.h>
+#include <utils/builtins.h>
+#include <utils/sets.h>
+#include <utils/lsyscache.h>
 #include <optimizer/internal.h>
 #include <optimizer/planner.h>
-#include <utils/lsyscache.h>
-#include <miscadmin.h>
 #ifndef HAVE_MEMMOVE
 #include <regex/utils.h>
 #else
@@ -200,7 +200,7 @@ ProcedureCreate(char *procedureName,
 	if (parameterCount == 1 &&
 		(toid = TypeGet(strVal(lfirst(argList)), &defined)) &&
 		defined &&
-		(relid = typeid_get_relid(toid)) != 0 &&
+		(relid = typeidTypeRelid(toid)) != 0 &&
 		get_attnum(relid, procedureName) != InvalidAttrNumber)
 		elog(WARN, "method %s already an attribute of type %s",
 			 procedureName, strVal(lfirst(argList)));
diff --git a/src/backend/catalog/pg_type.c b/src/backend/catalog/pg_type.c
index 2dc80bbbe002ec4da346d07f53e12379caa9d18e..1cd0fa936c8c83b033d21c74714e3df6b6134a78 100644
--- a/src/backend/catalog/pg_type.c
+++ b/src/backend/catalog/pg_type.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/catalog/pg_type.c,v 1.13 1997/11/24 05:08:17 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/catalog/pg_type.c,v 1.14 1997/11/25 21:58:50 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -20,9 +20,10 @@
 #include <utils/builtins.h>
 #include <utils/tqual.h>
 #include <fmgr.h>
-#include <parser/catalog_utils.h>
 #include <catalog/catname.h>
 #include <catalog/indexing.h>
+#include <catalog/pg_type.h>
+#include <parser/parse_func.h>
 #include <storage/lmgr.h>
 #include <miscadmin.h>
 #ifndef HAVE_MEMMOVE
diff --git a/src/backend/commands/_deadcode/version.c b/src/backend/commands/_deadcode/version.c
index 0059405767209fcd54d73c2e8df1d1c8530520f8..829f9241ee8cfc4b1b57060dc67e8b09250d3799 100644
--- a/src/backend/commands/_deadcode/version.c
+++ b/src/backend/commands/_deadcode/version.c
@@ -10,7 +10,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/commands/_deadcode/Attic/version.c,v 1.7 1997/09/08 02:22:18 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/_deadcode/Attic/version.c,v 1.8 1997/11/25 21:59:11 momjian Exp $
  *
  * NOTES
  *	  At the point the version is defined, 2 physical relations are created
@@ -30,6 +30,7 @@
 #include <utils/builtins.h>
 #include <commands/version.h>
 #include <access/xact.h>		/* for GetCurrentXactStartTime */
+#include <parser/parse_node.h>
 #include <tcop/tcopprot.h>
 
 #define MAX_QUERY_LEN 1024
diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c
index c0a74122765d657fc0594ac168dbfdc5acbd21b5..5c2c1a28597bea36f487144ae3e484487e93bb08 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.14 1997/09/18 20:20:22 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/explain.c,v 1.15 1997/11/25 21:58:53 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -16,12 +16,11 @@
 
 #include <postgres.h>
 
-#include <parser/catalog_utils.h>
-#include <parser/parse_query.h> /* for MakeTimeRange() */
 #include <nodes/plannodes.h>
 #include <tcop/tcopprot.h>
 #include <lib/stringinfo.h>
 #include <commands/explain.h>
+#include <parser/parse_node.h>
 #include <optimizer/planner.h>
 #include <access/xact.h>
 
diff --git a/src/backend/commands/recipe.c b/src/backend/commands/recipe.c
index 9e5d2819e06b87a4a9db684ea98bdca9ee5a01af..5b77b732a8827765308d2acb648d6769e8dec020 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.12 1997/11/21 18:09:51 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/Attic/recipe.c,v 1.13 1997/11/25 21:59:00 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -20,9 +20,9 @@
 #include <catalog/pg_type.h>
 #include <commands/recipe.h>
 #include <libpq/libpq-be.h>
+#include <parser/parse_node.h>
 #include <utils/builtins.h>
 #include <utils/relcache.h>		/* for RelationNameGetRelation */
-#include <parser/parse_query.h>
 #include <rewrite/rewriteHandler.h>
 #include <rewrite/rewriteManip.h>
 #include <tcop/pquery.h>
@@ -488,7 +488,7 @@ tg_replaceNumberedParam(Node *expression,
 						 * "result" attribute from the tee relation
 						 */
 
-						isRel = (typeid_get_relid(p->paramtype) != 0);
+						isRel = (typeidTypeRelid(p->paramtype) != 0);
 						if (isRel)
 						{
 							newVar = makeVar(rt_ind,
diff --git a/src/backend/commands/remove.c b/src/backend/commands/remove.c
index aaf2127e460bd0aa8636907ce09bbb4967b50ddf..3bfdfb09629fb692e1fde46a54396dc550de4819 100644
--- a/src/backend/commands/remove.c
+++ b/src/backend/commands/remove.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/commands/Attic/remove.c,v 1.16 1997/11/20 23:21:13 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/Attic/remove.c,v 1.17 1997/11/25 21:59:03 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -24,7 +24,8 @@
 #include <catalog/pg_language.h>
 #include <catalog/pg_operator.h>
 #include <catalog/pg_proc.h>
-#include <parser/catalog_utils.h>
+#include <catalog/pg_type.h>
+#include <parser/parse_func.h>
 #include <storage/bufmgr.h>
 #include <fmgr.h>
 #ifndef HAVE_MEMMOVE
diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 7ae8fa1256d0de9384b7f80bd36ffe099fbae61c..2de53600ceb8f1a9049704fc656a30765b948113 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.52 1997/11/21 19:59:34 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.53 1997/11/25 21:59:09 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -36,6 +36,7 @@
 #include <catalog/pg_statistic.h>
 #include <catalog/pg_type.h>
 #include <catalog/pg_operator.h>
+#include <parser/parse_oper.h>
 #include <storage/smgr.h>
 #include <storage/lmgr.h>
 #include <utils/inval.h>
@@ -44,7 +45,6 @@
 #include <utils/syscache.h>
 #include <utils/builtins.h>
 #include <commands/vacuum.h>
-#include <parser/catalog_utils.h>
 #include <storage/bufpage.h>
 #include "storage/shmem.h"
 #ifndef HAVE_GETRUSAGE
diff --git a/src/backend/commands/view.c b/src/backend/commands/view.c
index 64b4de2ef4b15148b04af7492bd30f30432f58ba..a752e3020c88000de813ad365acddddcdbb59dca 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.15 1997/11/21 18:09:58 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/view.c,v 1.16 1997/11/25 21:59:12 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -21,8 +21,8 @@
 #include <access/xact.h>
 #include <utils/builtins.h>
 #include <nodes/relation.h>
-#include <parser/catalog_utils.h>
-#include <parser/parse_query.h>
+#include <parser/parse_relation.h>
+#include <parser/parse_type.h>
 #include <rewrite/rewriteDefine.h>
 #include <rewrite/rewriteHandler.h>
 #include <rewrite/rewriteManip.h>
@@ -72,7 +72,7 @@ DefineVirtualRelation(char *relname, List *tlist)
 			entry = lfirst(t);
 			res = entry->resdom;
 			resname = res->resname;
-			restypename = tname(get_id_type(res->restype));
+			restypename = typeidTypeName(res->restype);
 
 			typename = makeNode(TypeName);
 
diff --git a/src/backend/executor/execTuples.c b/src/backend/executor/execTuples.c
index f513354e4958aeb738a4ff28a1a088be3d5dcac9..d541f29d9ec730575d4336d2b9e2b4e279202596 100644
--- a/src/backend/executor/execTuples.c
+++ b/src/backend/executor/execTuples.c
@@ -14,7 +14,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/executor/execTuples.c,v 1.10 1997/09/18 20:20:32 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/executor/execTuples.c,v 1.11 1997/11/25 21:59:16 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -125,11 +125,11 @@
 #undef ExecStoreTuple
 
 #include "access/tupdesc.h"
+#include "catalog/pg_type.h"
+#include "parser/parse_type.h"
+#include "storage/bufmgr.h"
 #include "utils/palloc.h"
 #include "utils/lsyscache.h"
-#include "storage/bufmgr.h"
-#include "parser/catalog_utils.h"
-#include "catalog/pg_type.h"
 
 static TupleTableSlot *NodeGetResultTupleSlot(Plan *node);
 
diff --git a/src/backend/executor/functions.c b/src/backend/executor/functions.c
index a2f143d862c4f6d1a4e99a9241ab3bd7d08967c4..2f0e0b91e202133cf5d91c87c5c6111cd4837d09 100644
--- a/src/backend/executor/functions.c
+++ b/src/backend/executor/functions.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/executor/functions.c,v 1.12 1997/09/18 20:20:37 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/executor/functions.c,v 1.13 1997/11/25 21:59:19 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -21,7 +21,6 @@
 #include "nodes/plannodes.h"
 
 #include "catalog/pg_proc.h"
-#include "parser/parse_query.h"
 #include "tcop/pquery.h"
 #include "tcop/tcopprot.h"
 #include "tcop/utility.h"
diff --git a/src/backend/executor/nodeAgg.c b/src/backend/executor/nodeAgg.c
index b9d7999573f6cdbe474ae7720f16920d7ae632ba..accc7b1fb7c07db54fee0ffe9f328b8b61371b11 100644
--- a/src/backend/executor/nodeAgg.c
+++ b/src/backend/executor/nodeAgg.c
@@ -23,12 +23,12 @@
 #include "access/heapam.h"
 #include "catalog/pg_aggregate.h"
 #include "catalog/catalog.h"
+#include "parser/parse_type.h"
 #include "executor/executor.h"
 #include "executor/nodeAgg.h"
 #include "storage/bufmgr.h"
 #include "utils/palloc.h"
 #include "utils/syscache.h"
-#include "parser/catalog_utils.h"
 
 /*
  * AggFuncInfo -
@@ -172,7 +172,7 @@ ExecAgg(Agg *node)
 		if (!HeapTupleIsValid(aggTuple))
 			elog(WARN, "ExecAgg: cache lookup failed for aggregate \"%s\"(%s)",
 				 aggname,
-				 tname(get_id_type(agg->basetype)));
+				 typeidTypeName(agg->basetype));
 		aggp = (Form_pg_aggregate) GETSTRUCT(aggTuple);
 
 		xfn1_oid = aggp->aggtransfn1;
diff --git a/src/backend/executor/spi.c b/src/backend/executor/spi.c
index 16a8ee3212834d9eaf1d76259af1833e798d2151..f954dbe432ee4f4966b741880282b29322ba8c25 100644
--- a/src/backend/executor/spi.c
+++ b/src/backend/executor/spi.c
@@ -6,6 +6,7 @@
  *-------------------------------------------------------------------------
  */
 #include "executor/spi.h"
+#include "catalog/pg_type.h"
 #include "access/printtup.h"
 #include "fmgr.h"
 
diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c
index 62b72ab8344f0eed527309222b1050ed73bd2091..5d848df5ab46cc20f77043aa0e4df4b272cdec45 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.15 1997/11/20 23:21:40 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.16 1997/11/25 21:59:40 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -22,7 +22,6 @@
 #include "nodes/parsenodes.h"
 #include "nodes/primnodes.h"
 #include "nodes/relation.h"
-#include "parser/parse_query.h"
 
 #include "utils/syscache.h"
 #include "utils/builtins.h"		/* for namecpy */
diff --git a/src/backend/nodes/print.c b/src/backend/nodes/print.c
index d674263a32480fe52d0264bf111fc2b14aa17ae2..6b62064de9edd2e24589f549afa68abf95d1f081 100644
--- a/src/backend/nodes/print.c
+++ b/src/backend/nodes/print.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/nodes/print.c,v 1.10 1997/10/25 01:09:28 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/nodes/print.c,v 1.11 1997/11/25 21:59:44 momjian Exp $
  *
  * HISTORY
  *	  AUTHOR			DATE			MAJOR EVENT
@@ -26,11 +26,11 @@
 #include "nodes/parsenodes.h"
 #include "nodes/print.h"
 #include "parser/parsetree.h"
-#include "parser/catalog_utils.h"
 #include "access/heapam.h"
 #include "utils/lsyscache.h"
 #include "nodes/nodes.h"
 #include "nodes/plannodes.h"
+#include "parser/parse_relation.h"
 #include "optimizer/clauses.h"
 
 static char *plannode_type(Plan *p);
@@ -194,7 +194,7 @@ print_expr(Node *expr, List *rtable)
 					r = heap_openr(relname);
 					if (rt->refname)
 						relname = rt->refname;	/* table renamed */
-					attname = getAttrName(r, var->varattno);
+					attname = attnumAttName(r, var->varattno);
 					heap_close(r);
 				}
 				break;
diff --git a/src/backend/optimizer/path/xfunc.c b/src/backend/optimizer/path/xfunc.c
index 39d41319798d0e2cd56e98a79f4b09dec320b780..0f6894eec485d8f15784f0363e82ee911ed79479 100644
--- a/src/backend/optimizer/path/xfunc.c
+++ b/src/backend/optimizer/path/xfunc.c
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/optimizer/path/Attic/xfunc.c,v 1.6 1997/09/08 21:45:10 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/optimizer/path/Attic/xfunc.c,v 1.7 1997/11/25 21:59:50 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -641,10 +641,10 @@ xfunc_width(LispValue clause)
 	}
 	else if (IsA(clause, Param))
 	{
-		if (typeid_get_relid(get_paramtype((Param) clause)))
+		if (typeidTypeRelid(get_paramtype((Param) clause)))
 		{
 			/* Param node returns a tuple.	Find its width */
-			rd = heap_open(typeid_get_relid(get_paramtype((Param) clause)));
+			rd = heap_open(typeidTypeRelid(get_paramtype((Param) clause)));
 			retval = xfunc_tuple_width(rd);
 			heap_close(rd);
 		}
@@ -659,7 +659,7 @@ xfunc_width(LispValue clause)
 		else
 		{
 			/* Param node returns a base type */
-			retval = tlen(get_id_type(get_paramtype((Param) clause)));
+			retval = typeLen(typeidType(get_paramtype((Param) clause)));
 		}
 		goto exit;
 	}
@@ -1324,9 +1324,9 @@ xfunc_func_width(RegProcedure funcid, LispValue args)
 	proc = (Form_pg_proc) GETSTRUCT(tupl);
 
 	/* if function returns a tuple, get the width of that */
-	if (typeid_get_relid(proc->prorettype))
+	if (typeidTypeRelid(proc->prorettype))
 	{
-		rd = heap_open(typeid_get_relid(proc->prorettype));
+		rd = heap_open(typeidTypeRelid(proc->prorettype));
 		retval = xfunc_tuple_width(rd);
 		heap_close(rd);
 		goto exit;
diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c
index 11d777e8341aef085fc981e836ed9253a84f02a9..00898ded097b31272f2b8ef6362b12f3ee6aba51 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.15 1997/09/08 21:45:13 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.16 1997/11/25 21:59:56 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -31,7 +31,6 @@
 #include "utils/palloc.h"
 #include "utils/builtins.h"
 
-#include "parser/parse_query.h"
 #include "optimizer/clauseinfo.h"
 #include "optimizer/clauses.h"
 #include "optimizer/planmain.h"
diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
index e10e36bdcd92b4bd7393dfb2551420de1d34aa0c..ceddbbe2d6beacdd924b35c3e3b9ac32a0de231f 100644
--- a/src/backend/optimizer/plan/planner.c
+++ b/src/backend/optimizer/plan/planner.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.10 1997/11/21 18:10:26 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.11 1997/11/25 21:59:59 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -19,9 +19,8 @@
 #include "nodes/plannodes.h"
 #include "nodes/parsenodes.h"
 #include "nodes/relation.h"
+#include "parser/parse_expr.h"
 
-#include "parser/catalog_utils.h"
-#include "parser/parse_query.h"
 #include "utils/elog.h"
 #include "utils/lsyscache.h"
 #include "access/heapam.h"
@@ -310,7 +309,7 @@ pg_checkretval(Oid rettype, QueryTreeList *queryTreeList)
 	}
 
 	/* by here, the function is declared to return some type */
-	if ((typ = (Type) get_id_type(rettype)) == NULL)
+	if ((typ = typeidType(rettype)) == NULL)
 		elog(WARN, "can't find return type %d for function\n", rettype);
 
 	/*
@@ -318,21 +317,21 @@ pg_checkretval(Oid rettype, QueryTreeList *queryTreeList)
 	 * final query had better be a retrieve.
 	 */
 	if (cmd != CMD_SELECT)
-		elog(WARN, "function declared to return type %s, but final query is not a retrieve", tname(typ));
+		elog(WARN, "function declared to return type %s, but final query is not a retrieve", typeTypeName(typ));
 
 	/*
 	 * test 4:	for base type returns, the target list should have exactly
 	 * one entry, and its type should agree with what the user declared.
 	 */
 
-	if (get_typrelid(typ) == InvalidOid)
+	if (typeTypeRelid(typ) == InvalidOid)
 	{
 		if (exec_tlist_length(tlist) > 1)
-			elog(WARN, "function declared to return %s returns multiple values in final retrieve", tname(typ));
+			elog(WARN, "function declared to return %s returns multiple values in final retrieve", typeTypeName(typ));
 
 		resnode = (Resdom *) ((TargetEntry *) lfirst(tlist))->resdom;
 		if (resnode->restype != rettype)
-			elog(WARN, "return type mismatch in function: declared to return %s, returns %s", tname(typ), tname(get_id_type(resnode->restype)));
+			elog(WARN, "return type mismatch in function: declared to return %s, returns %s", typeTypeName(typ), typeidTypeName(resnode->restype));
 
 		/* by here, base return types match */
 		return;
@@ -358,16 +357,16 @@ pg_checkretval(Oid rettype, QueryTreeList *queryTreeList)
 	 * declared return type, and be sure that attributes 1 .. n in the
 	 * target list match the declared types.
 	 */
-	reln = heap_open(get_typrelid(typ));
+	reln = heap_open(typeTypeRelid(typ));
 
 	if (!RelationIsValid(reln))
-		elog(WARN, "cannot open relation relid %d", get_typrelid(typ));
+		elog(WARN, "cannot open relation relid %d", typeTypeRelid(typ));
 
 	relid = reln->rd_id;
 	relnatts = reln->rd_rel->relnatts;
 
 	if (exec_tlist_length(tlist) != relnatts)
-		elog(WARN, "function declared to return type %s does not retrieve (%s.*)", tname(typ), tname(typ));
+		elog(WARN, "function declared to return type %s does not retrieve (%s.*)", typeTypeName(typ), typeTypeName(typ));
 
 	/* expect attributes 1 .. n in order */
 	for (i = 1; i <= relnatts; i++)
@@ -397,14 +396,14 @@ pg_checkretval(Oid rettype, QueryTreeList *queryTreeList)
 			else if (IsA(thenode, Func))
 				tletype = (Oid) get_functype((Func *) thenode);
 			else
-				elog(WARN, "function declared to return type %s does not retrieve (%s.all)", tname(typ), tname(typ));
+				elog(WARN, "function declared to return type %s does not retrieve (%s.all)", typeTypeName(typ), typeTypeName(typ));
 		}
 		else
-			elog(WARN, "function declared to return type %s does not retrieve (%s.all)", tname(typ), tname(typ));
+			elog(WARN, "function declared to return type %s does not retrieve (%s.all)", typeTypeName(typ), typeTypeName(typ));
 #endif
 		/* reach right in there, why don't you? */
 		if (tletype != reln->rd_att->attrs[i - 1]->atttypid)
-			elog(WARN, "function declared to return type %s does not retrieve (%s.all)", tname(typ), tname(typ));
+			elog(WARN, "function declared to return type %s does not retrieve (%s.all)", typeTypeName(typ), typeTypeName(typ));
 	}
 
 	heap_close(reln);
diff --git a/src/backend/optimizer/prep/preptlist.c b/src/backend/optimizer/prep/preptlist.c
index 0010c69d6abe4a7e2d628ca3169f1d65aac03ed9..faf281985e4332810c9a6520451672394e341da4 100644
--- a/src/backend/optimizer/prep/preptlist.c
+++ b/src/backend/optimizer/prep/preptlist.c
@@ -7,13 +7,14 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/optimizer/prep/preptlist.c,v 1.5 1997/09/08 21:45:36 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/optimizer/prep/preptlist.c,v 1.6 1997/11/25 22:00:06 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
 #include <string.h>
 #include "postgres.h"
 
+#include "catalog/pg_type.h"
 #include "nodes/pg_list.h"
 #include "nodes/relation.h"
 #include "nodes/primnodes.h"
@@ -24,9 +25,9 @@
 #include "utils/builtins.h"
 #include "utils/lsyscache.h"
 #include "utils/palloc.h"
+#include "parser/parse_type.h"
 
 #include "parser/parsetree.h"	/* for getrelid() */
-#include "parser/catalog_utils.h"
 
 #include "optimizer/internal.h"
 #include "optimizer/prep.h"
@@ -278,7 +279,7 @@ new_relation_targetlist(Oid relid, Index rt_index, NodeTag node_type)
 		attisset = get_attisset( /* type_id, */ relid, attname);
 		if (attisset)
 		{
-			typlen = tlen(type("oid"));
+			typlen = typeLen(typeidType(OIDOID));
 		}
 		else
 		{
diff --git a/src/backend/optimizer/prep/prepunion.c b/src/backend/optimizer/prep/prepunion.c
index a686f94e01cc63bbad18af2e8702a5137256f98b..00dd4079780f2c72a330e664ae1ff5c3c35d65e5 100644
--- a/src/backend/optimizer/prep/prepunion.c
+++ b/src/backend/optimizer/prep/prepunion.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/optimizer/prep/prepunion.c,v 1.8 1997/11/21 18:10:44 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/optimizer/prep/prepunion.c,v 1.9 1997/11/25 22:00:10 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -22,7 +22,6 @@
 #include "nodes/plannodes.h"
 #include "nodes/relation.h"
 
-#include "parser/parse_query.h"
 #include "parser/parsetree.h"
 
 #include "utils/elog.h"
diff --git a/src/backend/optimizer/util/tlist.c b/src/backend/optimizer/util/tlist.c
index 089633033b154185de0d4d240e3959b7eca09940..aa867f4b5a3845ef8194a036ff844072c0f885e8 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.7 1997/09/08 21:45:55 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/optimizer/util/tlist.c,v 1.8 1997/11/25 22:00:16 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -26,7 +26,6 @@
 #include "optimizer/clauses.h"
 
 #include "nodes/makefuncs.h"
-#include "parser/catalog_utils.h"
 
 static Node *flatten_tlistentry(Node *tlistentry, List *flat_tlist);
 
diff --git a/src/backend/parser/Makefile b/src/backend/parser/Makefile
index 8559100ee3e21c82cb0da5886ae69ea72c15449b..7ab45e4beea8ec2de600d64f38294f5b25b27998 100644
--- a/src/backend/parser/Makefile
+++ b/src/backend/parser/Makefile
@@ -4,7 +4,7 @@
 #    Makefile for parser
 #
 # IDENTIFICATION
-#    $Header: /cvsroot/pgsql/src/backend/parser/Makefile,v 1.11 1997/11/24 05:20:57 momjian Exp $
+#    $Header: /cvsroot/pgsql/src/backend/parser/Makefile,v 1.12 1997/11/25 22:00:21 momjian Exp $
 #
 #-------------------------------------------------------------------------
 
@@ -22,8 +22,9 @@ CFLAGS+= -Wno-error
 endif
 
 
-OBJS= analyze.o catalog_utils.o gram.o \
-      keywords.o parser.o parse_query.o scan.o scansup.o
+OBJS= analyze.o gram.o keywords.o parser.o parse_agg.o parse_clause.o \
+      parse_expr.o parse_func.o parse_node.o parse_oper.o parse_relation.o \
+      parse_type.o parse_target.o scan.o scansup.o
 
 all: SUBSYS.o
 
diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c
index bee5132a8b94062b434e62617b04a40f80236fde..4a3800a8a4ed3af9fe30110dd49d181f1d001d34 100644
--- a/src/backend/parser/analyze.c
+++ b/src/backend/parser/analyze.c
@@ -7,46 +7,30 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.49 1997/11/20 23:22:11 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.50 1997/11/25 22:00:27 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include "postgres.h"
-#include "nodes/nodes.h"
-#include "nodes/params.h"
-#include "nodes/primnodes.h"
-#include "nodes/parsenodes.h"
-#include "nodes/relation.h"
-#include "parse.h"				/* for AND, OR, etc. */
-#include "catalog/pg_aggregate.h"
-#include "catalog/pg_type.h"	/* for INT4OID, etc. */
-#include "catalog/pg_proc.h"
-#include "utils/elog.h"
-#include "utils/builtins.h"		/* namecmp(), textout() */
-#include "utils/lsyscache.h"
-#include "utils/palloc.h"
-#include "utils/mcxt.h"
-#include "utils/syscache.h"
-#include "utils/acl.h"
-#include "parser/parse_query.h"
-#include "parser/parse_state.h"
-#include "nodes/makefuncs.h"	/* for makeResdom(), etc. */
-#include "nodes/nodeFuncs.h"
-#include "commands/sequence.h"
-
-#include "optimizer/clauses.h"
-#include "access/heapam.h"
-
-#include "miscadmin.h"
 
-#include "port-protos.h"		/* strdup() */
+#include "access/heapam.h"
+#include "nodes/makefuncs.h"
+#include "nodes/memnodes.h"
+#include "nodes/pg_list.h"
+#include "parser/analyze.h"
+#include "parser/parse_agg.h"
+#include "parser/parse_node.h"
+#include "parser/parse_relation.h"
+#include "parser/parse_target.h"
+#include "parser/parse_clause.h"
+#include "utils/builtins.h"
+#include "utils/mcxt.h"
 
-/* convert the parse tree into a query tree */
 static Query *transformStmt(ParseState *pstate, Node *stmt);
-
 static Query *transformDeleteStmt(ParseState *pstate, DeleteStmt *stmt);
 static Query *transformInsertStmt(ParseState *pstate, AppendStmt *stmt);
 static Query *transformIndexStmt(ParseState *pstate, IndexStmt *stmt);
@@ -55,74 +39,7 @@ static Query *transformRuleStmt(ParseState *query, RuleStmt *stmt);
 static Query *transformSelectStmt(ParseState *pstate, RetrieveStmt *stmt);
 static Query *transformUpdateStmt(ParseState *pstate, ReplaceStmt *stmt);
 static Query *transformCursorStmt(ParseState *pstate, CursorStmt *stmt);
-static Node *handleNestedDots(ParseState *pstate, Attr *attr, int *curr_resno);
-
-#define EXPR_COLUMN_FIRST	 1
-#define EXPR_RELATION_FIRST  2
-static Node *transformExpr(ParseState *pstate, Node *expr, int precedence);
-static Node *transformIdent(ParseState *pstate, Node *expr, int precedence);
-
-static void makeRangeTable(ParseState *pstate, char *relname, List *frmList);
-static List *expandAllTables(ParseState *pstate);
-static char *figureColname(Node *expr, Node *resval);
-static List *makeTargetNames(ParseState *pstate, List *cols);
-static List *transformTargetList(ParseState *pstate, List *targetlist);
-static TargetEntry *make_targetlist_expr(ParseState *pstate,
-					 char *colname, Node *expr,
-					 List *arrayRef);
-static bool inWhereClause = false;
-static Node *transformWhereClause(ParseState *pstate, Node *a_expr);
-static List *transformGroupClause(ParseState *pstate, List *grouplist,
-					 List *targetlist);
-static List *transformSortClause(ParseState *pstate,
-					List *orderlist, List *targetlist,
-					char *uniqueFlag);
-
-static void parseFromClause(ParseState *pstate, List *frmList);
-static Node *ParseFunc(ParseState *pstate, char *funcname,
-		  List *fargs, int *curr_resno);
-static List *setup_tlist(char *attname, Oid relid);
-static List *setup_base_tlist(Oid typeid);
-static void make_arguments(int nargs, List *fargs, Oid *input_typeids,
-			   Oid *function_typeids);
-static void AddAggToParseState(ParseState *pstate, Aggreg *aggreg);
-static void finalizeAggregates(ParseState *pstate, Query *qry);
-static void parseCheckAggregates(ParseState *pstate, Query *qry);
-static ParseState *makeParseState(void);
-static Node *parser_typecast(Value *expr, TypeName *typename, int typlen);
-static Node *parser_typecast2(Node *expr, Oid exprType, Type tp, int typlen);
-static Aggreg *ParseAgg(char *aggname, Oid basetype, Node *target);
-
-/*****************************************************************************
- *
- *****************************************************************************/
 
-/*
- * makeParseState() --
- *	  allocate and initialize a new ParseState.
- *	the CALLERS is responsible for freeing the ParseState* returned
- *
- */
-
-static ParseState *
-makeParseState(void)
-{
-	ParseState *pstate;
-
-	pstate = malloc(sizeof(ParseState));
-	pstate->p_last_resno = 1;
-	pstate->p_rtable = NIL;
-	pstate->p_numAgg = 0;
-	pstate->p_aggs = NIL;
-	pstate->p_is_insert = false;
-	pstate->p_insert_columns = NIL;
-	pstate->p_is_update = false;
-	pstate->p_is_rule = false;
-	pstate->p_target_relation = NULL;
-	pstate->p_target_rangetblentry = NULL;
-
-	return (pstate);
-}
 
 /*
  * parse_analyze -
@@ -144,11 +61,9 @@ parse_analyze(List *pl)
 	result->len = length(pl);
 	result->qtrees = (Query **) malloc(result->len * sizeof(Query *));
 
-	inWhereClause = false;		/* to avoid nextval(sequence) in WHERE */
-
 	while (pl != NIL)
 	{
-		pstate = makeParseState();
+		pstate = make_parsestate();
 		result->qtrees[i++] = transformStmt(pstate, lfirst(pl));
 		pl = lnext(pl);
 		if (pstate->p_target_relation != NULL)
@@ -620,2580 +535,3 @@ transformCursorStmt(ParseState *pstate, CursorStmt *stmt)
 
 	return (Query *) qry;
 }
-
-/*****************************************************************************
- *
- * Transform Exprs, Aggs, etc.
- *
- *****************************************************************************/
-
-/*
- * transformExpr -
- *	  analyze and transform expressions. Type checking and type casting is
- *	  done here. The optimizer and the executor cannot handle the original
- *	  (raw) expressions collected by the parse tree. Hence the transformation
- *	  here.
- */
-static Node *
-transformExpr(ParseState *pstate, Node *expr, int precedence)
-{
-	Node	   *result = NULL;
-
-	if (expr == NULL)
-		return NULL;
-
-	switch (nodeTag(expr))
-	{
-		case T_Attr:
-			{
-				Attr	   *att = (Attr *) expr;
-				Node	   *temp;
-
-				/* what if att.attrs == "*"?? */
-				temp = handleNestedDots(pstate, att, &pstate->p_last_resno);
-				if (att->indirection != NIL)
-				{
-					List	   *idx = att->indirection;
-
-					while (idx != NIL)
-					{
-						A_Indices  *ai = (A_Indices *) lfirst(idx);
-						Node	   *lexpr = NULL,
-								   *uexpr;
-
-						uexpr = transformExpr(pstate, ai->uidx, precedence);	/* must exists */
-						if (exprType(uexpr) != INT4OID)
-							elog(WARN, "array index expressions must be int4's");
-						if (ai->lidx != NULL)
-						{
-							lexpr = transformExpr(pstate, ai->lidx, precedence);
-							if (exprType(lexpr) != INT4OID)
-								elog(WARN, "array index expressions must be int4's");
-						}
-#if 0
-						pfree(ai->uidx);
-						if (ai->lidx != NULL)
-							pfree(ai->lidx);
-#endif
-						ai->lidx = lexpr;
-						ai->uidx = uexpr;
-
-						/*
-						 * note we reuse the list of indices, make sure we
-						 * don't free them! Otherwise, make a new list
-						 * here
-						 */
-						idx = lnext(idx);
-					}
-					result = (Node *) make_array_ref(temp, att->indirection);
-				}
-				else
-				{
-					result = temp;
-				}
-				break;
-			}
-		case T_A_Const:
-			{
-				A_Const    *con = (A_Const *) expr;
-				Value	   *val = &con->val;
-
-				if (con->typename != NULL)
-				{
-					result = parser_typecast(val, con->typename, -1);
-				}
-				else
-				{
-					result = (Node *) make_const(val);
-				}
-				break;
-			}
-		case T_ParamNo:
-			{
-				ParamNo    *pno = (ParamNo *) expr;
-				Oid			toid;
-				int			paramno;
-				Param	   *param;
-
-				paramno = pno->number;
-				toid = param_type(paramno);
-				if (!OidIsValid(toid))
-				{
-					elog(WARN, "Parameter '$%d' is out of range",
-						 paramno);
-				}
-				param = makeNode(Param);
-				param->paramkind = PARAM_NUM;
-				param->paramid = (AttrNumber) paramno;
-				param->paramname = "<unnamed>";
-				param->paramtype = (Oid) toid;
-				param->param_tlist = (List *) NULL;
-
-				result = (Node *) param;
-				break;
-			}
-		case T_A_Expr:
-			{
-				A_Expr	   *a = (A_Expr *) expr;
-
-				switch (a->oper)
-				{
-					case OP:
-						{
-							Node	   *lexpr = transformExpr(pstate, a->lexpr, precedence);
-							Node	   *rexpr = transformExpr(pstate, a->rexpr, precedence);
-
-							result = (Node *) make_op(a->opname, lexpr, rexpr);
-						}
-						break;
-					case ISNULL:
-						{
-							Node	   *lexpr = transformExpr(pstate, a->lexpr, precedence);
-
-							result = ParseFunc(pstate,
-										  "nullvalue", lcons(lexpr, NIL),
-											   &pstate->p_last_resno);
-						}
-						break;
-					case NOTNULL:
-						{
-							Node	   *lexpr = transformExpr(pstate, a->lexpr, precedence);
-
-							result = ParseFunc(pstate,
-									   "nonnullvalue", lcons(lexpr, NIL),
-											   &pstate->p_last_resno);
-						}
-						break;
-					case AND:
-						{
-							Expr	   *expr = makeNode(Expr);
-							Node	   *lexpr = transformExpr(pstate, a->lexpr, precedence);
-							Node	   *rexpr = transformExpr(pstate, a->rexpr, precedence);
-
-							if (exprType(lexpr) != BOOLOID)
-								elog(WARN,
-									 "left-hand side of AND is type '%s', not bool",
-									 tname(get_id_type(exprType(lexpr))));
-							if (exprType(rexpr) != BOOLOID)
-								elog(WARN,
-									 "right-hand side of AND is type '%s', not bool",
-									 tname(get_id_type(exprType(rexpr))));
-							expr->typeOid = BOOLOID;
-							expr->opType = AND_EXPR;
-							expr->args = makeList(lexpr, rexpr, -1);
-							result = (Node *) expr;
-						}
-						break;
-					case OR:
-						{
-							Expr	   *expr = makeNode(Expr);
-							Node	   *lexpr = transformExpr(pstate, a->lexpr, precedence);
-							Node	   *rexpr = transformExpr(pstate, a->rexpr, precedence);
-
-							if (exprType(lexpr) != BOOLOID)
-								elog(WARN,
-									 "left-hand side of OR is type '%s', not bool",
-									 tname(get_id_type(exprType(lexpr))));
-							if (exprType(rexpr) != BOOLOID)
-								elog(WARN,
-									 "right-hand side of OR is type '%s', not bool",
-									 tname(get_id_type(exprType(rexpr))));
-							expr->typeOid = BOOLOID;
-							expr->opType = OR_EXPR;
-							expr->args = makeList(lexpr, rexpr, -1);
-							result = (Node *) expr;
-						}
-						break;
-					case NOT:
-						{
-							Expr	   *expr = makeNode(Expr);
-							Node	   *rexpr = transformExpr(pstate, a->rexpr, precedence);
-
-							if (exprType(rexpr) != BOOLOID)
-								elog(WARN,
-								"argument to NOT is type '%s', not bool",
-									 tname(get_id_type(exprType(rexpr))));
-							expr->typeOid = BOOLOID;
-							expr->opType = NOT_EXPR;
-							expr->args = makeList(rexpr, -1);
-							result = (Node *) expr;
-						}
-						break;
-				}
-				break;
-			}
-		case T_Ident:
-			{
-
-				/*
-				 * look for a column name or a relation name (the default
-				 * behavior)
-				 */
-				result = transformIdent(pstate, expr, precedence);
-				break;
-			}
-		case T_FuncCall:
-			{
-				FuncCall   *fn = (FuncCall *) expr;
-				List	   *args;
-
-				/* transform the list of arguments */
-				foreach(args, fn->args)
-					lfirst(args) = transformExpr(pstate, (Node *) lfirst(args), precedence);
-				result = ParseFunc(pstate,
-						  fn->funcname, fn->args, &pstate->p_last_resno);
-				break;
-			}
-		default:
-			/* should not reach here */
-			elog(WARN, "transformExpr: does not know how to transform %d\n",
-				 nodeTag(expr));
-			break;
-	}
-
-	return result;
-}
-
-static Node *
-transformIdent(ParseState *pstate, Node *expr, int precedence)
-{
-	Ident	   *ident = (Ident *) expr;
-	RangeTblEntry *rte;
-	Node	   *column_result,
-			   *relation_result,
-			   *result;
-
-	column_result = relation_result = result = 0;
-	/* try to find the ident as a column */
-	if ((rte = colnameRangeTableEntry(pstate, ident->name)) != NULL)
-	{
-		Attr	   *att = makeNode(Attr);
-
-		att->relname = rte->refname;
-		att->attrs = lcons(makeString(ident->name), NIL);
-		column_result =
-			(Node *) handleNestedDots(pstate, att, &pstate->p_last_resno);
-	}
-
-	/* try to find the ident as a relation */
-	if (refnameRangeTableEntry(pstate->p_rtable, ident->name) != NULL)
-	{
-		ident->isRel = TRUE;
-		relation_result = (Node *) ident;
-	}
-
-	/* choose the right result based on the precedence */
-	if (precedence == EXPR_COLUMN_FIRST)
-	{
-		if (column_result)
-			result = column_result;
-		else
-			result = relation_result;
-	}
-	else
-	{
-		if (relation_result)
-			result = relation_result;
-		else
-			result = column_result;
-	}
-
-	if (result == NULL)
-		elog(WARN, "attribute '%s' not found", ident->name);
-
-	return result;
-}
-
-/*****************************************************************************
- *
- * From Clause
- *
- *****************************************************************************/
-
-/*
- * parseFromClause -
- *	  turns the table references specified in the from-clause into a
- *	  range table. The range table may grow as we transform the expressions
- *	  in the target list. (Note that this happens because in POSTQUEL, we
- *	  allow references to relations not specified in the from-clause. We
- *	  also allow that in our POST-SQL)
- *
- */
-static void
-parseFromClause(ParseState *pstate, List *frmList)
-{
-	List	   *fl;
-
-	foreach(fl, frmList)
-	{
-		RangeVar   *r = lfirst(fl);
-		RelExpr    *baserel = r->relExpr;
-		char	   *relname = baserel->relname;
-		char	   *refname = r->name;
-		RangeTblEntry *rte;
-
-		if (refname == NULL)
-			refname = relname;
-
-		/*
-		 * marks this entry to indicate it comes from the FROM clause. In
-		 * SQL, the target list can only refer to range variables
-		 * specified in the from clause but we follow the more powerful
-		 * POSTQUEL semantics and automatically generate the range
-		 * variable if not specified. However there are times we need to
-		 * know whether the entries are legitimate.
-		 *
-		 * eg. select * from foo f where f.x = 1; will generate wrong answer
-		 * if we expand * to foo.x.
-		 */
-		rte = addRangeTableEntry(pstate, relname, refname, baserel->inh, TRUE);
-	}
-}
-
-/*
- * makeRangeTable -
- *	  make a range table with the specified relation (optional) and the
- *	  from-clause.
- */
-static 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);
-
-	pstate->p_target_rangetblentry = rte;
-	Assert(pstate->p_target_relation == NULL);
-	pstate->p_target_relation = heap_open(rte->relid);
-	Assert(pstate->p_target_relation != NULL);
-	/* will close relation later */
-}
-
-/*
- *	exprType -
- *	  returns the Oid of the type of the expression. (Used for typechecking.)
- */
-Oid
-exprType(Node *expr)
-{
-	Oid			type = (Oid) 0;
-
-	switch (nodeTag(expr))
-	{
-		case T_Func:
-			type = ((Func *) expr)->functype;
-			break;
-		case T_Iter:
-			type = ((Iter *) expr)->itertype;
-			break;
-		case T_Var:
-			type = ((Var *) expr)->vartype;
-			break;
-		case T_Expr:
-			type = ((Expr *) expr)->typeOid;
-			break;
-		case T_Const:
-			type = ((Const *) expr)->consttype;
-			break;
-		case T_ArrayRef:
-			type = ((ArrayRef *) expr)->refelemtype;
-			break;
-		case T_Aggreg:
-			type = ((Aggreg *) expr)->aggtype;
-			break;
-		case T_Param:
-			type = ((Param *) expr)->paramtype;
-			break;
-		case T_Ident:
-			/* is this right? */
-			type = UNKNOWNOID;
-			break;
-		default:
-			elog(WARN, "exprType: don't know how to get type for %d node",
-				 nodeTag(expr));
-			break;
-	}
-	return type;
-}
-
-/*
- * expandAllTables -
- *	  turns '*' (in the target list) into a list of attributes
- *	   (of all relations in the range table)
- */
-static List *
-expandAllTables(ParseState *pstate)
-{
-	List	   *target = NIL;
-	List	   *legit_rtable = NIL;
-	List	   *rt,
-			   *rtable;
-
-	rtable = pstate->p_rtable;
-	if (pstate->p_is_rule)
-	{
-
-		/*
-		 * skip first two entries, "*new*" and "*current*"
-		 */
-		rtable = lnext(lnext(pstate->p_rtable));
-	}
-
-	/* this should not happen */
-	if (rtable == NULL)
-		elog(WARN, "cannot expand: null p_rtable");
-
-	/*
-	 * go through the range table and make a list of range table entries
-	 * which we will expand.
-	 */
-	foreach(rt, rtable)
-	{
-		RangeTblEntry *rte = lfirst(rt);
-
-		/*
-		 * we only expand those specify in the from clause. (This will
-		 * also prevent us from using the wrong table in inserts: eg.
-		 * tenk2 in "insert into tenk2 select * from tenk1;")
-		 */
-		if (!rte->inFromCl)
-			continue;
-		legit_rtable = lappend(legit_rtable, rte);
-	}
-
-	foreach(rt, legit_rtable)
-	{
-		RangeTblEntry *rte = lfirst(rt);
-		List	   *temp = target;
-
-		if (temp == NIL)
-			target = expandAll(pstate, rte->relname, rte->refname,
-							   &pstate->p_last_resno);
-		else
-		{
-			while (temp != NIL && lnext(temp) != NIL)
-				temp = lnext(temp);
-			lnext(temp) = expandAll(pstate, rte->relname, rte->refname,
-									&pstate->p_last_resno);
-		}
-	}
-	return target;
-}
-
-
-/*
- * figureColname -
- *	  if the name of the resulting column is not specified in the target
- *	  list, we have to guess.
- *
- */
-static char *
-figureColname(Node *expr, Node *resval)
-{
-	switch (nodeTag(expr))
-	{
-			case T_Aggreg:
-			return (char *)		/* XXX */
-			((Aggreg *) expr)->aggname;
-		case T_Expr:
-			if (((Expr *) expr)->opType == FUNC_EXPR)
-			{
-				if (nodeTag(resval) == T_FuncCall)
-					return ((FuncCall *) resval)->funcname;
-			}
-			break;
-		default:
-			break;
-	}
-
-	return "?column?";
-}
-
-/*****************************************************************************
- *
- * Target list
- *
- *****************************************************************************/
-
-/*
- * makeTargetNames -
- *	  generate a list of column names if not supplied or
- *	  test supplied column names to make sure they are in target table
- *	  (used exclusively for inserts)
- */
-static List *
-makeTargetNames(ParseState *pstate, List *cols)
-{
-	List	   *tl = NULL;
-
-	/* Generate ResTarget if not supplied */
-
-	if (cols == NIL)
-	{
-		int			numcol;
-		int			i;
-		AttributeTupleForm *attr = pstate->p_target_relation->rd_att->attrs;
-
-		numcol = pstate->p_target_relation->rd_rel->relnatts;
-		for (i = 0; i < numcol; i++)
-		{
-			Ident	   *id = makeNode(Ident);
-
-			id->name = palloc(NAMEDATALEN);
-			StrNCpy(id->name, attr[i]->attname.data, NAMEDATALEN);
-			id->indirection = NIL;
-			id->isRel = false;
-			if (tl == NIL)
-				cols = tl = lcons(id, NIL);
-			else
-			{
-				lnext(tl) = lcons(id, NIL);
-				tl = lnext(tl);
-			}
-		}
-	}
-	else
-	{
-		foreach(tl, cols)
-		{
-			List	   *nxt;
-			char	   *name = ((Ident *) lfirst(tl))->name;
-		
-			/* elog on failure */
-			varattno(pstate->p_target_relation, name);
-			foreach(nxt, lnext(tl))
-				if (!strcmp(name, ((Ident *) lfirst(nxt))->name))
-					elog (WARN, "Attribute '%s' should be specified only once", name);
-		}
-	}
-	
-	return cols;
-}
-
-/*
- * transformTargetList -
- *	  turns a list of ResTarget's into a list of TargetEntry's
- */
-static List *
-transformTargetList(ParseState *pstate, List *targetlist)
-{
-	List	   *p_target = NIL;
-	List	   *tail_p_target = NIL;
-
-	while (targetlist != NIL)
-	{
-		ResTarget  *res = (ResTarget *) lfirst(targetlist);
-		TargetEntry *tent = makeNode(TargetEntry);
-
-		switch (nodeTag(res->val))
-		{
-			case T_Ident:
-				{
-					Node	   *expr;
-					Oid			type_id;
-					int			type_len;
-					char	   *identname;
-					char	   *resname;
-
-					identname = ((Ident *) res->val)->name;
-					handleTargetColname(pstate, &res->name, NULL, identname);
-
-					/*
-					 * here we want to look for column names only, not relation
-					 * names (even though they can be stored in Ident nodes, too)
-					 */
-					expr = transformIdent(pstate, (Node *) res->val, EXPR_COLUMN_FIRST);
-					type_id = exprType(expr);
-					type_len = tlen(get_id_type(type_id));
-					resname = (res->name) ? res->name : identname;
-					tent->resdom = makeResdom((AttrNumber) pstate->p_last_resno++,
-											  (Oid) type_id,
-											  (Size) type_len,
-											  resname,
-											  (Index) 0,
-											  (Oid) 0,
-											  0);
-
-					tent->expr = expr;
-					break;
-				}
-			case T_ParamNo:
-			case T_FuncCall:
-			case T_A_Const:
-			case T_A_Expr:
-				{
-					Node	   *expr = transformExpr(pstate, (Node *) res->val, EXPR_COLUMN_FIRST);
-
-					handleTargetColname(pstate, &res->name, NULL, NULL);
-					/* note indirection has not been transformed */
-					if (pstate->p_is_insert && res->indirection != NIL)
-					{
-						/* this is an array assignment */
-						char	   *val;
-						char	   *str,
-								   *save_str;
-						List	   *elt;
-						int			i = 0,
-									ndims;
-						int			lindx[MAXDIM],
-									uindx[MAXDIM];
-						int			resdomno;
-						Relation	rd;
-						Value	   *constval;
-
-						if (exprType(expr) != UNKNOWNOID ||
-							!IsA(expr, Const))
-							elog(WARN, "yyparse: string constant expected");
-
-						val = (char *) textout((struct varlena *)
-										   ((Const *) expr)->constvalue);
-						str = save_str = (char *) palloc(strlen(val) + MAXDIM * 25 + 2);
-						foreach(elt, res->indirection)
-						{
-							A_Indices  *aind = (A_Indices *) lfirst(elt);
-
-							aind->uidx = transformExpr(pstate, aind->uidx, EXPR_COLUMN_FIRST);
-							if (!IsA(aind->uidx, Const))
-								elog(WARN,
-									 "Array Index for Append should be a constant");
-							uindx[i] = ((Const *) aind->uidx)->constvalue;
-							if (aind->lidx != NULL)
-							{
-								aind->lidx = transformExpr(pstate, aind->lidx, EXPR_COLUMN_FIRST);
-								if (!IsA(aind->lidx, Const))
-									elog(WARN,
-										 "Array Index for Append should be a constant");
-								lindx[i] = ((Const *) aind->lidx)->constvalue;
-							}
-							else
-							{
-								lindx[i] = 1;
-							}
-							if (lindx[i] > uindx[i])
-								elog(WARN, "yyparse: lower index cannot be greater than upper index");
-							sprintf(str, "[%d:%d]", lindx[i], uindx[i]);
-							str += strlen(str);
-							i++;
-						}
-						sprintf(str, "=%s", val);
-						rd = pstate->p_target_relation;
-						Assert(rd != NULL);
-						resdomno = varattno(rd, res->name);
-						ndims = att_attnelems(rd, resdomno);
-						if (i != ndims)
-							elog(WARN, "yyparse: array dimensions do not match");
-						constval = makeNode(Value);
-						constval->type = T_String;
-						constval->val.str = save_str;
-						tent = make_targetlist_expr(pstate, res->name,
-										   (Node *) make_const(constval),
-													NULL);
-						pfree(save_str);
-					}
-					else
-					{
-						char	   *colname = res->name;
-
-						/* this is not an array assignment */
-						if (colname == NULL)
-						{
-
-							/*
-							 * if you're wondering why this is here, look
-							 * at the yacc grammar for why a name can be
-							 * missing. -ay
-							 */
-							colname = figureColname(expr, res->val);
-						}
-						if (res->indirection)
-						{
-							List	   *ilist = res->indirection;
-
-							while (ilist != NIL)
-							{
-								A_Indices  *ind = lfirst(ilist);
-
-								ind->lidx = transformExpr(pstate, ind->lidx, EXPR_COLUMN_FIRST);
-								ind->uidx = transformExpr(pstate, ind->uidx, EXPR_COLUMN_FIRST);
-								ilist = lnext(ilist);
-							}
-						}
-						res->name = colname;
-						tent = make_targetlist_expr(pstate, res->name, expr,
-													res->indirection);
-					}
-					break;
-				}
-			case T_Attr:
-				{
-					Oid			type_id;
-					int			type_len;
-					Attr	   *att = (Attr *) res->val;
-					Node	   *result;
-					char	   *attrname;
-					char	   *resname;
-					Resdom	   *resnode;
-					List	   *attrs = att->attrs;
-
-					/*
-					 * Target item is a single '*', expand all tables (eg.
-					 * SELECT * FROM emp)
-					 */
-					if (att->relname != NULL && !strcmp(att->relname, "*"))
-					{
-						if (tail_p_target == NIL)
-							p_target = tail_p_target = expandAllTables(pstate);
-						else
-							lnext(tail_p_target) = expandAllTables(pstate);
-
-						while (lnext(tail_p_target) != NIL)
-							/* make sure we point to the last target entry */
-							tail_p_target = lnext(tail_p_target);
-
-						/*
-						 * skip rest of while loop
-						 */
-						targetlist = lnext(targetlist);
-						continue;
-					}
-
-					/*
-					 * Target item is relation.*, expand the table (eg.
-					 * SELECT emp.*, dname FROM emp, dept)
-					 */
-					attrname = strVal(lfirst(att->attrs));
-					if (att->attrs != NIL && !strcmp(attrname, "*"))
-					{
-
-						/*
-						 * tail_p_target is the target list we're building
-						 * in the while loop. Make sure we fix it after
-						 * appending more nodes.
-						 */
-						if (tail_p_target == NIL)
-							p_target = tail_p_target = expandAll(pstate, att->relname,
-									att->relname, &pstate->p_last_resno);
-						else
-							lnext(tail_p_target) =
-								expandAll(pstate, att->relname, att->relname,
-										  &pstate->p_last_resno);
-						while (lnext(tail_p_target) != NIL)
-							/* make sure we point to the last target entry */
-							tail_p_target = lnext(tail_p_target);
-
-						/*
-						 * skip the rest of the while loop
-						 */
-						targetlist = lnext(targetlist);
-						continue;
-					}
-
-
-					/*
-					 * Target item is fully specified: ie.
-					 * relation.attribute
-					 */
-					result = handleNestedDots(pstate, att, &pstate->p_last_resno);
-					handleTargetColname(pstate, &res->name, att->relname, attrname);
-					if (att->indirection != NIL)
-					{
-						List	   *ilist = att->indirection;
-
-						while (ilist != NIL)
-						{
-							A_Indices  *ind = lfirst(ilist);
-
-							ind->lidx = transformExpr(pstate, ind->lidx, EXPR_COLUMN_FIRST);
-							ind->uidx = transformExpr(pstate, ind->uidx, EXPR_COLUMN_FIRST);
-							ilist = lnext(ilist);
-						}
-						result = (Node *) make_array_ref(result, att->indirection);
-					}
-					type_id = exprType(result);
-					type_len = tlen(get_id_type(type_id));
-					/* move to last entry */
-					while (lnext(attrs) != NIL)
-						attrs = lnext(attrs);
-					resname = (res->name) ? res->name : strVal(lfirst(attrs));
-					resnode = makeResdom((AttrNumber) pstate->p_last_resno++,
-										 (Oid) type_id,
-										 (Size) type_len,
-										 resname,
-										 (Index) 0,
-										 (Oid) 0,
-										 0);
-					tent->resdom = resnode;
-					tent->expr = result;
-					break;
-				}
-			default:
-				/* internal error */
-				elog(WARN,
-					 "internal error: do not know how to transform targetlist");
-				break;
-		}
-
-		if (p_target == NIL)
-		{
-			p_target = tail_p_target = lcons(tent, NIL);
-		}
-		else
-		{
-			lnext(tail_p_target) = lcons(tent, NIL);
-			tail_p_target = lnext(tail_p_target);
-		}
-		targetlist = lnext(targetlist);
-	}
-
-	return p_target;
-}
-
-
-/*
- * make_targetlist_expr -
- *	  make a TargetEntry from an expression
- *
- * arrayRef is a list of transformed A_Indices
- */
-static TargetEntry *
-make_targetlist_expr(ParseState *pstate,
-					 char *colname,
-					 Node *expr,
-					 List *arrayRef)
-{
-	Oid			type_id,
-				attrtype;
-	int			type_len,
-				attrlen;
-	int			resdomno;
-	Relation	rd;
-	bool		attrisset;
-	TargetEntry *tent;
-	Resdom	   *resnode;
-
-	if (expr == NULL)
-		elog(WARN, "make_targetlist_expr: invalid use of NULL expression");
-
-	type_id = exprType(expr);
-	if (type_id == InvalidOid)
-	{
-		type_len = 0;
-	}
-	else
-		type_len = tlen(get_id_type(type_id));
-
-	/* I have no idea what the following does! */
-	/* It appears to process target columns that will be receiving results */
-	if (pstate->p_is_insert || pstate->p_is_update)
-	{
-
-		/*
-		 * append or replace query -- append, replace work only on one
-		 * relation, so multiple occurence of same resdomno is bogus
-		 */
-		rd = pstate->p_target_relation;
-		Assert(rd != NULL);
-		resdomno = varattno(rd, colname);
-		attrisset = varisset(rd, colname);
-		attrtype = att_typeid(rd, resdomno);
-		if ((arrayRef != NIL) && (lfirst(arrayRef) == NIL))
-			attrtype = GetArrayElementType(attrtype);
-		if (attrtype == BPCHAROID || attrtype == VARCHAROID)
-		{
-			attrlen = rd->rd_att->attrs[resdomno - 1]->attlen;
-		}
-		else
-		{
-			attrlen = tlen(get_id_type(attrtype));
-		}
-#if 0
-		if (Input_is_string && Typecast_ok)
-		{
-			Datum		val;
-
-			if (type_id == typeid(type("unknown")))
-			{
-				val = (Datum) textout((struct varlena *)
-									  ((Const) lnext(expr))->constvalue);
-			}
-			else
-			{
-				val = ((Const) lnext(expr))->constvalue;
-			}
-			if (attrisset)
-			{
-				lnext(expr) = makeConst(attrtype,
-										attrlen,
-										val,
-										false,
-										true,
-										true,	/* is set */
-										false);
-			}
-			else
-			{
-				lnext(expr) =
-					makeConst(attrtype,
-							  attrlen,
-							  (Datum) fmgr(typeid_get_retinfunc(attrtype),
-										 val, get_typelem(attrtype), -1),
-							  false,
-							  true /* Maybe correct-- 80% chance */ ,
-							  false,	/* is not a set */
-							  false);
-			}
-		}
-		else if ((Typecast_ok) && (attrtype != type_id))
-		{
-			lnext(expr) =
-				parser_typecast2(expr, get_id_type(attrtype));
-		}
-		else if (attrtype != type_id)
-		{
-			if ((attrtype == INT2OID) && (type_id == INT4OID))
-				lfirst(expr) = lispInteger(INT2OID);	/* handle CASHOID too */
-			else if ((attrtype == FLOAT4OID) && (type_id == FLOAT8OID))
-				lfirst(expr) = lispInteger(FLOAT4OID);
-			else
-				elog(WARN, "unequal type in tlist : %s \n", colname);
-		}
-
-		Input_is_string = false;
-		Input_is_integer = false;
-		Typecast_ok = true;
-#endif
-
-		if (attrtype != type_id)
-		{
-			if (IsA(expr, Const))
-			{
-				/* try to cast the constant */
-				if (arrayRef && !(((A_Indices *) lfirst(arrayRef))->lidx))
-				{
-					/* updating a single item */
-					Oid			typelem = get_typelem(attrtype);
-
-					expr = (Node *) parser_typecast2(expr,
-													 type_id,
-													 get_id_type(typelem),
-													 attrlen);
-				}
-				else
-					expr = (Node *) parser_typecast2(expr,
-													 type_id,
-												   get_id_type(attrtype),
-													 attrlen);
-			}
-			else
-			{
-				/* currently, we can't handle casting of expressions */
-				elog(WARN, "parser: attribute '%s' is of type '%s' but expression is of type '%s'",
-					 colname,
-					 get_id_typname(attrtype),
-					 get_id_typname(type_id));
-			}
-		}
-
-		if (arrayRef != NIL)
-		{
-			Expr	   *target_expr;
-			Attr	   *att = makeNode(Attr);
-			List	   *ar = arrayRef;
-			List	   *upperIndexpr = NIL;
-			List	   *lowerIndexpr = NIL;
-
-			att->relname = pstrdup(RelationGetRelationName(rd)->data);
-			att->attrs = lcons(makeString(colname), NIL);
-			target_expr = (Expr *) handleNestedDots(pstate, att,
-												  &pstate->p_last_resno);
-			while (ar != NIL)
-			{
-				A_Indices  *ind = lfirst(ar);
-
-				if (lowerIndexpr || (!upperIndexpr && ind->lidx))
-				{
-
-					/*
-					 * XXX assume all lowerIndexpr is non-null in this
-					 * case
-					 */
-					lowerIndexpr = lappend(lowerIndexpr, ind->lidx);
-				}
-				upperIndexpr = lappend(upperIndexpr, ind->uidx);
-				ar = lnext(ar);
-			}
-
-			expr = (Node *) make_array_set(target_expr,
-										   upperIndexpr,
-										   lowerIndexpr,
-										   (Expr *) expr);
-			attrtype = att_typeid(rd, resdomno);
-			attrlen = tlen(get_id_type(attrtype));
-		}
-	}
-	else
-	{
-		resdomno = pstate->p_last_resno++;
-		attrtype = type_id;
-		attrlen = type_len;
-	}
-	tent = makeNode(TargetEntry);
-
-	resnode = makeResdom((AttrNumber) resdomno,
-						 (Oid) attrtype,
-						 (Size) attrlen,
-						 colname,
-						 (Index) 0,
-						 (Oid) 0,
-						 0);
-
-	tent->resdom = resnode;
-	tent->expr = expr;
-
-	return tent;
-}
-
-
-/*****************************************************************************
- *
- * Where Clause
- *
- *****************************************************************************/
-
-/*
- * transformWhereClause -
- *	  transforms the qualification and make sure it is of type Boolean
- *
- */
-static Node *
-transformWhereClause(ParseState *pstate, Node *a_expr)
-{
-	Node	   *qual;
-
-	if (a_expr == NULL)
-		return (Node *) NULL;	/* no qualifiers */
-
-	inWhereClause = true;
-	qual = transformExpr(pstate, a_expr, EXPR_COLUMN_FIRST);
-	inWhereClause = false;
-	if (exprType(qual) != BOOLOID)
-	{
-		elog(WARN,
-			 "where clause must return type bool, not %s",
-			 tname(get_id_type(exprType(qual))));
-	}
-	return qual;
-}
-
-/*****************************************************************************
- *
- * Sort Clause
- *
- *****************************************************************************/
-
-/*
- *	find_targetlist_entry -
- *	  returns the Resdom in the target list matching the specified varname
- *	  and range
- *
- */
-static TargetEntry *
-find_targetlist_entry(ParseState *pstate, SortGroupBy *sortgroupby, List *tlist)
-{
-	List	   *i;
-	int			real_rtable_pos = 0,
-				target_pos = 0;
-	TargetEntry *target_result = NULL;
-
-	if (sortgroupby->range)
-		real_rtable_pos = refnameRangeTablePosn(pstate->p_rtable,
-												sortgroupby->range);
-
-	foreach(i, tlist)
-	{
-		TargetEntry *target = (TargetEntry *) lfirst(i);
-		Resdom	   *resnode = target->resdom;
-		Var		   *var = (Var *) target->expr;
-		char	   *resname = resnode->resname;
-		int			test_rtable_pos = var->varno;
-
-#ifdef PARSEDEBUG
-		printf("find_targetlist_entry- target name is %s, position %d, resno %d\n",
-			   (sortgroupby->name ? sortgroupby->name : "(null)"), target_pos + 1, sortgroupby->resno);
-#endif
-
-		if (!sortgroupby->name)
-		{
-			if (sortgroupby->resno == ++target_pos)
-			{
-				target_result = target;
-				break;
-			}
-		}
-		else
-		{
-			if (!strcmp(resname, sortgroupby->name))
-			{
-				if (sortgroupby->range)
-				{
-					if (real_rtable_pos == test_rtable_pos)
-					{
-						if (target_result != NULL)
-							elog(WARN, "Order/Group By '%s' is ambiguous", sortgroupby->name);
-						else
-							target_result = target;
-					}
-				}
-				else
-				{
-					if (target_result != NULL)
-						elog(WARN, "Order/Group By '%s' is ambiguous", sortgroupby->name);
-					else
-						target_result = target;
-				}
-			}
-		}
-	}
-	return target_result;
-}
-
-static Oid
-any_ordering_op(int restype)
-{
-	Operator	order_op;
-	Oid			order_opid;
-
-	order_op = oper("<", restype, restype, false);
-	order_opid = oprid(order_op);
-
-	return order_opid;
-}
-
-/*
- * transformGroupClause -
- *	  transform a Group By clause
- *
- */
-static List *
-transformGroupClause(ParseState *pstate, List *grouplist, List *targetlist)
-{
-	List	   *glist = NIL,
-			   *gl = NIL;
-
-	while (grouplist != NIL)
-	{
-		GroupClause *grpcl = makeNode(GroupClause);
-		TargetEntry *restarget;
-		Resdom	   *resdom;
-
-		restarget = find_targetlist_entry(pstate, lfirst(grouplist), targetlist);
-
-		if (restarget == NULL)
-			elog(WARN, "The field being grouped by must appear in the target list");
-
-		grpcl->entry = restarget;
-		resdom = restarget->resdom;
-		grpcl->grpOpoid = oprid(oper("<",
-									 resdom->restype,
-									 resdom->restype, false));
-		if (glist == NIL)
-			gl = glist = lcons(grpcl, NIL);
-		else
-		{
-			List	   *i;
-			
-			foreach (i, glist)
-			{
-				GroupClause *gcl = (GroupClause *) lfirst (i);
-				
-				if ( gcl->entry == grpcl->entry )
-					break;
-			}
-			if ( i == NIL )			/* not in grouplist already */
-			{
-				lnext(gl) = lcons(grpcl, NIL);
-				gl = lnext(gl);
-			}
-			else
-				pfree (grpcl);		/* get rid of this */
-		}
-		grouplist = lnext(grouplist);
-	}
-
-	return glist;
-}
-
-/*
- * transformSortClause -
- *	  transform an Order By clause
- *
- */
-static List *
-transformSortClause(ParseState *pstate,
-					List *orderlist, List *targetlist,
-					char *uniqueFlag)
-{
-	List	   *sortlist = NIL;
-	List	   *s = NIL;
-
-	while (orderlist != NIL)
-	{
-		SortGroupBy *sortby = lfirst(orderlist);
-		SortClause *sortcl = makeNode(SortClause);
-		TargetEntry *restarget;
-		Resdom	   *resdom;
-
-		restarget = find_targetlist_entry(pstate, sortby, targetlist);
-		if (restarget == NULL)
-			elog(WARN, "The field being ordered by must appear in the target list");
-
-		sortcl->resdom = resdom = restarget->resdom;
-		sortcl->opoid = oprid(oper(sortby->useOp,
-								   resdom->restype,
-								   resdom->restype, false));
-		if (sortlist == NIL)
-		{
-			s = sortlist = lcons(sortcl, NIL);
-		}
-		else
-		{
-			List	   *i;
-			
-			foreach (i, sortlist)
-			{
-				SortClause *scl = (SortClause *) lfirst (i);
-				
-				if ( scl->resdom == sortcl->resdom )
-					break;
-			}
-			if ( i == NIL )			/* not in sortlist already */
-			{
-				lnext(s) = lcons(sortcl, NIL);
-				s = lnext(s);
-			}
-			else
-				pfree (sortcl);		/* get rid of this */
-		}
-		orderlist = lnext(orderlist);
-	}
-
-	if (uniqueFlag)
-	{
-		List	   *i;
-		
-		if (uniqueFlag[0] == '*')
-		{
-
-			/*
-			 * concatenate all elements from target list that are not
-			 * already in the sortby list
-			 */
-			foreach(i, targetlist)
-			{
-				TargetEntry *tlelt = (TargetEntry *) lfirst(i);
-
-				s = sortlist;
-				while (s != NIL)
-				{
-					SortClause *sortcl = lfirst(s);
-
-					if (sortcl->resdom == tlelt->resdom)
-						break;
-					s = lnext(s);
-				}
-				if (s == NIL)
-				{
-					/* not a member of the sortclauses yet */
-					SortClause *sortcl = makeNode(SortClause);
-
-					sortcl->resdom = tlelt->resdom;
-					sortcl->opoid = any_ordering_op(tlelt->resdom->restype);
-
-					sortlist = lappend(sortlist, sortcl);
-				}
-			}
-		}
-		else
-		{
-			TargetEntry *tlelt = NULL;
-			char	   *uniqueAttrName = uniqueFlag;
-
-			/* only create sort clause with the specified unique attribute */
-			foreach(i, targetlist)
-			{
-				tlelt = (TargetEntry *) lfirst(i);
-				if (strcmp(tlelt->resdom->resname, uniqueAttrName) == 0)
-					break;
-			}
-			if (i == NIL)
-			{
-				elog(WARN, "The field specified in the UNIQUE ON clause is not in the targetlist");
-			}
-			s = sortlist;
-			foreach(s, sortlist)
-			{
-				SortClause *sortcl = lfirst(s);
-
-				if (sortcl->resdom == tlelt->resdom)
-					break;
-			}
-			if (s == NIL)
-			{
-				/* not a member of the sortclauses yet */
-				SortClause *sortcl = makeNode(SortClause);
-
-				sortcl->resdom = tlelt->resdom;
-				sortcl->opoid = any_ordering_op(tlelt->resdom->restype);
-
-				sortlist = lappend(sortlist, sortcl);
-			}
-		}
-
-	}
-
-	return sortlist;
-}
-
-/*
- ** HandleNestedDots --
- **    Given a nested dot expression (i.e. (relation func ... attr), build up
- ** a tree with of Iter and Func nodes.
- */
-static Node *
-handleNestedDots(ParseState *pstate, Attr *attr, int *curr_resno)
-{
-	List	   *mutator_iter;
-	Node	   *retval = NULL;
-
-	if (attr->paramNo != NULL)
-	{
-		Param	   *param = (Param *) transformExpr(pstate, (Node *) attr->paramNo, EXPR_RELATION_FIRST);
-
-		retval =
-			ParseFunc(pstate, strVal(lfirst(attr->attrs)),
-					  lcons(param, NIL),
-					  curr_resno);
-	}
-	else
-	{
-		Ident	   *ident = makeNode(Ident);
-
-		ident->name = attr->relname;
-		ident->isRel = TRUE;
-		retval =
-			ParseFunc(pstate, strVal(lfirst(attr->attrs)),
-					  lcons(ident, NIL),
-					  curr_resno);
-	}
-
-	foreach(mutator_iter, lnext(attr->attrs))
-	{
-		retval = ParseFunc(pstate, strVal(lfirst(mutator_iter)),
-						   lcons(retval, NIL),
-						   curr_resno);
-	}
-
-	return (retval);
-}
-
-/*
- ** make_arguments --
- **   Given the number and types of arguments to a function, and the
- **   actual arguments and argument types, do the necessary typecasting.
- */
-static void
-make_arguments(int nargs,
-			   List *fargs,
-			   Oid *input_typeids,
-			   Oid *function_typeids)
-{
-
-	/*
-	 * there are two ways an input typeid can differ from a function
-	 * typeid : either the input type inherits the function type, so no
-	 * typecasting is necessary, or the input type can be typecast into
-	 * the function type. right now, we only typecast unknowns, and that
-	 * is all we check for.
-	 */
-
-	List	   *current_fargs;
-	int			i;
-
-	for (i = 0, current_fargs = fargs;
-		 i < nargs;
-		 i++, current_fargs = lnext(current_fargs))
-	{
-
-		if (input_typeids[i] == UNKNOWNOID && function_typeids[i] != InvalidOid)
-		{
-			lfirst(current_fargs) =
-				parser_typecast2(lfirst(current_fargs),
-								 input_typeids[i],
-								 get_id_type(function_typeids[i]),
-								 -1);
-		}
-	}
-}
-
-/*
- ** setup_tlist --
- **		Build a tlist that says which attribute to project to.
- **		This routine is called by ParseFunc() to set up a target list
- **		on a tuple parameter or return value.  Due to a bug in 4.0,
- **		it's not possible to refer to system attributes in this case.
- */
-static List *
-setup_tlist(char *attname, Oid relid)
-{
-	TargetEntry *tle;
-	Resdom	   *resnode;
-	Var		   *varnode;
-	Oid			typeid;
-	int			attno;
-
-	attno = get_attnum(relid, attname);
-	if (attno < 0)
-		elog(WARN, "cannot reference attribute '%s' of tuple params/return values for functions", attname);
-
-	typeid = find_atttype(relid, attname);
-	resnode = makeResdom(1,
-						 typeid,
-						 tlen(get_id_type(typeid)),
-						 get_attname(relid, attno),
-						 0,
-						 (Oid) 0,
-						 0);
-	varnode = makeVar(-1, attno, typeid, -1, attno);
-
-	tle = makeNode(TargetEntry);
-	tle->resdom = resnode;
-	tle->expr = (Node *) varnode;
-	return (lcons(tle, NIL));
-}
-
-/*
- ** setup_base_tlist --
- **		Build a tlist that extracts a base type from the tuple
- **		returned by the executor.
- */
-static List *
-setup_base_tlist(Oid typeid)
-{
-	TargetEntry *tle;
-	Resdom	   *resnode;
-	Var		   *varnode;
-
-	resnode = makeResdom(1,
-						 typeid,
-						 tlen(get_id_type(typeid)),
-						 "<noname>",
-						 0,
-						 (Oid) 0,
-						 0);
-	varnode = makeVar(-1, 1, typeid, -1, 1);
-	tle = makeNode(TargetEntry);
-	tle->resdom = resnode;
-	tle->expr = (Node *) varnode;
-
-	return (lcons(tle, NIL));
-}
-
-/*
- * ParseComplexProjection -
- *	  handles function calls with a single argument that is of complex type.
- *	  This routine returns NULL if it can't handle the projection (eg. sets).
- */
-static Node *
-ParseComplexProjection(ParseState *pstate,
-					   char *funcname,
-					   Node *first_arg,
-					   bool *attisset)
-{
-	Oid			argtype;
-	Oid			argrelid;
-	Name		relname;
-	Relation	rd;
-	Oid			relid;
-	int			attnum;
-
-	switch (nodeTag(first_arg))
-	{
-		case T_Iter:
-			{
-				Func	   *func;
-				Iter	   *iter;
-
-				iter = (Iter *) first_arg;
-				func = (Func *) ((Expr *) iter->iterexpr)->oper;
-				argtype = funcid_get_rettype(func->funcid);
-				argrelid = typeid_get_relid(argtype);
-				if (argrelid &&
-					((attnum = get_attnum(argrelid, funcname))
-					 != InvalidAttrNumber))
-				{
-
-					/*
-					 * the argument is a function returning a tuple, so
-					 * funcname may be a projection
-					 */
-
-					/* add a tlist to the func node and return the Iter */
-					rd = heap_openr(tname(get_id_type(argtype)));
-					if (RelationIsValid(rd))
-					{
-						relid = RelationGetRelationId(rd);
-						relname = RelationGetRelationName(rd);
-						heap_close(rd);
-					}
-					if (RelationIsValid(rd))
-					{
-						func->func_tlist =
-							setup_tlist(funcname, argrelid);
-						iter->itertype = att_typeid(rd, attnum);
-						return ((Node *) iter);
-					}
-					else
-					{
-						elog(WARN,
-							 "Function '%s' has bad returntype %d",
-							 funcname, argtype);
-					}
-				}
-				else
-				{
-					/* drop through */
-					;
-				}
-				break;
-			}
-		case T_Var:
-			{
-
-				/*
-				 * The argument is a set, so this is either a projection
-				 * or a function call on this set.
-				 */
-				*attisset = true;
-				break;
-			}
-		case T_Expr:
-			{
-				Expr	   *expr = (Expr *) first_arg;
-				Func	   *funcnode;
-
-				if (expr->opType != FUNC_EXPR)
-					break;
-
-				funcnode = (Func *) expr->oper;
-				argtype = funcid_get_rettype(funcnode->funcid);
-				argrelid = typeid_get_relid(argtype);
-
-				/*
-				 * the argument is a function returning a tuple, so
-				 * funcname may be a projection
-				 */
-				if (argrelid &&
-					(attnum = get_attnum(argrelid, funcname))
-					!= InvalidAttrNumber)
-				{
-
-					/* add a tlist to the func node */
-					rd = heap_openr(tname(get_id_type(argtype)));
-					if (RelationIsValid(rd))
-					{
-						relid = RelationGetRelationId(rd);
-						relname = RelationGetRelationName(rd);
-						heap_close(rd);
-					}
-					if (RelationIsValid(rd))
-					{
-						Expr	   *newexpr;
-
-						funcnode->func_tlist =
-							setup_tlist(funcname, argrelid);
-						funcnode->functype = att_typeid(rd, attnum);
-
-						newexpr = makeNode(Expr);
-						newexpr->typeOid = funcnode->functype;
-						newexpr->opType = FUNC_EXPR;
-						newexpr->oper = (Node *) funcnode;
-						newexpr->args = lcons(first_arg, NIL);
-
-						return ((Node *) newexpr);
-					}
-
-				}
-
-				elog(WARN, "Function '%s' has bad returntype %d",
-					 funcname, argtype);
-				break;
-			}
-		case T_Param:
-			{
-				Param	   *param = (Param *) first_arg;
-
-				/*
-				 * If the Param is a complex type, this could be a
-				 * projection
-				 */
-				rd = heap_openr(tname(get_id_type(param->paramtype)));
-				if (RelationIsValid(rd))
-				{
-					relid = RelationGetRelationId(rd);
-					relname = RelationGetRelationName(rd);
-					heap_close(rd);
-				}
-				if (RelationIsValid(rd) &&
-					(attnum = get_attnum(relid, funcname))
-					!= InvalidAttrNumber)
-				{
-
-					param->paramtype = att_typeid(rd, attnum);
-					param->param_tlist = setup_tlist(funcname, relid);
-					return ((Node *) param);
-				}
-				break;
-			}
-		default:
-			break;
-	}
-
-	return NULL;
-}
-
-static Node *
-ParseFunc(ParseState *pstate, char *funcname, List *fargs, int *curr_resno)
-{
-	Oid			rettype = (Oid) 0;
-	Oid			argrelid = (Oid) 0;
-	Oid			funcid = (Oid) 0;
-	List	   *i = NIL;
-	Node	   *first_arg = NULL;
-	char	   *relname = NULL;
-	char	   *refname = NULL;
-	Relation	rd;
-	Oid			relid;
-	int			nargs;
-	Func	   *funcnode;
-	Oid			oid_array[8];
-	Oid		   *true_oid_array;
-	Node	   *retval;
-	bool		retset;
-	bool		exists;
-	bool		attisset = false;
-	Oid			toid = (Oid) 0;
-	Expr	   *expr;
-
-	if (fargs)
-	{
-		first_arg = lfirst(fargs);
-		if (first_arg == NULL)
-			elog(WARN, "function '%s' does not allow NULL input", funcname);
-	}
-
-	/*
-	 * * check for projection methods: if function takes one argument, and *
-	 * that argument is a relation, param, or PQ function returning a
-	 * complex * type, then the function could be a projection.
-	 */
-	if (length(fargs) == 1)
-	{
-
-		if (nodeTag(first_arg) == T_Ident && ((Ident *) first_arg)->isRel)
-		{
-			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);
-			if (rte == NULL)
-				rte = addRangeTableEntry(pstate, refname, refname, FALSE, FALSE);
-
-			relname = rte->relname;
-			relid = rte->relid;
-
-			/*
-			 * If the attr isn't a set, just make a var for it.  If it is
-			 * a set, treat it like a function and drop through.
-			 */
-			if (get_attnum(relid, funcname) != InvalidAttrNumber)
-			{
-				Oid			dummyTypeId;
-
-				return
-					((Node *) make_var(pstate,
-									   refname,
-									   funcname,
-									   &dummyTypeId));
-			}
-			else
-			{
-				/* drop through - attr is a set */
-				;
-			}
-		}
-		else if (ISCOMPLEX(exprType(first_arg)))
-		{
-
-			/*
-			 * Attempt to handle projection of a complex argument. If
-			 * ParseComplexProjection can't handle the projection, we have
-			 * to keep going.
-			 */
-			retval = ParseComplexProjection(pstate,
-											funcname,
-											first_arg,
-											&attisset);
-			if (attisset)
-			{
-				toid = exprType(first_arg);
-				rd = heap_openr(tname(get_id_type(toid)));
-				if (RelationIsValid(rd))
-				{
-					relname = RelationGetRelationName(rd)->data;
-					heap_close(rd);
-				}
-				else
-					elog(WARN,
-						 "Type '%s' is not a relation type",
-						 tname(get_id_type(toid)));
-				argrelid = typeid_get_relid(toid);
-
-				/*
-				 * A projection contains either an attribute name or the
-				 * "*".
-				 */
-				if ((get_attnum(argrelid, funcname) == InvalidAttrNumber)
-					&& strcmp(funcname, "*"))
-				{
-					elog(WARN, "Functions on sets are not yet supported");
-				}
-			}
-
-			if (retval)
-				return retval;
-		}
-		else
-		{
-
-			/*
-			 * Parsing aggregates.
-			 */
-			Oid			basetype;
-
-			/*
-			 * the aggregate count is a special case, ignore its base
-			 * type.  Treat it as zero
-			 */
-			if (strcmp(funcname, "count") == 0)
-				basetype = 0;
-			else
-				basetype = exprType(lfirst(fargs));
-			if (SearchSysCacheTuple(AGGNAME,
-									PointerGetDatum(funcname),
-									ObjectIdGetDatum(basetype),
-									0, 0))
-			{
-				Aggreg	   *aggreg = ParseAgg(funcname, basetype, lfirst(fargs));
-
-				AddAggToParseState(pstate, aggreg);
-				return (Node *) aggreg;
-			}
-		}
-	}
-
-
-	/*
-	 * * If we dropped through to here it's really a function (or a set,
-	 * which * is implemented as a function.) * extract arg type info and
-	 * transform relation name arguments into * varnodes of the
-	 * appropriate form.
-	 */
-	MemSet(&oid_array[0], 0, 8 * sizeof(Oid));
-
-	nargs = 0;
-	foreach(i, fargs)
-	{
-		int			vnum;
-		RangeTblEntry *rte;
-		Node	   *pair = lfirst(i);
-
-		if (nodeTag(pair) == T_Ident && ((Ident *) pair)->isRel)
-		{
-
-			/*
-			 * a relation
-			 */
-			refname = ((Ident *) pair)->name;
-
-			rte = refnameRangeTableEntry(pstate->p_rtable, refname);
-			if (rte == NULL)
-				rte = addRangeTableEntry(pstate, refname, refname,
-										 FALSE, FALSE);
-			relname = rte->relname;
-
-			vnum = refnameRangeTablePosn(pstate->p_rtable, rte->refname);
-
-			/*
-			 * for func(relname), the param to the function is the tuple
-			 * under consideration.  we build a special VarNode to reflect
-			 * this -- it has varno set to the correct range table entry,
-			 * but has varattno == 0 to signal that the whole tuple is the
-			 * argument.
-			 */
-			toid = typeid(type(relname));
-			/* replace it in the arg list */
-			lfirst(fargs) =
-				makeVar(vnum, 0, toid, vnum, 0);
-		}
-		else if (!attisset)
-		{						/* set functions don't have parameters */
-
-			/*
-			 * any functiona args which are typed "unknown", but aren't
-			 * constants, we don't know what to do with, because we can't
-			 * cast them	- jolly
-			 */
-			if (exprType(pair) == UNKNOWNOID &&
-				!IsA(pair, Const))
-			{
-				elog(WARN, "ParseFunc: no function named '%s' that takes in an unknown type as argument #%d", funcname, nargs);
-			}
-			else
-				toid = exprType(pair);
-		}
-
-		oid_array[nargs++] = toid;
-	}
-
-	/*
-	 * func_get_detail looks up the function in the catalogs, does
-	 * disambiguation for polymorphic functions, handles inheritance, and
-	 * returns the funcid and type and set or singleton status of the
-	 * function's return value.  it also returns the true argument types
-	 * to the function.  if func_get_detail returns true, the function
-	 * exists.	otherwise, there was an error.
-	 */
-	if (attisset)
-	{							/* we know all of these fields already */
-
-		/*
-		 * We create a funcnode with a placeholder function SetEval.
-		 * SetEval() never actually gets executed.	When the function
-		 * evaluation routines see it, they use the funcid projected out
-		 * from the relation as the actual function to call. Example:
-		 * retrieve (emp.mgr.name) The plan for this will scan the emp
-		 * relation, projecting out the mgr attribute, which is a funcid.
-		 * This function is then called (instead of SetEval) and "name" is
-		 * projected from its result.
-		 */
-		funcid = SetEvalRegProcedure;
-		rettype = toid;
-		retset = true;
-		true_oid_array = oid_array;
-		exists = true;
-	}
-	else
-	{
-		exists = func_get_detail(funcname, nargs, oid_array, &funcid,
-								 &rettype, &retset, &true_oid_array);
-	}
-
-	if (!exists)
-		elog(WARN, "no such attribute or function '%s'", funcname);
-
-	/* got it */
-	funcnode = makeNode(Func);
-	funcnode->funcid = funcid;
-	funcnode->functype = rettype;
-	funcnode->funcisindex = false;
-	funcnode->funcsize = 0;
-	funcnode->func_fcache = NULL;
-	funcnode->func_tlist = NIL;
-	funcnode->func_planlist = NIL;
-
-	/* perform the necessary typecasting */
-	make_arguments(nargs, fargs, oid_array, true_oid_array);
-
-	/*
-	 * for functions returning base types, we want to project out the
-	 * return value.  set up a target list to do that.	the executor will
-	 * ignore these for c functions, and do the right thing for postquel
-	 * functions.
-	 */
-
-	if (typeid_get_relid(rettype) == InvalidOid)
-		funcnode->func_tlist = setup_base_tlist(rettype);
-
-	/*
-	 * For sets, we want to make a targetlist to project out this
-	 * attribute of the set tuples.
-	 */
-	if (attisset)
-	{
-		if (!strcmp(funcname, "*"))
-		{
-			funcnode->func_tlist =
-				expandAll(pstate, relname, refname, curr_resno);
-		}
-		else
-		{
-			funcnode->func_tlist = setup_tlist(funcname, argrelid);
-			rettype = find_atttype(argrelid, funcname);
-		}
-	}
-
-	/*
-	 * Sequence handling.
-	 */
-	if (funcid == SeqNextValueRegProcedure ||
-		funcid == SeqCurrValueRegProcedure)
-	{
-		Const	   *seq;
-		char	   *seqrel;
-		text	   *seqname;
-		int32		aclcheck_result = -1;
-		extern text *lower (text *string);
-
-		Assert(length(fargs) == 1);
-		seq = (Const *) lfirst(fargs);
-		if (!IsA((Node *) seq, Const))
-			elog(WARN, "%s: only constant sequence names are acceptable", funcname);
-		seqname = lower ((text*)DatumGetPointer(seq->constvalue));
-		pfree (DatumGetPointer(seq->constvalue));
-		seq->constvalue = PointerGetDatum (seqname);
-		seqrel = textout(seqname);
-
-		if ((aclcheck_result = pg_aclcheck(seqrel, GetPgUserName(),
-			   ((funcid == SeqNextValueRegProcedure) ? ACL_WR : ACL_RD)))
-			!= ACLCHECK_OK)
-			elog(WARN, "%s.%s: %s",
-			  seqrel, funcname, aclcheck_error_strings[aclcheck_result]);
-
-		pfree(seqrel);
-
-		if (funcid == SeqNextValueRegProcedure && inWhereClause)
-			elog(WARN, "nextval of a sequence in WHERE disallowed");
-	}
-
-	expr = makeNode(Expr);
-	expr->typeOid = rettype;
-	expr->opType = FUNC_EXPR;
-	expr->oper = (Node *) funcnode;
-	expr->args = fargs;
-	retval = (Node *) expr;
-
-	/*
-	 * if the function returns a set of values, then we need to iterate
-	 * over all the returned values in the executor, so we stick an iter
-	 * node here.  if it returns a singleton, then we don't need the iter
-	 * node.
-	 */
-
-	if (retset)
-	{
-		Iter	   *iter = makeNode(Iter);
-
-		iter->itertype = rettype;
-		iter->iterexpr = retval;
-		retval = (Node *) iter;
-	}
-
-	return (retval);
-}
-
-/*****************************************************************************
- *
- *****************************************************************************/
-
-/*
- * AddAggToParseState -
- *	  add the aggregate to the list of unique aggregates in pstate.
- *
- * SIDE EFFECT: aggno in target list entry will be modified
- */
-static void
-AddAggToParseState(ParseState *pstate, Aggreg *aggreg)
-{
-	List	   *ag;
-	int			i;
-
-	/*
-	 * see if we have the aggregate already (we only need to record the
-	 * aggregate once)
-	 */
-	i = 0;
-	foreach(ag, pstate->p_aggs)
-	{
-		Aggreg	   *a = lfirst(ag);
-
-		if (!strcmp(a->aggname, aggreg->aggname) &&
-			equal(a->target, aggreg->target))
-		{
-
-			/* fill in the aggno and we're done */
-			aggreg->aggno = i;
-			return;
-		}
-		i++;
-	}
-
-	/* not found, new aggregate */
-	aggreg->aggno = i;
-	pstate->p_numAgg++;
-	pstate->p_aggs = lappend(pstate->p_aggs, aggreg);
-	return;
-}
-
-/*
- * finalizeAggregates -
- *	  fill in qry_aggs from pstate. Also checks to make sure that aggregates
- *	  are used in the proper place.
- */
-static void
-finalizeAggregates(ParseState *pstate, Query *qry)
-{
-	List	   *l;
-	int			i;
-
-	parseCheckAggregates(pstate, qry);
-
-	qry->qry_numAgg = pstate->p_numAgg;
-	qry->qry_aggs =
-		(Aggreg **) palloc(sizeof(Aggreg *) * qry->qry_numAgg);
-	i = 0;
-	foreach(l, pstate->p_aggs)
-		qry->qry_aggs[i++] = (Aggreg *) lfirst(l);
-}
-
-/*
- * contain_agg_clause--
- *	  Recursively find aggreg nodes from a clause.
- *
- *	  Returns true if any aggregate found.
- */
-static bool
-contain_agg_clause(Node *clause)
-{
-	if (clause == NULL)
-		return FALSE;
-	else if (IsA(clause, Aggreg))
-		return TRUE;
-	else if (IsA(clause, Iter))
-		return contain_agg_clause(((Iter *) clause)->iterexpr);
-	else if (single_node(clause))
-		return FALSE;
-	else if (or_clause(clause))
-	{
-		List	   *temp;
-
-		foreach(temp, ((Expr *) clause)->args)
-			if (contain_agg_clause(lfirst(temp)))
-			return TRUE;
-		return FALSE;
-	}
-	else if (is_funcclause(clause))
-	{
-		List	   *temp;
-
-		foreach(temp, ((Expr *) clause)->args)
-			if (contain_agg_clause(lfirst(temp)))
-			return TRUE;
-		return FALSE;
-	}
-	else if (IsA(clause, ArrayRef))
-	{
-		List	   *temp;
-
-		foreach(temp, ((ArrayRef *) clause)->refupperindexpr)
-			if (contain_agg_clause(lfirst(temp)))
-			return TRUE;
-		foreach(temp, ((ArrayRef *) clause)->reflowerindexpr)
-			if (contain_agg_clause(lfirst(temp)))
-			return TRUE;
-		if (contain_agg_clause(((ArrayRef *) clause)->refexpr))
-			return TRUE;
-		if (contain_agg_clause(((ArrayRef *) clause)->refassgnexpr))
-			return TRUE;
-		return FALSE;
-	}
-	else if (not_clause(clause))
-		return contain_agg_clause((Node *) get_notclausearg((Expr *) clause));
-	else if (is_opclause(clause))
-		return (contain_agg_clause((Node *) get_leftop((Expr *) clause)) ||
-			  contain_agg_clause((Node *) get_rightop((Expr *) clause)));
-
-	return FALSE;
-}
-
-/*
- * exprIsAggOrGroupCol -
- *	  returns true if the expression does not contain non-group columns.
- */
-static bool
-exprIsAggOrGroupCol(Node *expr, List *groupClause)
-{
-	List	   *gl;
-
-	if (expr == NULL || IsA(expr, Const) ||
-		IsA(expr, Param) ||IsA(expr, Aggreg))
-		return TRUE;
-
-	foreach(gl, groupClause)
-	{
-		GroupClause *grpcl = lfirst(gl);
-
-		if (equal(expr, grpcl->entry->expr))
-			return TRUE;
-	}
-
-	if (IsA(expr, Expr))
-	{
-		List	   *temp;
-
-		foreach(temp, ((Expr *) expr)->args)
-			if (!exprIsAggOrGroupCol(lfirst(temp), groupClause))
-			return FALSE;
-		return TRUE;
-	}
-
-	return FALSE;
-}
-
-/*
- * tleIsAggOrGroupCol -
- *	  returns true if the TargetEntry is Agg or GroupCol.
- */
-static bool
-tleIsAggOrGroupCol(TargetEntry *tle, List *groupClause)
-{
-	Node	   *expr = tle->expr;
-	List	   *gl;
-
-	if (expr == NULL || IsA(expr, Const) ||IsA(expr, Param))
-		return TRUE;
-
-	foreach(gl, groupClause)
-	{
-		GroupClause *grpcl = lfirst(gl);
-
-		if (tle->resdom->resno == grpcl->entry->resdom->resno)
-		{
-			if (contain_agg_clause((Node *) expr))
-				elog(WARN, "parser: aggregates not allowed in GROUP BY clause");
-			return TRUE;
-		}
-	}
-
-	if (IsA(expr, Aggreg))
-		return TRUE;
-
-	if (IsA(expr, Expr))
-	{
-		List	   *temp;
-
-		foreach(temp, ((Expr *) expr)->args)
-			if (!exprIsAggOrGroupCol(lfirst(temp), groupClause))
-			return FALSE;
-		return TRUE;
-	}
-
-	return FALSE;
-}
-
-/*
- * parseCheckAggregates -
- *	  this should really be done earlier but the current grammar
- *	  cannot differentiate functions from aggregates. So we have do check
- *	  here when the target list and the qualifications are finalized.
- */
-static void
-parseCheckAggregates(ParseState *pstate, Query *qry)
-{
-	List	   *tl;
-
-	Assert(pstate->p_numAgg > 0);
-
-	/*
-	 * aggregates never appear in WHERE clauses. (we have to check where
-	 * clause first because if there is an aggregate, the check for
-	 * non-group column in target list may fail.)
-	 */
-	if (contain_agg_clause(qry->qual))
-		elog(WARN, "parser: aggregates not allowed in WHERE clause");
-
-	/*
-	 * the target list can only contain aggregates, group columns and
-	 * functions thereof.
-	 */
-	foreach(tl, qry->targetList)
-	{
-		TargetEntry *tle = lfirst(tl);
-
-		if (!tleIsAggOrGroupCol(tle, qry->groupClause))
-			elog(WARN,
-				 "parser: illegal use of aggregates or non-group column in target list");
-	}
-
-	/*
-	 * the expression specified in the HAVING clause has the same
-	 * restriction as those in the target list.
-	 */
-/*
- * Need to change here when we get HAVING works. Currently
- * qry->havingQual is NULL.		- vadim 04/05/97
-	if (!exprIsAggOrGroupCol(qry->havingQual, qry->groupClause))
-		elog(WARN,
-			 "parser: illegal use of aggregates or non-group column in HAVING clause");
- */
-	return;
-}
-
-/* not used
-#define    PSIZE(PTR)	   (*((int32 *)(PTR) - 1))
-*/
-
-static Node	   *
-parser_typecast(Value *expr, TypeName *typename, int typlen)
-{
-	/* check for passing non-ints */
-	Const	   *adt;
-	Datum		lcp;
-	Type		tp;
-	char		type_string[NAMEDATALEN];
-	int32		len;
-	char	   *cp = NULL;
-	char	   *const_string = NULL;
-	bool		string_palloced = false;
-
-	switch (nodeTag(expr))
-	{
-		case T_String:
-			const_string = DatumGetPointer(expr->val.str);
-			break;
-		case T_Integer:
-			const_string = (char *) palloc(256);
-			string_palloced = true;
-			sprintf(const_string, "%ld", expr->val.ival);
-			break;
-		default:
-			elog(WARN,
-			"parser_typecast: cannot cast this expression to type \"%s\"",
-				 typename->name);
-	}
-
-	if (typename->arrayBounds != NIL)
-	{
-		sprintf(type_string, "_%s", typename->name);
-		tp = (Type) type(type_string);
-	}
-	else
-	{
-		tp = (Type) type(typename->name);
-	}
-
-	len = tlen(tp);
-
-#if 0							/* fix me */
-	switch (CInteger(lfirst(expr)))
-	{
-		case INT4OID:			/* int4 */
-			const_string = (char *) palloc(256);
-			string_palloced = true;
-			sprintf(const_string, "%d", ((Const *) lnext(expr))->constvalue);
-			break;
-
-		case NAMEOID:			/* char16 */
-			const_string = (char *) palloc(256);
-			string_palloced = true;
-			sprintf(const_string, "%s", ((Const *) lnext(expr))->constvalue);
-			break;
-
-		case CHAROID:			/* char */
-			const_string = (char *) palloc(256);
-			string_palloced = true;
-			sprintf(const_string, "%c", ((Const) lnext(expr))->constvalue);
-			break;
-
-		case FLOAT8OID: /* float8 */
-			const_string = (char *) palloc(256);
-			string_palloced = true;
-			sprintf(const_string, "%f", ((Const) lnext(expr))->constvalue);
-			break;
-
-		case CASHOID:			/* money */
-			const_string = (char *) palloc(256);
-			string_palloced = true;
-			sprintf(const_string, "%d",
-					(int) ((Const *) expr)->constvalue);
-			break;
-
-		case TEXTOID:			/* text */
-			const_string = DatumGetPointer(((Const) lnext(expr))->constvalue);
-			const_string = (char *) textout((struct varlena *) const_string);
-			break;
-
-		case UNKNOWNOID:		/* unknown */
-			const_string = DatumGetPointer(((Const) lnext(expr))->constvalue);
-			const_string = (char *) textout((struct varlena *) const_string);
-			break;
-
-		default:
-			elog(WARN, "unknown type %d", CInteger(lfirst(expr)));
-	}
-#endif
-
-	cp = instr2(tp, const_string, typlen);
-
-	if (!tbyvalue(tp))
-	{
-/*
-		if (len >= 0 && len != PSIZE(cp)) {
-			char *pp;
-			pp = (char *) palloc(len);
-			memmove(pp, cp, len);
-			cp = pp;
-		}
-*/
-		lcp = PointerGetDatum(cp);
-	}
-	else
-	{
-		switch (len)
-		{
-			case 1:
-				lcp = Int8GetDatum(cp);
-				break;
-			case 2:
-				lcp = Int16GetDatum(cp);
-				break;
-			case 4:
-				lcp = Int32GetDatum(cp);
-				break;
-			default:
-				lcp = PointerGetDatum(cp);
-				break;
-		}
-	}
-
-	adt = makeConst(typeid(tp),
-					len,
-					(Datum) lcp,
-					false,
-					tbyvalue(tp),
-					false,		/* not a set */
-					true /* is cast */ );
-
-	if (string_palloced)
-		pfree(const_string);
-
-	return (Node *) adt;
-}
-
-static Node	   *
-parser_typecast2(Node *expr, Oid exprType, Type tp, int typlen)
-{
-	/* check for passing non-ints */
-	Const	   *adt;
-	Datum		lcp;
-	int32		len = tlen(tp);
-	char	   *cp = NULL;
-
-	char	   *const_string = NULL;
-	bool		string_palloced = false;
-
-	Assert(IsA(expr, Const));
-
-	switch (exprType)
-	{
-		case 0:			/* NULL */
-			break;
-		case INT4OID:			/* int4 */
-			const_string = (char *) palloc(256);
-			string_palloced = true;
-			sprintf(const_string, "%d",
-					(int) ((Const *) expr)->constvalue);
-			break;
-		case NAMEOID:			/* char16 */
-			const_string = (char *) palloc(256);
-			string_palloced = true;
-			sprintf(const_string, "%s",
-					(char *) ((Const *) expr)->constvalue);
-			break;
-		case CHAROID:			/* char */
-			const_string = (char *) palloc(256);
-			string_palloced = true;
-			sprintf(const_string, "%c",
-					(char) ((Const *) expr)->constvalue);
-			break;
-		case FLOAT4OID: /* float4 */
-			{
-				float32		floatVal =
-				DatumGetFloat32(((Const *) expr)->constvalue);
-
-				const_string = (char *) palloc(256);
-				string_palloced = true;
-				sprintf(const_string, "%f", *floatVal);
-				break;
-			}
-		case FLOAT8OID: /* float8 */
-			{
-				float64		floatVal =
-				DatumGetFloat64(((Const *) expr)->constvalue);
-
-				const_string = (char *) palloc(256);
-				string_palloced = true;
-				sprintf(const_string, "%f", *floatVal);
-				break;
-			}
-		case CASHOID:			/* money */
-			const_string = (char *) palloc(256);
-			string_palloced = true;
-			sprintf(const_string, "%ld",
-					(long) ((Const *) expr)->constvalue);
-			break;
-		case TEXTOID:			/* text */
-			const_string =
-				DatumGetPointer(((Const *) expr)->constvalue);
-			const_string = (char *) textout((struct varlena *) const_string);
-			break;
-		case UNKNOWNOID:		/* unknown */
-			const_string =
-				DatumGetPointer(((Const *) expr)->constvalue);
-			const_string = (char *) textout((struct varlena *) const_string);
-			break;
-		default:
-			elog(WARN, "unknown type %u ", exprType);
-	}
-
-	if (!exprType)
-	{
-		adt = makeConst(typeid(tp),
-						(Size) 0,
-						(Datum) NULL,
-						true,	/* isnull */
-						false,	/* was omitted */
-						false,	/* not a set */
-						true /* is cast */ );
-		return ((Node *) adt);
-	}
-
-	cp = instr2(tp, const_string, typlen);
-
-
-	if (!tbyvalue(tp))
-	{
-/*
-		if (len >= 0 && len != PSIZE(cp)) {
-			char *pp;
-			pp = (char *) palloc(len);
-			memmove(pp, cp, len);
-			cp = pp;
-		}
-*/
-		lcp = PointerGetDatum(cp);
-	}
-	else
-	{
-		switch (len)
-		{
-			case 1:
-				lcp = Int8GetDatum(cp);
-				break;
-			case 2:
-				lcp = Int16GetDatum(cp);
-				break;
-			case 4:
-				lcp = Int32GetDatum(cp);
-				break;
-			default:
-				lcp = PointerGetDatum(cp);
-				break;
-		}
-	}
-
-	adt = makeConst(typeid(tp),
-					(Size) len,
-					(Datum) lcp,
-					false,
-					false,		/* was omitted */
-					false,		/* not a set */
-					true /* is cast */ );
-
-	/*
-	 * printf("adt %s : %u %d %d\n",CString(expr),typeid(tp) , len,cp);
-	 */
-	if (string_palloced)
-		pfree(const_string);
-
-	return ((Node *) adt);
-}
-
-static Aggreg	   *
-ParseAgg(char *aggname, Oid basetype, Node *target)
-{
-	Oid			fintype;
-	Oid			vartype;
-	Oid			xfn1;
-	Form_pg_aggregate aggform;
-	Aggreg	   *aggreg;
-	HeapTuple	theAggTuple;
-
-	theAggTuple = SearchSysCacheTuple(AGGNAME, PointerGetDatum(aggname),
-									  ObjectIdGetDatum(basetype),
-									  0, 0);
-	if (!HeapTupleIsValid(theAggTuple))
-	{
-		elog(WARN, "aggregate %s does not exist", aggname);
-	}
-
-	aggform = (Form_pg_aggregate) GETSTRUCT(theAggTuple);
-	fintype = aggform->aggfinaltype;
-	xfn1 = aggform->aggtransfn1;
-
-	if (nodeTag(target) != T_Var && nodeTag(target) != T_Expr)
-		elog(WARN, "parser: aggregate can only be applied on an attribute or expression");
-
-	/* only aggregates with transfn1 need a base type */
-	if (OidIsValid(xfn1))
-	{
-		basetype = aggform->aggbasetype;
-		if (nodeTag(target) == T_Var)
-			vartype = ((Var *) target)->vartype;
-		else
-			vartype = ((Expr *) target)->typeOid;
-
-		if (basetype != vartype)
-		{
-			Type		tp1,
-						tp2;
-
-			tp1 = get_id_type(basetype);
-			tp2 = get_id_type(vartype);
-			elog(NOTICE, "Aggregate type mismatch:");
-			elog(WARN, "%s works on %s, not %s", aggname,
-				 tname(tp1), tname(tp2));
-		}
-	}
-
-	aggreg = makeNode(Aggreg);
-	aggreg->aggname = pstrdup(aggname);
-	aggreg->basetype = aggform->aggbasetype;
-	aggreg->aggtype = fintype;
-
-	aggreg->target = target;
-
-	return aggreg;
-}
diff --git a/src/backend/parser/catalog_utils.c b/src/backend/parser/catalog_utils.c
deleted file mode 100644
index b119c7dbb5a75ce4757bc167e62d762b538e0efc..0000000000000000000000000000000000000000
--- a/src/backend/parser/catalog_utils.c
+++ /dev/null
@@ -1,1686 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * catalog_utils.c--
- *
- * Copyright (c) 1994, Regents of the University of California
- *
- *
- * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/parser/Attic/catalog_utils.c,v 1.30 1997/11/20 23:22:14 momjian Exp $
- *
- *-------------------------------------------------------------------------
- */
-#include <string.h>
-#include "postgres.h"
-
-#include "lib/dllist.h"
-#include "utils/datum.h"
-
-#include "utils/builtins.h"
-#include "utils/elog.h"
-#include "utils/palloc.h"
-#include "fmgr.h"
-
-#include "nodes/pg_list.h"
-#include "nodes/parsenodes.h"
-#include "utils/syscache.h"
-#include "catalog/catname.h"
-
-#include "parser/catalog_utils.h"
-#include "catalog/pg_inherits.h"
-#include "catalog/pg_operator.h"
-#include "catalog/pg_type.h"
-#include "catalog/pg_proc.h"
-#include "catalog/indexing.h"
-#include "catalog/catname.h"
-
-#include "access/skey.h"
-#include "access/relscan.h"
-#include "access/tupdesc.h"
-#include "access/htup.h"
-#include "access/heapam.h"
-#include "access/genam.h"
-#include "access/itup.h"
-#include "access/tupmacs.h"
-
-#include "storage/buf.h"
-#include "storage/bufmgr.h"
-#include "utils/lsyscache.h"
-#include "storage/lmgr.h"
-
-#include "port-protos.h"		/* strdup() */
-
-struct
-{
-	char	   *field;
-	int			code;
-}			special_attr[] =
-
-{
-	{
-		"ctid", SelfItemPointerAttributeNumber
-	},
-	{
-		"oid", ObjectIdAttributeNumber
-	},
-	{
-		"xmin", MinTransactionIdAttributeNumber
-	},
-	{
-		"cmin", MinCommandIdAttributeNumber
-	},
-	{
-		"xmax", MaxTransactionIdAttributeNumber
-	},
-	{
-		"cmax", MaxCommandIdAttributeNumber
-	},
-};
-
-#define SPECIALS (sizeof(special_attr)/sizeof(*special_attr))
-
-static char *attnum_type[SPECIALS] = {
-	"tid",
-	"oid",
-	"xid",
-	"cid",
-	"xid",
-	"cid",
-};
-
-#define MAXFARGS 8				/* max # args to a c or postquel function */
-
-/*
- *	This structure is used to explore the inheritance hierarchy above
- *	nodes in the type tree in order to disambiguate among polymorphic
- *	functions.
- */
-
-typedef struct _InhPaths
-{
-	int			nsupers;		/* number of superclasses */
-	Oid			self;			/* this class */
-	Oid		   *supervec;		/* vector of superclasses */
-} InhPaths;
-
-/*
- *	This structure holds a list of possible functions or operators that
- *	agree with the known name and argument types of the function/operator.
- */
-typedef struct _CandidateList
-{
-	Oid		   *args;
-	struct _CandidateList *next;
-}		   *CandidateList;
-
-static Oid **argtype_inherit(int nargs, Oid *oid_array);
-static Oid **genxprod(InhPaths *arginh, int nargs);
-static int	findsupers(Oid relid, Oid **supervec);
-static bool check_typeid(Oid id);
-static char *instr1(TypeTupleForm tp, char *string, int typlen);
-static void op_error(char *op, Oid arg1, Oid arg2);
-
-/* check to see if a type id is valid,
- * returns true if it is. By using this call before calling
- * get_id_type or get_id_typname, more meaningful error messages
- * can be produced because the caller typically has more context of
- *	what's going on                 - jolly
- */
-static bool
-check_typeid(Oid id)
-{
-	return (SearchSysCacheTuple(TYPOID,
-								ObjectIdGetDatum(id),
-								0, 0, 0) != NULL);
-}
-
-
-/* return a Type structure, given an typid */
-Type
-get_id_type(Oid id)
-{
-	HeapTuple	tup;
-
-	if (!(tup = SearchSysCacheTuple(TYPOID, ObjectIdGetDatum(id),
-									0, 0, 0)))
-	{
-		elog(WARN, "type id lookup of %ud failed", id);
-		return (NULL);
-	}
-	return ((Type) tup);
-}
-
-/* return a type name, given a typeid */
-char	   *
-get_id_typname(Oid id)
-{
-	HeapTuple	tup;
-	TypeTupleForm typetuple;
-
-	if (!(tup = SearchSysCacheTuple(TYPOID, ObjectIdGetDatum(id),
-									0, 0, 0)))
-	{
-		elog(WARN, "type id lookup of %ud failed", id);
-		return (NULL);
-	}
-	typetuple = (TypeTupleForm) GETSTRUCT(tup);
-	return (typetuple->typname).data;
-}
-
-/* return a Type structure, given type name */
-Type
-type(char *s)
-{
-	HeapTuple	tup;
-
-	if (s == NULL)
-	{
-		elog(WARN, "type(): Null type");
-	}
-
-	if (!(tup = SearchSysCacheTuple(TYPNAME, PointerGetDatum(s), 0, 0, 0)))
-	{
-		elog(WARN, "type name lookup of %s failed", s);
-	}
-	return ((Type) tup);
-}
-
-/* given attribute id, return type of that attribute */
-/* XXX Special case for pseudo-attributes is a hack */
-Oid
-att_typeid(Relation rd, int attid)
-{
-
-	if (attid < 0)
-	{
-		return (typeid(type(attnum_type[-attid - 1])));
-	}
-
-	/*
-	 * -1 because varattno (where attid comes from) returns one more than
-	 * index
-	 */
-	return (rd->rd_att->attrs[attid - 1]->atttypid);
-}
-
-
-int
-att_attnelems(Relation rd, int attid)
-{
-	return (rd->rd_att->attrs[attid - 1]->attnelems);
-}
-
-/* given type, return the type OID */
-Oid
-typeid(Type tp)
-{
-	if (tp == NULL)
-	{
-		elog(WARN, "typeid() called with NULL type struct");
-	}
-	return (tp->t_oid);
-}
-
-/* given type (as type struct), return the length of type */
-int16
-tlen(Type t)
-{
-	TypeTupleForm typ;
-
-	typ = (TypeTupleForm) GETSTRUCT(t);
-	return (typ->typlen);
-}
-
-/* given type (as type struct), return the value of its 'byval' attribute.*/
-bool
-tbyval(Type t)
-{
-	TypeTupleForm typ;
-
-	typ = (TypeTupleForm) GETSTRUCT(t);
-	return (typ->typbyval);
-}
-
-/* given type (as type struct), return the name of type */
-char	   *
-tname(Type t)
-{
-	TypeTupleForm typ;
-
-	typ = (TypeTupleForm) GETSTRUCT(t);
-	return (typ->typname).data;
-}
-
-/* given type (as type struct), return wether type is passed by value */
-int
-tbyvalue(Type t)
-{
-	TypeTupleForm typ;
-
-	typ = (TypeTupleForm) GETSTRUCT(t);
-	return (typ->typbyval);
-}
-
-/* given a type, return its typetype ('c' for 'c'atalog types) */
-static char
-typetypetype(Type t)
-{
-	TypeTupleForm typ;
-
-	typ = (TypeTupleForm) GETSTRUCT(t);
-	return (typ->typtype);
-}
-
-/* given operator, return the operator OID */
-Oid
-oprid(Operator op)
-{
-	return (op->t_oid);
-}
-
-/*
- *	given opname, leftTypeId and rightTypeId,
- *	find all possible (arg1, arg2) pairs for which an operator named
- *	opname exists, such that leftTypeId can be coerced to arg1 and
- *	rightTypeId can be coerced to arg2
- */
-static int
-binary_oper_get_candidates(char *opname,
-						   Oid leftTypeId,
-						   Oid rightTypeId,
-						   CandidateList *candidates)
-{
-	CandidateList current_candidate;
-	Relation	pg_operator_desc;
-	HeapScanDesc pg_operator_scan;
-	HeapTuple	tup;
-	OperatorTupleForm oper;
-	Buffer		buffer;
-	int			nkeys;
-	int			ncandidates = 0;
-	ScanKeyData opKey[3];
-
-	*candidates = NULL;
-
-	ScanKeyEntryInitialize(&opKey[0], 0,
-						   Anum_pg_operator_oprname,
-						   NameEqualRegProcedure,
-						   NameGetDatum(opname));
-
-	ScanKeyEntryInitialize(&opKey[1], 0,
-						   Anum_pg_operator_oprkind,
-						   CharacterEqualRegProcedure,
-						   CharGetDatum('b'));
-
-
-	if (leftTypeId == UNKNOWNOID)
-	{
-		if (rightTypeId == UNKNOWNOID)
-		{
-			nkeys = 2;
-		}
-		else
-		{
-			nkeys = 3;
-
-			ScanKeyEntryInitialize(&opKey[2], 0,
-								   Anum_pg_operator_oprright,
-								   ObjectIdEqualRegProcedure,
-								   ObjectIdGetDatum(rightTypeId));
-		}
-	}
-	else if (rightTypeId == UNKNOWNOID)
-	{
-		nkeys = 3;
-
-		ScanKeyEntryInitialize(&opKey[2], 0,
-							   Anum_pg_operator_oprleft,
-							   ObjectIdEqualRegProcedure,
-							   ObjectIdGetDatum(leftTypeId));
-	}
-	else
-	{
-		/* currently only "unknown" can be coerced */
-		return 0;
-	}
-
-	pg_operator_desc = heap_openr(OperatorRelationName);
-	pg_operator_scan = heap_beginscan(pg_operator_desc,
-									  0,
-									  true,
-									  nkeys,
-									  opKey);
-
-	do
-	{
-		tup = heap_getnext(pg_operator_scan, 0, &buffer);
-		if (HeapTupleIsValid(tup))
-		{
-			current_candidate = (CandidateList) palloc(sizeof(struct _CandidateList));
-			current_candidate->args = (Oid *) palloc(2 * sizeof(Oid));
-
-			oper = (OperatorTupleForm) GETSTRUCT(tup);
-			current_candidate->args[0] = oper->oprleft;
-			current_candidate->args[1] = oper->oprright;
-			current_candidate->next = *candidates;
-			*candidates = current_candidate;
-			ncandidates++;
-			ReleaseBuffer(buffer);
-		}
-	} while (HeapTupleIsValid(tup));
-
-	heap_endscan(pg_operator_scan);
-	heap_close(pg_operator_desc);
-
-	return ncandidates;
-}
-
-/*
- * equivalentOpersAfterPromotion -
- *	  checks if a list of candidate operators obtained from
- *	  binary_oper_get_candidates() contain equivalent operators. If
- *	  this routine is called, we have more than 1 candidate and need to
- *	  decided whether to pick one of them. This routine returns true if
- *	  the all the candidates operate on the same data types after
- *	  promotion (int2, int4, float4 -> float8).
- */
-static bool
-equivalentOpersAfterPromotion(CandidateList candidates)
-{
-	CandidateList result;
-	CandidateList promotedCandidates = NULL;
-	Oid			leftarg,
-				rightarg;
-
-	for (result = candidates; result != NULL; result = result->next)
-	{
-		CandidateList c;
-
-		c = (CandidateList) palloc(sizeof(*c));
-		c->args = (Oid *) palloc(2 * sizeof(Oid));
-		switch (result->args[0])
-		{
-			case FLOAT4OID:
-			case INT4OID:
-			case INT2OID:
-			case CASHOID:
-				c->args[0] = FLOAT8OID;
-				break;
-			default:
-				c->args[0] = result->args[0];
-				break;
-		}
-		switch (result->args[1])
-		{
-			case FLOAT4OID:
-			case INT4OID:
-			case INT2OID:
-			case CASHOID:
-				c->args[1] = FLOAT8OID;
-				break;
-			default:
-				c->args[1] = result->args[1];
-				break;
-		}
-		c->next = promotedCandidates;
-		promotedCandidates = c;
-	}
-
-	/*
-	 * if we get called, we have more than 1 candidates so we can do the
-	 * following safely
-	 */
-	leftarg = promotedCandidates->args[0];
-	rightarg = promotedCandidates->args[1];
-
-	for (result = promotedCandidates->next; result != NULL; result = result->next)
-	{
-		if (result->args[0] != leftarg || result->args[1] != rightarg)
-
-			/*
-			 * this list contains operators that operate on different data
-			 * types even after promotion. Hence we can't decide on which
-			 * one to pick. The user must do explicit type casting.
-			 */
-			return FALSE;
-	}
-
-	/*
-	 * all the candidates are equivalent in the following sense: they
-	 * operate on equivalent data types and picking any one of them is as
-	 * good.
-	 */
-	return TRUE;
-}
-
-
-/*
- *	given a choice of argument type pairs for a binary operator,
- *	try to choose a default pair
- */
-static CandidateList
-binary_oper_select_candidate(Oid arg1,
-							 Oid arg2,
-							 CandidateList candidates)
-{
-	CandidateList result;
-
-	/*
-	 * if both are "unknown", there is no way to select a candidate
-	 *
-	 * current wisdom holds that the default operator should be one in which
-	 * both operands have the same type (there will only be one such
-	 * operator)
-	 *
-	 * 7.27.93 - I have decided not to do this; it's too hard to justify, and
-	 * it's easy enough to typecast explicitly -avi [the rest of this
-	 * routine were commented out since then -ay]
-	 */
-
-	if (arg1 == UNKNOWNOID && arg2 == UNKNOWNOID)
-		return (NULL);
-
-	/*
-	 * 6/23/95 - I don't complete agree with avi. In particular, casting
-	 * floats is a pain for users. Whatever the rationale behind not doing
-	 * this is, I need the following special case to work.
-	 *
-	 * In the WHERE clause of a query, if a float is specified without
-	 * quotes, we treat it as float8. I added the float48* operators so
-	 * that we can operate on float4 and float8. But now we have more than
-	 * one matching operator if the right arg is unknown (eg. float
-	 * specified with quotes). This break some stuff in the regression
-	 * test where there are floats in quotes not properly casted. Below is
-	 * the solution. In addition to requiring the operator operates on the
-	 * same type for both operands [as in the code Avi originally
-	 * commented out], we also require that the operators be equivalent in
-	 * some sense. (see equivalentOpersAfterPromotion for details.) - ay
-	 * 6/95
-	 */
-	if (!equivalentOpersAfterPromotion(candidates))
-		return NULL;
-
-	/*
-	 * if we get here, any one will do but we're more picky and require
-	 * both operands be the same.
-	 */
-	for (result = candidates; result != NULL; result = result->next)
-	{
-		if (result->args[0] == result->args[1])
-			return result;
-	}
-
-	return (NULL);
-}
-
-/* Given operator, types of arg1, and arg2, return oper struct */
-/* arg1, arg2 --typeids */
-Operator
-oper(char *op, Oid arg1, Oid arg2, bool noWarnings)
-{
-	HeapTuple	tup;
-	CandidateList candidates;
-	int			ncandidates;
-
-	if (!arg2)
-		arg2 = arg1;
-	if (!arg1)
-		arg1 = arg2;
-
-	if (!(tup = SearchSysCacheTuple(OPRNAME,
-									PointerGetDatum(op),
-									ObjectIdGetDatum(arg1),
-									ObjectIdGetDatum(arg2),
-									Int8GetDatum('b'))))
-	{
-		ncandidates = binary_oper_get_candidates(op, arg1, arg2, &candidates);
-		if (ncandidates == 0)
-		{
-
-			/*
-			 * no operators of the desired types found
-			 */
-			if (!noWarnings)
-				op_error(op, arg1, arg2);
-			return (NULL);
-		}
-		else if (ncandidates == 1)
-		{
-
-			/*
-			 * exactly one operator of the desired types found
-			 */
-			tup = SearchSysCacheTuple(OPRNAME,
-									  PointerGetDatum(op),
-								   ObjectIdGetDatum(candidates->args[0]),
-								   ObjectIdGetDatum(candidates->args[1]),
-									  Int8GetDatum('b'));
-			Assert(HeapTupleIsValid(tup));
-		}
-		else
-		{
-
-			/*
-			 * multiple operators of the desired types found
-			 */
-			candidates = binary_oper_select_candidate(arg1, arg2, candidates);
-			if (candidates != NULL)
-			{
-				/* we chose one of them */
-				tup = SearchSysCacheTuple(OPRNAME,
-										  PointerGetDatum(op),
-								   ObjectIdGetDatum(candidates->args[0]),
-								   ObjectIdGetDatum(candidates->args[1]),
-										  Int8GetDatum('b'));
-				Assert(HeapTupleIsValid(tup));
-			}
-			else
-			{
-				Type		tp1,
-							tp2;
-
-				/* we chose none of them */
-				tp1 = get_id_type(arg1);
-				tp2 = get_id_type(arg2);
-				if (!noWarnings)
-				{
-					elog(NOTICE, "there is more than one operator %s for types", op);
-					elog(NOTICE, "%s and %s. You will have to retype this query",
-						 tname(tp1), tname(tp2));
-					elog(WARN, "using an explicit cast");
-				}
-				return (NULL);
-			}
-		}
-	}
-	return ((Operator) tup);
-}
-
-/*
- *	given opname and typeId, find all possible types for which
- *	a right/left unary operator named opname exists,
- *	such that typeId can be coerced to it
- */
-static int
-unary_oper_get_candidates(char *op,
-						  Oid typeId,
-						  CandidateList *candidates,
-						  char rightleft)
-{
-	CandidateList current_candidate;
-	Relation	pg_operator_desc;
-	HeapScanDesc pg_operator_scan;
-	HeapTuple	tup;
-	OperatorTupleForm oper;
-	Buffer		buffer;
-	int			ncandidates = 0;
-
-	static ScanKeyData opKey[2] = {
-		{0, Anum_pg_operator_oprname, NameEqualRegProcedure},
-	{0, Anum_pg_operator_oprkind, CharacterEqualRegProcedure}};
-
-	*candidates = NULL;
-
-	fmgr_info(NameEqualRegProcedure, (func_ptr *) &opKey[0].sk_func,
-			  &opKey[0].sk_nargs);
-	opKey[0].sk_argument = NameGetDatum(op);
-	fmgr_info(CharacterEqualRegProcedure, (func_ptr *) &opKey[1].sk_func,
-			  &opKey[1].sk_nargs);
-	opKey[1].sk_argument = CharGetDatum(rightleft);
-
-	/* currently, only "unknown" can be coerced */
-
-	/*
-	 * but we should allow types that are internally the same to be
-	 * "coerced"
-	 */
-	if (typeId != UNKNOWNOID)
-	{
-		return 0;
-	}
-
-	pg_operator_desc = heap_openr(OperatorRelationName);
-	pg_operator_scan = heap_beginscan(pg_operator_desc,
-									  0,
-									  true,
-									  2,
-									  opKey);
-
-	do
-	{
-		tup = heap_getnext(pg_operator_scan, 0, &buffer);
-		if (HeapTupleIsValid(tup))
-		{
-			current_candidate = (CandidateList) palloc(sizeof(struct _CandidateList));
-			current_candidate->args = (Oid *) palloc(sizeof(Oid));
-
-			oper = (OperatorTupleForm) GETSTRUCT(tup);
-			if (rightleft == 'r')
-				current_candidate->args[0] = oper->oprleft;
-			else
-				current_candidate->args[0] = oper->oprright;
-			current_candidate->next = *candidates;
-			*candidates = current_candidate;
-			ncandidates++;
-			ReleaseBuffer(buffer);
-		}
-	} while (HeapTupleIsValid(tup));
-
-	heap_endscan(pg_operator_scan);
-	heap_close(pg_operator_desc);
-
-	return ncandidates;
-}
-
-/* Given unary right-side operator (operator on right), return oper struct */
-/* arg-- type id */
-Operator
-right_oper(char *op, Oid arg)
-{
-	HeapTuple	tup;
-	CandidateList candidates;
-	int			ncandidates;
-
-	/*
-	 * if (!OpCache) { init_op_cache(); }
-	 */
-	if (!(tup = SearchSysCacheTuple(OPRNAME,
-									PointerGetDatum(op),
-									ObjectIdGetDatum(arg),
-									ObjectIdGetDatum(InvalidOid),
-									Int8GetDatum('r'))))
-	{
-		ncandidates = unary_oper_get_candidates(op, arg, &candidates, 'r');
-		if (ncandidates == 0)
-		{
-			elog(WARN,
-				 "Can't find right op: %s for type %d", op, arg);
-			return (NULL);
-		}
-		else if (ncandidates == 1)
-		{
-			tup = SearchSysCacheTuple(OPRNAME,
-									  PointerGetDatum(op),
-								   ObjectIdGetDatum(candidates->args[0]),
-									  ObjectIdGetDatum(InvalidOid),
-									  Int8GetDatum('r'));
-			Assert(HeapTupleIsValid(tup));
-		}
-		else
-		{
-			elog(NOTICE, "there is more than one right operator %s", op);
-			elog(NOTICE, "you will have to retype this query");
-			elog(WARN, "using an explicit cast");
-			return (NULL);
-		}
-	}
-	return ((Operator) tup);
-}
-
-/* Given unary left-side operator (operator on left), return oper struct */
-/* arg--type id */
-Operator
-left_oper(char *op, Oid arg)
-{
-	HeapTuple	tup;
-	CandidateList candidates;
-	int			ncandidates;
-
-	/*
-	 * if (!OpCache) { init_op_cache(); }
-	 */
-	if (!(tup = SearchSysCacheTuple(OPRNAME,
-									PointerGetDatum(op),
-									ObjectIdGetDatum(InvalidOid),
-									ObjectIdGetDatum(arg),
-									Int8GetDatum('l'))))
-	{
-		ncandidates = unary_oper_get_candidates(op, arg, &candidates, 'l');
-		if (ncandidates == 0)
-		{
-			elog(WARN,
-				 "Can't find left op: %s for type %d", op, arg);
-			return (NULL);
-		}
-		else if (ncandidates == 1)
-		{
-			tup = SearchSysCacheTuple(OPRNAME,
-									  PointerGetDatum(op),
-									  ObjectIdGetDatum(InvalidOid),
-								   ObjectIdGetDatum(candidates->args[0]),
-									  Int8GetDatum('l'));
-			Assert(HeapTupleIsValid(tup));
-		}
-		else
-		{
-			elog(NOTICE, "there is more than one left operator %s", op);
-			elog(NOTICE, "you will have to retype this query");
-			elog(WARN, "using an explicit cast");
-			return (NULL);
-		}
-	}
-	return ((Operator) tup);
-}
-
-/* given range variable, return id of variable */
-
-int
-varattno(Relation rd, char *a)
-{
-	int			i;
-
-	for (i = 0; i < rd->rd_rel->relnatts; i++)
-	{
-		if (!namestrcmp(&(rd->rd_att->attrs[i]->attname), a))
-		{
-			return (i + 1);
-		}
-	}
-	for (i = 0; i < SPECIALS; i++)
-	{
-		if (!strcmp(special_attr[i].field, a))
-		{
-			return (special_attr[i].code);
-		}
-	}
-
-	elog(WARN, "Relation %s does not have attribute %s",
-		 RelationGetRelationName(rd), a);
-	return (-1);
-}
-
-/* Given range variable, return whether attribute of this name
- * is a set.
- * NOTE the ASSUMPTION here that no system attributes are, or ever
- * will be, sets.
- */
-bool
-varisset(Relation rd, char *name)
-{
-	int			i;
-
-	/* First check if this is a system attribute */
-	for (i = 0; i < SPECIALS; i++)
-	{
-		if (!strcmp(special_attr[i].field, name))
-		{
-			return (false);		/* no sys attr is a set */
-		}
-	}
-	return (get_attisset(rd->rd_id, name));
-}
-
-/* given range variable, return id of variable */
-int
-nf_varattno(Relation rd, char *a)
-{
-	int			i;
-
-	for (i = 0; i < rd->rd_rel->relnatts; i++)
-	{
-		if (!namestrcmp(&(rd->rd_att->attrs[i]->attname), a))
-		{
-			return (i + 1);
-		}
-	}
-	for (i = 0; i < SPECIALS; i++)
-	{
-		if (!strcmp(special_attr[i].field, a))
-		{
-			return (special_attr[i].code);
-		}
-	}
-	return InvalidAttrNumber;
-}
-
-/*-------------
- * given an attribute number and a relation, return its relation name
- */
-char	   *
-getAttrName(Relation rd, int attrno)
-{
-	char	   *name;
-	int			i;
-
-	if (attrno < 0)
-	{
-		for (i = 0; i < SPECIALS; i++)
-		{
-			if (special_attr[i].code == attrno)
-			{
-				name = special_attr[i].field;
-				return (name);
-			}
-		}
-		elog(WARN, "Illegal attr no %d for relation %s",
-			 attrno, RelationGetRelationName(rd));
-	}
-	else if (attrno >= 1 && attrno <= RelationGetNumberOfAttributes(rd))
-	{
-		name = (rd->rd_att->attrs[attrno - 1]->attname).data;
-		return (name);
-	}
-	else
-	{
-		elog(WARN, "Illegal attr no %d for relation %s",
-			 attrno, RelationGetRelationName(rd));
-	}
-
-	/*
-	 * Shouldn't get here, but we want lint to be happy...
-	 */
-
-	return (NULL);
-}
-
-/* Given a typename and value, returns the ascii form of the value */
-
-#ifdef NOT_USED
-char	   *
-outstr(char *typename,			/* Name of type of value */
-	   char *value)				/* Could be of any type */
-{
-	TypeTupleForm tp;
-	Oid			op;
-
-	tp = (TypeTupleForm) GETSTRUCT(type(typename));
-	op = tp->typoutput;
-	return ((char *) fmgr(op, value));
-}
-
-#endif
-
-/* Given a Type and a string, return the internal form of that string */
-char	   *
-instr2(Type tp, char *string, int typlen)
-{
-	return (instr1((TypeTupleForm) GETSTRUCT(tp), string, typlen));
-}
-
-/* Given a type structure and a string, returns the internal form of
-   that string */
-static char *
-instr1(TypeTupleForm tp, char *string, int typlen)
-{
-	Oid			op;
-	Oid			typelem;
-
-	op = tp->typinput;
-	typelem = tp->typelem;		/* XXX - used for array_in */
-	/* typlen is for bpcharin() and varcharin() */
-	return ((char *) fmgr(op, string, typelem, typlen));
-}
-
-/* Given the attribute type of an array return the arrtribute type of
-   an element of the array */
-
-Oid
-GetArrayElementType(Oid typearray)
-{
-	HeapTuple	type_tuple;
-	TypeTupleForm type_struct_array;
-
-	type_tuple = SearchSysCacheTuple(TYPOID,
-									 ObjectIdGetDatum(typearray),
-									 0, 0, 0);
-
-	if (!HeapTupleIsValid(type_tuple))
-		elog(WARN, "GetArrayElementType: Cache lookup failed for type %d",
-			 typearray);
-
-	/* get the array type struct from the type tuple */
-	type_struct_array = (TypeTupleForm) GETSTRUCT(type_tuple);
-
-	if (type_struct_array->typelem == InvalidOid)
-	{
-		elog(WARN, "GetArrayElementType: type %s is not an array",
-			 (Name) &(type_struct_array->typname.data[0]));
-	}
-
-	return (type_struct_array->typelem);
-}
-
-Oid
-funcid_get_rettype(Oid funcid)
-{
-	HeapTuple	func_tuple = NULL;
-	Oid			funcrettype = (Oid) 0;
-
-	func_tuple = SearchSysCacheTuple(PROOID, ObjectIdGetDatum(funcid),
-									 0, 0, 0);
-
-	if (!HeapTupleIsValid(func_tuple))
-		elog(WARN, "function  %d does not exist", funcid);
-
-	funcrettype = (Oid)
-		((Form_pg_proc) GETSTRUCT(func_tuple))->prorettype;
-
-	return (funcrettype);
-}
-
-/*
- * get a list of all argument type vectors for which a function named
- * funcname taking nargs arguments exists
- */
-static CandidateList
-func_get_candidates(char *funcname, int nargs)
-{
-	Relation	heapRelation;
-	Relation	idesc;
-	ScanKeyData skey;
-	HeapTuple	tuple;
-	IndexScanDesc sd;
-	RetrieveIndexResult indexRes;
-	Buffer		buffer;
-	Form_pg_proc pgProcP;
-	bool		bufferUsed = FALSE;
-	CandidateList candidates = NULL;
-	CandidateList current_candidate;
-	int			i;
-
-	heapRelation = heap_openr(ProcedureRelationName);
-	ScanKeyEntryInitialize(&skey,
-						   (bits16) 0x0,
-						   (AttrNumber) 1,
-						   (RegProcedure) NameEqualRegProcedure,
-						   (Datum) funcname);
-
-	idesc = index_openr(ProcedureNameIndex);
-
-	sd = index_beginscan(idesc, false, 1, &skey);
-
-	do
-	{
-		tuple = (HeapTuple) NULL;
-		if (bufferUsed)
-		{
-			ReleaseBuffer(buffer);
-			bufferUsed = FALSE;
-		}
-
-		indexRes = index_getnext(sd, ForwardScanDirection);
-		if (indexRes)
-		{
-			ItemPointer iptr;
-
-			iptr = &indexRes->heap_iptr;
-			tuple = heap_fetch(heapRelation, false, iptr, &buffer);
-			pfree(indexRes);
-			if (HeapTupleIsValid(tuple))
-			{
-				pgProcP = (Form_pg_proc) GETSTRUCT(tuple);
-				bufferUsed = TRUE;
-				if (pgProcP->pronargs == nargs)
-				{
-					current_candidate = (CandidateList)
-						palloc(sizeof(struct _CandidateList));
-					current_candidate->args = (Oid *)
-						palloc(8 * sizeof(Oid));
-					MemSet(current_candidate->args, 0, 8 * sizeof(Oid));
-					for (i = 0; i < nargs; i++)
-					{
-						current_candidate->args[i] =
-							pgProcP->proargtypes[i];
-					}
-
-					current_candidate->next = candidates;
-					candidates = current_candidate;
-				}
-			}
-		}
-	} while (indexRes);
-
-	index_endscan(sd);
-	index_close(idesc);
-	heap_close(heapRelation);
-
-	return candidates;
-}
-
-/*
- * can input_typeids be coerced to func_typeids?
- */
-static bool
-can_coerce(int nargs, Oid *input_typeids, Oid *func_typeids)
-{
-	int			i;
-	Type		tp;
-
-	/*
-	 * right now, we only coerce "unknown", and we cannot coerce it to a
-	 * relation type
-	 */
-	for (i = 0; i < nargs; i++)
-	{
-		if (input_typeids[i] != func_typeids[i])
-		{
-			if ((input_typeids[i] == BPCHAROID && func_typeids[i] == TEXTOID) ||
-				(input_typeids[i] == BPCHAROID && func_typeids[i] == VARCHAROID) ||
-				(input_typeids[i] == VARCHAROID && func_typeids[i] == TEXTOID) ||
-				(input_typeids[i] == VARCHAROID && func_typeids[i] == BPCHAROID) ||
-			(input_typeids[i] == CASHOID && func_typeids[i] == INT4OID) ||
-			 (input_typeids[i] == INT4OID && func_typeids[i] == CASHOID))
-				;				/* these are OK */
-			else if (input_typeids[i] != UNKNOWNOID || func_typeids[i] == 0)
-				return false;
-
-			tp = get_id_type(input_typeids[i]);
-			if (typetypetype(tp) == 'c')
-				return false;
-		}
-	}
-
-	return true;
-}
-
-/*
- * given a list of possible typeid arrays to a function and an array of
- * input typeids, produce a shortlist of those function typeid arrays
- * that match the input typeids (either exactly or by coercion), and
- * return the number of such arrays
- */
-static int
-match_argtypes(int nargs,
-			   Oid *input_typeids,
-			   CandidateList function_typeids,
-			   CandidateList *candidates)		/* return value */
-{
-	CandidateList current_candidate;
-	CandidateList matching_candidate;
-	Oid		   *current_typeids;
-	int			ncandidates = 0;
-
-	*candidates = NULL;
-
-	for (current_candidate = function_typeids;
-		 current_candidate != NULL;
-		 current_candidate = current_candidate->next)
-	{
-		current_typeids = current_candidate->args;
-		if (can_coerce(nargs, input_typeids, current_typeids))
-		{
-			matching_candidate = (CandidateList)
-				palloc(sizeof(struct _CandidateList));
-			matching_candidate->args = current_typeids;
-			matching_candidate->next = *candidates;
-			*candidates = matching_candidate;
-			ncandidates++;
-		}
-	}
-
-	return ncandidates;
-}
-
-/*
- * given the input argtype array and more than one candidate
- * for the function argtype array, attempt to resolve the conflict.
- * returns the selected argtype array if the conflict can be resolved,
- * otherwise returns NULL
- */
-static Oid *
-func_select_candidate(int nargs,
-					  Oid *input_typeids,
-					  CandidateList candidates)
-{
-	/* XXX no conflict resolution implemeneted yet */
-	return (NULL);
-}
-
-bool
-func_get_detail(char *funcname,
-				int nargs,
-				Oid *oid_array,
-				Oid *funcid,	/* return value */
-				Oid *rettype,	/* return value */
-				bool *retset,	/* return value */
-				Oid **true_typeids)		/* return value */
-{
-	Oid		  **input_typeid_vector;
-	Oid		   *current_input_typeids;
-	CandidateList function_typeids;
-	CandidateList current_function_typeids;
-	HeapTuple	ftup;
-	Form_pg_proc pform;
-
-	/*
-	 * attempt to find named function in the system catalogs with
-	 * arguments exactly as specified - so that the normal case is just as
-	 * quick as before
-	 */
-	ftup = SearchSysCacheTuple(PRONAME,
-							   PointerGetDatum(funcname),
-							   Int32GetDatum(nargs),
-							   PointerGetDatum(oid_array),
-							   0);
-	*true_typeids = oid_array;
-
-	/*
-	 * If an exact match isn't found : 1) get a vector of all possible
-	 * input arg type arrays constructed from the superclasses of the
-	 * original input arg types 2) get a list of all possible argument
-	 * type arrays to the function with given name and number of arguments
-	 * 3) for each input arg type array from vector #1 : a) find how many
-	 * of the function arg type arrays from list #2 it can be coerced to
-	 * b) - if the answer is one, we have our function - if the answer is
-	 * more than one, attempt to resolve the conflict - if the answer is
-	 * zero, try the next array from vector #1
-	 */
-	if (!HeapTupleIsValid(ftup))
-	{
-		function_typeids = func_get_candidates(funcname, nargs);
-
-		if (function_typeids != NULL)
-		{
-			int			ncandidates = 0;
-
-			input_typeid_vector = argtype_inherit(nargs, oid_array);
-			current_input_typeids = oid_array;
-
-			do
-			{
-				ncandidates = match_argtypes(nargs, current_input_typeids,
-											 function_typeids,
-											 &current_function_typeids);
-				if (ncandidates == 1)
-				{
-					*true_typeids = current_function_typeids->args;
-					ftup = SearchSysCacheTuple(PRONAME,
-											   PointerGetDatum(funcname),
-											   Int32GetDatum(nargs),
-										  PointerGetDatum(*true_typeids),
-											   0);
-					Assert(HeapTupleIsValid(ftup));
-				}
-				else if (ncandidates > 1)
-				{
-					*true_typeids =
-						func_select_candidate(nargs,
-											  current_input_typeids,
-											  current_function_typeids);
-					if (*true_typeids == NULL)
-					{
-						elog(NOTICE, "there is more than one function named \"%s\"",
-							 funcname);
-						elog(NOTICE, "that satisfies the given argument types. you will have to");
-						elog(NOTICE, "retype your query using explicit typecasts.");
-						func_error("func_get_detail", funcname, nargs, oid_array);
-					}
-					else
-					{
-						ftup = SearchSysCacheTuple(PRONAME,
-											   PointerGetDatum(funcname),
-												   Int32GetDatum(nargs),
-										  PointerGetDatum(*true_typeids),
-												   0);
-						Assert(HeapTupleIsValid(ftup));
-					}
-				}
-				current_input_typeids = *input_typeid_vector++;
-			}
-			while (current_input_typeids !=
-				   InvalidOid && ncandidates == 0);
-		}
-	}
-
-	if (!HeapTupleIsValid(ftup))
-	{
-		Type		tp;
-
-		if (nargs == 1)
-		{
-			tp = get_id_type(oid_array[0]);
-			if (typetypetype(tp) == 'c')
-				elog(WARN, "no such attribute or function \"%s\"",
-					 funcname);
-		}
-		func_error("func_get_detail", funcname, nargs, oid_array);
-	}
-	else
-	{
-		pform = (Form_pg_proc) GETSTRUCT(ftup);
-		*funcid = ftup->t_oid;
-		*rettype = pform->prorettype;
-		*retset = pform->proretset;
-
-		return (true);
-	}
-/* shouldn't reach here */
-	return (false);
-
-}
-
-/*
- *	argtype_inherit() -- Construct an argtype vector reflecting the
- *						 inheritance properties of the supplied argv.
- *
- *		This function is used to disambiguate among functions with the
- *		same name but different signatures.  It takes an array of eight
- *		type ids.  For each type id in the array that's a complex type
- *		(a class), it walks up the inheritance tree, finding all
- *		superclasses of that type.	A vector of new Oid type arrays
- *		is returned to the caller, reflecting the structure of the
- *		inheritance tree above the supplied arguments.
- *
- *		The order of this vector is as follows:  all superclasses of the
- *		rightmost complex class are explored first.  The exploration
- *		continues from right to left.  This policy means that we favor
- *		keeping the leftmost argument type as low in the inheritance tree
- *		as possible.  This is intentional; it is exactly what we need to
- *		do for method dispatch.  The last type array we return is all
- *		zeroes.  This will match any functions for which return types are
- *		not defined.  There are lots of these (mostly builtins) in the
- *		catalogs.
- */
-static Oid **
-argtype_inherit(int nargs, Oid *oid_array)
-{
-	Oid			relid;
-	int			i;
-	InhPaths	arginh[MAXFARGS];
-
-	for (i = 0; i < MAXFARGS; i++)
-	{
-		if (i < nargs)
-		{
-			arginh[i].self = oid_array[i];
-			if ((relid = typeid_get_relid(oid_array[i])) != InvalidOid)
-			{
-				arginh[i].nsupers = findsupers(relid, &(arginh[i].supervec));
-			}
-			else
-			{
-				arginh[i].nsupers = 0;
-				arginh[i].supervec = (Oid *) NULL;
-			}
-		}
-		else
-		{
-			arginh[i].self = InvalidOid;
-			arginh[i].nsupers = 0;
-			arginh[i].supervec = (Oid *) NULL;
-		}
-	}
-
-	/* return an ordered cross-product of the classes involved */
-	return (genxprod(arginh, nargs));
-}
-
-typedef struct _SuperQE
-{
-	Oid			sqe_relid;
-} SuperQE;
-
-static int
-findsupers(Oid relid, Oid **supervec)
-{
-	Oid		   *relidvec;
-	Relation	inhrel;
-	HeapScanDesc inhscan;
-	ScanKeyData skey;
-	HeapTuple	inhtup;
-	TupleDesc	inhtupdesc;
-	int			nvisited;
-	SuperQE    *qentry,
-			   *vnode;
-	Dllist	   *visited,
-			   *queue;
-	Dlelem	   *qe,
-			   *elt;
-
-	Relation	rd;
-	Buffer		buf;
-	Datum		d;
-	bool		newrelid;
-	char		isNull;
-
-	nvisited = 0;
-	queue = DLNewList();
-	visited = DLNewList();
-
-
-	inhrel = heap_openr(InheritsRelationName);
-	RelationSetLockForRead(inhrel);
-	inhtupdesc = RelationGetTupleDescriptor(inhrel);
-
-	/*
-	 * Use queue to do a breadth-first traversal of the inheritance graph
-	 * from the relid supplied up to the root.
-	 */
-	do
-	{
-		ScanKeyEntryInitialize(&skey, 0x0, Anum_pg_inherits_inhrel,
-							   ObjectIdEqualRegProcedure,
-							   ObjectIdGetDatum(relid));
-
-		inhscan = heap_beginscan(inhrel, 0, false, 1, &skey);
-
-		while (HeapTupleIsValid(inhtup = heap_getnext(inhscan, 0, &buf)))
-		{
-			qentry = (SuperQE *) palloc(sizeof(SuperQE));
-
-			d = fastgetattr(inhtup, Anum_pg_inherits_inhparent,
-							inhtupdesc, &isNull);
-			qentry->sqe_relid = DatumGetObjectId(d);
-
-			/* put this one on the queue */
-			DLAddTail(queue, DLNewElem(qentry));
-
-			ReleaseBuffer(buf);
-		}
-
-		heap_endscan(inhscan);
-
-		/* pull next unvisited relid off the queue */
-		do
-		{
-			qe = DLRemHead(queue);
-			qentry = qe ? (SuperQE *) DLE_VAL(qe) : NULL;
-
-			if (qentry == (SuperQE *) NULL)
-				break;
-
-			relid = qentry->sqe_relid;
-			newrelid = true;
-
-			for (elt = DLGetHead(visited); elt; elt = DLGetSucc(elt))
-			{
-				vnode = (SuperQE *) DLE_VAL(elt);
-				if (vnode && (qentry->sqe_relid == vnode->sqe_relid))
-				{
-					newrelid = false;
-					break;
-				}
-			}
-		} while (!newrelid);
-
-		if (qentry != (SuperQE *) NULL)
-		{
-
-			/* save the type id, rather than the relation id */
-			if ((rd = heap_open(qentry->sqe_relid)) == (Relation) NULL)
-				elog(WARN, "relid %d does not exist", qentry->sqe_relid);
-			qentry->sqe_relid = typeid(type(RelationGetRelationName(rd)->data));
-			heap_close(rd);
-
-			DLAddTail(visited, qe);
-
-			nvisited++;
-		}
-	} while (qentry != (SuperQE *) NULL);
-
-	RelationUnsetLockForRead(inhrel);
-	heap_close(inhrel);
-
-	if (nvisited > 0)
-	{
-		relidvec = (Oid *) palloc(nvisited * sizeof(Oid));
-		*supervec = relidvec;
-
-		for (elt = DLGetHead(visited); elt; elt = DLGetSucc(elt))
-		{
-			vnode = (SuperQE *) DLE_VAL(elt);
-			*relidvec++ = vnode->sqe_relid;
-		}
-
-	}
-	else
-	{
-		*supervec = (Oid *) NULL;
-	}
-
-	return (nvisited);
-}
-
-static Oid **
-genxprod(InhPaths *arginh, int nargs)
-{
-	int			nanswers;
-	Oid		  **result,
-			  **iter;
-	Oid		   *oneres;
-	int			i,
-				j;
-	int			cur[MAXFARGS];
-
-	nanswers = 1;
-	for (i = 0; i < nargs; i++)
-	{
-		nanswers *= (arginh[i].nsupers + 2);
-		cur[i] = 0;
-	}
-
-	iter = result = (Oid **) palloc(sizeof(Oid *) * nanswers);
-
-	/* compute the cross product from right to left */
-	for (;;)
-	{
-		oneres = (Oid *) palloc(MAXFARGS * sizeof(Oid));
-		MemSet(oneres, 0, MAXFARGS * sizeof(Oid));
-
-		for (i = nargs - 1; i >= 0 && cur[i] > arginh[i].nsupers; i--)
-			continue;
-
-		/* if we're done, terminate with NULL pointer */
-		if (i < 0)
-		{
-			*iter = NULL;
-			return (result);
-		}
-
-		/* no, increment this column and zero the ones after it */
-		cur[i] = cur[i] + 1;
-		for (j = nargs - 1; j > i; j--)
-			cur[j] = 0;
-
-		for (i = 0; i < nargs; i++)
-		{
-			if (cur[i] == 0)
-				oneres[i] = arginh[i].self;
-			else if (cur[i] > arginh[i].nsupers)
-				oneres[i] = 0;	/* wild card */
-			else
-				oneres[i] = arginh[i].supervec[cur[i] - 1];
-		}
-
-		*iter++ = oneres;
-	}
-}
-
-/* Given a type id, returns the in-conversion function of the type */
-Oid
-typeid_get_retinfunc(Oid type_id)
-{
-	HeapTuple	typeTuple;
-	TypeTupleForm type;
-	Oid			infunc;
-
-	typeTuple = SearchSysCacheTuple(TYPOID,
-									ObjectIdGetDatum(type_id),
-									0, 0, 0);
-	if (!HeapTupleIsValid(typeTuple))
-		elog(WARN, "typeid_get_retinfunc: Invalid type - oid = %u", type_id);
-
-	type = (TypeTupleForm) GETSTRUCT(typeTuple);
-	infunc = type->typinput;
-	return (infunc);
-}
-
-/* Given a type id, returns the out-conversion function of the type */
-Oid
-typeid_get_retoutfunc(Oid type_id)
-{
-	HeapTuple	typeTuple;
-	TypeTupleForm type;
-	Oid			outfunc;
-
-	typeTuple = SearchSysCacheTuple(TYPOID,
-									ObjectIdGetDatum(type_id),
-									0, 0, 0);
-	if (!HeapTupleIsValid(typeTuple))
-		elog(WARN, "typeid_get_retoutfunc: Invalid type - oid = %u", type_id);
-
-	type = (TypeTupleForm) GETSTRUCT(typeTuple);
-	outfunc = type->typoutput;
-	return (outfunc);
-}
-
-Oid
-typeid_get_relid(Oid type_id)
-{
-	HeapTuple	typeTuple;
-	TypeTupleForm type;
-	Oid			infunc;
-
-	typeTuple = SearchSysCacheTuple(TYPOID,
-									ObjectIdGetDatum(type_id),
-									0, 0, 0);
-	if (!HeapTupleIsValid(typeTuple))
-		elog(WARN, "typeid_get_relid: Invalid type - oid = %u", type_id);
-
-	type = (TypeTupleForm) GETSTRUCT(typeTuple);
-	infunc = type->typrelid;
-	return (infunc);
-}
-
-Oid
-get_typrelid(Type typ)
-{
-	TypeTupleForm typtup;
-
-	typtup = (TypeTupleForm) GETSTRUCT(typ);
-
-	return (typtup->typrelid);
-}
-
-Oid
-get_typelem(Oid type_id)
-{
-	HeapTuple	typeTuple;
-	TypeTupleForm type;
-
-	if (!(typeTuple = SearchSysCacheTuple(TYPOID,
-										  ObjectIdGetDatum(type_id),
-										  0, 0, 0)))
-	{
-		elog(WARN, "type id lookup of %u failed", type_id);
-	}
-	type = (TypeTupleForm) GETSTRUCT(typeTuple);
-
-	return (type->typelem);
-}
-
-#ifdef NOT_USED
-char
-FindDelimiter(char *typename)
-{
-	char		delim;
-	HeapTuple	typeTuple;
-	TypeTupleForm type;
-
-
-	if (!(typeTuple = SearchSysCacheTuple(TYPNAME,
-										  PointerGetDatum(typename),
-										  0, 0, 0)))
-	{
-		elog(WARN, "type name lookup of %s failed", typename);
-	}
-	type = (TypeTupleForm) GETSTRUCT(typeTuple);
-
-	delim = type->typdelim;
-	return (delim);
-}
-
-#endif
-
-/*
- * Give a somewhat useful error message when the operator for two types
- * is not found.
- */
-static void
-op_error(char *op, Oid arg1, Oid arg2)
-{
-	Type		tp1 = NULL,
-				tp2 = NULL;
-
-	if (check_typeid(arg1))
-	{
-		tp1 = get_id_type(arg1);
-	}
-	else
-	{
-		elog(WARN, "left hand side of operator %s has an unknown type, probably a bad attribute name", op);
-	}
-
-	if (check_typeid(arg2))
-	{
-		tp2 = get_id_type(arg2);
-	}
-	else
-	{
-		elog(WARN, "right hand side of operator %s has an unknown type, probably a bad attribute name", op);
-	}
-
-	elog(NOTICE, "there is no operator %s for types %s and %s",
-		 op, tname(tp1), tname(tp2));
-	elog(NOTICE, "You will either have to retype this query using an");
-	elog(NOTICE, "explicit cast, or you will have to define the operator");
-	elog(WARN, "%s for %s and %s using CREATE OPERATOR",
-		 op, tname(tp1), tname(tp2));
-}
-
-/*
- * Error message when function lookup fails that gives details of the
- * argument types
- */
-void
-func_error(char *caller, char *funcname, int nargs, Oid *argtypes)
-{
-	char		p[(NAMEDATALEN + 2) * MAXFMGRARGS],
-			   *ptr;
-	int			i;
-
-	ptr = p;
-	*ptr = '\0';
-	for (i = 0; i < nargs; i++)
-	{
-		if (i)
-		{
-			*ptr++ = ',';
-			*ptr++ = ' ';
-		}
-		if (argtypes[i] != 0)
-		{
-			strcpy(ptr, tname(get_id_type(argtypes[i])));
-			*(ptr + NAMEDATALEN) = '\0';
-		}
-		else
-			strcpy(ptr, "opaque");
-		ptr += strlen(ptr);
-	}
-
-	elog(WARN, "%s: function %s(%s) does not exist", caller, funcname, p);
-}
-
-/*
- * Error message when aggregate lookup fails that gives details of the
- * basetype
- */
-void
-agg_error(char *caller, char *aggname, Oid basetypeID)
-{
-
-	/*
-	 * basetypeID that is Invalid (zero) means aggregate over all types.
-	 * (count)
-	 */
-
-	if (basetypeID == InvalidOid)
-	{
-		elog(WARN, "%s: aggregate '%s' for all types does not exist", caller, aggname);
-	}
-	else
-	{
-		elog(WARN, "%s: aggregate '%s' for '%s' does not exist", caller, aggname,
-			 tname(get_id_type(basetypeID)));
-	}
-}
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index abaedbb57bb725b0bdfe7a3ba60dcdba8e5f945b..d146b6e4ce1a5d5da861cc0c5893ab5b9aa973b5 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -10,7 +10,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 1.71 1997/11/24 16:55:22 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 1.72 1997/11/25 22:05:29 momjian Exp $
  *
  * HISTORY
  *	  AUTHOR			DATE			MAJOR EVENT
@@ -39,8 +39,6 @@
 #include "nodes/parsenodes.h"
 #include "nodes/print.h"
 #include "parser/gramparse.h"
-#include "parser/catalog_utils.h"
-#include "parser/parse_query.h"
 #include "utils/acl.h"
 #include "catalog/catname.h"
 #include "utils/elog.h"
@@ -49,8 +47,11 @@
 static char saved_relname[NAMEDATALEN];  /* need this for complex attributes */
 static bool QueryIsRule = FALSE;
 static Node *saved_In_Expr;
+static Oid	*param_type_info;
+static int	pfunc_num_args;
 extern List *parsetree;
 
+
 /*
  * If you need access to certain yacc-generated variables and find that
  * they're static by default, uncomment the next line.  (this is not a
@@ -64,6 +65,9 @@ static List *makeConstantList( A_Const *node);
 static char *FlattenStringList(List *list);
 static char *fmtId(char *rawid);
 static Node *makeIndexable(char *opname, Node *lexpr, Node *rexpr);
+static void param_type_init(Oid *typev, int nargs);
+
+Oid	param_type(int t); /* used in parse_expr.c */
 
 /* old versions of flex define this as a macro */
 #if defined(yywrap)
@@ -2324,7 +2328,7 @@ Typename:  Array opt_array_bounds
 						 * emp(name=text,mgr=emp)
 						 */
 						$$->setof = TRUE;
-					else if (get_typrelid((Type)type($$->name)) != InvalidOid)
+					else if (typeTypeRelid(typenameType($$->name)) != InvalidOid)
 						 /* (Eventually add in here that the set can only
 						  * contain one element.)
 						  */
@@ -3690,4 +3694,24 @@ printf("fmtId- %sconvert %s to %s\n", ((cp == rawid)? "do not ": ""), rawid, cp)
 #endif
 
 	return(cp);
-} /* fmtId() */
+}
+
+/*
+ * param_type_init()
+ *
+ * keep enough information around fill out the type of param nodes
+ * used in postquel functions
+ */
+static void
+param_type_init(Oid *typev, int nargs)
+{
+	pfunc_num_args = nargs;
+	param_type_info = typev;
+}
+
+Oid param_type(int t)
+{
+	if ((t > pfunc_num_args) || (t == 0))
+		return InvalidOid;
+	return param_type_info[t - 1];
+}
diff --git a/src/backend/parser/keywords.c b/src/backend/parser/keywords.c
index 0312e0251be1637c534c1b07730aedcad18af96d..1c4b63c44efdba6de4db29e3f3b3a29d55f04f91 100644
--- a/src/backend/parser/keywords.c
+++ b/src/backend/parser/keywords.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/parser/keywords.c,v 1.24 1997/11/24 05:32:28 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/parser/keywords.c,v 1.25 1997/11/25 22:05:32 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -18,8 +18,8 @@
 #include "nodes/pg_list.h"
 #include "nodes/parsenodes.h"
 #include "parse.h"
-#include "utils/elog.h"
 #include "parser/keywords.h"
+#include "utils/elog.h"
 
 /*
  * List of (keyword-name, keyword-token-value) pairs.
diff --git a/src/backend/parser/parse_agg.c b/src/backend/parser/parse_agg.c
new file mode 100644
index 0000000000000000000000000000000000000000..b64b92079eff2877371e6e90b06f68bf12750980
--- /dev/null
+++ b/src/backend/parser/parse_agg.c
@@ -0,0 +1,371 @@
+/*-------------------------------------------------------------------------
+ *
+ * parse_agg.c--
+ *	  handle aggregates in parser
+ *
+ * Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ *	  $Header: /cvsroot/pgsql/src/backend/parser/parse_agg.c,v 1.1 1997/11/25 22:05:34 momjian Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "postgres.h"
+#include "access/heapam.h"
+#include "catalog/pg_aggregate.h"
+#include "nodes/nodeFuncs.h"
+#include "nodes/primnodes.h"
+#include "nodes/relation.h"
+#include "optimizer/clauses.h"
+#include "parser/parse_agg.h"
+#include "parser/parse_node.h"
+#include "parser/parse_target.h"
+#include "utils/syscache.h"
+
+#ifdef 0
+#include "nodes/nodes.h"
+#include "nodes/params.h"
+#include "parse.h"				/* for AND, OR, etc. */
+#include "catalog/pg_type.h"	/* for INT4OID, etc. */
+#include "catalog/pg_proc.h"
+#include "utils/elog.h"
+#include "utils/builtins.h"		/* namecmp(), textout() */
+#include "utils/lsyscache.h"
+#include "utils/palloc.h"
+#include "utils/mcxt.h"
+#include "utils/acl.h"
+#include "nodes/makefuncs.h"	/* for makeResdom(), etc. */
+#include "commands/sequence.h"
+
+#endif
+
+/*
+ * AddAggToParseState -
+ *	  add the aggregate to the list of unique aggregates in pstate.
+ *
+ * SIDE EFFECT: aggno in target list entry will be modified
+ */
+void
+AddAggToParseState(ParseState *pstate, Aggreg *aggreg)
+{
+	List	   *ag;
+	int			i;
+
+	/*
+	 * see if we have the aggregate already (we only need to record the
+	 * aggregate once)
+	 */
+	i = 0;
+	foreach(ag, pstate->p_aggs)
+	{
+		Aggreg	   *a = lfirst(ag);
+
+		if (!strcmp(a->aggname, aggreg->aggname) &&
+			equal(a->target, aggreg->target))
+		{
+
+			/* fill in the aggno and we're done */
+			aggreg->aggno = i;
+			return;
+		}
+		i++;
+	}
+
+	/* not found, new aggregate */
+	aggreg->aggno = i;
+	pstate->p_numAgg++;
+	pstate->p_aggs = lappend(pstate->p_aggs, aggreg);
+	return;
+}
+
+/*
+ * finalizeAggregates -
+ *	  fill in qry_aggs from pstate. Also checks to make sure that aggregates
+ *	  are used in the proper place.
+ */
+void
+finalizeAggregates(ParseState *pstate, Query *qry)
+{
+	List	   *l;
+	int			i;
+
+	parseCheckAggregates(pstate, qry);
+
+	qry->qry_numAgg = pstate->p_numAgg;
+	qry->qry_aggs =
+		(Aggreg **) palloc(sizeof(Aggreg *) * qry->qry_numAgg);
+	i = 0;
+	foreach(l, pstate->p_aggs)
+		qry->qry_aggs[i++] = (Aggreg *) lfirst(l);
+}
+
+/*
+ * contain_agg_clause--
+ *	  Recursively find aggreg nodes from a clause.
+ *
+ *	  Returns true if any aggregate found.
+ */
+bool
+contain_agg_clause(Node *clause)
+{
+	if (clause == NULL)
+		return FALSE;
+	else if (IsA(clause, Aggreg))
+		return TRUE;
+	else if (IsA(clause, Iter))
+		return contain_agg_clause(((Iter *) clause)->iterexpr);
+	else if (single_node(clause))
+		return FALSE;
+	else if (or_clause(clause))
+	{
+		List	   *temp;
+
+		foreach(temp, ((Expr *) clause)->args)
+			if (contain_agg_clause(lfirst(temp)))
+			return TRUE;
+		return FALSE;
+	}
+	else if (is_funcclause(clause))
+	{
+		List	   *temp;
+
+		foreach(temp, ((Expr *) clause)->args)
+			if (contain_agg_clause(lfirst(temp)))
+			return TRUE;
+		return FALSE;
+	}
+	else if (IsA(clause, ArrayRef))
+	{
+		List	   *temp;
+
+		foreach(temp, ((ArrayRef *) clause)->refupperindexpr)
+			if (contain_agg_clause(lfirst(temp)))
+			return TRUE;
+		foreach(temp, ((ArrayRef *) clause)->reflowerindexpr)
+			if (contain_agg_clause(lfirst(temp)))
+			return TRUE;
+		if (contain_agg_clause(((ArrayRef *) clause)->refexpr))
+			return TRUE;
+		if (contain_agg_clause(((ArrayRef *) clause)->refassgnexpr))
+			return TRUE;
+		return FALSE;
+	}
+	else if (not_clause(clause))
+		return contain_agg_clause((Node *) get_notclausearg((Expr *) clause));
+	else if (is_opclause(clause))
+		return (contain_agg_clause((Node *) get_leftop((Expr *) clause)) ||
+			  contain_agg_clause((Node *) get_rightop((Expr *) clause)));
+
+	return FALSE;
+}
+
+/*
+ * exprIsAggOrGroupCol -
+ *	  returns true if the expression does not contain non-group columns.
+ */
+bool
+exprIsAggOrGroupCol(Node *expr, List *groupClause)
+{
+	List	   *gl;
+
+	if (expr == NULL || IsA(expr, Const) ||
+		IsA(expr, Param) ||IsA(expr, Aggreg))
+		return TRUE;
+
+	foreach(gl, groupClause)
+	{
+		GroupClause *grpcl = lfirst(gl);
+
+		if (equal(expr, grpcl->entry->expr))
+			return TRUE;
+	}
+
+	if (IsA(expr, Expr))
+	{
+		List	   *temp;
+
+		foreach(temp, ((Expr *) expr)->args)
+			if (!exprIsAggOrGroupCol(lfirst(temp), groupClause))
+			return FALSE;
+		return TRUE;
+	}
+
+	return FALSE;
+}
+
+/*
+ * tleIsAggOrGroupCol -
+ *	  returns true if the TargetEntry is Agg or GroupCol.
+ */
+bool
+tleIsAggOrGroupCol(TargetEntry *tle, List *groupClause)
+{
+	Node	   *expr = tle->expr;
+	List	   *gl;
+
+	if (expr == NULL || IsA(expr, Const) ||IsA(expr, Param))
+		return TRUE;
+
+	foreach(gl, groupClause)
+	{
+		GroupClause *grpcl = lfirst(gl);
+
+		if (tle->resdom->resno == grpcl->entry->resdom->resno)
+		{
+			if (contain_agg_clause((Node *) expr))
+				elog(WARN, "parser: aggregates not allowed in GROUP BY clause");
+			return TRUE;
+		}
+	}
+
+	if (IsA(expr, Aggreg))
+		return TRUE;
+
+	if (IsA(expr, Expr))
+	{
+		List	   *temp;
+
+		foreach(temp, ((Expr *) expr)->args)
+			if (!exprIsAggOrGroupCol(lfirst(temp), groupClause))
+			return FALSE;
+		return TRUE;
+	}
+
+	return FALSE;
+}
+
+/*
+ * parseCheckAggregates -
+ *	  this should really be done earlier but the current grammar
+ *	  cannot differentiate functions from aggregates. So we have do check
+ *	  here when the target list and the qualifications are finalized.
+ */
+void
+parseCheckAggregates(ParseState *pstate, Query *qry)
+{
+	List	   *tl;
+
+	Assert(pstate->p_numAgg > 0);
+
+	/*
+	 * aggregates never appear in WHERE clauses. (we have to check where
+	 * clause first because if there is an aggregate, the check for
+	 * non-group column in target list may fail.)
+	 */
+	if (contain_agg_clause(qry->qual))
+		elog(WARN, "parser: aggregates not allowed in WHERE clause");
+
+	/*
+	 * the target list can only contain aggregates, group columns and
+	 * functions thereof.
+	 */
+	foreach(tl, qry->targetList)
+	{
+		TargetEntry *tle = lfirst(tl);
+
+		if (!tleIsAggOrGroupCol(tle, qry->groupClause))
+			elog(WARN,
+				 "parser: illegal use of aggregates or non-group column in target list");
+	}
+
+	/*
+	 * the expression specified in the HAVING clause has the same
+	 * restriction as those in the target list.
+	 */
+/*
+ * Need to change here when we get HAVING works. Currently
+ * qry->havingQual is NULL.		- vadim 04/05/97
+	if (!exprIsAggOrGroupCol(qry->havingQual, qry->groupClause))
+		elog(WARN,
+			 "parser: illegal use of aggregates or non-group column in HAVING clause");
+ */
+	return;
+}
+
+
+Aggreg	   *
+ParseAgg(char *aggname, Oid basetype, Node *target)
+{
+	Oid			fintype;
+	Oid			vartype;
+	Oid			xfn1;
+	Form_pg_aggregate aggform;
+	Aggreg	   *aggreg;
+	HeapTuple	theAggTuple;
+
+	theAggTuple = SearchSysCacheTuple(AGGNAME, PointerGetDatum(aggname),
+									  ObjectIdGetDatum(basetype),
+									  0, 0);
+	if (!HeapTupleIsValid(theAggTuple))
+	{
+		elog(WARN, "aggregate %s does not exist", aggname);
+	}
+
+	aggform = (Form_pg_aggregate) GETSTRUCT(theAggTuple);
+	fintype = aggform->aggfinaltype;
+	xfn1 = aggform->aggtransfn1;
+
+	if (nodeTag(target) != T_Var && nodeTag(target) != T_Expr)
+		elog(WARN, "parser: aggregate can only be applied on an attribute or expression");
+
+	/* only aggregates with transfn1 need a base type */
+	if (OidIsValid(xfn1))
+	{
+		basetype = aggform->aggbasetype;
+		if (nodeTag(target) == T_Var)
+			vartype = ((Var *) target)->vartype;
+		else
+			vartype = ((Expr *) target)->typeOid;
+
+		if (basetype != vartype)
+		{
+			Type		tp1,
+						tp2;
+
+			tp1 = typeidType(basetype);
+			tp2 = typeidType(vartype);
+			elog(NOTICE, "Aggregate type mismatch:");
+			elog(WARN, "%s works on %s, not %s", aggname,
+				 typeTypeName(tp1), typeTypeName(tp2));
+		}
+	}
+
+	aggreg = makeNode(Aggreg);
+	aggreg->aggname = pstrdup(aggname);
+	aggreg->basetype = aggform->aggbasetype;
+	aggreg->aggtype = fintype;
+
+	aggreg->target = target;
+
+	return aggreg;
+}
+
+/*
+ * Error message when aggregate lookup fails that gives details of the
+ * basetype
+ */
+void
+agg_error(char *caller, char *aggname, Oid basetypeID)
+{
+
+	/*
+	 * basetypeID that is Invalid (zero) means aggregate over all types.
+	 * (count)
+	 */
+
+	if (basetypeID == InvalidOid)
+	{
+		elog(WARN, "%s: aggregate '%s' for all types does not exist", caller, aggname);
+	}
+	else
+	{
+		elog(WARN, "%s: aggregate '%s' for '%s' does not exist", caller, aggname,
+			 typeidTypeName(basetypeID));
+	}
+}
+
diff --git a/src/backend/parser/parse_clause.c b/src/backend/parser/parse_clause.c
new file mode 100644
index 0000000000000000000000000000000000000000..8e08e00a2ea179e095460f9f221d8178b57899bc
--- /dev/null
+++ b/src/backend/parser/parse_clause.c
@@ -0,0 +1,407 @@
+/*-------------------------------------------------------------------------
+ *
+ * parse_clause.c--
+ *	  handle clauses in parser
+ *
+ * Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ *	  $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.1 1997/11/25 22:05:35 momjian Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "postgres.h"
+#include "access/heapam.h"
+#include "parser/parse_clause.h"
+#include "parser/parse_expr.h"
+#include "parser/parse_node.h"
+#include "parser/parse_oper.h"
+#include "parser/parse_relation.h"
+#include "parser/parse_target.h"
+#include "catalog/pg_type.h"
+
+#ifdef 0
+#include "nodes/nodes.h"
+#include "nodes/params.h"
+#include "nodes/primnodes.h"
+#include "nodes/parsenodes.h"
+#include "nodes/relation.h"
+#include "parse.h"				/* for AND, OR, etc. */
+#include "catalog/pg_aggregate.h"
+#include "catalog/pg_proc.h"
+#include "utils/elog.h"
+#include "utils/builtins.h"		/* namecmp(), textout() */
+#include "utils/lsyscache.h"
+#include "utils/palloc.h"
+#include "utils/mcxt.h"
+#include "utils/syscache.h"
+#include "utils/acl.h"
+#include "nodes/makefuncs.h"	/* for makeResdom(), etc. */
+#include "nodes/nodeFuncs.h"
+#include "commands/sequence.h"
+
+#include "optimizer/clauses.h"
+
+#include "miscadmin.h"
+
+#include "port-protos.h"		/* strdup() */
+#endif
+
+/*
+ * parseFromClause -
+ *	  turns the table references specified in the from-clause into a
+ *	  range table. The range table may grow as we transform the expressions
+ *	  in the target list. (Note that this happens because in POSTQUEL, we
+ *	  allow references to relations not specified in the from-clause. We
+ *	  also allow that in our POST-SQL)
+ *
+ */
+void
+parseFromClause(ParseState *pstate, List *frmList)
+{
+	List	   *fl;
+
+	foreach(fl, frmList)
+	{
+		RangeVar   *r = lfirst(fl);
+		RelExpr    *baserel = r->relExpr;
+		char	   *relname = baserel->relname;
+		char	   *refname = r->name;
+		RangeTblEntry *rte;
+
+		if (refname == NULL)
+			refname = relname;
+
+		/*
+		 * marks this entry to indicate it comes from the FROM clause. In
+		 * SQL, the target list can only refer to range variables
+		 * specified in the from clause but we follow the more powerful
+		 * POSTQUEL semantics and automatically generate the range
+		 * variable if not specified. However there are times we need to
+		 * know whether the entries are legitimate.
+		 *
+		 * eg. select * from foo f where f.x = 1; will generate wrong answer
+		 * if we expand * to foo.x.
+		 */
+		rte = addRangeTableEntry(pstate, relname, refname, baserel->inh, TRUE);
+	}
+}
+
+/*
+ * makeRangeTable -
+ *	  make a range table with the specified relation (optional) and the
+ *	  from-clause.
+ */
+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);
+
+	pstate->p_target_rangetblentry = rte;
+	Assert(pstate->p_target_relation == NULL);
+	pstate->p_target_relation = heap_open(rte->relid);
+	Assert(pstate->p_target_relation != NULL);
+	/* will close relation later */
+}
+
+/*****************************************************************************
+ *
+ * Where Clause
+ *
+ *****************************************************************************/
+
+/*
+ * transformWhereClause -
+ *	  transforms the qualification and make sure it is of type Boolean
+ *
+ */
+Node *
+transformWhereClause(ParseState *pstate, Node *a_expr)
+{
+	Node	   *qual;
+
+	if (a_expr == NULL)
+		return (Node *) NULL;	/* no qualifiers */
+
+	pstate->p_in_where_clause = true;
+	qual = transformExpr(pstate, a_expr, EXPR_COLUMN_FIRST);
+	pstate->p_in_where_clause = false;
+	if (exprType(qual) != BOOLOID)
+	{
+		elog(WARN,
+			 "where clause must return type bool, not %s",
+			 typeidTypeName(exprType(qual)));
+	}
+	return qual;
+}
+
+/*****************************************************************************
+ *
+ * Sort Clause
+ *
+ *****************************************************************************/
+
+/*
+ *	find_targetlist_entry -
+ *	  returns the Resdom in the target list matching the specified varname
+ *	  and range
+ *
+ */
+TargetEntry *
+find_targetlist_entry(ParseState *pstate, SortGroupBy *sortgroupby, List *tlist)
+{
+	List	   *i;
+	int			real_rtable_pos = 0,
+				target_pos = 0;
+	TargetEntry *target_result = NULL;
+
+	if (sortgroupby->range)
+		real_rtable_pos = refnameRangeTablePosn(pstate->p_rtable,
+												sortgroupby->range);
+
+	foreach(i, tlist)
+	{
+		TargetEntry *target = (TargetEntry *) lfirst(i);
+		Resdom	   *resnode = target->resdom;
+		Var		   *var = (Var *) target->expr;
+		char	   *resname = resnode->resname;
+		int			test_rtable_pos = var->varno;
+
+#ifdef PARSEDEBUG
+		printf("find_targetlist_entry- target name is %s, position %d, resno %d\n",
+			   (sortgroupby->name ? sortgroupby->name : "(null)"), target_pos + 1, sortgroupby->resno);
+#endif
+
+		if (!sortgroupby->name)
+		{
+			if (sortgroupby->resno == ++target_pos)
+			{
+				target_result = target;
+				break;
+			}
+		}
+		else
+		{
+			if (!strcmp(resname, sortgroupby->name))
+			{
+				if (sortgroupby->range)
+				{
+					if (real_rtable_pos == test_rtable_pos)
+					{
+						if (target_result != NULL)
+							elog(WARN, "Order/Group By '%s' is ambiguous", sortgroupby->name);
+						else
+							target_result = target;
+					}
+				}
+				else
+				{
+					if (target_result != NULL)
+						elog(WARN, "Order/Group By '%s' is ambiguous", sortgroupby->name);
+					else
+						target_result = target;
+				}
+			}
+		}
+	}
+	return target_result;
+}
+
+/*
+ * transformGroupClause -
+ *	  transform a Group By clause
+ *
+ */
+List *
+transformGroupClause(ParseState *pstate, List *grouplist, List *targetlist)
+{
+	List	   *glist = NIL,
+			   *gl = NIL;
+
+	while (grouplist != NIL)
+	{
+		GroupClause *grpcl = makeNode(GroupClause);
+		TargetEntry *restarget;
+		Resdom	   *resdom;
+
+		restarget = find_targetlist_entry(pstate, lfirst(grouplist), targetlist);
+
+		if (restarget == NULL)
+			elog(WARN, "The field being grouped by must appear in the target list");
+
+		grpcl->entry = restarget;
+		resdom = restarget->resdom;
+		grpcl->grpOpoid = oprid(oper("<",
+									 resdom->restype,
+									 resdom->restype, false));
+		if (glist == NIL)
+			gl = glist = lcons(grpcl, NIL);
+		else
+		{
+			List	   *i;
+			
+			foreach (i, glist)
+			{
+				GroupClause *gcl = (GroupClause *) lfirst (i);
+				
+				if ( gcl->entry == grpcl->entry )
+					break;
+			}
+			if ( i == NIL )			/* not in grouplist already */
+			{
+				lnext(gl) = lcons(grpcl, NIL);
+				gl = lnext(gl);
+			}
+			else
+				pfree (grpcl);		/* get rid of this */
+		}
+		grouplist = lnext(grouplist);
+	}
+
+	return glist;
+}
+
+/*
+ * transformSortClause -
+ *	  transform an Order By clause
+ *
+ */
+List *
+transformSortClause(ParseState *pstate,
+					List *orderlist, List *targetlist,
+					char *uniqueFlag)
+{
+	List	   *sortlist = NIL;
+	List	   *s = NIL;
+
+	while (orderlist != NIL)
+	{
+		SortGroupBy *sortby = lfirst(orderlist);
+		SortClause *sortcl = makeNode(SortClause);
+		TargetEntry *restarget;
+		Resdom	   *resdom;
+
+		restarget = find_targetlist_entry(pstate, sortby, targetlist);
+		if (restarget == NULL)
+			elog(WARN, "The field being ordered by must appear in the target list");
+
+		sortcl->resdom = resdom = restarget->resdom;
+		sortcl->opoid = oprid(oper(sortby->useOp,
+								   resdom->restype,
+								   resdom->restype, false));
+		if (sortlist == NIL)
+		{
+			s = sortlist = lcons(sortcl, NIL);
+		}
+		else
+		{
+			List	   *i;
+			
+			foreach (i, sortlist)
+			{
+				SortClause *scl = (SortClause *) lfirst (i);
+				
+				if ( scl->resdom == sortcl->resdom )
+					break;
+			}
+			if ( i == NIL )			/* not in sortlist already */
+			{
+				lnext(s) = lcons(sortcl, NIL);
+				s = lnext(s);
+			}
+			else
+				pfree (sortcl);		/* get rid of this */
+		}
+		orderlist = lnext(orderlist);
+	}
+
+	if (uniqueFlag)
+	{
+		List	   *i;
+		
+		if (uniqueFlag[0] == '*')
+		{
+
+			/*
+			 * concatenate all elements from target list that are not
+			 * already in the sortby list
+			 */
+			foreach(i, targetlist)
+			{
+				TargetEntry *tlelt = (TargetEntry *) lfirst(i);
+
+				s = sortlist;
+				while (s != NIL)
+				{
+					SortClause *sortcl = lfirst(s);
+
+					if (sortcl->resdom == tlelt->resdom)
+						break;
+					s = lnext(s);
+				}
+				if (s == NIL)
+				{
+					/* not a member of the sortclauses yet */
+					SortClause *sortcl = makeNode(SortClause);
+
+					sortcl->resdom = tlelt->resdom;
+					sortcl->opoid = any_ordering_op(tlelt->resdom->restype);
+
+					sortlist = lappend(sortlist, sortcl);
+				}
+			}
+		}
+		else
+		{
+			TargetEntry *tlelt = NULL;
+			char	   *uniqueAttrName = uniqueFlag;
+
+			/* only create sort clause with the specified unique attribute */
+			foreach(i, targetlist)
+			{
+				tlelt = (TargetEntry *) lfirst(i);
+				if (strcmp(tlelt->resdom->resname, uniqueAttrName) == 0)
+					break;
+			}
+			if (i == NIL)
+			{
+				elog(WARN, "The field specified in the UNIQUE ON clause is not in the targetlist");
+			}
+			s = sortlist;
+			foreach(s, sortlist)
+			{
+				SortClause *sortcl = lfirst(s);
+
+				if (sortcl->resdom == tlelt->resdom)
+					break;
+			}
+			if (s == NIL)
+			{
+				/* not a member of the sortclauses yet */
+				SortClause *sortcl = makeNode(SortClause);
+
+				sortcl->resdom = tlelt->resdom;
+				sortcl->opoid = any_ordering_op(tlelt->resdom->restype);
+
+				sortlist = lappend(sortlist, sortcl);
+			}
+		}
+
+	}
+
+	return sortlist;
+}
diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c
new file mode 100644
index 0000000000000000000000000000000000000000..fe00b2b48ac90e94e8ce9e5e7093ffd92f943e2a
--- /dev/null
+++ b/src/backend/parser/parse_expr.c
@@ -0,0 +1,694 @@
+/*-------------------------------------------------------------------------
+ *
+ * parse_expr.c
+ *	  handle expressions in parser
+ *
+ * Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ *	  $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.1 1997/11/25 22:05:39 momjian Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "postgres.h"
+#include "catalog/pg_type.h"
+#include "nodes/makefuncs.h"
+#include "nodes/nodes.h"
+#include "nodes/params.h"
+#include "nodes/relation.h"
+#include "parser/parse_expr.h"
+#include "parser/parse_func.h"
+#include "parser/parse_node.h"
+#include "parser/parse_relation.h"
+#include "parser/parse_target.h"
+#include "parse.h"
+#include "utils/builtins.h"
+
+#ifdef 0
+#include "nodes/primnodes.h"
+#include "nodes/parsenodes.h"
+#include "catalog/pg_aggregate.h"
+#include "catalog/pg_proc.h"
+#include "utils/elog.h"
+#include "utils/lsyscache.h"
+#include "utils/palloc.h"
+#include "utils/mcxt.h"
+#include "utils/syscache.h"
+#include "utils/acl.h"
+#include "nodes/nodeFuncs.h"
+#include "commands/sequence.h"
+
+#include "optimizer/clauses.h"
+#include "access/heapam.h"
+
+#include "miscadmin.h"
+#endif
+
+Oid param_type(int t); /* from gram.y */
+
+/*
+ * transformExpr -
+ *	  analyze and transform expressions. Type checking and type casting is
+ *	  done here. The optimizer and the executor cannot handle the original
+ *	  (raw) expressions collected by the parse tree. Hence the transformation
+ *	  here.
+ */
+Node *
+transformExpr(ParseState *pstate, Node *expr, int precedence)
+{
+	Node	   *result = NULL;
+
+	if (expr == NULL)
+		return NULL;
+
+	switch (nodeTag(expr))
+	{
+		case T_Attr:
+			{
+				Attr	   *att = (Attr *) expr;
+				Node	   *temp;
+
+				/* what if att.attrs == "*"?? */
+				temp = handleNestedDots(pstate, att, &pstate->p_last_resno);
+				if (att->indirection != NIL)
+				{
+					List	   *idx = att->indirection;
+
+					while (idx != NIL)
+					{
+						A_Indices  *ai = (A_Indices *) lfirst(idx);
+						Node	   *lexpr = NULL,
+								   *uexpr;
+
+						uexpr = transformExpr(pstate, ai->uidx, precedence);	/* must exists */
+						if (exprType(uexpr) != INT4OID)
+							elog(WARN, "array index expressions must be int4's");
+						if (ai->lidx != NULL)
+						{
+							lexpr = transformExpr(pstate, ai->lidx, precedence);
+							if (exprType(lexpr) != INT4OID)
+								elog(WARN, "array index expressions must be int4's");
+						}
+#if 0
+						pfree(ai->uidx);
+						if (ai->lidx != NULL)
+							pfree(ai->lidx);
+#endif
+						ai->lidx = lexpr;
+						ai->uidx = uexpr;
+
+						/*
+						 * note we reuse the list of indices, make sure we
+						 * don't free them! Otherwise, make a new list
+						 * here
+						 */
+						idx = lnext(idx);
+					}
+					result = (Node *) make_array_ref(temp, att->indirection);
+				}
+				else
+				{
+					result = temp;
+				}
+				break;
+			}
+		case T_A_Const:
+			{
+				A_Const    *con = (A_Const *) expr;
+				Value	   *val = &con->val;
+
+				if (con->typename != NULL)
+				{
+					result = parser_typecast(val, con->typename, -1);
+				}
+				else
+				{
+					result = (Node *) make_const(val);
+				}
+				break;
+			}
+		case T_ParamNo:
+			{
+				ParamNo    *pno = (ParamNo *) expr;
+				Oid			toid;
+				int			paramno;
+				Param	   *param;
+
+				paramno = pno->number;
+				toid = param_type(paramno);
+				if (!OidIsValid(toid))
+				{
+					elog(WARN, "Parameter '$%d' is out of range",
+						 paramno);
+				}
+				param = makeNode(Param);
+				param->paramkind = PARAM_NUM;
+				param->paramid = (AttrNumber) paramno;
+				param->paramname = "<unnamed>";
+				param->paramtype = (Oid) toid;
+				param->param_tlist = (List *) NULL;
+
+				result = (Node *) param;
+				break;
+			}
+		case T_A_Expr:
+			{
+				A_Expr	   *a = (A_Expr *) expr;
+
+				switch (a->oper)
+				{
+					case OP:
+						{
+							Node	   *lexpr = transformExpr(pstate, a->lexpr, precedence);
+							Node	   *rexpr = transformExpr(pstate, a->rexpr, precedence);
+
+							result = (Node *) make_op(a->opname, lexpr, rexpr);
+						}
+						break;
+					case ISNULL:
+						{
+							Node	   *lexpr = transformExpr(pstate, a->lexpr, precedence);
+
+							result = ParseFunc(pstate,
+										  "nullvalue", lcons(lexpr, NIL),
+											   &pstate->p_last_resno);
+						}
+						break;
+					case NOTNULL:
+						{
+							Node	   *lexpr = transformExpr(pstate, a->lexpr, precedence);
+
+							result = ParseFunc(pstate,
+									   "nonnullvalue", lcons(lexpr, NIL),
+											   &pstate->p_last_resno);
+						}
+						break;
+					case AND:
+						{
+							Expr	   *expr = makeNode(Expr);
+							Node	   *lexpr = transformExpr(pstate, a->lexpr, precedence);
+							Node	   *rexpr = transformExpr(pstate, a->rexpr, precedence);
+
+							if (exprType(lexpr) != BOOLOID)
+								elog(WARN,
+									 "left-hand side of AND is type '%s', not bool",
+									 typeidTypeName(exprType(lexpr)));
+							if (exprType(rexpr) != BOOLOID)
+								elog(WARN,
+									 "right-hand side of AND is type '%s', not bool",
+									 typeidTypeName(exprType(rexpr)));
+							expr->typeOid = BOOLOID;
+							expr->opType = AND_EXPR;
+							expr->args = makeList(lexpr, rexpr, -1);
+							result = (Node *) expr;
+						}
+						break;
+					case OR:
+						{
+							Expr	   *expr = makeNode(Expr);
+							Node	   *lexpr = transformExpr(pstate, a->lexpr, precedence);
+							Node	   *rexpr = transformExpr(pstate, a->rexpr, precedence);
+
+							if (exprType(lexpr) != BOOLOID)
+								elog(WARN,
+									 "left-hand side of OR is type '%s', not bool",
+									 typeidTypeName(exprType(lexpr)));
+							if (exprType(rexpr) != BOOLOID)
+								elog(WARN,
+									 "right-hand side of OR is type '%s', not bool",
+									 typeidTypeName(exprType(rexpr)));
+							expr->typeOid = BOOLOID;
+							expr->opType = OR_EXPR;
+							expr->args = makeList(lexpr, rexpr, -1);
+							result = (Node *) expr;
+						}
+						break;
+					case NOT:
+						{
+							Expr	   *expr = makeNode(Expr);
+							Node	   *rexpr = transformExpr(pstate, a->rexpr, precedence);
+
+							if (exprType(rexpr) != BOOLOID)
+								elog(WARN,
+								"argument to NOT is type '%s', not bool",
+									 typeidTypeName(exprType(rexpr)));
+							expr->typeOid = BOOLOID;
+							expr->opType = NOT_EXPR;
+							expr->args = makeList(rexpr, -1);
+							result = (Node *) expr;
+						}
+						break;
+				}
+				break;
+			}
+		case T_Ident:
+			{
+
+				/*
+				 * look for a column name or a relation name (the default
+				 * behavior)
+				 */
+				result = transformIdent(pstate, expr, precedence);
+				break;
+			}
+		case T_FuncCall:
+			{
+				FuncCall   *fn = (FuncCall *) expr;
+				List	   *args;
+
+				/* transform the list of arguments */
+				foreach(args, fn->args)
+					lfirst(args) = transformExpr(pstate, (Node *) lfirst(args), precedence);
+				result = ParseFunc(pstate,
+						  fn->funcname, fn->args, &pstate->p_last_resno);
+				break;
+			}
+		default:
+			/* should not reach here */
+			elog(WARN, "transformExpr: does not know how to transform %d\n",
+				 nodeTag(expr));
+			break;
+	}
+
+	return result;
+}
+
+Node *
+transformIdent(ParseState *pstate, Node *expr, int precedence)
+{
+	Ident	   *ident = (Ident *) expr;
+	RangeTblEntry *rte;
+	Node	   *column_result,
+			   *relation_result,
+			   *result;
+
+	column_result = relation_result = result = 0;
+	/* try to find the ident as a column */
+	if ((rte = colnameRangeTableEntry(pstate, ident->name)) != NULL)
+	{
+		Attr	   *att = makeNode(Attr);
+
+		att->relname = rte->refname;
+		att->attrs = lcons(makeString(ident->name), NIL);
+		column_result =
+			(Node *) handleNestedDots(pstate, att, &pstate->p_last_resno);
+	}
+
+	/* try to find the ident as a relation */
+	if (refnameRangeTableEntry(pstate->p_rtable, ident->name) != NULL)
+	{
+		ident->isRel = TRUE;
+		relation_result = (Node *) ident;
+	}
+
+	/* choose the right result based on the precedence */
+	if (precedence == EXPR_COLUMN_FIRST)
+	{
+		if (column_result)
+			result = column_result;
+		else
+			result = relation_result;
+	}
+	else
+	{
+		if (relation_result)
+			result = relation_result;
+		else
+			result = column_result;
+	}
+
+	if (result == NULL)
+		elog(WARN, "attribute '%s' not found", ident->name);
+
+	return result;
+}
+
+/*
+ *	exprType -
+ *	  returns the Oid of the type of the expression. (Used for typechecking.)
+ */
+Oid
+exprType(Node *expr)
+{
+	Oid			type = (Oid) 0;
+
+	switch (nodeTag(expr))
+	{
+		case T_Func:
+			type = ((Func *) expr)->functype;
+			break;
+		case T_Iter:
+			type = ((Iter *) expr)->itertype;
+			break;
+		case T_Var:
+			type = ((Var *) expr)->vartype;
+			break;
+		case T_Expr:
+			type = ((Expr *) expr)->typeOid;
+			break;
+		case T_Const:
+			type = ((Const *) expr)->consttype;
+			break;
+		case T_ArrayRef:
+			type = ((ArrayRef *) expr)->refelemtype;
+			break;
+		case T_Aggreg:
+			type = ((Aggreg *) expr)->aggtype;
+			break;
+		case T_Param:
+			type = ((Param *) expr)->paramtype;
+			break;
+		case T_Ident:
+			/* is this right? */
+			type = UNKNOWNOID;
+			break;
+		default:
+			elog(WARN, "exprType: don't know how to get type for %d node",
+				 nodeTag(expr));
+			break;
+	}
+	return type;
+}
+
+/*
+ ** HandleNestedDots --
+ **    Given a nested dot expression (i.e. (relation func ... attr), build up
+ ** a tree with of Iter and Func nodes.
+ */
+Node *
+handleNestedDots(ParseState *pstate, Attr *attr, int *curr_resno)
+{
+	List	   *mutator_iter;
+	Node	   *retval = NULL;
+
+	if (attr->paramNo != NULL)
+	{
+		Param	   *param = (Param *) transformExpr(pstate, (Node *) attr->paramNo, EXPR_RELATION_FIRST);
+
+		retval =
+			ParseFunc(pstate, strVal(lfirst(attr->attrs)),
+					  lcons(param, NIL),
+					  curr_resno);
+	}
+	else
+	{
+		Ident	   *ident = makeNode(Ident);
+
+		ident->name = attr->relname;
+		ident->isRel = TRUE;
+		retval =
+			ParseFunc(pstate, strVal(lfirst(attr->attrs)),
+					  lcons(ident, NIL),
+					  curr_resno);
+	}
+
+	foreach(mutator_iter, lnext(attr->attrs))
+	{
+		retval = ParseFunc(pstate, strVal(lfirst(mutator_iter)),
+						   lcons(retval, NIL),
+						   curr_resno);
+	}
+
+	return (retval);
+}
+
+Node	   *
+parser_typecast(Value *expr, TypeName *typename, int typlen)
+{
+	/* check for passing non-ints */
+	Const	   *adt;
+	Datum		lcp;
+	Type		tp;
+	char		type_string[NAMEDATALEN];
+	int32		len;
+	char	   *cp = NULL;
+	char	   *const_string = NULL;
+	bool		string_palloced = false;
+
+	switch (nodeTag(expr))
+	{
+		case T_String:
+			const_string = DatumGetPointer(expr->val.str);
+			break;
+		case T_Integer:
+			const_string = (char *) palloc(256);
+			string_palloced = true;
+			sprintf(const_string, "%ld", expr->val.ival);
+			break;
+		default:
+			elog(WARN,
+			"parser_typecast: cannot cast this expression to type \"%s\"",
+				 typename->name);
+	}
+
+	if (typename->arrayBounds != NIL)
+	{
+		sprintf(type_string, "_%s", typename->name);
+		tp = (Type) typenameType(type_string);
+	}
+	else
+	{
+		tp = (Type) typenameType(typename->name);
+	}
+
+	len = typeLen(tp);
+
+#if 0							/* fix me */
+	switch (CInteger(lfirst(expr)))
+	{
+		case INT4OID:			/* int4 */
+			const_string = (char *) palloc(256);
+			string_palloced = true;
+			sprintf(const_string, "%d", ((Const *) lnext(expr))->constvalue);
+			break;
+
+		case NAMEOID:			/* char16 */
+			const_string = (char *) palloc(256);
+			string_palloced = true;
+			sprintf(const_string, "%s", ((Const *) lnext(expr))->constvalue);
+			break;
+
+		case CHAROID:			/* char */
+			const_string = (char *) palloc(256);
+			string_palloced = true;
+			sprintf(const_string, "%c", ((Const) lnext(expr))->constvalue);
+			break;
+
+		case FLOAT8OID: /* float8 */
+			const_string = (char *) palloc(256);
+			string_palloced = true;
+			sprintf(const_string, "%f", ((Const) lnext(expr))->constvalue);
+			break;
+
+		case CASHOID:			/* money */
+			const_string = (char *) palloc(256);
+			string_palloced = true;
+			sprintf(const_string, "%d",
+					(int) ((Const *) expr)->constvalue);
+			break;
+
+		case TEXTOID:			/* text */
+			const_string = DatumGetPointer(((Const) lnext(expr))->constvalue);
+			const_string = (char *) textout((struct varlena *) const_string);
+			break;
+
+		case UNKNOWNOID:		/* unknown */
+			const_string = DatumGetPointer(((Const) lnext(expr))->constvalue);
+			const_string = (char *) textout((struct varlena *) const_string);
+			break;
+
+		default:
+			elog(WARN, "unknown type %d", CInteger(lfirst(expr)));
+	}
+#endif
+
+	cp = stringTypeString(tp, const_string, typlen);
+
+	if (!typeByVal(tp))
+	{
+/*
+		if (len >= 0 && len != PSIZE(cp)) {
+			char *pp;
+			pp = (char *) palloc(len);
+			memmove(pp, cp, len);
+			cp = pp;
+		}
+*/
+		lcp = PointerGetDatum(cp);
+	}
+	else
+	{
+		switch (len)
+		{
+			case 1:
+				lcp = Int8GetDatum(cp);
+				break;
+			case 2:
+				lcp = Int16GetDatum(cp);
+				break;
+			case 4:
+				lcp = Int32GetDatum(cp);
+				break;
+			default:
+				lcp = PointerGetDatum(cp);
+				break;
+		}
+	}
+
+	adt = makeConst(typeTypeId(tp),
+					len,
+					(Datum) lcp,
+					false,
+					typeByVal(tp),
+					false,		/* not a set */
+					true /* is cast */ );
+
+	if (string_palloced)
+		pfree(const_string);
+
+	return (Node *) adt;
+}
+
+Node	   *
+parser_typecast2(Node *expr, Oid exprType, Type tp, int typlen)
+{
+	/* check for passing non-ints */
+	Const	   *adt;
+	Datum		lcp;
+	int32		len = typeLen(tp);
+	char	   *cp = NULL;
+
+	char	   *const_string = NULL;
+	bool		string_palloced = false;
+
+	Assert(IsA(expr, Const));
+
+	switch (exprType)
+	{
+		case 0:			/* NULL */
+			break;
+		case INT4OID:			/* int4 */
+			const_string = (char *) palloc(256);
+			string_palloced = true;
+			sprintf(const_string, "%d",
+					(int) ((Const *) expr)->constvalue);
+			break;
+		case NAMEOID:			/* char16 */
+			const_string = (char *) palloc(256);
+			string_palloced = true;
+			sprintf(const_string, "%s",
+					(char *) ((Const *) expr)->constvalue);
+			break;
+		case CHAROID:			/* char */
+			const_string = (char *) palloc(256);
+			string_palloced = true;
+			sprintf(const_string, "%c",
+					(char) ((Const *) expr)->constvalue);
+			break;
+		case FLOAT4OID: /* float4 */
+			{
+				float32		floatVal =
+				DatumGetFloat32(((Const *) expr)->constvalue);
+
+				const_string = (char *) palloc(256);
+				string_palloced = true;
+				sprintf(const_string, "%f", *floatVal);
+				break;
+			}
+		case FLOAT8OID: /* float8 */
+			{
+				float64		floatVal =
+				DatumGetFloat64(((Const *) expr)->constvalue);
+
+				const_string = (char *) palloc(256);
+				string_palloced = true;
+				sprintf(const_string, "%f", *floatVal);
+				break;
+			}
+		case CASHOID:			/* money */
+			const_string = (char *) palloc(256);
+			string_palloced = true;
+			sprintf(const_string, "%ld",
+					(long) ((Const *) expr)->constvalue);
+			break;
+		case TEXTOID:			/* text */
+			const_string =
+				DatumGetPointer(((Const *) expr)->constvalue);
+			const_string = (char *) textout((struct varlena *) const_string);
+			break;
+		case UNKNOWNOID:		/* unknown */
+			const_string =
+				DatumGetPointer(((Const *) expr)->constvalue);
+			const_string = (char *) textout((struct varlena *) const_string);
+			break;
+		default:
+			elog(WARN, "unknown type %u ", exprType);
+	}
+
+	if (!exprType)
+	{
+		adt = makeConst(typeTypeId(tp),
+						(Size) 0,
+						(Datum) NULL,
+						true,	/* isnull */
+						false,	/* was omitted */
+						false,	/* not a set */
+						true /* is cast */ );
+		return ((Node *) adt);
+	}
+
+	cp = stringTypeString(tp, const_string, typlen);
+
+
+	if (!typeByVal(tp))
+	{
+/*
+		if (len >= 0 && len != PSIZE(cp)) {
+			char *pp;
+			pp = (char *) palloc(len);
+			memmove(pp, cp, len);
+			cp = pp;
+		}
+*/
+		lcp = PointerGetDatum(cp);
+	}
+	else
+	{
+		switch (len)
+		{
+			case 1:
+				lcp = Int8GetDatum(cp);
+				break;
+			case 2:
+				lcp = Int16GetDatum(cp);
+				break;
+			case 4:
+				lcp = Int32GetDatum(cp);
+				break;
+			default:
+				lcp = PointerGetDatum(cp);
+				break;
+		}
+	}
+
+	adt = makeConst(typeTypeId(tp),
+					(Size) len,
+					(Datum) lcp,
+					false,
+					false,		/* was omitted */
+					false,		/* not a set */
+					true /* is cast */ );
+
+	/*
+	 * printf("adt %s : %u %d %d\n",CString(expr),typeTypeId(tp) , len,cp);
+	 */
+	if (string_palloced)
+		pfree(const_string);
+
+	return ((Node *) adt);
+} 
diff --git a/src/backend/parser/parse_func.c b/src/backend/parser/parse_func.c
new file mode 100644
index 0000000000000000000000000000000000000000..bb2a7773fdd9f8de360b87cd1befa43e5fe4dc92
--- /dev/null
+++ b/src/backend/parser/parse_func.c
@@ -0,0 +1,1264 @@
+/*-------------------------------------------------------------------------
+ *
+ * parse_func.c
+ *		handle function calls in parser
+ *
+ * Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ *	  $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.1 1997/11/25 22:05:41 momjian Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+#include <string.h>
+#include "postgres.h"
+#include "fmgr.h"
+#include "miscadmin.h"
+#include "access/genam.h"
+#include "access/heapam.h"
+#include "access/itup.h"
+#include "access/relscan.h"
+#include "access/sdir.h"
+#include "catalog/catname.h"
+#include "catalog/indexing.h"
+#include "catalog/pg_inherits.h"
+#include "catalog/pg_proc.h"
+#include "catalog/pg_type.h"
+#include "lib/dllist.h"
+#include "nodes/makefuncs.h"
+#include "nodes/relation.h"
+#include "parser/parse_agg.h"
+#include "parser/parse_expr.h"
+#include "parser/parse_func.h"
+#include "parser/parse_node.h"
+#include "parser/parse_relation.h"
+#include "parser/parse_type.h"
+#include "storage/bufmgr.h"
+#include "storage/lmgr.h"
+#include "utils/acl.h"
+#include "utils/builtins.h"
+#include "utils/lsyscache.h"
+#include "utils/syscache.h"
+
+#ifdef 0
+#include "utils/datum.h"
+
+#include "utils/elog.h"
+#include "utils/palloc.h"
+
+#include "nodes/pg_list.h"
+#include "nodes/parsenodes.h"
+
+#include "catalog/pg_operator.h"
+#include "catalog/catname.h"
+
+#include "access/skey.h"
+#include "access/tupdesc.h"
+#include "access/htup.h"
+#include "access/genam.h"
+#include "access/itup.h"
+#include "access/tupmacs.h"
+
+#include "storage/buf.h"
+#endif
+
+#define ISCOMPLEX(type) (typeidTypeRelid(type) ? true : false)
+
+#define MAXFARGS 8				/* max # args to a c or postquel function */
+
+typedef struct _SuperQE
+{
+	Oid			sqe_relid;
+} SuperQE;
+
+/*
+ * parse function
+ */
+
+Node *
+ParseFunc(ParseState *pstate, char *funcname, List *fargs, int *curr_resno)
+{
+	Oid			rettype = (Oid) 0;
+	Oid			argrelid = (Oid) 0;
+	Oid			funcid = (Oid) 0;
+	List	   *i = NIL;
+	Node	   *first_arg = NULL;
+	char	   *relname = NULL;
+	char	   *refname = NULL;
+	Relation	rd;
+	Oid			relid;
+	int			nargs;
+	Func	   *funcnode;
+	Oid			oid_array[8];
+	Oid		   *true_oid_array;
+	Node	   *retval;
+	bool		retset;
+	bool		exists;
+	bool		attisset = false;
+	Oid			toid = (Oid) 0;
+	Expr	   *expr;
+
+	if (fargs)
+	{
+		first_arg = lfirst(fargs);
+		if (first_arg == NULL)
+			elog(WARN, "function '%s' does not allow NULL input", funcname);
+	}
+
+	/*
+	 * check for projection methods: if function takes one argument, and
+	 * that argument is a relation, param, or PQ function returning a
+	 * complex * type, then the function could be a projection.
+	 */
+	if (length(fargs) == 1)
+	{
+
+		if (nodeTag(first_arg) == T_Ident && ((Ident *) first_arg)->isRel)
+		{
+			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);
+			if (rte == NULL)
+				rte = addRangeTableEntry(pstate, refname, refname, FALSE, FALSE);
+
+			relname = rte->relname;
+			relid = rte->relid;
+
+			/*
+			 * If the attr isn't a set, just make a var for it.  If it is
+			 * a set, treat it like a function and drop through.
+			 */
+			if (get_attnum(relid, funcname) != InvalidAttrNumber)
+			{
+				Oid			dummyTypeId;
+
+				return
+					((Node *) make_var(pstate,
+									   refname,
+									   funcname,
+									   &dummyTypeId));
+			}
+			else
+			{
+				/* drop through - attr is a set */
+				;
+			}
+		}
+		else if (ISCOMPLEX(exprType(first_arg)))
+		{
+
+			/*
+			 * Attempt to handle projection of a complex argument. If
+			 * ParseComplexProjection can't handle the projection, we have
+			 * to keep going.
+			 */
+			retval = ParseComplexProjection(pstate,
+											funcname,
+											first_arg,
+											&attisset);
+			if (attisset)
+			{
+				toid = exprType(first_arg);
+				rd = heap_openr(typeidTypeName(toid));
+				if (RelationIsValid(rd))
+				{
+					relname = RelationGetRelationName(rd)->data;
+					heap_close(rd);
+				}
+				else
+					elog(WARN,
+						 "Type '%s' is not a relation type",
+						 typeidTypeName(toid));
+				argrelid = typeidTypeRelid(toid);
+
+				/*
+				 * A projection contains either an attribute name or the
+				 * "*".
+				 */
+				if ((get_attnum(argrelid, funcname) == InvalidAttrNumber)
+					&& strcmp(funcname, "*"))
+				{
+					elog(WARN, "Functions on sets are not yet supported");
+				}
+			}
+
+			if (retval)
+				return retval;
+		}
+		else
+		{
+
+			/*
+			 * Parsing aggregates.
+			 */
+			Oid			basetype;
+
+			/*
+			 * the aggregate count is a special case, ignore its base
+			 * type.  Treat it as zero
+			 */
+			if (strcmp(funcname, "count") == 0)
+				basetype = 0;
+			else
+				basetype = exprType(lfirst(fargs));
+			if (SearchSysCacheTuple(AGGNAME,
+									PointerGetDatum(funcname),
+									ObjectIdGetDatum(basetype),
+									0, 0))
+			{
+				Aggreg	   *aggreg = ParseAgg(funcname, basetype, lfirst(fargs));
+
+				AddAggToParseState(pstate, aggreg);
+				return (Node *) aggreg;
+			}
+		}
+	}
+
+
+	/*
+	 * * If we dropped through to here it's really a function (or a set,
+	 * which * is implemented as a function.) * extract arg type info and
+	 * transform relation name arguments into * varnodes of the
+	 * appropriate form.
+	 */
+	MemSet(&oid_array[0], 0, 8 * sizeof(Oid));
+
+	nargs = 0;
+	foreach(i, fargs)
+	{
+		int			vnum;
+		RangeTblEntry *rte;
+		Node	   *pair = lfirst(i);
+
+		if (nodeTag(pair) == T_Ident && ((Ident *) pair)->isRel)
+		{
+
+			/*
+			 * a relation
+			 */
+			refname = ((Ident *) pair)->name;
+
+			rte = refnameRangeTableEntry(pstate->p_rtable, refname);
+			if (rte == NULL)
+				rte = addRangeTableEntry(pstate, refname, refname,
+										 FALSE, FALSE);
+			relname = rte->relname;
+
+			vnum = refnameRangeTablePosn(pstate->p_rtable, rte->refname);
+
+			/*
+			 * for func(relname), the param to the function is the tuple
+			 * under consideration.  we build a special VarNode to reflect
+			 * this -- it has varno set to the correct range table entry,
+			 * but has varattno == 0 to signal that the whole tuple is the
+			 * argument.
+			 */
+			toid = typeTypeId(typenameType(relname));
+			/* replace it in the arg list */
+			lfirst(fargs) =
+				makeVar(vnum, 0, toid, vnum, 0);
+		}
+		else if (!attisset)
+		{						/* set functions don't have parameters */
+
+			/*
+			 * any functiona args which are typed "unknown", but aren't
+			 * constants, we don't know what to do with, because we can't
+			 * cast them	- jolly
+			 */
+			if (exprType(pair) == UNKNOWNOID &&
+				!IsA(pair, Const))
+			{
+				elog(WARN, "ParseFunc: no function named '%s' that takes in an unknown type as argument #%d", funcname, nargs);
+			}
+			else
+				toid = exprType(pair);
+		}
+
+		oid_array[nargs++] = toid;
+	}
+
+	/*
+	 * func_get_detail looks up the function in the catalogs, does
+	 * disambiguation for polymorphic functions, handles inheritance, and
+	 * returns the funcid and type and set or singleton status of the
+	 * function's return value.  it also returns the true argument types
+	 * to the function.  if func_get_detail returns true, the function
+	 * exists.	otherwise, there was an error.
+	 */
+	if (attisset)
+	{							/* we know all of these fields already */
+
+		/*
+		 * We create a funcnode with a placeholder function SetEval.
+		 * SetEval() never actually gets executed.	When the function
+		 * evaluation routines see it, they use the funcid projected out
+		 * from the relation as the actual function to call. Example:
+		 * retrieve (emp.mgr.name) The plan for this will scan the emp
+		 * relation, projecting out the mgr attribute, which is a funcid.
+		 * This function is then called (instead of SetEval) and "name" is
+		 * projected from its result.
+		 */
+		funcid = SetEvalRegProcedure;
+		rettype = toid;
+		retset = true;
+		true_oid_array = oid_array;
+		exists = true;
+	}
+	else
+	{
+		exists = func_get_detail(funcname, nargs, oid_array, &funcid,
+								 &rettype, &retset, &true_oid_array);
+	}
+
+	if (!exists)
+		elog(WARN, "no such attribute or function '%s'", funcname);
+
+	/* got it */
+	funcnode = makeNode(Func);
+	funcnode->funcid = funcid;
+	funcnode->functype = rettype;
+	funcnode->funcisindex = false;
+	funcnode->funcsize = 0;
+	funcnode->func_fcache = NULL;
+	funcnode->func_tlist = NIL;
+	funcnode->func_planlist = NIL;
+
+	/* perform the necessary typecasting */
+	make_arguments(nargs, fargs, oid_array, true_oid_array);
+
+	/*
+	 * for functions returning base types, we want to project out the
+	 * return value.  set up a target list to do that.	the executor will
+	 * ignore these for c functions, and do the right thing for postquel
+	 * functions.
+	 */
+
+	if (typeidTypeRelid(rettype) == InvalidOid)
+		funcnode->func_tlist = setup_base_tlist(rettype);
+
+	/*
+	 * For sets, we want to make a targetlist to project out this
+	 * attribute of the set tuples.
+	 */
+	if (attisset)
+	{
+		if (!strcmp(funcname, "*"))
+		{
+			funcnode->func_tlist =
+				expandAll(pstate, relname, refname, curr_resno);
+		}
+		else
+		{
+			funcnode->func_tlist = setup_tlist(funcname, argrelid);
+			rettype = attnameTypeId(argrelid, funcname);
+		}
+	}
+
+	/*
+	 * Sequence handling.
+	 */
+	if (funcid == SeqNextValueRegProcedure ||
+		funcid == SeqCurrValueRegProcedure)
+	{
+		Const	   *seq;
+		char	   *seqrel;
+		text	   *seqname;
+		int32		aclcheck_result = -1;
+		extern text *lower (text *string);
+
+		Assert(length(fargs) == 1);
+		seq = (Const *) lfirst(fargs);
+		if (!IsA((Node *) seq, Const))
+			elog(WARN, "%s: only constant sequence names are acceptable", funcname);
+		seqname = lower ((text*)DatumGetPointer(seq->constvalue));
+		pfree (DatumGetPointer(seq->constvalue));
+		seq->constvalue = PointerGetDatum (seqname);
+		seqrel = textout(seqname);
+
+		if ((aclcheck_result = pg_aclcheck(seqrel, GetPgUserName(),
+			   ((funcid == SeqNextValueRegProcedure) ? ACL_WR : ACL_RD)))
+			!= ACLCHECK_OK)
+			elog(WARN, "%s.%s: %s",
+			  seqrel, funcname, aclcheck_error_strings[aclcheck_result]);
+
+		pfree(seqrel);
+
+		if (funcid == SeqNextValueRegProcedure && pstate->p_in_where_clause)
+			elog(WARN, "nextval of a sequence in WHERE disallowed");
+	}
+
+	expr = makeNode(Expr);
+	expr->typeOid = rettype;
+	expr->opType = FUNC_EXPR;
+	expr->oper = (Node *) funcnode;
+	expr->args = fargs;
+	retval = (Node *) expr;
+
+	/*
+	 * if the function returns a set of values, then we need to iterate
+	 * over all the returned values in the executor, so we stick an iter
+	 * node here.  if it returns a singleton, then we don't need the iter
+	 * node.
+	 */
+
+	if (retset)
+	{
+		Iter	   *iter = makeNode(Iter);
+
+		iter->itertype = rettype;
+		iter->iterexpr = retval;
+		retval = (Node *) iter;
+	}
+
+	return (retval);
+}
+
+Oid
+funcid_get_rettype(Oid funcid)
+{
+	HeapTuple	func_tuple = NULL;
+	Oid			funcrettype = (Oid) 0;
+
+	func_tuple = SearchSysCacheTuple(PROOID, ObjectIdGetDatum(funcid),
+									 0, 0, 0);
+
+	if (!HeapTupleIsValid(func_tuple))
+		elog(WARN, "function  %d does not exist", funcid);
+
+	funcrettype = (Oid)
+		((Form_pg_proc) GETSTRUCT(func_tuple))->prorettype;
+
+	return (funcrettype);
+}
+
+/*
+ * get a list of all argument type vectors for which a function named
+ * funcname taking nargs arguments exists
+ */
+CandidateList
+func_get_candidates(char *funcname, int nargs)
+{
+	Relation	heapRelation;
+	Relation	idesc;
+	ScanKeyData skey;
+	HeapTuple	tuple;
+	IndexScanDesc sd;
+	RetrieveIndexResult indexRes;
+	Buffer		buffer;
+	Form_pg_proc pgProcP;
+	bool		bufferUsed = FALSE;
+	CandidateList candidates = NULL;
+	CandidateList current_candidate;
+	int			i;
+
+	heapRelation = heap_openr(ProcedureRelationName);
+	ScanKeyEntryInitialize(&skey,
+						   (bits16) 0x0,
+						   (AttrNumber) 1,
+						   (RegProcedure) NameEqualRegProcedure,
+						   (Datum) funcname);
+
+	idesc = index_openr(ProcedureNameIndex);
+
+	sd = index_beginscan(idesc, false, 1, &skey);
+
+	do
+	{
+		tuple = (HeapTuple) NULL;
+		if (bufferUsed)
+		{
+			ReleaseBuffer(buffer);
+			bufferUsed = FALSE;
+		}
+
+		indexRes = index_getnext(sd, ForwardScanDirection);
+		if (indexRes)
+		{
+			ItemPointer iptr;
+
+			iptr = &indexRes->heap_iptr;
+			tuple = heap_fetch(heapRelation, false, iptr, &buffer);
+			pfree(indexRes);
+			if (HeapTupleIsValid(tuple))
+			{
+				pgProcP = (Form_pg_proc) GETSTRUCT(tuple);
+				bufferUsed = TRUE;
+				if (pgProcP->pronargs == nargs)
+				{
+					current_candidate = (CandidateList)
+						palloc(sizeof(struct _CandidateList));
+					current_candidate->args = (Oid *)
+						palloc(8 * sizeof(Oid));
+					MemSet(current_candidate->args, 0, 8 * sizeof(Oid));
+					for (i = 0; i < nargs; i++)
+					{
+						current_candidate->args[i] =
+							pgProcP->proargtypes[i];
+					}
+
+					current_candidate->next = candidates;
+					candidates = current_candidate;
+				}
+			}
+		}
+	} while (indexRes);
+
+	index_endscan(sd);
+	index_close(idesc);
+	heap_close(heapRelation);
+
+	return candidates;
+}
+
+/*
+ * can input_typeids be coerced to func_typeids?
+ */
+bool
+can_coerce(int nargs, Oid *input_typeids, Oid *func_typeids)
+{
+	int			i;
+	Type		tp;
+
+	/*
+	 * right now, we only coerce "unknown", and we cannot coerce it to a
+	 * relation type
+	 */
+	for (i = 0; i < nargs; i++)
+	{
+		if (input_typeids[i] != func_typeids[i])
+		{
+			if ((input_typeids[i] == BPCHAROID && func_typeids[i] == TEXTOID) ||
+				(input_typeids[i] == BPCHAROID && func_typeids[i] == VARCHAROID) ||
+				(input_typeids[i] == VARCHAROID && func_typeids[i] == TEXTOID) ||
+				(input_typeids[i] == VARCHAROID && func_typeids[i] == BPCHAROID) ||
+			(input_typeids[i] == CASHOID && func_typeids[i] == INT4OID) ||
+			 (input_typeids[i] == INT4OID && func_typeids[i] == CASHOID))
+				;				/* these are OK */
+			else if (input_typeids[i] != UNKNOWNOID || func_typeids[i] == 0)
+				return false;
+
+			tp = typeidType(input_typeids[i]);
+			if (typeTypeFlag(tp) == 'c')
+				return false;
+		}
+	}
+
+	return true;
+}
+
+/*
+ * given a list of possible typeid arrays to a function and an array of
+ * input typeids, produce a shortlist of those function typeid arrays
+ * that match the input typeids (either exactly or by coercion), and
+ * return the number of such arrays
+ */
+int
+match_argtypes(int nargs,
+			   Oid *input_typeids,
+			   CandidateList function_typeids,
+			   CandidateList *candidates)		/* return value */
+{
+	CandidateList current_candidate;
+	CandidateList matching_candidate;
+	Oid		   *current_typeids;
+	int			ncandidates = 0;
+
+	*candidates = NULL;
+
+	for (current_candidate = function_typeids;
+		 current_candidate != NULL;
+		 current_candidate = current_candidate->next)
+	{
+		current_typeids = current_candidate->args;
+		if (can_coerce(nargs, input_typeids, current_typeids))
+		{
+			matching_candidate = (CandidateList)
+				palloc(sizeof(struct _CandidateList));
+			matching_candidate->args = current_typeids;
+			matching_candidate->next = *candidates;
+			*candidates = matching_candidate;
+			ncandidates++;
+		}
+	}
+
+	return ncandidates;
+}
+
+/*
+ * given the input argtype array and more than one candidate
+ * for the function argtype array, attempt to resolve the conflict.
+ * returns the selected argtype array if the conflict can be resolved,
+ * otherwise returns NULL
+ */
+Oid *
+func_select_candidate(int nargs,
+					  Oid *input_typeids,
+					  CandidateList candidates)
+{
+	/* XXX no conflict resolution implemeneted yet */
+	return (NULL);
+}
+
+bool
+func_get_detail(char *funcname,
+				int nargs,
+				Oid *oid_array,
+				Oid *funcid,	/* return value */
+				Oid *rettype,	/* return value */
+				bool *retset,	/* return value */
+				Oid **true_typeids)		/* return value */
+{
+	Oid		  **input_typeid_vector;
+	Oid		   *current_input_typeids;
+	CandidateList function_typeids;
+	CandidateList current_function_typeids;
+	HeapTuple	ftup;
+	Form_pg_proc pform;
+
+	/*
+	 * attempt to find named function in the system catalogs with
+	 * arguments exactly as specified - so that the normal case is just as
+	 * quick as before
+	 */
+	ftup = SearchSysCacheTuple(PRONAME,
+							   PointerGetDatum(funcname),
+							   Int32GetDatum(nargs),
+							   PointerGetDatum(oid_array),
+							   0);
+	*true_typeids = oid_array;
+
+	/*
+	 * If an exact match isn't found : 1) get a vector of all possible
+	 * input arg type arrays constructed from the superclasses of the
+	 * original input arg types 2) get a list of all possible argument
+	 * type arrays to the function with given name and number of arguments
+	 * 3) for each input arg type array from vector #1 : a) find how many
+	 * of the function arg type arrays from list #2 it can be coerced to
+	 * b) - if the answer is one, we have our function - if the answer is
+	 * more than one, attempt to resolve the conflict - if the answer is
+	 * zero, try the next array from vector #1
+	 */
+	if (!HeapTupleIsValid(ftup))
+	{
+		function_typeids = func_get_candidates(funcname, nargs);
+
+		if (function_typeids != NULL)
+		{
+			int			ncandidates = 0;
+
+			input_typeid_vector = argtype_inherit(nargs, oid_array);
+			current_input_typeids = oid_array;
+
+			do
+			{
+				ncandidates = match_argtypes(nargs, current_input_typeids,
+											 function_typeids,
+											 &current_function_typeids);
+				if (ncandidates == 1)
+				{
+					*true_typeids = current_function_typeids->args;
+					ftup = SearchSysCacheTuple(PRONAME,
+											   PointerGetDatum(funcname),
+											   Int32GetDatum(nargs),
+										  PointerGetDatum(*true_typeids),
+											   0);
+					Assert(HeapTupleIsValid(ftup));
+				}
+				else if (ncandidates > 1)
+				{
+					*true_typeids =
+						func_select_candidate(nargs,
+											  current_input_typeids,
+											  current_function_typeids);
+					if (*true_typeids == NULL)
+					{
+						elog(NOTICE, "there is more than one function named \"%s\"",
+							 funcname);
+						elog(NOTICE, "that satisfies the given argument types. you will have to");
+						elog(NOTICE, "retype your query using explicit typecasts.");
+						func_error("func_get_detail", funcname, nargs, oid_array);
+					}
+					else
+					{
+						ftup = SearchSysCacheTuple(PRONAME,
+											   PointerGetDatum(funcname),
+												   Int32GetDatum(nargs),
+										  PointerGetDatum(*true_typeids),
+												   0);
+						Assert(HeapTupleIsValid(ftup));
+					}
+				}
+				current_input_typeids = *input_typeid_vector++;
+			}
+			while (current_input_typeids !=
+				   InvalidOid && ncandidates == 0);
+		}
+	}
+
+	if (!HeapTupleIsValid(ftup))
+	{
+		Type		tp;
+
+		if (nargs == 1)
+		{
+			tp = typeidType(oid_array[0]);
+			if (typeTypeFlag(tp) == 'c')
+				elog(WARN, "no such attribute or function \"%s\"",
+					 funcname);
+		}
+		func_error("func_get_detail", funcname, nargs, oid_array);
+	}
+	else
+	{
+		pform = (Form_pg_proc) GETSTRUCT(ftup);
+		*funcid = ftup->t_oid;
+		*rettype = pform->prorettype;
+		*retset = pform->proretset;
+
+		return (true);
+	}
+/* shouldn't reach here */
+	return (false);
+
+}
+
+/*
+ *	argtype_inherit() -- Construct an argtype vector reflecting the
+ *						 inheritance properties of the supplied argv.
+ *
+ *		This function is used to disambiguate among functions with the
+ *		same name but different signatures.  It takes an array of eight
+ *		type ids.  For each type id in the array that's a complex type
+ *		(a class), it walks up the inheritance tree, finding all
+ *		superclasses of that type.	A vector of new Oid type arrays
+ *		is returned to the caller, reflecting the structure of the
+ *		inheritance tree above the supplied arguments.
+ *
+ *		The order of this vector is as follows:  all superclasses of the
+ *		rightmost complex class are explored first.  The exploration
+ *		continues from right to left.  This policy means that we favor
+ *		keeping the leftmost argument type as low in the inheritance tree
+ *		as possible.  This is intentional; it is exactly what we need to
+ *		do for method dispatch.  The last type array we return is all
+ *		zeroes.  This will match any functions for which return types are
+ *		not defined.  There are lots of these (mostly builtins) in the
+ *		catalogs.
+ */
+Oid **
+argtype_inherit(int nargs, Oid *oid_array)
+{
+	Oid			relid;
+	int			i;
+	InhPaths	arginh[MAXFARGS];
+
+	for (i = 0; i < MAXFARGS; i++)
+	{
+		if (i < nargs)
+		{
+			arginh[i].self = oid_array[i];
+			if ((relid = typeidTypeRelid(oid_array[i])) != InvalidOid)
+			{
+				arginh[i].nsupers = findsupers(relid, &(arginh[i].supervec));
+			}
+			else
+			{
+				arginh[i].nsupers = 0;
+				arginh[i].supervec = (Oid *) NULL;
+			}
+		}
+		else
+		{
+			arginh[i].self = InvalidOid;
+			arginh[i].nsupers = 0;
+			arginh[i].supervec = (Oid *) NULL;
+		}
+	}
+
+	/* return an ordered cross-product of the classes involved */
+	return (genxprod(arginh, nargs));
+}
+
+int findsupers(Oid relid, Oid **supervec)
+{
+	Oid		   *relidvec;
+	Relation	inhrel;
+	HeapScanDesc inhscan;
+	ScanKeyData skey;
+	HeapTuple	inhtup;
+	TupleDesc	inhtupdesc;
+	int			nvisited;
+	SuperQE    *qentry,
+			   *vnode;
+	Dllist	   *visited,
+			   *queue;
+	Dlelem	   *qe,
+			   *elt;
+
+	Relation	rd;
+	Buffer		buf;
+	Datum		d;
+	bool		newrelid;
+	char		isNull;
+
+	nvisited = 0;
+	queue = DLNewList();
+	visited = DLNewList();
+
+
+	inhrel = heap_openr(InheritsRelationName);
+	RelationSetLockForRead(inhrel);
+	inhtupdesc = RelationGetTupleDescriptor(inhrel);
+
+	/*
+	 * Use queue to do a breadth-first traversal of the inheritance graph
+	 * from the relid supplied up to the root.
+	 */
+	do
+	{
+		ScanKeyEntryInitialize(&skey, 0x0, Anum_pg_inherits_inhrel,
+							   ObjectIdEqualRegProcedure,
+							   ObjectIdGetDatum(relid));
+
+		inhscan = heap_beginscan(inhrel, 0, false, 1, &skey);
+
+		while (HeapTupleIsValid(inhtup = heap_getnext(inhscan, 0, &buf)))
+		{
+			qentry = (SuperQE *) palloc(sizeof(SuperQE));
+
+			d = fastgetattr(inhtup, Anum_pg_inherits_inhparent,
+							inhtupdesc, &isNull);
+			qentry->sqe_relid = DatumGetObjectId(d);
+
+			/* put this one on the queue */
+			DLAddTail(queue, DLNewElem(qentry));
+
+			ReleaseBuffer(buf);
+		}
+
+		heap_endscan(inhscan);
+
+		/* pull next unvisited relid off the queue */
+		do
+		{
+			qe = DLRemHead(queue);
+			qentry = qe ? (SuperQE *) DLE_VAL(qe) : NULL;
+
+			if (qentry == (SuperQE *) NULL)
+				break;
+
+			relid = qentry->sqe_relid;
+			newrelid = true;
+
+			for (elt = DLGetHead(visited); elt; elt = DLGetSucc(elt))
+			{
+				vnode = (SuperQE *) DLE_VAL(elt);
+				if (vnode && (qentry->sqe_relid == vnode->sqe_relid))
+				{
+					newrelid = false;
+					break;
+				}
+			}
+		} while (!newrelid);
+
+		if (qentry != (SuperQE *) NULL)
+		{
+
+			/* save the type id, rather than the relation id */
+			if ((rd = heap_open(qentry->sqe_relid)) == (Relation) NULL)
+				elog(WARN, "relid %d does not exist", qentry->sqe_relid);
+			qentry->sqe_relid = typeTypeId(typenameType(RelationGetRelationName(rd)->data));
+			heap_close(rd);
+
+			DLAddTail(visited, qe);
+
+			nvisited++;
+		}
+	} while (qentry != (SuperQE *) NULL);
+
+	RelationUnsetLockForRead(inhrel);
+	heap_close(inhrel);
+
+	if (nvisited > 0)
+	{
+		relidvec = (Oid *) palloc(nvisited * sizeof(Oid));
+		*supervec = relidvec;
+
+		for (elt = DLGetHead(visited); elt; elt = DLGetSucc(elt))
+		{
+			vnode = (SuperQE *) DLE_VAL(elt);
+			*relidvec++ = vnode->sqe_relid;
+		}
+
+	}
+	else
+	{
+		*supervec = (Oid *) NULL;
+	}
+
+	return (nvisited);
+}
+
+Oid **
+genxprod(InhPaths *arginh, int nargs)
+{
+	int			nanswers;
+	Oid		  **result,
+			  **iter;
+	Oid		   *oneres;
+	int			i,
+				j;
+	int			cur[MAXFARGS];
+
+	nanswers = 1;
+	for (i = 0; i < nargs; i++)
+	{
+		nanswers *= (arginh[i].nsupers + 2);
+		cur[i] = 0;
+	}
+
+	iter = result = (Oid **) palloc(sizeof(Oid *) * nanswers);
+
+	/* compute the cross product from right to left */
+	for (;;)
+	{
+		oneres = (Oid *) palloc(MAXFARGS * sizeof(Oid));
+		MemSet(oneres, 0, MAXFARGS * sizeof(Oid));
+
+		for (i = nargs - 1; i >= 0 && cur[i] > arginh[i].nsupers; i--)
+			continue;
+
+		/* if we're done, terminate with NULL pointer */
+		if (i < 0)
+		{
+			*iter = NULL;
+			return (result);
+		}
+
+		/* no, increment this column and zero the ones after it */
+		cur[i] = cur[i] + 1;
+		for (j = nargs - 1; j > i; j--)
+			cur[j] = 0;
+
+		for (i = 0; i < nargs; i++)
+		{
+			if (cur[i] == 0)
+				oneres[i] = arginh[i].self;
+			else if (cur[i] > arginh[i].nsupers)
+				oneres[i] = 0;	/* wild card */
+			else
+				oneres[i] = arginh[i].supervec[cur[i] - 1];
+		}
+
+		*iter++ = oneres;
+	}
+}
+
+
+/*
+ ** make_arguments --
+ **   Given the number and types of arguments to a function, and the
+ **   actual arguments and argument types, do the necessary typecasting.
+ */
+void
+make_arguments(int nargs,
+			   List *fargs,
+			   Oid *input_typeids,
+			   Oid *function_typeids)
+{
+
+	/*
+	 * there are two ways an input typeid can differ from a function
+	 * typeid : either the input type inherits the function type, so no
+	 * typecasting is necessary, or the input type can be typecast into
+	 * the function type. right now, we only typecast unknowns, and that
+	 * is all we check for.
+	 */
+
+	List	   *current_fargs;
+	int			i;
+
+	for (i = 0, current_fargs = fargs;
+		 i < nargs;
+		 i++, current_fargs = lnext(current_fargs))
+	{
+
+		if (input_typeids[i] == UNKNOWNOID && function_typeids[i] != InvalidOid)
+		{
+			lfirst(current_fargs) =
+				parser_typecast2(lfirst(current_fargs),
+								 input_typeids[i],
+								 typeidType(function_typeids[i]),
+								 -1);
+		}
+	}
+}
+
+/*
+ ** setup_tlist --
+ **		Build a tlist that says which attribute to project to.
+ **		This routine is called by ParseFunc() to set up a target list
+ **		on a tuple parameter or return value.  Due to a bug in 4.0,
+ **		it's not possible to refer to system attributes in this case.
+ */
+List *
+setup_tlist(char *attname, Oid relid)
+{
+	TargetEntry *tle;
+	Resdom	   *resnode;
+	Var		   *varnode;
+	Oid			typeid;
+	int			attno;
+
+	attno = get_attnum(relid, attname);
+	if (attno < 0)
+		elog(WARN, "cannot reference attribute '%s' of tuple params/return values for functions", attname);
+
+	typeid = attnameTypeId(relid, attname);
+	resnode = makeResdom(1,
+						 typeid,
+						 typeLen(typeidType(typeid)),
+						 get_attname(relid, attno),
+						 0,
+						 (Oid) 0,
+						 0);
+	varnode = makeVar(-1, attno, typeid, -1, attno);
+
+	tle = makeNode(TargetEntry);
+	tle->resdom = resnode;
+	tle->expr = (Node *) varnode;
+	return (lcons(tle, NIL));
+}
+
+/*
+ ** setup_base_tlist --
+ **		Build a tlist that extracts a base type from the tuple
+ **		returned by the executor.
+ */
+List *
+setup_base_tlist(Oid typeid)
+{
+	TargetEntry *tle;
+	Resdom	   *resnode;
+	Var		   *varnode;
+
+	resnode = makeResdom(1,
+						 typeid,
+						 typeLen(typeidType(typeid)),
+						 "<noname>",
+						 0,
+						 (Oid) 0,
+						 0);
+	varnode = makeVar(-1, 1, typeid, -1, 1);
+	tle = makeNode(TargetEntry);
+	tle->resdom = resnode;
+	tle->expr = (Node *) varnode;
+
+	return (lcons(tle, NIL));
+}
+
+/*
+ * ParseComplexProjection -
+ *	  handles function calls with a single argument that is of complex type.
+ *	  This routine returns NULL if it can't handle the projection (eg. sets).
+ */
+Node *
+ParseComplexProjection(ParseState *pstate,
+					   char *funcname,
+					   Node *first_arg,
+					   bool *attisset)
+{
+	Oid			argtype;
+	Oid			argrelid;
+	Name		relname;
+	Relation	rd;
+	Oid			relid;
+	int			attnum;
+
+	switch (nodeTag(first_arg))
+	{
+		case T_Iter:
+			{
+				Func	   *func;
+				Iter	   *iter;
+
+				iter = (Iter *) first_arg;
+				func = (Func *) ((Expr *) iter->iterexpr)->oper;
+				argtype = funcid_get_rettype(func->funcid);
+				argrelid = typeidTypeRelid(argtype);
+				if (argrelid &&
+					((attnum = get_attnum(argrelid, funcname))
+					 != InvalidAttrNumber))
+				{
+
+					/*
+					 * the argument is a function returning a tuple, so
+					 * funcname may be a projection
+					 */
+
+					/* add a tlist to the func node and return the Iter */
+					rd = heap_openr(typeidTypeName(argtype));
+					if (RelationIsValid(rd))
+					{
+						relid = RelationGetRelationId(rd);
+						relname = RelationGetRelationName(rd);
+						heap_close(rd);
+					}
+					if (RelationIsValid(rd))
+					{
+						func->func_tlist =
+							setup_tlist(funcname, argrelid);
+						iter->itertype = attnumTypeId(rd, attnum);
+						return ((Node *) iter);
+					}
+					else
+					{
+						elog(WARN,
+							 "Function '%s' has bad returntype %d",
+							 funcname, argtype);
+					}
+				}
+				else
+				{
+					/* drop through */
+					;
+				}
+				break;
+			}
+		case T_Var:
+			{
+
+				/*
+				 * The argument is a set, so this is either a projection
+				 * or a function call on this set.
+				 */
+				*attisset = true;
+				break;
+			}
+		case T_Expr:
+			{
+				Expr	   *expr = (Expr *) first_arg;
+				Func	   *funcnode;
+
+				if (expr->opType != FUNC_EXPR)
+					break;
+
+				funcnode = (Func *) expr->oper;
+				argtype = funcid_get_rettype(funcnode->funcid);
+				argrelid = typeidTypeRelid(argtype);
+
+				/*
+				 * the argument is a function returning a tuple, so
+				 * funcname may be a projection
+				 */
+				if (argrelid &&
+					(attnum = get_attnum(argrelid, funcname))
+					!= InvalidAttrNumber)
+				{
+
+					/* add a tlist to the func node */
+					rd = heap_openr(typeidTypeName(argtype));
+					if (RelationIsValid(rd))
+					{
+						relid = RelationGetRelationId(rd);
+						relname = RelationGetRelationName(rd);
+						heap_close(rd);
+					}
+					if (RelationIsValid(rd))
+					{
+						Expr	   *newexpr;
+
+						funcnode->func_tlist =
+							setup_tlist(funcname, argrelid);
+						funcnode->functype = attnumTypeId(rd, attnum);
+
+						newexpr = makeNode(Expr);
+						newexpr->typeOid = funcnode->functype;
+						newexpr->opType = FUNC_EXPR;
+						newexpr->oper = (Node *) funcnode;
+						newexpr->args = lcons(first_arg, NIL);
+
+						return ((Node *) newexpr);
+					}
+
+				}
+
+				elog(WARN, "Function '%s' has bad returntype %d",
+					 funcname, argtype);
+				break;
+			}
+		case T_Param:
+			{
+				Param	   *param = (Param *) first_arg;
+
+				/*
+				 * If the Param is a complex type, this could be a
+				 * projection
+				 */
+				rd = heap_openr(typeidTypeName(param->paramtype));
+				if (RelationIsValid(rd))
+				{
+					relid = RelationGetRelationId(rd);
+					relname = RelationGetRelationName(rd);
+					heap_close(rd);
+				}
+				if (RelationIsValid(rd) &&
+					(attnum = get_attnum(relid, funcname))
+					!= InvalidAttrNumber)
+				{
+
+					param->paramtype = attnumTypeId(rd, attnum);
+					param->param_tlist = setup_tlist(funcname, relid);
+					return ((Node *) param);
+				}
+				break;
+			}
+		default:
+			break;
+	}
+
+	return NULL;
+}
+
+/*
+ * Error message when function lookup fails that gives details of the
+ * argument types
+ */
+void
+func_error(char *caller, char *funcname, int nargs, Oid *argtypes)
+{
+	char		p[(NAMEDATALEN + 2) * MAXFMGRARGS],
+			   *ptr;
+	int			i;
+
+	ptr = p;
+	*ptr = '\0';
+	for (i = 0; i < nargs; i++)
+	{
+		if (i)
+		{
+			*ptr++ = ',';
+			*ptr++ = ' ';
+		}
+		if (argtypes[i] != 0)
+		{
+			strcpy(ptr, typeidTypeName(argtypes[i]));
+			*(ptr + NAMEDATALEN) = '\0';
+		}
+		else
+			strcpy(ptr, "opaque");
+		ptr += strlen(ptr);
+	}
+
+	elog(WARN, "%s: function %s(%s) does not exist", caller, funcname, p);
+}
+
+
+
diff --git a/src/backend/parser/parse_query.c b/src/backend/parser/parse_node.c
similarity index 56%
rename from src/backend/parser/parse_query.c
rename to src/backend/parser/parse_node.c
index c47feeaa1145a1ecc7fc7297f24ebb99e5f7b66d..c06e00888b90526b2aeddb2a417280f93a6330ab 100644
--- a/src/backend/parser/parse_query.c
+++ b/src/backend/parser/parse_node.c
@@ -1,259 +1,76 @@
 /*-------------------------------------------------------------------------
  *
- * parse_query.c--
- *	  take an "optimizable" stmt and make the query tree that
- *	   the planner requires.
+ * parse_node.c--
+ *	  various routines that make nodes for query plans
  *
  * Copyright (c) 1994, Regents of the University of California
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/parser/Attic/parse_query.c,v 1.25 1997/11/24 05:08:27 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/parser/parse_node.c,v 1.1 1997/11/25 22:05:42 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
 #include <ctype.h>
 #include <string.h>
-#include "postgres.h"
 
+#include "postgres.h"
 #include "fmgr.h"
 #include "access/heapam.h"
-#include "access/tupmacs.h"
+#include "catalog/pg_operator.h"
+#include "catalog/pg_type.h"
+#include "nodes/makefuncs.h"
+#include "parser/parse_expr.h"
+#include "parser/parse_oper.h"
+#include "parser/parse_node.h"
+#include "parser/parse_relation.h"
+#include "parser/parse_type.h"
 #include "utils/builtins.h"
+#include "utils/syscache.h"
+
+#ifdef 0
+#include "access/tupmacs.h"
 #include "utils/elog.h"
 #include "utils/palloc.h"
 #include "utils/acl.h"			/* for ACL_NO_PRIV_WARNING */
 #include "utils/rel.h"			/* Relation stuff */
 
 #include "utils/syscache.h"
-#include "catalog/pg_type.h"
-#include "catalog/pg_operator.h"
-#include "parser/catalog_utils.h"
-#include "parser/parse_query.h"
-#include "utils/lsyscache.h"
 
 #include "nodes/pg_list.h"
 #include "nodes/primnodes.h"
 #include "nodes/parsenodes.h"
-#include "nodes/makefuncs.h"
-
-static void
-checkTargetTypes(ParseState *pstate, char *target_colname,
-				 char *refname, char *colname);
-
-Oid		   *param_type_info;
-int			pfunc_num_args;
-
-/* given refname, return a pointer to the range table entry */
-RangeTblEntry *
-refnameRangeTableEntry(List *rtable, char *refname)
-{
-	List	   *temp;
-
-	foreach(temp, rtable)
-	{
-		RangeTblEntry *rte = lfirst(temp);
-
-		if (!strcmp(rte->refname, refname))
-			return rte;
-	}
-	return NULL;
-}
-
-/* given refname, return id of variable; position starts with 1 */
-int
-refnameRangeTablePosn(List *rtable, char *refname)
-{
-	int			index;
-	List	   *temp;
-
-	index = 1;
-	foreach(temp, rtable)
-	{
-		RangeTblEntry *rte = lfirst(temp);
-
-		if (!strcmp(rte->refname, refname))
-			return index;
-		index++;
-	}
-	return (0);
-}
+#endif
 
 /*
- * returns range entry if found, else NULL
+ * make_parsestate() --
+ *	  allocate and initialize a new ParseState.
+ *	the CALLERS is responsible for freeing the ParseState* returned
+ *
  */
-RangeTblEntry *
-colnameRangeTableEntry(ParseState *pstate, char *colname)
-{
-	List	   *et;
-	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)
-	{
-		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 (rte_result != NULL)
-			{
-				if (!pstate->p_is_insert ||
-					rte != pstate->p_target_rangetblentry)
-					elog(WARN, "Column %s is ambiguous", colname);
-			}
-			else
-				rte_result = rte;
-		}
-	}
-	return rte_result;
-}
 
-/*
- * put new entry in pstate p_rtable structure, or return pointer
- * if pstate null
-*/
-RangeTblEntry *
-addRangeTableEntry(ParseState *pstate,
-				   char *relname,
-				   char *refname,
-				   bool inh,
-				   bool inFromCl)
-{
-	Relation	relation;
-	RangeTblEntry *rte = makeNode(RangeTblEntry);
-
-	if (pstate != NULL &&
-		refnameRangeTableEntry(pstate->p_rtable, refname) != NULL)
-		elog(WARN, "Table name %s specified more than once", refname);
-
-	rte->relname = pstrdup(relname);
-	rte->refname = pstrdup(refname);
-
-	relation = heap_openr(relname);
-	if (relation == NULL)
-	{
-		elog(WARN, "%s: %s",
-			 relname, aclcheck_error_strings[ACLCHECK_NO_CLASS]);
-	}
-
-	/*
-	 * Flags - zero or more from inheritance,union,version or
-	 * recursive (transitive closure) [we don't support them all -- ay
-	 * 9/94 ]
-	 */
-	rte->inh = inh;
-
-	/* RelOID */
-	rte->relid = RelationGetRelationId(relation);
-
-	rte->inFromCl = inFromCl;
-
-	/*
-	 * close the relation we're done with it for now.
-	 */
-	if (pstate != NULL)
-		pstate->p_rtable = lappend(pstate->p_rtable, rte);
-
-	heap_close(relation);
-
-	return rte;
-}
-
-/*
- * expandAll -
- *	  makes a list of attributes
- *	  assumes reldesc caching works
- */
-List	   *
-expandAll(ParseState *pstate, char *relname, char *refname, int *this_resno)
+ParseState *
+make_parsestate(void)
 {
-	Relation	rdesc;
-	List	   *te_tail = NIL,
-			   *te_head = NIL;
-	Var		   *varnode;
-	int			varattno,
-				maxattrs;
-	Oid			type_id;
-	int			type_len;
-	RangeTblEntry *rte;
-
-	rte = refnameRangeTableEntry(pstate->p_rtable, refname);
-	if (rte == NULL)
-		rte = addRangeTableEntry(pstate, relname, refname, FALSE, FALSE);
-
-	rdesc = heap_open(rte->relid);
-
-	if (rdesc == NULL)
-	{
-		elog(WARN, "Unable to expand all -- heap_open failed on %s",
-			 rte->refname);
-		return NIL;
-	}
-	maxattrs = RelationGetNumberOfAttributes(rdesc);
-
-	for (varattno = 0; varattno <= maxattrs - 1; varattno++)
-	{
-		char	   *attrname;
-		char	   *resname = NULL;
-		TargetEntry *te = makeNode(TargetEntry);
-
-		attrname = pstrdup((rdesc->rd_att->attrs[varattno]->attname).data);
-		varnode = (Var *) make_var(pstate, refname, attrname, &type_id);
-		type_len = (int) tlen(get_id_type(type_id));
-
-		handleTargetColname(pstate, &resname, refname, attrname);
-		if (resname != NULL)
-			attrname = resname;
-
-		/*
-		 * Even if the elements making up a set are complex, the set
-		 * itself is not.
-		 */
-
-		te->resdom = makeResdom((AttrNumber) (*this_resno)++,
-								type_id,
-								(Size) type_len,
-								attrname,
-								(Index) 0,
-								(Oid) 0,
-								0);
-		te->expr = (Node *) varnode;
-		if (te_head == NIL)
-			te_head = te_tail = lcons(te, NIL);
-		else
-			te_tail = lappend(te_tail, te);
-	}
-
-	heap_close(rdesc);
-	return (te_head);
+	ParseState *pstate;
+
+	pstate = malloc(sizeof(ParseState));
+	pstate->p_last_resno = 1;
+	pstate->p_rtable = NIL;
+	pstate->p_numAgg = 0;
+	pstate->p_aggs = NIL;
+	pstate->p_is_insert = false;
+	pstate->p_insert_columns = NIL;
+	pstate->p_is_update = false;
+	pstate->p_is_rule = false;
+	pstate->p_in_where_clause = false;
+	pstate->p_target_relation = NULL;
+	pstate->p_target_rangetblentry = NULL;
+
+	return (pstate);
 }
 
-static void
-disallow_setop(char *op, Type optype, Node *operand)
-{
-	if (operand == NULL)
-		return;
-
-	if (nodeTag(operand) == T_Iter)
-	{
-		elog(NOTICE, "An operand to the '%s' operator returns a set of %s,",
-			 op, tname(optype));
-		elog(WARN, "but '%s' takes single values, not sets.",
-			 op);
-	}
-}
-
-static Node *
+Node *
 make_operand(char *opname,
 			 Node *tree,
 			 Oid orig_typeId,
@@ -267,7 +84,7 @@ make_operand(char *opname,
 	if (tree != NULL)
 	{
 		result = tree;
-		true_type = get_id_type(true_typeId);
+		true_type = typeidType(true_typeId);
 		disallow_setop(opname, true_type, result);
 		if (true_typeId != orig_typeId)
 		{						/* must coerce */
@@ -276,13 +93,13 @@ make_operand(char *opname,
 			Assert(nodeTag(result) == T_Const);
 			val = (Datum) textout((struct varlena *)
 								  con->constvalue);
-			infunc = typeid_get_retinfunc(true_typeId);
+			infunc = typeidRetinfunc(true_typeId);
 			con = makeNode(Const);
 			con->consttype = true_typeId;
-			con->constlen = tlen(true_type);
+			con->constlen = typeLen(true_type);
 			con->constvalue = (Datum) fmgr(infunc,
 										   val,
-										   get_typelem(true_typeId),
+										   typeidTypElem(true_typeId),
 										   -1 /* for varchar() type */ );
 			con->constisnull = false;
 			con->constbyval = true;
@@ -307,6 +124,21 @@ make_operand(char *opname,
 }
 
 
+void
+disallow_setop(char *op, Type optype, Node *operand)
+{
+	if (operand == NULL)
+		return;
+
+	if (nodeTag(operand) == T_Iter)
+	{
+		elog(NOTICE, "An operand to the '%s' operator returns a set of %s,",
+			 op, typeTypeName(optype));
+		elog(WARN, "but '%s' takes single values, not sets.",
+			 op);
+	}
+}
+
 Expr	   *
 make_op(char *opname, Node *ltree, Node *rtree)
 {
@@ -367,30 +199,30 @@ make_op(char *opname, Node *ltree, Node *rtree)
 			CONVERTABLE_TYPE(rtypeId) && nodeTag(rtree) == T_Const &&
 			!((Const *) rtree)->constiscast)
 		{
-			outfunc = typeid_get_retoutfunc(rtypeId);
-			infunc = typeid_get_retinfunc(ltypeId);
+			outfunc = typeidRetoutfunc(rtypeId);
+			infunc = typeidRetinfunc(ltypeId);
 			outstr = (char *) fmgr(outfunc, ((Const *) rtree)->constvalue);
 			((Const *) rtree)->constvalue = (Datum) fmgr(infunc, outstr);
 			pfree(outstr);
 			((Const *) rtree)->consttype = rtypeId = ltypeId;
-			newtype = get_id_type(rtypeId);
-			((Const *) rtree)->constlen = tlen(newtype);
-			((Const *) rtree)->constbyval = tbyval(newtype);
+			newtype = typeidType(rtypeId);
+			((Const *) rtree)->constlen = typeLen(newtype);
+			((Const *) rtree)->constbyval = typeByVal(newtype);
 		}
 
 		if (CONVERTABLE_TYPE(rtypeId) && nodeTag(rtree) != T_Const &&
 			CONVERTABLE_TYPE(ltypeId) && nodeTag(ltree) == T_Const &&
 			!((Const *) ltree)->constiscast)
 		{
-			outfunc = typeid_get_retoutfunc(ltypeId);
-			infunc = typeid_get_retinfunc(rtypeId);
+			outfunc = typeidRetoutfunc(ltypeId);
+			infunc = typeidRetinfunc(rtypeId);
 			outstr = (char *) fmgr(outfunc, ((Const *) ltree)->constvalue);
 			((Const *) ltree)->constvalue = (Datum) fmgr(infunc, outstr);
 			pfree(outstr);
 			((Const *) ltree)->consttype = ltypeId = rtypeId;
-			newtype = get_id_type(ltypeId);
-			((Const *) ltree)->constlen = tlen(newtype);
-			((Const *) ltree)->constbyval = tbyval(newtype);
+			newtype = typeidType(ltypeId);
+			((Const *) ltree)->constlen = typeLen(newtype);
+			((Const *) ltree)->constbyval = typeByVal(newtype);
 		}
 
 		temp = oper(opname, ltypeId, rtypeId, false);
@@ -426,38 +258,6 @@ make_op(char *opname, Node *ltree, Node *rtree)
 	return result;
 }
 
-Oid
-find_atttype(Oid relid, char *attrname)
-{
-	int			attid;
-	Oid			vartype;
-	Relation	rd;
-
-	rd = heap_open(relid);
-	if (!RelationIsValid(rd))
-	{
-		rd = heap_openr(tname(get_id_type(relid)));
-		if (!RelationIsValid(rd))
-			elog(WARN, "cannot compute type of att %s for relid %d",
-				 attrname, relid);
-	}
-
-	attid = nf_varattno(rd, attrname);
-
-	if (attid == InvalidAttrNumber)
-		elog(WARN, "Invalid attribute %s\n", attrname);
-
-	vartype = att_typeid(rd, attid);
-
-	/*
-	 * close relation we're done with it now
-	 */
-	heap_close(rd);
-
-	return (vartype);
-}
-
-
 Var		   *
 make_var(ParseState *pstate, char *refname, char *attrname, Oid *type_id)
 {
@@ -476,10 +276,8 @@ make_var(ParseState *pstate, char *refname, char *attrname, Oid *type_id)
 
 	rd = heap_open(rte->relid);
 
-	attid = nf_varattno(rd, attrname);
-	if (attid == InvalidAttrNumber)
-		elog(WARN, "Invalid attribute %s\n", attrname);
-	vartypeid = att_typeid(rd, attid);
+	attid = attnameAttNum(rd, attrname); /* could elog(WARN) */
+	vartypeid = attnumTypeId(rd, attid);
 
 	varnode = makeVar(vnum, attid, vartypeid, vnum, attid);
 
@@ -667,7 +465,7 @@ make_const(Value *value)
 	switch (nodeTag(value))
 	{
 		case T_Integer:
-			tp = type("int4");
+			tp = typeidType(INT4OID);
 			val = Int32GetDatum(intVal(value));
 			break;
 
@@ -675,7 +473,7 @@ make_const(Value *value)
 			{
 				float64		dummy;
 
-				tp = type("float8");
+				tp = typeidType(FLOAT8OID);
 
 				dummy = (float64) palloc(sizeof(float64data));
 				*dummy = floatVal(value);
@@ -685,7 +483,7 @@ make_const(Value *value)
 			break;
 
 		case T_String:
-			tp = type("unknown");		/* unknown for now, will be type
+			tp = typeidType(UNKNOWNOID);	/* unknown for now, will be type
 										 * coerced */
 			val = PointerGetDatum(textin(strVal(value)));
 			break;
@@ -702,111 +500,14 @@ make_const(Value *value)
 			}
 	}
 
-	con = makeConst(typeid(tp),
-					tlen(tp),
+	con = makeConst(typeTypeId(tp),
+					typeLen(tp),
 					val,
 					false,
-					tbyval(tp),
+					typeByVal(tp),
 					false,		/* not a set */
 					false);
 
 	return (con);
 }
 
-/*
- * param_type_init()
- *
- * keep enough information around fill out the type of param nodes
- * used in postquel functions
- */
-void
-param_type_init(Oid *typev, int nargs)
-{
-	pfunc_num_args = nargs;
-	param_type_info = typev;
-}
-
-Oid
-param_type(int t)
-{
-	if ((t > pfunc_num_args) || (t == 0))
-		return InvalidOid;
-	return param_type_info[t - 1];
-}
-
-/*
- * handleTargetColname -
- *	  use column names from insert
- */
-void
-handleTargetColname(ParseState *pstate, char **resname,
-					char *refname, char *colname)
-{
-	if (pstate->p_is_insert)
-	{
-		if (pstate->p_insert_columns != NIL)
-		{
-			Ident	   *id = lfirst(pstate->p_insert_columns);
-
-			*resname = id->name;
-			pstate->p_insert_columns = lnext(pstate->p_insert_columns);
-		}
-		else
-			elog(WARN, "insert: more expressions than target columns");
-	}
-	if (pstate->p_is_insert || pstate->p_is_update)
-		checkTargetTypes(pstate, *resname, refname, colname);
-}
-
-/*
- * checkTargetTypes -
- *	  checks value and target column types
- */
-static void
-checkTargetTypes(ParseState *pstate, char *target_colname,
-				 char *refname, char *colname)
-{
-	Oid			attrtype_id,
-				attrtype_target;
-	int			resdomno_id,
-				resdomno_target;
-	Relation	rd;
-	RangeTblEntry *rte;
-
-	if (target_colname == NULL || colname == NULL)
-		return;
-
-	if (refname != NULL)
-		rte = refnameRangeTableEntry(pstate->p_rtable, refname);
-	else
-	{
-		rte = colnameRangeTableEntry(pstate, colname);
-		if (rte == (RangeTblEntry *) NULL)
-			elog(WARN, "attribute %s not found", colname);
-		refname = rte->refname;
-	}
-
-/*
-	if (pstate->p_is_insert && rte == pstate->p_target_rangetblentry)
-		elog(WARN, "%s not available in this context", colname);
-*/
-	rd = heap_open(rte->relid);
-
-	resdomno_id = varattno(rd, colname);
-	attrtype_id = att_typeid(rd, resdomno_id);
-
-	resdomno_target = varattno(pstate->p_target_relation, target_colname);
-	attrtype_target = att_typeid(pstate->p_target_relation, resdomno_target);
-
-	if (attrtype_id != attrtype_target)
-		elog(WARN, "Type of %s does not match target column %s",
-			 colname, target_colname);
-
-	if ((attrtype_id == BPCHAROID || attrtype_id == VARCHAROID) &&
-		rd->rd_att->attrs[resdomno_id - 1]->attlen !=
-	pstate->p_target_relation->rd_att->attrs[resdomno_target - 1]->attlen)
-		elog(WARN, "Length of %s does not match length of target column %s",
-			 colname, target_colname);
-
-	heap_close(rd);
-}
diff --git a/src/backend/parser/parse_oper.c b/src/backend/parser/parse_oper.c
new file mode 100644
index 0000000000000000000000000000000000000000..d82a46bc2f1c0cd1f5ec0b9efb078248944282a7
--- /dev/null
+++ b/src/backend/parser/parse_oper.c
@@ -0,0 +1,613 @@
+/*-------------------------------------------------------------------------
+ *
+ * parse_oper.h
+ *		handle operator things for parser
+ *
+ * Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ *	  $Header: /cvsroot/pgsql/src/backend/parser/parse_oper.c,v 1.1 1997/11/25 22:05:43 momjian Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+#include <string.h>
+#include "postgres.h"
+#include <fmgr.h>
+
+#include <access/heapam.h>
+#include <access/relscan.h>
+#include <catalog/catname.h>
+#include <catalog/pg_operator.h>
+#include <catalog/pg_proc.h>
+#include <catalog/pg_type.h>
+#include <parser/parse_oper.h>
+#include <parser/parse_type.h>
+#include <storage/bufmgr.h>
+#include <utils/syscache.h>
+
+#ifdef 0
+#include "lib/dllist.h"
+#include "utils/datum.h"
+
+#include "utils/builtins.h"
+#include "utils/elog.h"
+#include "utils/palloc.h"
+
+#include "nodes/pg_list.h"
+#include "nodes/parsenodes.h"
+
+#include "catalog/pg_inherits.h"
+#include "catalog/pg_operator.h"
+#include "catalog/pg_proc.h"
+#include "catalog/indexing.h"
+#include "catalog/catname.h"
+
+#include "access/skey.h"
+#include "access/relscan.h"
+#include "access/tupdesc.h"
+#include "access/htup.h"
+#include "access/genam.h"
+#include "access/itup.h"
+#include "access/tupmacs.h"
+#include "storage/buf.h"
+#include "utils/lsyscache.h"
+#include "storage/lmgr.h"
+
+#include "port-protos.h"		/* strdup() */
+#endif
+
+Oid
+any_ordering_op(int restype)
+{
+	Operator	order_op;
+	Oid			order_opid;
+
+	order_op = oper("<", restype, restype, false);
+	order_opid = oprid(order_op);
+
+	return order_opid;
+}
+
+/* given operator, return the operator OID */
+Oid
+oprid(Operator op)
+{
+	return (op->t_oid);
+}
+
+/*
+ *	given opname, leftTypeId and rightTypeId,
+ *	find all possible (arg1, arg2) pairs for which an operator named
+ *	opname exists, such that leftTypeId can be coerced to arg1 and
+ *	rightTypeId can be coerced to arg2
+ */
+int
+binary_oper_get_candidates(char *opname,
+						   Oid leftTypeId,
+						   Oid rightTypeId,
+						   CandidateList *candidates)
+{
+	CandidateList current_candidate;
+	Relation	pg_operator_desc;
+	HeapScanDesc pg_operator_scan;
+	HeapTuple	tup;
+	OperatorTupleForm oper;
+	Buffer		buffer;
+	int			nkeys;
+	int			ncandidates = 0;
+	ScanKeyData opKey[3];
+
+	*candidates = NULL;
+
+	ScanKeyEntryInitialize(&opKey[0], 0,
+						   Anum_pg_operator_oprname,
+						   NameEqualRegProcedure,
+						   NameGetDatum(opname));
+
+	ScanKeyEntryInitialize(&opKey[1], 0,
+						   Anum_pg_operator_oprkind,
+						   CharacterEqualRegProcedure,
+						   CharGetDatum('b'));
+
+
+	if (leftTypeId == UNKNOWNOID)
+	{
+		if (rightTypeId == UNKNOWNOID)
+		{
+			nkeys = 2;
+		}
+		else
+		{
+			nkeys = 3;
+
+			ScanKeyEntryInitialize(&opKey[2], 0,
+								   Anum_pg_operator_oprright,
+								   ObjectIdEqualRegProcedure,
+								   ObjectIdGetDatum(rightTypeId));
+		}
+	}
+	else if (rightTypeId == UNKNOWNOID)
+	{
+		nkeys = 3;
+
+		ScanKeyEntryInitialize(&opKey[2], 0,
+							   Anum_pg_operator_oprleft,
+							   ObjectIdEqualRegProcedure,
+							   ObjectIdGetDatum(leftTypeId));
+	}
+	else
+		/* currently only "unknown" can be coerced */
+		return 0;
+
+	pg_operator_desc = heap_openr(OperatorRelationName);
+	pg_operator_scan = heap_beginscan(pg_operator_desc,
+									  0,
+									  true,
+									  nkeys,
+									  opKey);
+
+	do
+	{
+		tup = heap_getnext(pg_operator_scan, 0, &buffer);
+		if (HeapTupleIsValid(tup))
+		{
+			current_candidate = (CandidateList) palloc(sizeof(struct _CandidateList));
+			current_candidate->args = (Oid *) palloc(2 * sizeof(Oid));
+
+			oper = (OperatorTupleForm) GETSTRUCT(tup);
+			current_candidate->args[0] = oper->oprleft;
+			current_candidate->args[1] = oper->oprright;
+			current_candidate->next = *candidates;
+			*candidates = current_candidate;
+			ncandidates++;
+			ReleaseBuffer(buffer);
+		}
+	} while (HeapTupleIsValid(tup));
+
+	heap_endscan(pg_operator_scan);
+	heap_close(pg_operator_desc);
+
+	return ncandidates;
+}
+
+/*
+ * equivalentOpersAfterPromotion -
+ *	  checks if a list of candidate operators obtained from
+ *	  binary_oper_get_candidates() contain equivalent operators. If
+ *	  this routine is called, we have more than 1 candidate and need to
+ *	  decided whether to pick one of them. This routine returns true if
+ *	  the all the candidates operate on the same data types after
+ *	  promotion (int2, int4, float4 -> float8).
+ */
+bool
+equivalentOpersAfterPromotion(CandidateList candidates)
+{
+	CandidateList result;
+	CandidateList promotedCandidates = NULL;
+	Oid			leftarg,
+				rightarg;
+
+	for (result = candidates; result != NULL; result = result->next)
+	{
+		CandidateList c;
+
+		c = (CandidateList) palloc(sizeof(*c));
+		c->args = (Oid *) palloc(2 * sizeof(Oid));
+		switch (result->args[0])
+		{
+			case FLOAT4OID:
+			case INT4OID:
+			case INT2OID:
+			case CASHOID:
+				c->args[0] = FLOAT8OID;
+				break;
+			default:
+				c->args[0] = result->args[0];
+				break;
+		}
+		switch (result->args[1])
+		{
+			case FLOAT4OID:
+			case INT4OID:
+			case INT2OID:
+			case CASHOID:
+				c->args[1] = FLOAT8OID;
+				break;
+			default:
+				c->args[1] = result->args[1];
+				break;
+		}
+		c->next = promotedCandidates;
+		promotedCandidates = c;
+	}
+
+	/*
+	 * if we get called, we have more than 1 candidates so we can do the
+	 * following safely
+	 */
+	leftarg = promotedCandidates->args[0];
+	rightarg = promotedCandidates->args[1];
+
+	for (result = promotedCandidates->next; result != NULL; result = result->next)
+	{
+		if (result->args[0] != leftarg || result->args[1] != rightarg)
+
+			/*
+			 * this list contains operators that operate on different data
+			 * types even after promotion. Hence we can't decide on which
+			 * one to pick. The user must do explicit type casting.
+			 */
+			return FALSE;
+	}
+
+	/*
+	 * all the candidates are equivalent in the following sense: they
+	 * operate on equivalent data types and picking any one of them is as
+	 * good.
+	 */
+	return TRUE;
+}
+
+
+/*
+ *	given a choice of argument type pairs for a binary operator,
+ *	try to choose a default pair
+ */
+CandidateList
+binary_oper_select_candidate(Oid arg1,
+							 Oid arg2,
+							 CandidateList candidates)
+{
+	CandidateList result;
+
+	/*
+	 * if both are "unknown", there is no way to select a candidate
+	 *
+	 * current wisdom holds that the default operator should be one in which
+	 * both operands have the same type (there will only be one such
+	 * operator)
+	 *
+	 * 7.27.93 - I have decided not to do this; it's too hard to justify, and
+	 * it's easy enough to typecast explicitly -avi [the rest of this
+	 * routine were commented out since then -ay]
+	 */
+
+	if (arg1 == UNKNOWNOID && arg2 == UNKNOWNOID)
+		return (NULL);
+
+	/*
+	 * 6/23/95 - I don't complete agree with avi. In particular, casting
+	 * floats is a pain for users. Whatever the rationale behind not doing
+	 * this is, I need the following special case to work.
+	 *
+	 * In the WHERE clause of a query, if a float is specified without
+	 * quotes, we treat it as float8. I added the float48* operators so
+	 * that we can operate on float4 and float8. But now we have more than
+	 * one matching operator if the right arg is unknown (eg. float
+	 * specified with quotes). This break some stuff in the regression
+	 * test where there are floats in quotes not properly casted. Below is
+	 * the solution. In addition to requiring the operator operates on the
+	 * same type for both operands [as in the code Avi originally
+	 * commented out], we also require that the operators be equivalent in
+	 * some sense. (see equivalentOpersAfterPromotion for details.) - ay
+	 * 6/95
+	 */
+	if (!equivalentOpersAfterPromotion(candidates))
+		return NULL;
+
+	/*
+	 * if we get here, any one will do but we're more picky and require
+	 * both operands be the same.
+	 */
+	for (result = candidates; result != NULL; result = result->next)
+	{
+		if (result->args[0] == result->args[1])
+			return result;
+	}
+
+	return (NULL);
+}
+
+/* Given operator, types of arg1, and arg2, return oper struct */
+/* arg1, arg2 --typeids */
+Operator
+oper(char *op, Oid arg1, Oid arg2, bool noWarnings)
+{
+	HeapTuple	tup;
+	CandidateList candidates;
+	int			ncandidates;
+
+	if (!arg2)
+		arg2 = arg1;
+	if (!arg1)
+		arg1 = arg2;
+
+	if (!(tup = SearchSysCacheTuple(OPRNAME,
+									PointerGetDatum(op),
+									ObjectIdGetDatum(arg1),
+									ObjectIdGetDatum(arg2),
+									Int8GetDatum('b'))))
+	{
+		ncandidates = binary_oper_get_candidates(op, arg1, arg2, &candidates);
+		if (ncandidates == 0)
+		{
+
+			/*
+			 * no operators of the desired types found
+			 */
+			if (!noWarnings)
+				op_error(op, arg1, arg2);
+			return (NULL);
+		}
+		else if (ncandidates == 1)
+		{
+
+			/*
+			 * exactly one operator of the desired types found
+			 */
+			tup = SearchSysCacheTuple(OPRNAME,
+									  PointerGetDatum(op),
+								   ObjectIdGetDatum(candidates->args[0]),
+								   ObjectIdGetDatum(candidates->args[1]),
+									  Int8GetDatum('b'));
+			Assert(HeapTupleIsValid(tup));
+		}
+		else
+		{
+
+			/*
+			 * multiple operators of the desired types found
+			 */
+			candidates = binary_oper_select_candidate(arg1, arg2, candidates);
+			if (candidates != NULL)
+			{
+				/* we chose one of them */
+				tup = SearchSysCacheTuple(OPRNAME,
+										  PointerGetDatum(op),
+								   ObjectIdGetDatum(candidates->args[0]),
+								   ObjectIdGetDatum(candidates->args[1]),
+										  Int8GetDatum('b'));
+				Assert(HeapTupleIsValid(tup));
+			}
+			else
+			{
+				Type		tp1,
+							tp2;
+
+				/* we chose none of them */
+				tp1 = typeidType(arg1);
+				tp2 = typeidType(arg2);
+				if (!noWarnings)
+				{
+					elog(NOTICE, "there is more than one operator %s for types", op);
+					elog(NOTICE, "%s and %s. You will have to retype this query",
+						 typeTypeName(tp1), typeTypeName(tp2));
+					elog(WARN, "using an explicit cast");
+				}
+				return (NULL);
+			}
+		}
+	}
+	return ((Operator) tup);
+}
+
+/*
+ *	given opname and typeId, find all possible types for which
+ *	a right/left unary operator named opname exists,
+ *	such that typeId can be coerced to it
+ */
+int
+unary_oper_get_candidates(char *op,
+						  Oid typeId,
+						  CandidateList *candidates,
+						  char rightleft)
+{
+	CandidateList current_candidate;
+	Relation	pg_operator_desc;
+	HeapScanDesc pg_operator_scan;
+	HeapTuple	tup;
+	OperatorTupleForm oper;
+	Buffer		buffer;
+	int			ncandidates = 0;
+
+	static ScanKeyData opKey[2] = {
+		{0, Anum_pg_operator_oprname, NameEqualRegProcedure},
+	{0, Anum_pg_operator_oprkind, CharacterEqualRegProcedure}};
+
+	*candidates = NULL;
+
+	fmgr_info(NameEqualRegProcedure, (func_ptr *) &opKey[0].sk_func,
+			  &opKey[0].sk_nargs);
+	opKey[0].sk_argument = NameGetDatum(op);
+	fmgr_info(CharacterEqualRegProcedure, (func_ptr *) &opKey[1].sk_func,
+			  &opKey[1].sk_nargs);
+	opKey[1].sk_argument = CharGetDatum(rightleft);
+
+	/* currently, only "unknown" can be coerced */
+
+	/*
+	 * but we should allow types that are internally the same to be
+	 * "coerced"
+	 */
+	if (typeId != UNKNOWNOID)
+	{
+		return 0;
+	}
+
+	pg_operator_desc = heap_openr(OperatorRelationName);
+	pg_operator_scan = heap_beginscan(pg_operator_desc,
+									  0,
+									  true,
+									  2,
+									  opKey);
+
+	do
+	{
+		tup = heap_getnext(pg_operator_scan, 0, &buffer);
+		if (HeapTupleIsValid(tup))
+		{
+			current_candidate = (CandidateList) palloc(sizeof(struct _CandidateList));
+			current_candidate->args = (Oid *) palloc(sizeof(Oid));
+
+			oper = (OperatorTupleForm) GETSTRUCT(tup);
+			if (rightleft == 'r')
+				current_candidate->args[0] = oper->oprleft;
+			else
+				current_candidate->args[0] = oper->oprright;
+			current_candidate->next = *candidates;
+			*candidates = current_candidate;
+			ncandidates++;
+			ReleaseBuffer(buffer);
+		}
+	} while (HeapTupleIsValid(tup));
+
+	heap_endscan(pg_operator_scan);
+	heap_close(pg_operator_desc);
+
+	return ncandidates;
+}
+
+/* Given unary right-side operator (operator on right), return oper struct */
+/* arg-- type id */
+Operator
+right_oper(char *op, Oid arg)
+{
+	HeapTuple	tup;
+	CandidateList candidates;
+	int			ncandidates;
+
+	/*
+	 * if (!OpCache) { init_op_cache(); }
+	 */
+	if (!(tup = SearchSysCacheTuple(OPRNAME,
+									PointerGetDatum(op),
+									ObjectIdGetDatum(arg),
+									ObjectIdGetDatum(InvalidOid),
+									Int8GetDatum('r'))))
+	{
+		ncandidates = unary_oper_get_candidates(op, arg, &candidates, 'r');
+		if (ncandidates == 0)
+		{
+			elog(WARN,
+				 "Can't find right op: %s for type %d", op, arg);
+			return (NULL);
+		}
+		else if (ncandidates == 1)
+		{
+			tup = SearchSysCacheTuple(OPRNAME,
+									  PointerGetDatum(op),
+								   ObjectIdGetDatum(candidates->args[0]),
+									  ObjectIdGetDatum(InvalidOid),
+									  Int8GetDatum('r'));
+			Assert(HeapTupleIsValid(tup));
+		}
+		else
+		{
+			elog(NOTICE, "there is more than one right operator %s", op);
+			elog(NOTICE, "you will have to retype this query");
+			elog(WARN, "using an explicit cast");
+			return (NULL);
+		}
+	}
+	return ((Operator) tup);
+}
+
+/* Given unary left-side operator (operator on left), return oper struct */
+/* arg--type id */
+Operator
+left_oper(char *op, Oid arg)
+{
+	HeapTuple	tup;
+	CandidateList candidates;
+	int			ncandidates;
+
+	/*
+	 * if (!OpCache) { init_op_cache(); }
+	 */
+	if (!(tup = SearchSysCacheTuple(OPRNAME,
+									PointerGetDatum(op),
+									ObjectIdGetDatum(InvalidOid),
+									ObjectIdGetDatum(arg),
+									Int8GetDatum('l'))))
+	{
+		ncandidates = unary_oper_get_candidates(op, arg, &candidates, 'l');
+		if (ncandidates == 0)
+		{
+			elog(WARN,
+				 "Can't find left op: %s for type %d", op, arg);
+			return (NULL);
+		}
+		else if (ncandidates == 1)
+		{
+			tup = SearchSysCacheTuple(OPRNAME,
+									  PointerGetDatum(op),
+									  ObjectIdGetDatum(InvalidOid),
+								   ObjectIdGetDatum(candidates->args[0]),
+									  Int8GetDatum('l'));
+			Assert(HeapTupleIsValid(tup));
+		}
+		else
+		{
+			elog(NOTICE, "there is more than one left operator %s", op);
+			elog(NOTICE, "you will have to retype this query");
+			elog(WARN, "using an explicit cast");
+			return (NULL);
+		}
+	}
+	return ((Operator) tup);
+}
+
+/* Given a typename and value, returns the ascii form of the value */
+
+#ifdef NOT_USED
+char	   *
+outstr(char *typename,			/* Name of type of value */
+	   char *value)				/* Could be of any type */
+{
+	TypeTupleForm tp;
+	Oid			op;
+
+	tp = (TypeTupleForm) GETSTRUCT(type(typename));
+	op = tp->typoutput;
+	return ((char *) fmgr(op, value));
+}
+
+#endif
+
+/*
+ * Give a somewhat useful error message when the operator for two types
+ * is not found.
+ */
+void
+op_error(char *op, Oid arg1, Oid arg2)
+{
+	Type		tp1 = NULL,
+				tp2 = NULL;
+
+	if (typeidIsValid(arg1))
+	{
+		tp1 = typeidType(arg1);
+	}
+	else
+	{
+		elog(WARN, "left hand side of operator %s has an unknown type, probably a bad attribute name", op);
+	}
+
+	if (typeidIsValid(arg2))
+	{
+		tp2 = typeidType(arg2);
+	}
+	else
+	{
+		elog(WARN, "right hand side of operator %s has an unknown type, probably a bad attribute name", op);
+	}
+
+	elog(NOTICE, "there is no operator %s for types %s and %s",
+		 op, typeTypeName(tp1), typeTypeName(tp2));
+	elog(NOTICE, "You will either have to retype this query using an");
+	elog(NOTICE, "explicit cast, or you will have to define the operator");
+	elog(WARN, "%s for %s and %s using CREATE OPERATOR",
+		 op, typeTypeName(tp1), typeTypeName(tp2));
+}
+
diff --git a/src/backend/parser/parse_relation.c b/src/backend/parser/parse_relation.c
new file mode 100644
index 0000000000000000000000000000000000000000..dd3fa2787a10e6f1dbfb2a58960c06dc38327377
--- /dev/null
+++ b/src/backend/parser/parse_relation.c
@@ -0,0 +1,480 @@
+/*-------------------------------------------------------------------------
+ *
+ * parse_relation.c--
+ *	  parser support routines dealing with relations
+ *
+ * Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ *	  $Header: /cvsroot/pgsql/src/backend/parser/parse_relation.c,v 1.1 1997/11/25 22:05:45 momjian Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+#include <ctype.h>
+#include <string.h>
+
+#include "postgres.h"
+#include "access/heapam.h"
+#include <access/htup.h>
+#include <catalog/pg_type.h>
+#include "nodes/makefuncs.h"
+#include <parser/parse_relation.h>
+#include <utils/acl.h>
+#include "utils/builtins.h"
+#include <utils/lsyscache.h>
+
+#ifdef 0
+#include "fmgr.h"
+#include "access/tupmacs.h"
+#include "utils/elog.h"
+#include "utils/palloc.h"
+#include "utils/acl.h"			/* for ACL_NO_PRIV_WARNING */
+
+#include "utils/syscache.h"
+#include "catalog/pg_operator.h"
+
+#include "nodes/pg_list.h"
+#include "nodes/primnodes.h"
+#include "nodes/parsenodes.h"
+#endif
+
+struct
+{
+	char	   *field;
+	int			code;
+}			special_attr[] =
+
+{
+	{
+		"ctid", SelfItemPointerAttributeNumber
+	},
+	{
+		"oid", ObjectIdAttributeNumber
+	},
+	{
+		"xmin", MinTransactionIdAttributeNumber
+	},
+	{
+		"cmin", MinCommandIdAttributeNumber
+	},
+	{
+		"xmax", MaxTransactionIdAttributeNumber
+	},
+	{
+		"cmax", MaxCommandIdAttributeNumber
+	},
+};
+
+#define SPECIALS (sizeof(special_attr)/sizeof(*special_attr))
+
+static char *attnum_type[SPECIALS] = {
+	"tid",
+	"oid",
+	"xid",
+	"cid",
+	"xid",
+	"cid",
+};
+
+/* given refname, return a pointer to the range table entry */
+RangeTblEntry *
+refnameRangeTableEntry(List *rtable, char *refname)
+{
+	List	   *temp;
+
+	foreach(temp, rtable)
+	{
+		RangeTblEntry *rte = lfirst(temp);
+
+		if (!strcmp(rte->refname, refname))
+			return rte;
+	}
+	return NULL;
+}
+
+/* given refname, return id of variable; position starts with 1 */
+int
+refnameRangeTablePosn(List *rtable, char *refname)
+{
+	int			index;
+	List	   *temp;
+
+	index = 1;
+	foreach(temp, rtable)
+	{
+		RangeTblEntry *rte = lfirst(temp);
+
+		if (!strcmp(rte->refname, refname))
+			return index;
+		index++;
+	}
+	return (0);
+}
+
+/*
+ * returns range entry if found, else NULL
+ */
+RangeTblEntry *
+colnameRangeTableEntry(ParseState *pstate, char *colname)
+{
+	List	   *et;
+	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)
+	{
+		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 (rte_result != NULL)
+			{
+				if (!pstate->p_is_insert ||
+					rte != pstate->p_target_rangetblentry)
+					elog(WARN, "Column %s is ambiguous", colname);
+			}
+			else
+				rte_result = rte;
+		}
+	}
+	return rte_result;
+}
+
+/*
+ * put new entry in pstate p_rtable structure, or return pointer
+ * if pstate null
+*/
+RangeTblEntry *
+addRangeTableEntry(ParseState *pstate,
+				   char *relname,
+				   char *refname,
+				   bool inh,
+				   bool inFromCl)
+{
+	Relation	relation;
+	RangeTblEntry *rte = makeNode(RangeTblEntry);
+
+	if (pstate != NULL &&
+		refnameRangeTableEntry(pstate->p_rtable, refname) != NULL)
+		elog(WARN, "Table name %s specified more than once", refname);
+
+	rte->relname = pstrdup(relname);
+	rte->refname = pstrdup(refname);
+
+	relation = heap_openr(relname);
+	if (relation == NULL)
+	{
+		elog(WARN, "%s: %s",
+			 relname, aclcheck_error_strings[ACLCHECK_NO_CLASS]);
+	}
+
+	/*
+	 * Flags - zero or more from inheritance,union,version or
+	 * recursive (transitive closure) [we don't support them all -- ay
+	 * 9/94 ]
+	 */
+	rte->inh = inh;
+
+	/* RelOID */
+	rte->relid = RelationGetRelationId(relation);
+
+	rte->inFromCl = inFromCl;
+
+	/*
+	 * close the relation we're done with it for now.
+	 */
+	if (pstate != NULL)
+		pstate->p_rtable = lappend(pstate->p_rtable, rte);
+
+	heap_close(relation);
+
+	return rte;
+}
+
+/*
+ * expandAll -
+ *	  makes a list of attributes
+ *	  assumes reldesc caching works
+ */
+List	   *
+expandAll(ParseState *pstate, char *relname, char *refname, int *this_resno)
+{
+	Relation	rdesc;
+	List	   *te_tail = NIL,
+			   *te_head = NIL;
+	Var		   *varnode;
+	int			varattno,
+				maxattrs;
+	Oid			type_id;
+	int			type_len;
+	RangeTblEntry *rte;
+
+	rte = refnameRangeTableEntry(pstate->p_rtable, refname);
+	if (rte == NULL)
+		rte = addRangeTableEntry(pstate, relname, refname, FALSE, FALSE);
+
+	rdesc = heap_open(rte->relid);
+
+	if (rdesc == NULL)
+	{
+		elog(WARN, "Unable to expand all -- heap_open failed on %s",
+			 rte->refname);
+		return NIL;
+	}
+	maxattrs = RelationGetNumberOfAttributes(rdesc);
+
+	for (varattno = 0; varattno <= maxattrs - 1; varattno++)
+	{
+		char	   *attrname;
+		char	   *resname = NULL;
+		TargetEntry *te = makeNode(TargetEntry);
+
+		attrname = pstrdup((rdesc->rd_att->attrs[varattno]->attname).data);
+		varnode = (Var *) make_var(pstate, refname, attrname, &type_id);
+		type_len = (int) typeLen(typeidType(type_id));
+
+		handleTargetColname(pstate, &resname, refname, attrname);
+		if (resname != NULL)
+			attrname = resname;
+
+		/*
+		 * Even if the elements making up a set are complex, the set
+		 * itself is not.
+		 */
+
+		te->resdom = makeResdom((AttrNumber) (*this_resno)++,
+								type_id,
+								(Size) type_len,
+								attrname,
+								(Index) 0,
+								(Oid) 0,
+								0);
+		te->expr = (Node *) varnode;
+		if (te_head == NIL)
+			te_head = te_tail = lcons(te, NIL);
+		else
+			te_tail = lappend(te_tail, te);
+	}
+
+	heap_close(rdesc);
+	return (te_head);
+}
+
+/* given relation and att name, return id of variable */
+int
+attnameAttNum(Relation rd, char *a)
+{
+	int			i;
+
+	for (i = 0; i < rd->rd_rel->relnatts; i++)
+		if (!namestrcmp(&(rd->rd_att->attrs[i]->attname), a))
+			return (i + 1);
+
+	for (i = 0; i < SPECIALS; i++)
+		if (!strcmp(special_attr[i].field, a))
+			return (special_attr[i].code);
+
+	/* on failure */
+	elog(WARN, "Relation %s does not have attribute %s",
+		 RelationGetRelationName(rd), a);
+	return 0;  /* lint */
+}
+
+/* Given range variable, return whether attribute of this name
+ * is a set.
+ * NOTE the ASSUMPTION here that no system attributes are, or ever
+ * will be, sets.
+ */
+bool
+attnameIsSet(Relation rd, char *name)
+{
+	int			i;
+
+	/* First check if this is a system attribute */
+	for (i = 0; i < SPECIALS; i++)
+	{
+		if (!strcmp(special_attr[i].field, name))
+		{
+			return (false);		/* no sys attr is a set */
+		}
+	}
+	return (get_attisset(rd->rd_id, name));
+}
+
+/*-------------
+ * given an attribute number and a relation, return its relation name
+ */
+char	   *
+attnumAttName(Relation rd, int attrno)
+{
+	char	   *name;
+	int			i;
+
+	if (attrno < 0)
+	{
+		for (i = 0; i < SPECIALS; i++)
+		{
+			if (special_attr[i].code == attrno)
+			{
+				name = special_attr[i].field;
+				return (name);
+			}
+		}
+		elog(WARN, "Illegal attr no %d for relation %s",
+			 attrno, RelationGetRelationName(rd));
+	}
+	else if (attrno >= 1 && attrno <= RelationGetNumberOfAttributes(rd))
+	{
+		name = (rd->rd_att->attrs[attrno - 1]->attname).data;
+		return (name);
+	}
+	else
+	{
+		elog(WARN, "Illegal attr no %d for relation %s",
+			 attrno, RelationGetRelationName(rd));
+	}
+
+	/*
+	 * Shouldn't get here, but we want lint to be happy...
+	 */
+
+	return (NULL);
+}
+
+int
+attnumAttNelems(Relation rd, int attid)
+{
+	return (rd->rd_att->attrs[attid - 1]->attnelems);
+}
+
+Oid
+attnameTypeId(Oid relid, char *attrname)
+{
+	int			attid;
+	Oid			vartype;
+	Relation	rd;
+
+	rd = heap_open(relid);
+	if (!RelationIsValid(rd))
+	{
+		rd = heap_openr(typeidTypeName(relid));
+		if (!RelationIsValid(rd))
+			elog(WARN, "cannot compute type of att %s for relid %d",
+				 attrname, relid);
+	}
+
+	attid = attnameAttNum(rd, attrname); /* could elog(WARN) and never return */
+
+	vartype = attnumTypeId(rd, attid);
+
+	/*
+	 * close relation we're done with it now
+	 */
+	heap_close(rd);
+
+	return (vartype);
+}
+
+/* given attribute id, return type of that attribute */
+/* XXX Special case for pseudo-attributes is a hack */
+Oid
+attnumTypeId(Relation rd, int attid)
+{
+
+	if (attid < 0)
+		return (typeTypeId(typenameType(attnum_type[-attid - 1])));
+
+	/*
+	 * -1 because varattno (where attid comes from) returns one more than
+	 * index
+	 */
+	return (rd->rd_att->attrs[attid - 1]->atttypid);
+}
+
+/*
+ * handleTargetColname -
+ *	  use column names from insert
+ */
+void
+handleTargetColname(ParseState *pstate, char **resname,
+					char *refname, char *colname)
+{
+	if (pstate->p_is_insert)
+	{
+		if (pstate->p_insert_columns != NIL)
+		{
+			Ident	   *id = lfirst(pstate->p_insert_columns);
+
+			*resname = id->name;
+			pstate->p_insert_columns = lnext(pstate->p_insert_columns);
+		}
+		else
+			elog(WARN, "insert: more expressions than target columns");
+	}
+	if (pstate->p_is_insert || pstate->p_is_update)
+		checkTargetTypes(pstate, *resname, refname, colname);
+}
+
+/*
+ * checkTargetTypes -
+ *	  checks value and target column types
+ */
+void
+checkTargetTypes(ParseState *pstate, char *target_colname,
+				 char *refname, char *colname)
+{
+	Oid			attrtype_id,
+				attrtype_target;
+	int			resdomno_id,
+				resdomno_target;
+	Relation	rd;
+	RangeTblEntry *rte;
+
+	if (target_colname == NULL || colname == NULL)
+		return;
+
+	if (refname != NULL)
+		rte = refnameRangeTableEntry(pstate->p_rtable, refname);
+	else
+	{
+		rte = colnameRangeTableEntry(pstate, colname);
+		if (rte == (RangeTblEntry *) NULL)
+			elog(WARN, "attribute %s not found", colname);
+		refname = rte->refname;
+	}
+
+/*
+	if (pstate->p_is_insert && rte == pstate->p_target_rangetblentry)
+		elog(WARN, "%s not available in this context", colname);
+*/
+	rd = heap_open(rte->relid);
+
+	resdomno_id = attnameAttNum(rd, colname);
+	attrtype_id = attnumTypeId(rd, resdomno_id);
+
+	resdomno_target = attnameAttNum(pstate->p_target_relation, target_colname);
+	attrtype_target = attnumTypeId(pstate->p_target_relation, resdomno_target);
+
+	if (attrtype_id != attrtype_target)
+		elog(WARN, "Type of %s does not match target column %s",
+			 colname, target_colname);
+
+	if ((attrtype_id == BPCHAROID || attrtype_id == VARCHAROID) &&
+		rd->rd_att->attrs[resdomno_id - 1]->attlen !=
+	pstate->p_target_relation->rd_att->attrs[resdomno_target - 1]->attlen)
+		elog(WARN, "Length of %s does not match length of target column %s",
+			 colname, target_colname);
+
+	heap_close(rd);
+}
diff --git a/src/backend/parser/parse_target.c b/src/backend/parser/parse_target.c
new file mode 100644
index 0000000000000000000000000000000000000000..f29aa49d34206230cd2cba3475370a11bc64cc01
--- /dev/null
+++ b/src/backend/parser/parse_target.c
@@ -0,0 +1,679 @@
+/*-------------------------------------------------------------------------
+ *
+ * parse_target.c
+ *	  handle target lists
+ *
+ * Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ *	  $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.1 1997/11/25 22:05:47 momjian Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "postgres.h"
+#include "catalog/pg_type.h"
+#include "nodes/makefuncs.h"
+#include "nodes/primnodes.h"
+#include "parser/parse_expr.h"
+#include "parser/parse_relation.h"
+#include "parser/parse_target.h"
+#include "parser/parse_node.h"
+#include "utils/builtins.h"
+
+#ifdef 0
+#include "nodes/nodes.h"
+#include "nodes/params.h"
+#include "nodes/parsenodes.h"
+#include "nodes/relation.h"
+#include "parse.h"				/* for AND, OR, etc. */
+#include "catalog/pg_aggregate.h"
+#include "catalog/pg_proc.h"
+#include "utils/elog.h"
+#include "utils/palloc.h"
+#include "utils/mcxt.h"
+#include "utils/syscache.h"
+#include "utils/acl.h"
+#include "nodes/nodeFuncs.h"
+#include "commands/sequence.h"
+
+#include "optimizer/clauses.h"
+#include "access/heapam.h"
+
+#include "miscadmin.h"
+
+#include "port-protos.h"		/* strdup() */
+#endif
+
+/*
+ * transformTargetList -
+ *	  turns a list of ResTarget's into a list of TargetEntry's
+ */
+List *
+transformTargetList(ParseState *pstate, List *targetlist)
+{
+	List	   *p_target = NIL;
+	List	   *tail_p_target = NIL;
+
+	while (targetlist != NIL)
+	{
+		ResTarget  *res = (ResTarget *) lfirst(targetlist);
+		TargetEntry *tent = makeNode(TargetEntry);
+
+		switch (nodeTag(res->val))
+		{
+			case T_Ident:
+				{
+					Node	   *expr;
+					Oid			type_id;
+					int			type_len;
+					char	   *identname;
+					char	   *resname;
+
+					identname = ((Ident *) res->val)->name;
+					handleTargetColname(pstate, &res->name, NULL, identname);
+
+					/*
+					 * here we want to look for column names only, not relation
+					 * names (even though they can be stored in Ident nodes, too)
+					 */
+					expr = transformIdent(pstate, (Node *) res->val, EXPR_COLUMN_FIRST);
+					type_id = exprType(expr);
+					type_len = typeLen(typeidType(type_id));
+					resname = (res->name) ? res->name : identname;
+					tent->resdom = makeResdom((AttrNumber) pstate->p_last_resno++,
+											  (Oid) type_id,
+											  (Size) type_len,
+											  resname,
+											  (Index) 0,
+											  (Oid) 0,
+											  0);
+
+					tent->expr = expr;
+					break;
+				}
+			case T_ParamNo:
+			case T_FuncCall:
+			case T_A_Const:
+			case T_A_Expr:
+				{
+					Node	   *expr = transformExpr(pstate, (Node *) res->val, EXPR_COLUMN_FIRST);
+
+					handleTargetColname(pstate, &res->name, NULL, NULL);
+					/* note indirection has not been transformed */
+					if (pstate->p_is_insert && res->indirection != NIL)
+					{
+						/* this is an array assignment */
+						char	   *val;
+						char	   *str,
+								   *save_str;
+						List	   *elt;
+						int			i = 0,
+									ndims;
+						int			lindx[MAXDIM],
+									uindx[MAXDIM];
+						int			resdomno;
+						Relation	rd;
+						Value	   *constval;
+
+						if (exprType(expr) != UNKNOWNOID ||
+							!IsA(expr, Const))
+							elog(WARN, "yyparse: string constant expected");
+
+						val = (char *) textout((struct varlena *)
+										   ((Const *) expr)->constvalue);
+						str = save_str = (char *) palloc(strlen(val) + MAXDIM * 25 + 2);
+						foreach(elt, res->indirection)
+						{
+							A_Indices  *aind = (A_Indices *) lfirst(elt);
+
+							aind->uidx = transformExpr(pstate, aind->uidx, EXPR_COLUMN_FIRST);
+							if (!IsA(aind->uidx, Const))
+								elog(WARN,
+									 "Array Index for Append should be a constant");
+							uindx[i] = ((Const *) aind->uidx)->constvalue;
+							if (aind->lidx != NULL)
+							{
+								aind->lidx = transformExpr(pstate, aind->lidx, EXPR_COLUMN_FIRST);
+								if (!IsA(aind->lidx, Const))
+									elog(WARN,
+										 "Array Index for Append should be a constant");
+								lindx[i] = ((Const *) aind->lidx)->constvalue;
+							}
+							else
+							{
+								lindx[i] = 1;
+							}
+							if (lindx[i] > uindx[i])
+								elog(WARN, "yyparse: lower index cannot be greater than upper index");
+							sprintf(str, "[%d:%d]", lindx[i], uindx[i]);
+							str += strlen(str);
+							i++;
+						}
+						sprintf(str, "=%s", val);
+						rd = pstate->p_target_relation;
+						Assert(rd != NULL);
+						resdomno = attnameAttNum(rd, res->name);
+						ndims = attnumAttNelems(rd, resdomno);
+						if (i != ndims)
+							elog(WARN, "yyparse: array dimensions do not match");
+						constval = makeNode(Value);
+						constval->type = T_String;
+						constval->val.str = save_str;
+						tent = make_targetlist_expr(pstate, res->name,
+										   (Node *) make_const(constval),
+													NULL);
+						pfree(save_str);
+					}
+					else
+					{
+						char	   *colname = res->name;
+
+						/* this is not an array assignment */
+						if (colname == NULL)
+						{
+
+							/*
+							 * if you're wondering why this is here, look
+							 * at the yacc grammar for why a name can be
+							 * missing. -ay
+							 */
+							colname = figureColname(expr, res->val);
+						}
+						if (res->indirection)
+						{
+							List	   *ilist = res->indirection;
+
+							while (ilist != NIL)
+							{
+								A_Indices  *ind = lfirst(ilist);
+
+								ind->lidx = transformExpr(pstate, ind->lidx, EXPR_COLUMN_FIRST);
+								ind->uidx = transformExpr(pstate, ind->uidx, EXPR_COLUMN_FIRST);
+								ilist = lnext(ilist);
+							}
+						}
+						res->name = colname;
+						tent = make_targetlist_expr(pstate, res->name, expr,
+													res->indirection);
+					}
+					break;
+				}
+			case T_Attr:
+				{
+					Oid			type_id;
+					int			type_len;
+					Attr	   *att = (Attr *) res->val;
+					Node	   *result;
+					char	   *attrname;
+					char	   *resname;
+					Resdom	   *resnode;
+					List	   *attrs = att->attrs;
+
+					/*
+					 * Target item is a single '*', expand all tables (eg.
+					 * SELECT * FROM emp)
+					 */
+					if (att->relname != NULL && !strcmp(att->relname, "*"))
+					{
+						if (tail_p_target == NIL)
+							p_target = tail_p_target = expandAllTables(pstate);
+						else
+							lnext(tail_p_target) = expandAllTables(pstate);
+
+						while (lnext(tail_p_target) != NIL)
+							/* make sure we point to the last target entry */
+							tail_p_target = lnext(tail_p_target);
+
+						/*
+						 * skip rest of while loop
+						 */
+						targetlist = lnext(targetlist);
+						continue;
+					}
+
+					/*
+					 * Target item is relation.*, expand the table (eg.
+					 * SELECT emp.*, dname FROM emp, dept)
+					 */
+					attrname = strVal(lfirst(att->attrs));
+					if (att->attrs != NIL && !strcmp(attrname, "*"))
+					{
+
+						/*
+						 * tail_p_target is the target list we're building
+						 * in the while loop. Make sure we fix it after
+						 * appending more nodes.
+						 */
+						if (tail_p_target == NIL)
+							p_target = tail_p_target = expandAll(pstate, att->relname,
+									att->relname, &pstate->p_last_resno);
+						else
+							lnext(tail_p_target) =
+								expandAll(pstate, att->relname, att->relname,
+										  &pstate->p_last_resno);
+						while (lnext(tail_p_target) != NIL)
+							/* make sure we point to the last target entry */
+							tail_p_target = lnext(tail_p_target);
+
+						/*
+						 * skip the rest of the while loop
+						 */
+						targetlist = lnext(targetlist);
+						continue;
+					}
+
+
+					/*
+					 * Target item is fully specified: ie.
+					 * relation.attribute
+					 */
+					result = handleNestedDots(pstate, att, &pstate->p_last_resno);
+					handleTargetColname(pstate, &res->name, att->relname, attrname);
+					if (att->indirection != NIL)
+					{
+						List	   *ilist = att->indirection;
+
+						while (ilist != NIL)
+						{
+							A_Indices  *ind = lfirst(ilist);
+
+							ind->lidx = transformExpr(pstate, ind->lidx, EXPR_COLUMN_FIRST);
+							ind->uidx = transformExpr(pstate, ind->uidx, EXPR_COLUMN_FIRST);
+							ilist = lnext(ilist);
+						}
+						result = (Node *) make_array_ref(result, att->indirection);
+					}
+					type_id = exprType(result);
+					type_len = typeLen(typeidType(type_id));
+					/* move to last entry */
+					while (lnext(attrs) != NIL)
+						attrs = lnext(attrs);
+					resname = (res->name) ? res->name : strVal(lfirst(attrs));
+					resnode = makeResdom((AttrNumber) pstate->p_last_resno++,
+										 (Oid) type_id,
+										 (Size) type_len,
+										 resname,
+										 (Index) 0,
+										 (Oid) 0,
+										 0);
+					tent->resdom = resnode;
+					tent->expr = result;
+					break;
+				}
+			default:
+				/* internal error */
+				elog(WARN,
+					 "internal error: do not know how to transform targetlist");
+				break;
+		}
+
+		if (p_target == NIL)
+		{
+			p_target = tail_p_target = lcons(tent, NIL);
+		}
+		else
+		{
+			lnext(tail_p_target) = lcons(tent, NIL);
+			tail_p_target = lnext(tail_p_target);
+		}
+		targetlist = lnext(targetlist);
+	}
+
+	return p_target;
+}
+
+
+/*
+ * make_targetlist_expr -
+ *	  make a TargetEntry from an expression
+ *
+ * arrayRef is a list of transformed A_Indices
+ */
+TargetEntry *
+make_targetlist_expr(ParseState *pstate,
+					 char *colname,
+					 Node *expr,
+					 List *arrayRef)
+{
+	Oid			type_id,
+				attrtype;
+	int			type_len,
+				attrlen;
+	int			resdomno;
+	Relation	rd;
+	bool		attrisset;
+	TargetEntry *tent;
+	Resdom	   *resnode;
+
+	if (expr == NULL)
+		elog(WARN, "make_targetlist_expr: invalid use of NULL expression");
+
+	type_id = exprType(expr);
+	if (type_id == InvalidOid)
+	{
+		type_len = 0;
+	}
+	else
+		type_len = typeLen(typeidType(type_id));
+
+	/* I have no idea what the following does! */
+	/* It appears to process target columns that will be receiving results */
+	if (pstate->p_is_insert || pstate->p_is_update)
+	{
+
+		/*
+		 * append or replace query -- append, replace work only on one
+		 * relation, so multiple occurence of same resdomno is bogus
+		 */
+		rd = pstate->p_target_relation;
+		Assert(rd != NULL);
+		resdomno = attnameAttNum(rd, colname);
+		attrisset = attnameIsSet(rd, colname);
+		attrtype = attnumTypeId(rd, resdomno);
+		if ((arrayRef != NIL) && (lfirst(arrayRef) == NIL))
+			attrtype = GetArrayElementType(attrtype);
+		if (attrtype == BPCHAROID || attrtype == VARCHAROID)
+		{
+			attrlen = rd->rd_att->attrs[resdomno - 1]->attlen;
+		}
+		else
+		{
+			attrlen = typeLen(typeidType(attrtype));
+		}
+#if 0
+		if (Input_is_string && Typecast_ok)
+		{
+			Datum		val;
+
+			if (type_id == typeTypeId(type("unknown")))
+			{
+				val = (Datum) textout((struct varlena *)
+									  ((Const) lnext(expr))->constvalue);
+			}
+			else
+			{
+				val = ((Const) lnext(expr))->constvalue;
+			}
+			if (attrisset)
+			{
+				lnext(expr) = makeConst(attrtype,
+										attrlen,
+										val,
+										false,
+										true,
+										true,	/* is set */
+										false);
+			}
+			else
+			{
+				lnext(expr) =
+					makeConst(attrtype,
+							  attrlen,
+							  (Datum) fmgr(typeidRetinfunc(attrtype),
+										 val, typeidTypElem(attrtype), -1),
+							  false,
+							  true /* Maybe correct-- 80% chance */ ,
+							  false,	/* is not a set */
+							  false);
+			}
+		}
+		else if ((Typecast_ok) && (attrtype != type_id))
+		{
+			lnext(expr) =
+				parser_typecast2(expr, typeidType(attrtype));
+		}
+		else if (attrtype != type_id)
+		{
+			if ((attrtype == INT2OID) && (type_id == INT4OID))
+				lfirst(expr) = lispInteger(INT2OID);	/* handle CASHOID too */
+			else if ((attrtype == FLOAT4OID) && (type_id == FLOAT8OID))
+				lfirst(expr) = lispInteger(FLOAT4OID);
+			else
+				elog(WARN, "unequal type in tlist : %s \n", colname);
+		}
+
+		Input_is_string = false;
+		Input_is_integer = false;
+		Typecast_ok = true;
+#endif
+
+		if (attrtype != type_id)
+		{
+			if (IsA(expr, Const))
+			{
+				/* try to cast the constant */
+				if (arrayRef && !(((A_Indices *) lfirst(arrayRef))->lidx))
+				{
+					/* updating a single item */
+					Oid			typelem = typeidTypElem(attrtype);
+
+					expr = (Node *) parser_typecast2(expr,
+													 type_id,
+													 typeidType(typelem),
+													 attrlen);
+				}
+				else
+					expr = (Node *) parser_typecast2(expr,
+													 type_id,
+												   typeidType(attrtype),
+													 attrlen);
+			}
+			else
+			{
+				/* currently, we can't handle casting of expressions */
+				elog(WARN, "parser: attribute '%s' is of type '%s' but expression is of type '%s'",
+					 colname,
+					 typeidTypeName(attrtype),
+					 typeidTypeName(type_id));
+			}
+		}
+
+		if (arrayRef != NIL)
+		{
+			Expr	   *target_expr;
+			Attr	   *att = makeNode(Attr);
+			List	   *ar = arrayRef;
+			List	   *upperIndexpr = NIL;
+			List	   *lowerIndexpr = NIL;
+
+			att->relname = pstrdup(RelationGetRelationName(rd)->data);
+			att->attrs = lcons(makeString(colname), NIL);
+			target_expr = (Expr *) handleNestedDots(pstate, att,
+												  &pstate->p_last_resno);
+			while (ar != NIL)
+			{
+				A_Indices  *ind = lfirst(ar);
+
+				if (lowerIndexpr || (!upperIndexpr && ind->lidx))
+				{
+
+					/*
+					 * XXX assume all lowerIndexpr is non-null in this
+					 * case
+					 */
+					lowerIndexpr = lappend(lowerIndexpr, ind->lidx);
+				}
+				upperIndexpr = lappend(upperIndexpr, ind->uidx);
+				ar = lnext(ar);
+			}
+
+			expr = (Node *) make_array_set(target_expr,
+										   upperIndexpr,
+										   lowerIndexpr,
+										   (Expr *) expr);
+			attrtype = attnumTypeId(rd, resdomno);
+			attrlen = typeLen(typeidType(attrtype));
+		}
+	}
+	else
+	{
+		resdomno = pstate->p_last_resno++;
+		attrtype = type_id;
+		attrlen = type_len;
+	}
+	tent = makeNode(TargetEntry);
+
+	resnode = makeResdom((AttrNumber) resdomno,
+						 (Oid) attrtype,
+						 (Size) attrlen,
+						 colname,
+						 (Index) 0,
+						 (Oid) 0,
+						 0);
+
+	tent->resdom = resnode;
+	tent->expr = expr;
+
+	return tent;
+}
+
+/*
+ * makeTargetNames -
+ *	  generate a list of column names if not supplied or
+ *	  test supplied column names to make sure they are in target table
+ *	  (used exclusively for inserts)
+ */
+List *
+makeTargetNames(ParseState *pstate, List *cols)
+{
+	List	   *tl = NULL;
+
+	/* Generate ResTarget if not supplied */
+
+	if (cols == NIL)
+	{
+		int			numcol;
+		int			i;
+		AttributeTupleForm *attr = pstate->p_target_relation->rd_att->attrs;
+
+		numcol = pstate->p_target_relation->rd_rel->relnatts;
+		for (i = 0; i < numcol; i++)
+		{
+			Ident	   *id = makeNode(Ident);
+
+			id->name = palloc(NAMEDATALEN);
+			StrNCpy(id->name, attr[i]->attname.data, NAMEDATALEN);
+			id->indirection = NIL;
+			id->isRel = false;
+			if (tl == NIL)
+				cols = tl = lcons(id, NIL);
+			else
+			{
+				lnext(tl) = lcons(id, NIL);
+				tl = lnext(tl);
+			}
+		}
+	}
+	else
+	{
+		foreach(tl, cols)
+		{
+			List	   *nxt;
+			char	   *name = ((Ident *) lfirst(tl))->name;
+		
+			/* elog on failure */
+			attnameAttNum(pstate->p_target_relation, name);
+			foreach(nxt, lnext(tl))
+				if (!strcmp(name, ((Ident *) lfirst(nxt))->name))
+					elog (WARN, "Attribute '%s' should be specified only once", name);
+		}
+	}
+	
+	return cols;
+}
+
+/*
+ * expandAllTables -
+ *	  turns '*' (in the target list) into a list of attributes
+ *	   (of all relations in the range table)
+ */
+List *
+expandAllTables(ParseState *pstate)
+{
+	List	   *target = NIL;
+	List	   *legit_rtable = NIL;
+	List	   *rt,
+			   *rtable;
+
+	rtable = pstate->p_rtable;
+	if (pstate->p_is_rule)
+	{
+
+		/*
+		 * skip first two entries, "*new*" and "*current*"
+		 */
+		rtable = lnext(lnext(pstate->p_rtable));
+	}
+
+	/* this should not happen */
+	if (rtable == NULL)
+		elog(WARN, "cannot expand: null p_rtable");
+
+	/*
+	 * go through the range table and make a list of range table entries
+	 * which we will expand.
+	 */
+	foreach(rt, rtable)
+	{
+		RangeTblEntry *rte = lfirst(rt);
+
+		/*
+		 * we only expand those specify in the from clause. (This will
+		 * also prevent us from using the wrong table in inserts: eg.
+		 * tenk2 in "insert into tenk2 select * from tenk1;")
+		 */
+		if (!rte->inFromCl)
+			continue;
+		legit_rtable = lappend(legit_rtable, rte);
+	}
+
+	foreach(rt, legit_rtable)
+	{
+		RangeTblEntry *rte = lfirst(rt);
+		List	   *temp = target;
+
+		if (temp == NIL)
+			target = expandAll(pstate, rte->relname, rte->refname,
+							   &pstate->p_last_resno);
+		else
+		{
+			while (temp != NIL && lnext(temp) != NIL)
+				temp = lnext(temp);
+			lnext(temp) = expandAll(pstate, rte->relname, rte->refname,
+									&pstate->p_last_resno);
+		}
+	}
+	return target;
+}
+
+/*
+ * figureColname -
+ *	  if the name of the resulting column is not specified in the target
+ *	  list, we have to guess.
+ *
+ */
+char *
+figureColname(Node *expr, Node *resval)
+{
+	switch (nodeTag(expr))
+	{
+			case T_Aggreg:
+			return (char *)		/* XXX */
+			((Aggreg *) expr)->aggname;
+		case T_Expr:
+			if (((Expr *) expr)->opType == FUNC_EXPR)
+			{
+				if (nodeTag(resval) == T_FuncCall)
+					return ((FuncCall *) resval)->funcname;
+			}
+			break;
+		default:
+			break;
+	}
+
+	return "?column?";
+}
diff --git a/src/backend/parser/parse_type.c b/src/backend/parser/parse_type.c
new file mode 100644
index 0000000000000000000000000000000000000000..67632cdab6ff5580294504110c0745a16384b69c
--- /dev/null
+++ b/src/backend/parser/parse_type.c
@@ -0,0 +1,319 @@
+/*-------------------------------------------------------------------------
+ *
+ * parse_type.h
+ *		handle type operations for parser
+ *
+ * Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ *	  $Header: /cvsroot/pgsql/src/backend/parser/parse_type.c,v 1.1 1997/11/25 22:05:51 momjian Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+#include <string.h>
+#include "postgres.h"
+#include "fmgr.h"
+
+#include <catalog/pg_type.h>
+#include <parser/parse_target.h>
+#include <parser/parse_type.h>
+#include "utils/syscache.h"
+
+#ifdef 0
+#include "lib/dllist.h"
+#include "utils/datum.h"
+
+#include "utils/builtins.h"
+#include "utils/elog.h"
+#include "utils/palloc.h"
+
+#include "nodes/pg_list.h"
+#include "nodes/parsenodes.h"
+#include "catalog/catname.h"
+
+#include "catalog/pg_inherits.h"
+#include "catalog/pg_operator.h"
+#include "catalog/pg_proc.h"
+#include "catalog/indexing.h"
+#include "catalog/catname.h"
+
+#include "access/skey.h"
+#include "access/relscan.h"
+#include "access/tupdesc.h"
+#include "access/htup.h"
+#include "access/heapam.h"
+#include "access/genam.h"
+#include "access/itup.h"
+#include "access/tupmacs.h"
+
+#include "storage/buf.h"
+#include "storage/bufmgr.h"
+#include "utils/lsyscache.h"
+#include "storage/lmgr.h"
+
+#include "port-protos.h"		/* strdup() */
+#endif
+
+/* check to see if a type id is valid,
+ * returns true if it is. By using this call before calling
+ * typeidType or typeidTypeName, more meaningful error messages
+ * can be produced because the caller typically has more context of
+ *	what's going on                 - jolly
+ */
+bool
+typeidIsValid(Oid id)
+{
+	return (SearchSysCacheTuple(TYPOID,
+								ObjectIdGetDatum(id),
+								0, 0, 0) != NULL);
+}
+
+/* return a type name, given a typeid */
+char	   *
+typeidTypeName(Oid id)
+{
+	HeapTuple	tup;
+	TypeTupleForm typetuple;
+
+	if (!(tup = SearchSysCacheTuple(TYPOID, ObjectIdGetDatum(id),
+									0, 0, 0)))
+	{
+		elog(WARN, "type id lookup of %ud failed", id);
+		return (NULL);
+	}
+	typetuple = (TypeTupleForm) GETSTRUCT(tup);
+	return (typetuple->typname).data;
+}
+
+/* return a Type structure, given an typid */
+Type
+typeidType(Oid id)
+{
+	HeapTuple	tup;
+
+	if (!(tup = SearchSysCacheTuple(TYPOID, ObjectIdGetDatum(id),
+									0, 0, 0)))
+	{
+		elog(WARN, "type id lookup of %ud failed", id);
+		return (NULL);
+	}
+	return ((Type) tup);
+}
+
+/* return a Type structure, given type name */
+Type
+typenameType(char *s)
+{
+	HeapTuple	tup;
+
+	if (s == NULL)
+	{
+		elog(WARN, "type(): Null type");
+	}
+
+	if (!(tup = SearchSysCacheTuple(TYPNAME, PointerGetDatum(s), 0, 0, 0)))
+	{
+		elog(WARN, "type name lookup of %s failed", s);
+	}
+	return ((Type) tup);
+}
+
+/* given type, return the type OID */
+Oid
+typeTypeId(Type tp)
+{
+	if (tp == NULL)
+		elog(WARN, "typeTypeId() called with NULL type struct");
+	return (tp->t_oid);
+}
+
+/* given type (as type struct), return the length of type */
+int16
+typeLen(Type t)
+{
+	TypeTupleForm typ;
+
+	typ = (TypeTupleForm) GETSTRUCT(t);
+	return (typ->typlen);
+}
+
+/* given type (as type struct), return the value of its 'byval' attribute.*/
+bool
+typeByVal(Type t)
+{
+	TypeTupleForm typ;
+
+	typ = (TypeTupleForm) GETSTRUCT(t);
+	return (typ->typbyval);
+}
+
+/* given type (as type struct), return the name of type */
+char	   *
+typeTypeName(Type t)
+{
+	TypeTupleForm typ;
+
+	typ = (TypeTupleForm) GETSTRUCT(t);
+	return (typ->typname).data;
+}
+
+/* given a type, return its typetype ('c' for 'c'atalog types) */
+char
+typeTypeFlag(Type t)
+{
+	TypeTupleForm typ;
+
+	typ = (TypeTupleForm) GETSTRUCT(t);
+	return (typ->typtype);
+}
+
+/* Given a type structure and a string, returns the internal form of
+   that string */
+char *
+stringTypeString(Type tp, char *string, int typlen)
+{
+	Oid			op;
+	Oid			typelem;
+
+	op = ((TypeTupleForm) GETSTRUCT(tp))->typinput;
+	typelem = ((TypeTupleForm) GETSTRUCT(tp))->typelem;	/* XXX - used for array_in */
+	/* typlen is for bpcharin() and varcharin() */
+	return ((char *) fmgr(op, string, typelem, typlen));
+}
+
+/* Given a type id, returns the out-conversion function of the type */
+Oid
+typeidRetoutfunc(Oid type_id)
+{
+	HeapTuple	typeTuple;
+	TypeTupleForm type;
+	Oid			outfunc;
+
+	typeTuple = SearchSysCacheTuple(TYPOID,
+									ObjectIdGetDatum(type_id),
+									0, 0, 0);
+	if (!HeapTupleIsValid(typeTuple))
+		elog(WARN, "typeidRetoutfunc: Invalid type - oid = %u", type_id);
+
+	type = (TypeTupleForm) GETSTRUCT(typeTuple);
+	outfunc = type->typoutput;
+	return (outfunc);
+}
+
+Oid
+typeidTypeRelid(Oid type_id)
+{
+	HeapTuple	typeTuple;
+	TypeTupleForm type;
+	Oid			infunc;
+
+	typeTuple = SearchSysCacheTuple(TYPOID,
+									ObjectIdGetDatum(type_id),
+									0, 0, 0);
+	if (!HeapTupleIsValid(typeTuple))
+		elog(WARN, "typeidTypeRelid: Invalid type - oid = %u", type_id);
+
+	type = (TypeTupleForm) GETSTRUCT(typeTuple);
+	infunc = type->typrelid;
+	return (infunc);
+}
+
+Oid
+typeTypeRelid(Type typ)
+{
+	TypeTupleForm typtup;
+
+	typtup = (TypeTupleForm) GETSTRUCT(typ);
+
+	return (typtup->typrelid);
+}
+
+Oid
+typeidTypElem(Oid type_id)
+{
+	HeapTuple	typeTuple;
+	TypeTupleForm type;
+
+	if (!(typeTuple = SearchSysCacheTuple(TYPOID,
+										  ObjectIdGetDatum(type_id),
+										  0, 0, 0)))
+	{
+		elog(WARN, "type id lookup of %u failed", type_id);
+	}
+	type = (TypeTupleForm) GETSTRUCT(typeTuple);
+
+	return (type->typelem);
+}
+
+/* Given the attribute type of an array return the arrtribute type of
+   an element of the array */
+
+Oid
+GetArrayElementType(Oid typearray)
+{
+	HeapTuple	type_tuple;
+	TypeTupleForm type_struct_array;
+
+	type_tuple = SearchSysCacheTuple(TYPOID,
+									 ObjectIdGetDatum(typearray),
+									 0, 0, 0);
+
+	if (!HeapTupleIsValid(type_tuple))
+		elog(WARN, "GetArrayElementType: Cache lookup failed for type %d",
+			 typearray);
+
+	/* get the array type struct from the type tuple */
+	type_struct_array = (TypeTupleForm) GETSTRUCT(type_tuple);
+
+	if (type_struct_array->typelem == InvalidOid)
+	{
+		elog(WARN, "GetArrayElementType: type %s is not an array",
+			 (Name) &(type_struct_array->typname.data[0]));
+	}
+
+	return (type_struct_array->typelem);
+}
+
+/* Given a type id, returns the in-conversion function of the type */
+Oid
+typeidRetinfunc(Oid type_id)
+{
+	HeapTuple	typeTuple;
+	TypeTupleForm type;
+	Oid			infunc;
+
+	typeTuple = SearchSysCacheTuple(TYPOID,
+									ObjectIdGetDatum(type_id),
+									0, 0, 0);
+	if (!HeapTupleIsValid(typeTuple))
+		elog(WARN, "typeidRetinfunc: Invalid type - oid = %u", type_id);
+
+	type = (TypeTupleForm) GETSTRUCT(typeTuple);
+	infunc = type->typinput;
+	return (infunc);
+}
+
+
+#ifdef NOT_USED
+char
+FindDelimiter(char *typename)
+{
+	char		delim;
+	HeapTuple	typeTuple;
+	TypeTupleForm type;
+
+
+	if (!(typeTuple = SearchSysCacheTuple(TYPNAME,
+										  PointerGetDatum(typename),
+										  0, 0, 0)))
+	{
+		elog(WARN, "type name lookup of %s failed", typename);
+	}
+	type = (TypeTupleForm) GETSTRUCT(typeTuple);
+
+	delim = type->typdelim;
+	return (delim);
+}
+
+#endif
diff --git a/src/backend/parser/parser.c b/src/backend/parser/parser.c
index d658c30896c8c21451fee4c6f5ce5274f8d30fd9..ea309c3c28ecb216ec4d64f2b727f0d057682c7a 100644
--- a/src/backend/parser/parser.c
+++ b/src/backend/parser/parser.c
@@ -6,7 +6,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/parser/parser.c,v 1.28 1997/11/20 23:22:24 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/parser/parser.c,v 1.29 1997/11/25 22:05:52 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -14,9 +14,20 @@
 #include <stdio.h>
 
 #include "postgres.h"
+#include "nodes/pg_list.h"
+#include "parser/parser.h"
+#include "parser/analyze.h"
+#include "parser/parse_node.h"
+
+void	init_io();		/* from scan.l */
+void	parser_init(Oid *typev, int nargs); /* from gram.y */
+int 	yyparse();		/* from gram.c */
+
+#ifdef 0
+#include "parser/parse.h"
 #include "parser/gramparse.h"
-#include "parser/parse_query.h"
 #include "utils/palloc.h"
+#endif
 
 char	   *parseString;		/* the char* which holds the string to be
 								 * parsed */
@@ -103,10 +114,10 @@ static void
 define_sets(Node *clause)
 {
 	Oid			setoid;
-	Type		t = type("oid");
-	Oid			typeoid = typeid(t);
-	Size		oidsize = tlen(t);
-	bool		oidbyval = tbyval(t);
+	Type		t = typeidType(OIDOID);
+	Oid			typeoid = typeTypeId(t);
+	Size		oidsize = typeLen(t);
+	bool		oidbyval = typeByVal(t);
 
 	if (clause == NULL)
 	{
@@ -125,11 +136,11 @@ define_sets(Node *clause)
 			return;
 		}
 		setoid = SetDefine(((Const *) clause)->constvalue,
-						   get_id_typname(((Const *) clause)->consttype));
+						   typeidTypeName(((Const *) clause)->consttype));
 		set_constvalue((Const) clause, setoid);
 		set_consttype((Const) clause, typeoid);
 		set_constlen((Const) clause, oidsize);
-		set_constbyval((Const) clause, oidbyval);
+		set_constypeByVal((Const) clause, oidbyval);
 	}
 	else if (IsA(clause, Iter))
 	{
@@ -173,6 +184,5 @@ define_sets(Node *clause)
 		define_sets(get_rightop(clause));
 	}
 }
-
 #endif
 
diff --git a/src/backend/parser/scansup.c b/src/backend/parser/scansup.c
index dcc66145a5018cd54ec0f1e5541725e16375d4f4..e50757940aa3b0f6aa9b6029b9dfcc9686a95f4b 100644
--- a/src/backend/parser/scansup.c
+++ b/src/backend/parser/scansup.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/parser/scansup.c,v 1.7 1997/09/08 02:25:22 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/parser/scansup.c,v 1.8 1997/11/25 22:05:55 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -17,7 +17,6 @@
 
 #include <ctype.h>
 #include <string.h>
-#include "c.h"
 #include "postgres.h"
 #include "miscadmin.h"
 #include "utils/elog.h"
diff --git a/src/backend/rewrite/rewriteDefine.c b/src/backend/rewrite/rewriteDefine.c
index 37d1e1c1555765b8cd52ae924fbf6a47324ade8d..c6f471915c3a9fa58e12188c5b2f9845155ba843 100644
--- a/src/backend/rewrite/rewriteDefine.c
+++ b/src/backend/rewrite/rewriteDefine.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteDefine.c,v 1.7 1997/10/25 05:37:07 thomas Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteDefine.c,v 1.8 1997/11/25 22:06:04 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -23,7 +23,8 @@
 #include "utils/lsyscache.h"	/* for get_typlen */
 #include "nodes/pg_list.h"		/* for Lisp support */
 #include "nodes/parsenodes.h"
-#include "parser/catalog_utils.h"
+#include "parser/parse_relation.h"
+
 #include "rewrite/locks.h"
 #include "rewrite/rewriteDefine.h"
 #include "rewrite/rewriteRemove.h"
@@ -107,7 +108,7 @@ InsertRule(char *rulname,
 	if (evslot == NULL)
 		evslot_index = -1;
 	else
-		evslot_index = varattno(eventrel, (char *) evslot);
+		evslot_index = attnameAttNum(eventrel, (char *) evslot);
 	heap_close(eventrel);
 
 	if (evinstead)
@@ -221,8 +222,8 @@ DefineQueryRewrite(RuleStmt *stmt)
 	}
 	else
 	{
-		event_attno = varattno(event_relation, eslot_string);
-		event_attype = att_typeid(event_relation, event_attno);
+		event_attno = attnameAttNum(event_relation, eslot_string);
+		event_attype = attnumTypeId(event_relation, event_attno);
 	}
 	heap_close(event_relation);
 
diff --git a/src/backend/tcop/aclchk.c b/src/backend/tcop/aclchk.c
index 0b8a49f1882aecd85190b1f95ca3002d1ec227d6..0021213365c7125faa9b1a0add0932dbe0fff55b 100644
--- a/src/backend/tcop/aclchk.c
+++ b/src/backend/tcop/aclchk.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/tcop/Attic/aclchk.c,v 1.19 1997/11/24 05:08:47 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/tcop/Attic/aclchk.c,v 1.20 1997/11/25 22:06:08 momjian Exp $
  *
  * NOTES
  *	  See acl.h.
@@ -31,10 +31,12 @@
 #include "catalog/pg_operator.h"
 #include "catalog/pg_aggregate.h"
 #include "catalog/pg_proc.h"
+#include "catalog/pg_type.h"
 #include "catalog/pg_user.h"
+#include "parser/parse_agg.h"
+#include "parser/parse_func.h"
 #include "utils/syscache.h"
 #include "utils/tqual.h"
-#include "parser/catalog_utils.h"
 #include "fmgr.h"
 
 static int32 aclcheck(Acl *acl, AclId id, AclIdType idtype, AclMode mode);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 7659d90275cd0a1a4d1c474815bd2c75a8a4f3b0..d0d134e331ae54ebef0697097123cd4897057cbe 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.54 1997/11/10 15:24:55 thomas Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.55 1997/11/25 22:06:14 momjian Exp $
  *
  * NOTES
  *	  this is the "main" module of the postgres backend and
@@ -45,11 +45,10 @@
 
 #include "lib/dllist.h"
 
-#include "parser/catalog_utils.h"
-#include "parser/parse_query.h" /* for MakeTimeRange() */
 #include "commands/async.h"
 #include "tcop/tcopprot.h"		/* where declarations for this file go */
 #include "optimizer/planner.h"
+#include "parser/parser.h"
 
 #include "tcop/tcopprot.h"
 #include "tcop/tcopdebug.h"
@@ -1341,7 +1340,7 @@ PostgresMain(int argc, char *argv[])
 	if (IsUnderPostmaster == false)
 	{
 		puts("\nPOSTGRES backend interactive interface");
-		puts("$Revision: 1.54 $ $Date: 1997/11/10 15:24:55 $");
+		puts("$Revision: 1.55 $ $Date: 1997/11/25 22:06:14 $");
 	}
 
 	/* ----------------
diff --git a/src/include/executor/spi.h b/src/include/executor/spi.h
index 4a38e207e830a23f79373301b2f9f6c595fd399c..7a02f6aaabf89db565243c892f365c00445be7c7 100644
--- a/src/include/executor/spi.h
+++ b/src/include/executor/spi.h
@@ -15,7 +15,6 @@
 #include "nodes/execnodes.h"
 #include "nodes/plannodes.h"
 #include "catalog/pg_proc.h"
-#include "parser/parse_query.h"
 #include "tcop/pquery.h"
 #include "tcop/tcopprot.h"
 #include "tcop/utility.h"
diff --git a/src/include/nodes/nodeFuncs.h b/src/include/nodes/nodeFuncs.h
index de5ad32ab5085b798c8faf3aa044e8904a998ca1..696f5f7fa66b6c2ea7ef7fb4516007ab10f0f20e 100644
--- a/src/include/nodes/nodeFuncs.h
+++ b/src/include/nodes/nodeFuncs.h
@@ -6,13 +6,16 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: nodeFuncs.h,v 1.5 1997/09/08 21:52:45 momjian Exp $
+ * $Id: nodeFuncs.h,v 1.6 1997/11/25 22:06:30 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
 #ifndef NODEFUNCS_H
 #define NODEFUNCS_H
 
+#include <nodes/nodes.h>
+#include <nodes/primnodes.h>
+
 extern bool single_node(Node *node);
 extern bool var_is_outer(Var *var);
 extern bool var_is_rel(Var *var);
diff --git a/src/include/optimizer/planner.h b/src/include/optimizer/planner.h
index da90b768c611f6b973172a02c4b603bc6ae1a628..59bd8738d086c6cd0341614b10a428af03b73ca1 100644
--- a/src/include/optimizer/planner.h
+++ b/src/include/optimizer/planner.h
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: planner.h,v 1.5 1997/09/08 21:53:29 momjian Exp $
+ * $Id: planner.h,v 1.6 1997/11/25 22:06:37 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -16,6 +16,8 @@
 /*
 */
 
+#include <parser/parse_node.h>
+
 extern Plan *planner(Query *parse);
 extern void pg_checkretval(Oid rettype, QueryTreeList *querytree_list);
 
diff --git a/src/include/parser/analyze.h b/src/include/parser/analyze.h
new file mode 100644
index 0000000000000000000000000000000000000000..a85e2074bbe9ad9e46a4201d575ff6976c18ebec
--- /dev/null
+++ b/src/include/parser/analyze.h
@@ -0,0 +1,19 @@
+/*-------------------------------------------------------------------------
+ *
+ * analyze.h
+ *
+ *
+ * Copyright (c) 1994, Regents of the University of California
+ *
+ * $Id: analyze.h,v 1.1 1997/11/25 22:06:47 momjian Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef ANALYZE_H
+#define ANALYZE_H
+
+#include <parser/parse_node.h>
+
+QueryTreeList *parse_analyze(List *pl);
+
+#endif							/* ANALYZE_H */
diff --git a/src/include/parser/catalog_utils.h b/src/include/parser/catalog_utils.h
deleted file mode 100644
index 707ca3a1c6ed848cca86f78743cec7ca99ee56eb..0000000000000000000000000000000000000000
--- a/src/include/parser/catalog_utils.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * catalog_utils.h--
- *
- *
- *
- * Copyright (c) 1994, Regents of the University of California
- *
- * $Id: catalog_utils.h,v 1.13 1997/09/08 21:53:35 momjian Exp $
- *
- *-------------------------------------------------------------------------
- */
-#ifndef CATALOG_UTILS_H
-#define CATALOG_UTILS_H
-
-#include <catalog/pg_type.h>
-#include <access/htup.h>
-
-typedef HeapTuple Type;
-typedef HeapTuple Operator;
-
-extern Type get_id_type(Oid id);
-extern char *get_id_typname(Oid id);
-extern Type type(char *);
-extern Oid	att_typeid(Relation rd, int attid);
-extern int	att_attnelems(Relation rd, int attid);
-extern Oid	typeid(Type tp);
-extern int16 tlen(Type t);
-extern bool tbyval(Type t);
-extern char *tname(Type t);
-extern int	tbyvalue(Type t);
-extern Oid	oprid(Operator op);
-extern Operator oper(char *op, Oid arg1, Oid arg2, bool noWarnings);
-extern Operator right_oper(char *op, Oid arg);
-extern Operator left_oper(char *op, Oid arg);
-extern int	varattno(Relation rd, char *a);
-extern bool varisset(Relation rd, char *name);
-extern int	nf_varattno(Relation rd, char *a);
-extern char *getAttrName(Relation rd, int attrno);
-extern char *instr2(Type tp, char *string, int typlen);
-extern Oid	GetArrayElementType(Oid typearray);
-extern Oid	funcid_get_rettype(Oid funcid);
-extern bool
-func_get_detail(char *funcname, int nargs, Oid *oid_array,
-			Oid *funcid, Oid *rettype, bool *retset, Oid **true_typeids);
-extern Oid	typeid_get_retinfunc(Oid type_id);
-extern Oid	typeid_get_retoutfunc(Oid type_id);
-extern Oid	typeid_get_relid(Oid type_id);
-extern Oid	get_typrelid(Type typ);
-extern Oid	get_typelem(Oid type_id);
-extern void func_error(char *caller, char *funcname, int nargs, Oid *argtypes);
-extern void agg_error(char *caller, char *aggname, Oid basetypeID);
-
-#endif							/* CATALOG_UTILS_H */
diff --git a/src/include/parser/parse_agg.h b/src/include/parser/parse_agg.h
new file mode 100644
index 0000000000000000000000000000000000000000..21ef36248fdc981a82c5a282963f092412b069ad
--- /dev/null
+++ b/src/include/parser/parse_agg.h
@@ -0,0 +1,38 @@
+/*-------------------------------------------------------------------------
+ *
+ * parse_agg.h
+ *
+ *
+ *
+ * Copyright (c) 1994, Regents of the University of California
+ *
+ * $Id: parse_agg.h,v 1.1 1997/11/25 22:06:53 momjian Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PARSE_AGG_H
+#define PARSE_AGG_H
+
+#include <nodes/nodes.h>
+#include <nodes/parsenodes.h>
+#include <nodes/primnodes.h>
+#include <parser/parse_node.h>
+
+void AddAggToParseState(ParseState *pstate, Aggreg *aggreg);
+
+void finalizeAggregates(ParseState *pstate, Query *qry);
+
+bool contain_agg_clause(Node *clause);
+
+bool exprIsAggOrGroupCol(Node *expr, List *groupClause);
+
+bool tleIsAggOrGroupCol(TargetEntry *tle, List *groupClause);
+
+void parseCheckAggregates(ParseState *pstate, Query *qry);
+
+Aggreg *ParseAgg(char *aggname, Oid basetype, Node *target);
+
+void agg_error(char *caller, char *aggname, Oid basetypeID);
+
+#endif							/* PARSE_AGG_H */
+
diff --git a/src/include/parser/parse_clause.h b/src/include/parser/parse_clause.h
new file mode 100644
index 0000000000000000000000000000000000000000..2c0a5278f60e6bd7be794a4408dd412833bf814f
--- /dev/null
+++ b/src/include/parser/parse_clause.h
@@ -0,0 +1,39 @@
+/*-------------------------------------------------------------------------
+ *
+ * parse_clause.h
+ *
+ *
+ *
+ * Copyright (c) 1994, Regents of the University of California
+ *
+ * $Id: parse_clause.h,v 1.1 1997/11/25 22:06:54 momjian Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PARSE_CLAUSE_H
+#define PARSE_CLAUSE_H
+
+#include <nodes/pg_list.h>
+#include <nodes/nodes.h>
+#include <nodes/parsenodes.h>
+#include <nodes/primnodes.h>
+#include <parser/parse_node.h>
+
+void parseFromClause(ParseState *pstate, List *frmList);
+
+void makeRangeTable(ParseState *pstate, char *relname, List *frmList);
+
+Node *transformWhereClause(ParseState *pstate, Node *a_expr);
+
+TargetEntry *find_targetlist_entry(ParseState *pstate,
+			SortGroupBy *sortgroupby, List *tlist);
+
+List *transformGroupClause(ParseState *pstate, List *grouplist,
+			List *targetlist);
+
+List *transformSortClause(ParseState *pstate,
+					List *orderlist, List *targetlist,
+					char *uniqueFlag);
+
+#endif							/* PARSE_CLAUSE_H */
+
diff --git a/src/include/parser/parse_expr.h b/src/include/parser/parse_expr.h
new file mode 100644
index 0000000000000000000000000000000000000000..e7c4a04b011313b0e095e6ec482384edbfbf622b
--- /dev/null
+++ b/src/include/parser/parse_expr.h
@@ -0,0 +1,34 @@
+/*-------------------------------------------------------------------------
+ *
+ * parse_exer.h
+ *
+ *
+ *
+ * Copyright (c) 1994, Regents of the University of California
+ *
+ * $Id: parse_expr.h,v 1.1 1997/11/25 22:06:55 momjian Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PARSE_EXPR_H
+#define PARSE_EXPR_H
+
+#include <nodes/nodes.h>
+#include <nodes/parsenodes.h>
+#include <nodes/primnodes.h>
+#include <parser/parse_node.h>
+
+Node *transformExpr(ParseState *pstate, Node *expr, int precedence);
+
+Node *transformIdent(ParseState *pstate, Node *expr, int precedence);
+
+Oid exprType(Node *expr);
+
+Node *handleNestedDots(ParseState *pstate, Attr *attr, int *curr_resno);
+
+Node *parser_typecast(Value *expr, TypeName *typename, int typlen);
+
+Node *parser_typecast2(Node *expr, Oid exprType, Type tp, int typlen);
+
+#endif							/* PARSE_EXPR_H */
+
diff --git a/src/include/parser/parse_func.h b/src/include/parser/parse_func.h
new file mode 100644
index 0000000000000000000000000000000000000000..de8fc66d848fa51d8379b5126898b9bcca1734d9
--- /dev/null
+++ b/src/include/parser/parse_func.h
@@ -0,0 +1,97 @@
+/*-------------------------------------------------------------------------
+ *
+ * catalog_utils.h--
+ *
+ *
+ *
+ * Copyright (c) 1994, Regents of the University of California
+ *
+ * $Id: parse_func.h,v 1.1 1997/11/25 22:06:56 momjian Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PARSER_FUNC_H
+#define PARSER_FUNC_H
+
+#include <nodes/nodes.h>
+#include <nodes/pg_list.h>
+#include <nodes/parsenodes.h>
+#include <nodes/primnodes.h>
+#include <parser/parse_func.h>
+#include <parser/parse_node.h>
+
+/*
+ *	This structure is used to explore the inheritance hierarchy above
+ *	nodes in the type tree in order to disambiguate among polymorphic
+ *	functions.
+ */
+typedef struct _InhPaths
+{
+	int			nsupers;		/* number of superclasses */
+	Oid			self;			/* this class */
+	Oid		   *supervec;		/* vector of superclasses */
+} InhPaths;
+
+/*
+ *	This structure holds a list of possible functions or operators that
+ *	agree with the known name and argument types of the function/operator.
+ */
+typedef struct _CandidateList
+{
+	Oid		   *args;
+	struct _CandidateList *next;
+}		   *CandidateList;
+
+Node *ParseFunc(ParseState *pstate, char *funcname, List *fargs,
+	int *curr_resno);
+
+Oid funcid_get_rettype(Oid funcid);
+
+CandidateList func_get_candidates(char *funcname, int nargs);
+
+bool can_coerce(int nargs, Oid *input_typeids, Oid *func_typeids);
+
+int match_argtypes(int nargs,
+				   Oid *input_typeids,
+				   CandidateList function_typeids,
+				   CandidateList *candidates);
+
+Oid * func_select_candidate(int nargs,
+						  Oid *input_typeids,
+						  CandidateList candidates);
+
+bool func_get_detail(char *funcname,
+					int nargs,
+					Oid *oid_array,
+					Oid *funcid,	/* return value */
+					Oid *rettype,	/* return value */
+					bool *retset,	/* return value */
+					Oid **true_typeids);
+
+Oid ** argtype_inherit(int nargs, Oid *oid_array);
+
+int findsupers(Oid relid, Oid **supervec);
+
+Oid **genxprod(InhPaths *arginh, int nargs);
+
+void make_arguments(int nargs,
+				   List *fargs,
+				   Oid *input_typeids,
+				   Oid *function_typeids);
+
+List *setup_tlist(char *attname, Oid relid);
+
+List *setup_base_tlist(Oid typeid);
+
+Node *ParseComplexProjection(ParseState *pstate,
+						   char *funcname,
+						   Node *first_arg,
+						   bool *attisset);
+	
+void func_error(char *caller, char *funcname, int nargs, Oid *argtypes);
+
+				   
+
+
+#endif							/* PARSE_FUNC_H */
+
diff --git a/src/include/parser/parse_node.h b/src/include/parser/parse_node.h
new file mode 100644
index 0000000000000000000000000000000000000000..bac05cb1506d9fcccb8960f3f087b7442c9ab152
--- /dev/null
+++ b/src/include/parser/parse_node.h
@@ -0,0 +1,67 @@
+/*-------------------------------------------------------------------------
+ *
+ * parse_node.h
+ *
+ *
+ * Copyright (c) 1994, Regents of the University of California
+ *
+ * $Id: parse_node.h,v 1.1 1997/11/25 22:06:57 momjian Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PARSE_NODE_H
+#define PARSE_NODE_H
+
+#include <nodes/nodes.h>
+#include <nodes/pg_list.h>
+#include <nodes/primnodes.h>
+#include <nodes/parsenodes.h>
+#include <parser/parse_type.h>
+#include <utils/rel.h>
+
+typedef struct QueryTreeList
+{
+	int			len;			/* number of queries */
+	Query	  **qtrees;
+} QueryTreeList;
+
+/* state information used during parse analysis */
+typedef struct ParseState
+{
+	int			p_last_resno;
+	List	   *p_rtable;
+	int			p_numAgg;
+	List	   *p_aggs;
+	bool		p_is_insert;
+	List	   *p_insert_columns;
+	bool		p_is_update;
+	bool		p_is_rule;
+	bool		p_in_where_clause;
+	Relation	p_target_relation;
+	RangeTblEntry *p_target_rangetblentry;
+} ParseState;
+
+ParseState *make_parsestate(void);
+
+Node *make_operand(char *opname,
+			 Node *tree,
+			 Oid orig_typeId,
+			 Oid true_typeId);
+
+void disallow_setop(char *op, Type optype, Node *operand);
+
+Expr *make_op(char *opname, Node *ltree, Node *rtree);
+
+Var *make_var(ParseState *pstate, char *refname, char *attrname, Oid *type_id);
+
+ArrayRef   *make_array_ref(Node *expr,
+			   List *indirection);
+
+ArrayRef   *make_array_set(Expr *target_expr,
+						   List *upperIndexpr,
+						   List *lowerIndexpr,
+						   Expr *expr);
+
+Const *make_const(Value *value);
+			   
+#endif							/* PARSE_NODE_H */
diff --git a/src/include/parser/parse_oper.h b/src/include/parser/parse_oper.h
new file mode 100644
index 0000000000000000000000000000000000000000..c013af628c33b49b4d58aa1133c66f0d6ce285c9
--- /dev/null
+++ b/src/include/parser/parse_oper.h
@@ -0,0 +1,50 @@
+/*-------------------------------------------------------------------------
+ *
+ * catalog_utils.h--
+ *
+ *
+ *
+ * Copyright (c) 1994, Regents of the University of California
+ *
+ * $Id: parse_oper.h,v 1.1 1997/11/25 22:06:59 momjian Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PARSE_OPER_H
+#define PARSE_OPER_H
+
+#include <parser/parse_func.h>
+#include <parser/parse_node.h>
+
+typedef HeapTuple Operator;
+
+Oid any_ordering_op(int restype);
+
+Oid oprid(Operator op);
+
+int binary_oper_get_candidates(char *opname,
+						   Oid leftTypeId,
+						   Oid rightTypeId,
+						   CandidateList *candidates);
+
+bool equivalentOpersAfterPromotion(CandidateList candidates);
+
+CandidateList binary_oper_select_candidate(Oid arg1,
+							 Oid arg2,
+							 CandidateList candidates);
+
+Operator oper(char *op, Oid arg1, Oid arg2, bool noWarnings);
+
+int
+unary_oper_get_candidates(char *op,
+						  Oid typeId,
+						  CandidateList *candidates,
+						  char rightleft);
+
+Operator right_oper(char *op, Oid arg);
+						  
+Operator left_oper(char *op, Oid arg);
+
+void op_error(char *op, Oid arg1, Oid arg2);
+
+#endif							/* PARSE_OPER_H */
diff --git a/src/include/parser/parse_query.h b/src/include/parser/parse_query.h
deleted file mode 100644
index 0a7d534b85b81ce3b46e3d6b3733f4a315cef499..0000000000000000000000000000000000000000
--- a/src/include/parser/parse_query.h
+++ /dev/null
@@ -1,70 +0,0 @@
- /*-------------------------------------------------------------------------
- *
- * parse_query.h--
- *	  prototypes for parse_query.c.
- *
- *
- * Copyright (c) 1994, Regents of the University of California
- *
- * $Id: parse_query.h,v 1.14 1997/11/20 23:23:53 momjian Exp $
- *
- *-------------------------------------------------------------------------
- */
-#ifndef PARSE_QUERY_H
-#define PARSE_QUERY_H
-
-#include <parser/catalog_utils.h>
-#include <parser/parse_state.h>
-#include <nodes/parsenodes.h>
-
-typedef struct QueryTreeList
-{
-	int			len;			/* number of queries */
-	Query	  **qtrees;
-} QueryTreeList;
-
-extern RangeTblEntry *refnameRangeTableEntry(List *rtable, char *refname);
-extern RangeTblEntry *colnameRangeTableEntry(ParseState *pstate, char *colname);
-extern int	refnameRangeTablePosn(List *rtable, char *refname);
-extern RangeTblEntry *
-addRangeTableEntry(ParseState *pstate,
-				   char *relname, char *refname,
-				   bool inh, bool inFromCl);
-extern List *
-expandAll(ParseState *pstate, char *relname, char *refname,
-		  int *this_resno);
-extern Expr *make_op(char *opname, Node *ltree, Node *rtree);
-
-extern Oid	find_atttype(Oid relid, char *attrname);
-extern Var *
-make_var(ParseState *pstate,
-		 char *relname, char *attrname, Oid *type_id);
-extern ArrayRef *make_array_ref(Node *array, List *indirection);
-extern ArrayRef *
-make_array_set(Expr *target_expr, List *upperIndexpr,
-			   List *lowerIndexpr, Expr *expr);
-extern Const *make_const(Value *value);
-
-extern void param_type_init(Oid *typev, int nargs);
-extern Oid	param_type(int t);
-
-extern QueryTreeList *parser(char *str, Oid *typev, int nargs);
-
-extern void handleTargetColname(ParseState *pstate, char **resname,
-					char *refname, char *colname);
-
-/*
- * analyze.c
- */
-
-Oid			exprType(Node *expr);
-QueryTreeList *parse_analyze(List *querytree_list);
-
-/* define in parse_query.c, used in gram.y */
-extern Oid *param_type_info;
-extern int	pfunc_num_args;
-
-/* useful macros */
-#define ISCOMPLEX(type) (typeid_get_relid(type) ? true : false)
-
-#endif							/* PARSE_QUERY_H */
diff --git a/src/include/parser/parse_relation.h b/src/include/parser/parse_relation.h
new file mode 100644
index 0000000000000000000000000000000000000000..ed470822ff59a2a3a283477504c9388c749775e9
--- /dev/null
+++ b/src/include/parser/parse_relation.h
@@ -0,0 +1,56 @@
+ /*-------------------------------------------------------------------------
+ *
+ * parse_query.h--
+ *	  prototypes for parse_query.c.
+ *
+ *
+ * Copyright (c) 1994, Regents of the University of California
+ *
+ * $Id: parse_relation.h,v 1.1 1997/11/25 22:07:02 momjian Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PARSE_QUERY_H
+#define PARSE_RANGE_H
+
+#include <nodes/nodes.h>
+#include <nodes/parsenodes.h>
+#include <nodes/pg_list.h>
+#include <nodes/primnodes.h>
+#include <parser/parse_node.h>
+#include <utils/rel.h>
+
+RangeTblEntry *refnameRangeTableEntry(List *rtable, char *refname);
+
+int refnameRangeTablePosn(List *rtable, char *refname);
+
+RangeTblEntry *colnameRangeTableEntry(ParseState *pstate, char *colname);
+
+RangeTblEntry *addRangeTableEntry(ParseState *pstate,
+								   char *relname,
+								   char *refname,
+								   bool inh,
+								   bool inFromCl);
+
+List *expandAll(ParseState *pstate, char *relname, char *refname,
+						int *this_resno);
+
+int attnameAttNum(Relation rd, char *a);
+
+bool attnameIsSet(Relation rd, char *name);
+
+char *attnumAttName(Relation rd, int attrno);
+
+int attnumAttNelems(Relation rd, int attid);
+
+Oid attnameTypeId(Oid relid, char *attrname);
+
+Oid attnumTypeId(Relation rd, int attid);
+
+void handleTargetColname(ParseState *pstate, char **resname,
+					char *refname, char *colname);
+
+void checkTargetTypes(ParseState *pstate, char *target_colname,
+				 char *refname, char *colname);
+
+#endif							/* PARSE_RANGE_H */
diff --git a/src/include/parser/parse_state.h b/src/include/parser/parse_state.h
deleted file mode 100644
index abda19b18c5ae334396a883430d0c57559c55f3f..0000000000000000000000000000000000000000
--- a/src/include/parser/parse_state.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * parse_state.h--
- *
- * Copyright (c) 1994, Regents of the University of California
- *
- * $Id: parse_state.h,v 1.8 1997/09/08 21:53:40 momjian Exp $
- *
- *-------------------------------------------------------------------------
- */
-
-#ifndef PARSE_STATE_H
-#define PARSE_STATE_H
-
-#include <nodes/parsenodes.h>
-#include <utils/rel.h>
-
-/* state information used during parse analysis */
-typedef struct ParseState
-{
-	int			p_last_resno;
-	List	   *p_rtable;
-	int			p_numAgg;
-	List	   *p_aggs;
-	bool		p_is_insert;
-	List	   *p_insert_columns;
-	bool		p_is_update;
-	bool		p_is_rule;
-	Relation	p_target_relation;
-	RangeTblEntry *p_target_rangetblentry;
-} ParseState;
-
-
-#endif							/* PARSE_QUERY_H */
diff --git a/src/include/parser/parse_target.h b/src/include/parser/parse_target.h
new file mode 100644
index 0000000000000000000000000000000000000000..c7faa6b3db97c33924b4961f3eaf4bef894b71a2
--- /dev/null
+++ b/src/include/parser/parse_target.h
@@ -0,0 +1,39 @@
+/*-------------------------------------------------------------------------
+ *
+ * parse_target.h
+ *
+ *
+ *
+ * Copyright (c) 1994, Regents of the University of California
+ *
+ * $Id: parse_target.h,v 1.1 1997/11/25 22:07:06 momjian Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PARSE_TARGET_H
+#define PARSE_TARGET_H
+
+#include <nodes/pg_list.h>
+#include <nodes/nodes.h>
+#include <nodes/parsenodes.h>
+#include <nodes/primnodes.h>
+#include <parser/parse_node.h>
+
+#define EXPR_COLUMN_FIRST	1
+#define EXPR_RELATION_FIRST	2
+
+List *transformTargetList(ParseState *pstate, List *targetlist);
+
+TargetEntry *make_targetlist_expr(ParseState *pstate,
+					 char *colname,
+					 Node *expr,
+					 List *arrayRef);
+
+List *expandAllTables(ParseState *pstate);
+
+char *figureColname(Node *expr, Node *resval);
+
+List *makeTargetNames(ParseState *pstate, List *cols);
+
+#endif							/* PARSE_TARGET_H */
+
diff --git a/src/include/parser/parse_type.h b/src/include/parser/parse_type.h
new file mode 100644
index 0000000000000000000000000000000000000000..63c38ab98dca916ebf7c335e269eaf36ca246b54
--- /dev/null
+++ b/src/include/parser/parse_type.h
@@ -0,0 +1,37 @@
+/*-------------------------------------------------------------------------
+ *
+ * parse_type.h
+ *
+ *
+ *
+ * Copyright (c) 1994, Regents of the University of California
+ *
+ * $Id: parse_type.h,v 1.1 1997/11/25 22:07:07 momjian Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PARSE_TYPE_H
+#define PARSE_TYPE_H
+
+#include "access/htup.h"
+
+typedef HeapTuple Type;
+
+bool typeidIsValid(Oid id);
+Type typeidType(Oid id);
+Type typenameType(char *s);
+char *typeidTypeName(Oid id);
+Oid typeTypeId(Type tp);
+int16 typeLen(Type t);
+bool typeByVal(Type t);
+char *typeTypeName(Type t);
+char typeTypeFlag(Type t);
+char *stringTypeString(Type tp, char *string, int typlen);
+Oid typeidRetoutfunc(Oid type_id);
+Oid typeidTypeRelid(Oid type_id);
+Oid typeTypeRelid(Type typ);
+Oid typeidTypElem(Oid type_id);
+Oid GetArrayElementType(Oid typearray);
+Oid typeidRetinfunc(Oid type_id);
+
+#endif							/* PARSE_TYPE_H */
diff --git a/src/include/parser/parser.h b/src/include/parser/parser.h
new file mode 100644
index 0000000000000000000000000000000000000000..4362ebb48036d7bc29b988942b3de88b2e826e54
--- /dev/null
+++ b/src/include/parser/parser.h
@@ -0,0 +1,21 @@
+/*-------------------------------------------------------------------------
+ *
+ * parser.h
+ *
+ *
+ *
+ * Copyright (c) 1994, Regents of the University of California
+ *
+ * $Id: parser.h,v 1.1 1997/11/25 22:07:08 momjian Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PARSER_H
+#define PARSER_H
+
+#include <parser/parse_node.h>
+
+QueryTreeList *parser(char *str, Oid *typev, int nargs);
+
+#endif							/* PARSER_H */
+
diff --git a/src/include/tcop/tcopprot.h b/src/include/tcop/tcopprot.h
index 6142f24e9658af8b31149b6a0f7ad815438a590d..eeb21b91bed5a2fc0c989054b5dab47a555432c6 100644
--- a/src/include/tcop/tcopprot.h
+++ b/src/include/tcop/tcopprot.h
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: tcopprot.h,v 1.7 1997/09/08 21:54:42 momjian Exp $
+ * $Id: tcopprot.h,v 1.8 1997/11/25 22:07:10 momjian Exp $
  *
  * OLD COMMENTS
  *	  This file was created so that other c files could get the two
@@ -19,7 +19,7 @@
 #define TCOPPROT_H
 
 #include <executor/execdesc.h>
-#include <parser/parse_query.h>
+#include <parser/parse_node.h>
 
 #ifndef BOOTSTRAP_INCLUDE
 extern List *
diff --git a/src/test/regress/checkresults b/src/test/regress/checkresults
index 1536dc2dba1e045d3062cd4fdabd8b519c100aea..39783cf46822cfbef5f40cdbf4012ee930e0f5b4 100755
--- a/src/test/regress/checkresults
+++ b/src/test/regress/checkresults
@@ -1,6 +1,8 @@
 #!/bin/sh
 # check regression tests
-# usage:  checkresults < results.out
+# usage:  checkresults [ regress.out ]
+
+[ "$#" -eq 0 ] && set regress.out
 
 for file in `cat "$@" | grep 'failed$' | cut -d " " -f 1`
 do