diff --git a/src/backend/commands/Makefile b/src/backend/commands/Makefile
index b27e6d77b2abeddfbc7d16faa3fbabe3dc6b115e..190b0fd64f64d75290ce2767864f39c1e606f26f 100644
--- a/src/backend/commands/Makefile
+++ b/src/backend/commands/Makefile
@@ -1,10 +1,10 @@
 #-------------------------------------------------------------------------
 #
 # Makefile--
-#    Makefile for commands
+#    Makefile for backend/commands
 #
 # IDENTIFICATION
-#    $Header: /cvsroot/pgsql/src/backend/commands/Makefile,v 1.27 2001/07/13 22:55:59 tgl Exp $
+#    $Header: /cvsroot/pgsql/src/backend/commands/Makefile,v 1.28 2002/04/15 05:22:03 tgl Exp $
 #
 #-------------------------------------------------------------------------
 
@@ -12,10 +12,11 @@ subdir = src/backend/commands
 top_builddir = ../../..
 include $(top_builddir)/src/Makefile.global
 
-OBJS = async.o creatinh.o command.o comment.o copy.o indexcmds.o define.o \
-       remove.o rename.o vacuum.o vacuumlazy.o analyze.o view.o cluster.o \
-       explain.o sequence.o trigger.o user.o proclang.o \
-       dbcommands.o variable.o
+OBJS = aggregatecmds.o analyze.o async.o cluster.o comment.o copy.o \
+	dbcommands.o define.o explain.o functioncmds.o \
+	indexcmds.o lockcmds.o operatorcmds.o portalcmds.o proclang.o \
+	schemacmds.o sequence.o tablecmds.o trigger.o typecmds.o user.o \
+	vacuum.o vacuumlazy.o variable.o view.o
 
 all: SUBSYS.o
 
diff --git a/src/backend/commands/aggregatecmds.c b/src/backend/commands/aggregatecmds.c
new file mode 100644
index 0000000000000000000000000000000000000000..7ee0c8f0784c5b40928bb4c7f3f2aa9375d6f988
--- /dev/null
+++ b/src/backend/commands/aggregatecmds.c
@@ -0,0 +1,208 @@
+/*-------------------------------------------------------------------------
+ *
+ * aggregatecmds.c
+ *
+ *	  Routines for aggregate-manipulation commands
+ *
+ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/aggregatecmds.c,v 1.1 2002/04/15 05:22:03 tgl Exp $
+ *
+ * DESCRIPTION
+ *	  The "DefineFoo" routines take the parse tree and pick out the
+ *	  appropriate arguments/flags, passing the results to the
+ *	  corresponding "FooDefine" routines (in src/catalog) that do
+ *	  the actual catalog-munging.  These routines also verify permission
+ *	  of the user to execute the command.
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "access/heapam.h"
+#include "catalog/catname.h"
+#include "catalog/namespace.h"
+#include "catalog/pg_aggregate.h"
+#include "commands/comment.h"
+#include "commands/defrem.h"
+#include "miscadmin.h"
+#include "parser/parse_func.h"
+#include "parser/parse_type.h"
+#include "utils/acl.h"
+#include "utils/builtins.h"
+#include "utils/lsyscache.h"
+#include "utils/syscache.h"
+
+
+/*
+ *	DefineAggregate
+ */
+void
+DefineAggregate(List *names, List *parameters)
+{
+	char	   *aggName;
+	Oid			aggNamespace;
+	List	   *transfuncName = NIL;
+	List	   *finalfuncName = NIL;
+	TypeName   *baseType = NULL;
+	TypeName   *transType = NULL;
+	char	   *initval = NULL;
+	Oid			baseTypeId;
+	Oid			transTypeId;
+	List	   *pl;
+
+	/* Convert list of names to a name and namespace */
+	aggNamespace = QualifiedNameGetCreationNamespace(names, &aggName);
+
+	foreach(pl, parameters)
+	{
+		DefElem    *defel = (DefElem *) lfirst(pl);
+
+		/*
+		 * sfunc1, stype1, and initcond1 are accepted as obsolete
+		 * spellings for sfunc, stype, initcond.
+		 */
+		if (strcasecmp(defel->defname, "sfunc") == 0)
+			transfuncName = defGetQualifiedName(defel);
+		else if (strcasecmp(defel->defname, "sfunc1") == 0)
+			transfuncName = defGetQualifiedName(defel);
+		else if (strcasecmp(defel->defname, "finalfunc") == 0)
+			finalfuncName = defGetQualifiedName(defel);
+		else if (strcasecmp(defel->defname, "basetype") == 0)
+			baseType = defGetTypeName(defel);
+		else if (strcasecmp(defel->defname, "stype") == 0)
+			transType = defGetTypeName(defel);
+		else if (strcasecmp(defel->defname, "stype1") == 0)
+			transType = defGetTypeName(defel);
+		else if (strcasecmp(defel->defname, "initcond") == 0)
+			initval = defGetString(defel);
+		else if (strcasecmp(defel->defname, "initcond1") == 0)
+			initval = defGetString(defel);
+		else
+			elog(WARNING, "DefineAggregate: attribute \"%s\" not recognized",
+				 defel->defname);
+	}
+
+	/*
+	 * make sure we have our required definitions
+	 */
+	if (baseType == NULL)
+		elog(ERROR, "Define: \"basetype\" unspecified");
+	if (transType == NULL)
+		elog(ERROR, "Define: \"stype\" unspecified");
+	if (transfuncName == NIL)
+		elog(ERROR, "Define: \"sfunc\" unspecified");
+
+	/*
+	 * Handle the aggregate's base type (input data type).  This can be
+	 * specified as 'ANY' for a data-independent transition function, such
+	 * as COUNT(*).
+	 */
+	baseTypeId = LookupTypeName(baseType);
+	if (OidIsValid(baseTypeId))
+	{
+		/* no need to allow aggregates on as-yet-undefined types */
+		if (!get_typisdefined(baseTypeId))
+			elog(ERROR, "Type \"%s\" is only a shell",
+				 TypeNameToString(baseType));
+	}
+	else
+	{
+		char      *typnam = TypeNameToString(baseType);
+
+		if (strcasecmp(typnam, "ANY") != 0)
+			elog(ERROR, "Type \"%s\" does not exist", typnam);
+		baseTypeId = InvalidOid;
+	}
+
+	/* handle transtype --- no special cases here */
+	transTypeId = typenameTypeId(transType);
+
+	/*
+	 * Most of the argument-checking is done inside of AggregateCreate
+	 */
+	AggregateCreate(aggName,	/* aggregate name */
+					aggNamespace,	/* namespace */
+					transfuncName,		/* step function name */
+					finalfuncName,		/* final function name */
+					baseTypeId,	/* type of data being aggregated */
+					transTypeId,	/* transition data type */
+					initval);	/* initial condition */
+}
+
+
+void
+RemoveAggregate(List *aggName, TypeName *aggType)
+{
+	Relation	relation;
+	HeapTuple	tup;
+	Oid			basetypeID;
+	Oid			procOid;
+
+	/*
+	 * if a basetype is passed in, then attempt to find an aggregate for
+	 * that specific type.
+	 *
+	 * else if the basetype is blank, then attempt to find an aggregate with
+	 * a basetype of zero.	This is valid. It means that the aggregate is
+	 * to apply to all basetypes (eg, COUNT).
+	 */
+	if (aggType)
+		basetypeID = typenameTypeId(aggType);
+	else
+		basetypeID = InvalidOid;
+
+	procOid = find_aggregate_func("RemoveAggregate", aggName, basetypeID);
+
+	/* Permission check */
+
+	if (!pg_proc_ownercheck(procOid, GetUserId()))
+	{
+		if (basetypeID == InvalidOid)
+			elog(ERROR, "RemoveAggregate: aggregate %s for all types: permission denied",
+				 NameListToString(aggName));
+		else
+			elog(ERROR, "RemoveAggregate: aggregate %s for type %s: permission denied",
+				 NameListToString(aggName), format_type_be(basetypeID));
+	}
+
+	/* Remove the pg_proc tuple */
+
+	relation = heap_openr(ProcedureRelationName, RowExclusiveLock);
+
+	tup = SearchSysCache(PROCOID,
+						 ObjectIdGetDatum(procOid),
+						 0, 0, 0);
+	if (!HeapTupleIsValid(tup))	/* should not happen */
+		elog(ERROR, "RemoveAggregate: couldn't find pg_proc tuple for %s",
+			 NameListToString(aggName));
+
+	/* Delete any comments associated with this function */
+	DeleteComments(procOid, RelationGetRelid(relation));
+
+	simple_heap_delete(relation, &tup->t_self);
+
+	ReleaseSysCache(tup);
+
+	heap_close(relation, RowExclusiveLock);
+
+	/* Remove the pg_aggregate tuple */
+
+	relation = heap_openr(AggregateRelationName, RowExclusiveLock);
+
+	tup = SearchSysCache(AGGFNOID,
+						 ObjectIdGetDatum(procOid),
+						 0, 0, 0);
+	if (!HeapTupleIsValid(tup))	/* should not happen */
+		elog(ERROR, "RemoveAggregate: couldn't find pg_aggregate tuple for %s",
+			 NameListToString(aggName));
+
+	simple_heap_delete(relation, &tup->t_self);
+
+	ReleaseSysCache(tup);
+
+	heap_close(relation, RowExclusiveLock);
+}
diff --git a/src/backend/commands/cluster.c b/src/backend/commands/cluster.c
index aad5361b6b837d085c4ed7b8df261ece8b8b21ee..8883eddc49f7d0c9342507e2d063f14031dfdae4 100644
--- a/src/backend/commands/cluster.c
+++ b/src/backend/commands/cluster.c
@@ -15,7 +15,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/commands/cluster.c,v 1.77 2002/03/31 07:49:30 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/cluster.c,v 1.78 2002/04/15 05:22:03 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -29,8 +29,7 @@
 #include "catalog/pg_index.h"
 #include "catalog/pg_proc.h"
 #include "commands/cluster.h"
-#include "commands/command.h"
-#include "commands/rename.h"
+#include "commands/tablecmds.h"
 #include "miscadmin.h"
 #include "utils/builtins.h"
 #include "utils/lsyscache.h"
diff --git a/src/backend/commands/creatinh.c b/src/backend/commands/creatinh.c
deleted file mode 100644
index 6a0cf8114738a4537d01ec0ff7ee8c3cb9221b40..0000000000000000000000000000000000000000
--- a/src/backend/commands/creatinh.c
+++ /dev/null
@@ -1,932 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * creatinh.c
- *	  POSTGRES create/destroy relation with inheritance utility code.
- *
- * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- *
- * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/commands/Attic/creatinh.c,v 1.96 2002/04/12 20:38:22 tgl Exp $
- *
- *-------------------------------------------------------------------------
- */
-
-#include "postgres.h"
-
-#include "access/heapam.h"
-#include "catalog/catalog.h"
-#include "catalog/catname.h"
-#include "catalog/heap.h"
-#include "catalog/indexing.h"
-#include "catalog/namespace.h"
-#include "catalog/pg_inherits.h"
-#include "catalog/pg_type.h"
-#include "commands/creatinh.h"
-#include "miscadmin.h"
-#include "optimizer/clauses.h"
-#include "parser/parse_type.h"
-#include "utils/acl.h"
-#include "utils/syscache.h"
-
-
-/* ----------------
- *		local stuff
- * ----------------
- */
-
-static List *MergeAttributes(List *schema, List *supers, bool istemp,
-				List **supOids, List **supconstr, bool *supHasOids);
-static bool change_varattnos_of_a_node(Node *node, const AttrNumber *newattno);
-static void StoreCatalogInheritance(Oid relationId, List *supers);
-static int	findAttrByName(const char *attributeName, List *schema);
-static void setRelhassubclassInRelation(Oid relationId, bool relhassubclass);
-static List *MergeDomainAttributes(List *schema);
-
-
-/* ----------------------------------------------------------------
- *		DefineRelation
- *				Creates a new relation.
- *
- * If successful, returns the OID of the new relation.
- * ----------------------------------------------------------------
- */
-Oid
-DefineRelation(CreateStmt *stmt, char relkind)
-{
-	char	   *relname = palloc(NAMEDATALEN);
-	Oid			namespaceId;
-	List	   *schema = stmt->tableElts;
-	int			numberOfAttributes;
-	Oid			relationId;
-	Relation	rel;
-	TupleDesc	descriptor;
-	List	   *inheritOids;
-	List	   *old_constraints;
-	bool		parentHasOids;
-	List	   *rawDefaults;
-	List	   *listptr;
-	int			i;
-	AttrNumber	attnum;
-
-	/*
-	 * Truncate relname to appropriate length (probably a waste of time,
-	 * as parser should have done this already).
-	 */
-	StrNCpy(relname, (stmt->relation)->relname, NAMEDATALEN);
-
-	/*
-	 * Look up the namespace in which we are supposed to create the
-	 * relation.
-	 */
-	namespaceId = RangeVarGetCreationNamespace(stmt->relation);
-
-	/*
-	 * Merge domain attributes into the known columns before processing table
-	 * inheritance.  Otherwise we risk adding double constraints to a
-	 * domain-type column that's inherited.
-	 */
-	schema = MergeDomainAttributes(schema);
-
-	/*
-	 * Look up inheritance ancestors and generate relation schema,
-	 * including inherited attributes.
-	 */
-	schema = MergeAttributes(schema, stmt->inhRelations,
-							 stmt->relation->istemp,
-							 &inheritOids, &old_constraints, &parentHasOids);
-
-	numberOfAttributes = length(schema);
-	if (numberOfAttributes <= 0)
-		elog(ERROR, "DefineRelation: please inherit from a relation or define an attribute");
-
-	/*
-	 * Create a relation descriptor from the relation schema and create
-	 * the relation.  Note that in this stage only inherited (pre-cooked)
-	 * defaults and constraints will be included into the new relation.
-	 * (BuildDescForRelation takes care of the inherited defaults, but we
-	 * have to copy inherited constraints here.)
-	 */
-	descriptor = BuildDescForRelation(schema);
-
-	if (old_constraints != NIL)
-	{
-		ConstrCheck *check = (ConstrCheck *) palloc(length(old_constraints) *
-													sizeof(ConstrCheck));
-		int			ncheck = 0;
-
-		foreach(listptr, old_constraints)
-		{
-			Constraint *cdef = (Constraint *) lfirst(listptr);
-
-			if (cdef->contype != CONSTR_CHECK)
-				continue;
-
-			if (cdef->name != NULL)
-			{
-				for (i = 0; i < ncheck; i++)
-				{
-					if (strcmp(check[i].ccname, cdef->name) == 0)
-						elog(ERROR, "Duplicate CHECK constraint name: '%s'",
-							 cdef->name);
-				}
-				check[ncheck].ccname = cdef->name;
-			}
-			else
-			{
-				check[ncheck].ccname = (char *) palloc(NAMEDATALEN);
-				snprintf(check[ncheck].ccname, NAMEDATALEN, "$%d", ncheck + 1);
-			}
-			Assert(cdef->raw_expr == NULL && cdef->cooked_expr != NULL);
-			check[ncheck].ccbin = pstrdup(cdef->cooked_expr);
-			ncheck++;
-		}
-		if (ncheck > 0)
-		{
-			if (descriptor->constr == NULL)
-			{
-				descriptor->constr = (TupleConstr *) palloc(sizeof(TupleConstr));
-				descriptor->constr->defval = NULL;
-				descriptor->constr->num_defval = 0;
-				descriptor->constr->has_not_null = false;
-			}
-			descriptor->constr->num_check = ncheck;
-			descriptor->constr->check = check;
-		}
-	}
-
-	relationId = heap_create_with_catalog(relname,
-										  namespaceId,
-										  descriptor,
-										  relkind,
-										  stmt->hasoids || parentHasOids,
-										  allowSystemTableMods);
-
-	StoreCatalogInheritance(relationId, inheritOids);
-
-	/*
-	 * We must bump the command counter to make the newly-created relation
-	 * tuple visible for opening.
-	 */
-	CommandCounterIncrement();
-
-	/*
-	 * Open the new relation and acquire exclusive lock on it.	This isn't
-	 * really necessary for locking out other backends (since they can't
-	 * see the new rel anyway until we commit), but it keeps the lock
-	 * manager from complaining about deadlock risks.
-	 */
-	rel = heap_open(relationId, AccessExclusiveLock);
-
-	/*
-	 * Now add any newly specified column default values and CHECK
-	 * constraints to the new relation.  These are passed to us in the
-	 * form of raw parsetrees; we need to transform them to executable
-	 * expression trees before they can be added. The most convenient way
-	 * to do that is to apply the parser's transformExpr routine, but
-	 * transformExpr doesn't work unless we have a pre-existing relation.
-	 * So, the transformation has to be postponed to this final step of
-	 * CREATE TABLE.
-	 *
-	 * First, scan schema to find new column defaults.
-	 */
-	rawDefaults = NIL;
-	attnum = 0;
-
-	foreach(listptr, schema)
-	{
-		ColumnDef  *colDef = lfirst(listptr);
-		RawColumnDefault *rawEnt;
-
-		attnum++;
-
-		if (colDef->raw_default == NULL)
-			continue;
-		Assert(colDef->cooked_default == NULL);
-
-		rawEnt = (RawColumnDefault *) palloc(sizeof(RawColumnDefault));
-		rawEnt->attnum = attnum;
-		rawEnt->raw_default = colDef->raw_default;
-		rawDefaults = lappend(rawDefaults, rawEnt);
-	}
-
-	/*
-	 * Parse and add the defaults/constraints, if any.
-	 */
-	if (rawDefaults || stmt->constraints)
-		AddRelationRawConstraints(rel, rawDefaults, stmt->constraints);
-
-	/*
-	 * Clean up.  We keep lock on new relation (although it shouldn't be
-	 * visible to anyone else anyway, until commit).
-	 */
-	heap_close(rel, NoLock);
-
-	return relationId;
-}
-
-/*
- * RemoveRelation
- *		Deletes a relation.
- *
- * Exceptions:
- *		BadArg if name is invalid.
- *
- * Note:
- *		If the relation has indices defined on it, then the index relations
- * themselves will be destroyed, too.
- */
-void
-RemoveRelation(const RangeVar *relation)
-{
-	Oid			relOid;
-
-	relOid = RangeVarGetRelid(relation, false);
-	heap_drop_with_catalog(relOid, allowSystemTableMods);
-}
-
-/*
- * TruncateRelation
- *				  Removes all the rows from a relation
- *
- * Exceptions:
- *				  BadArg if name is invalid
- *
- * Note:
- *				  Rows are removed, indices are truncated and reconstructed.
- */
-void
-TruncateRelation(const RangeVar *relation)
-{
-	Relation	rel;
-	Oid			relid;
-
-	/* Grab exclusive lock in preparation for truncate */
-	rel = heap_openrv(relation, AccessExclusiveLock);
-	relid = RelationGetRelid(rel);
-
-	if (rel->rd_rel->relkind == RELKIND_SEQUENCE)
-		elog(ERROR, "TRUNCATE cannot be used on sequences. '%s' is a sequence",
-			 RelationGetRelationName(rel));
-
-	if (rel->rd_rel->relkind == RELKIND_VIEW)
-		elog(ERROR, "TRUNCATE cannot be used on views. '%s' is a view",
-			 RelationGetRelationName(rel));
-
-	if (!allowSystemTableMods && IsSystemRelation(rel))
-		elog(ERROR, "TRUNCATE cannot be used on system tables. '%s' is a system table",
-			 RelationGetRelationName(rel));
-
-	if (!pg_class_ownercheck(relid, GetUserId()))
-		elog(ERROR, "you do not own relation \"%s\"",
-			 RelationGetRelationName(rel));
-
-	/* Keep the lock until transaction commit */
-	heap_close(rel, NoLock);
-
-	heap_truncate(relid);
-}
-
-
-/*
- * MergeDomainAttributes
- *      Returns a new table schema with the constraints, types, and other
- *      attributes of domains resolved for fields using a domain as
- *      their type.
- */
-static List *
-MergeDomainAttributes(List *schema)
-{
-	List	   *entry;
-
-	/*
-	 * Loop through the table elements supplied. These should
-	 * never include inherited domains else they'll be
-	 * double (or more) processed.
-	 */
-	foreach(entry, schema)
-	{
-		ColumnDef  *coldef = lfirst(entry);
-		HeapTuple  tuple;
-		Form_pg_type typeTup;
-
-		tuple = typenameType(coldef->typename);
-		typeTup = (Form_pg_type) GETSTRUCT(tuple);
-
-		if (typeTup->typtype == 'd')
-		{
-			/* Force the column to have the correct typmod. */
-			coldef->typename->typmod = typeTup->typtypmod;
-			/* XXX more to do here? */
-		}
-
-		/* Enforce type NOT NULL || column definition NOT NULL -> NOT NULL */
-		/* Currently only used for domains, but could be valid for all */
-		coldef->is_not_null |= typeTup->typnotnull;
-
-		ReleaseSysCache(tuple);
-	}
-
-	return schema;
-}
-
-/*----------
- * MergeAttributes
- *		Returns new schema given initial schema and superclasses.
- *
- * Input arguments:
- * 'schema' is the column/attribute definition for the table. (It's a list
- *		of ColumnDef's.) It is destructively changed.
- * 'supers' is a list of names (as RangeVar nodes) of parent relations.
- * 'istemp' is TRUE if we are creating a temp relation.
- *
- * Output arguments:
- * 'supOids' receives an integer list of the OIDs of the parent relations.
- * 'supconstr' receives a list of constraints belonging to the parents,
- *		updated as necessary to be valid for the child.
- * 'supHasOids' is set TRUE if any parent has OIDs, else it is set FALSE.
- *
- * Return value:
- * Completed schema list.
- *
- * Notes:
- *	  The order in which the attributes are inherited is very important.
- *	  Intuitively, the inherited attributes should come first. If a table
- *	  inherits from multiple parents, the order of those attributes are
- *	  according to the order of the parents specified in CREATE TABLE.
- *
- *	  Here's an example:
- *
- *		create table person (name text, age int4, location point);
- *		create table emp (salary int4, manager text) inherits(person);
- *		create table student (gpa float8) inherits (person);
- *		create table stud_emp (percent int4) inherits (emp, student);
- *
- *	  The order of the attributes of stud_emp is:
- *
- *							person {1:name, 2:age, 3:location}
- *							/	 \
- *			   {6:gpa}	student   emp {4:salary, 5:manager}
- *							\	 /
- *						   stud_emp {7:percent}
- *
- *	   If the same attribute name appears multiple times, then it appears
- *	   in the result table in the proper location for its first appearance.
- *
- *	   Constraints (including NOT NULL constraints) for the child table
- *	   are the union of all relevant constraints, from both the child schema
- *	   and parent tables.
- *
- *	   The default value for a child column is defined as:
- *		(1) If the child schema specifies a default, that value is used.
- *		(2) If neither the child nor any parent specifies a default, then
- *			the column will not have a default.
- *		(3) If conflicting defaults are inherited from different parents
- *			(and not overridden by the child), an error is raised.
- *		(4) Otherwise the inherited default is used.
- *		Rule (3) is new in Postgres 7.1; in earlier releases you got a
- *		rather arbitrary choice of which parent default to use.
- *----------
- */
-static List *
-MergeAttributes(List *schema, List *supers, bool istemp,
-				List **supOids, List **supconstr, bool *supHasOids)
-{
-	List	   *entry;
-	List	   *inhSchema = NIL;
-	List	   *parentOids = NIL;
-	List	   *constraints = NIL;
-	bool		parentHasOids = false;
-	bool		have_bogus_defaults = false;
-	char	   *bogus_marker = "Bogus!";		/* marks conflicting
-												 * defaults */
-	int			child_attno;
-
-	/*
-	 * Check for duplicate names in the explicit list of attributes.
-	 *
-	 * Although we might consider merging such entries in the same way that
-	 * we handle name conflicts for inherited attributes, it seems to make
-	 * more sense to assume such conflicts are errors.
-	 */
-	foreach(entry, schema)
-	{
-		ColumnDef  *coldef = lfirst(entry);
-		List	   *rest;
-
-		foreach(rest, lnext(entry))
-		{
-			ColumnDef  *restdef = lfirst(rest);
-
-			if (strcmp(coldef->colname, restdef->colname) == 0)
-				elog(ERROR, "CREATE TABLE: attribute \"%s\" duplicated",
-					 coldef->colname);
-		}
-	}
-
-	/*
-	 * Scan the parents left-to-right, and merge their attributes to form
-	 * a list of inherited attributes (inhSchema).	Also check to see if
-	 * we need to inherit an OID column.
-	 */
-	child_attno = 0;
-	foreach(entry, supers)
-	{
-		RangeVar   *parent = (RangeVar *) lfirst(entry);
-		Relation	relation;
-		TupleDesc	tupleDesc;
-		TupleConstr *constr;
-		AttrNumber *newattno;
-		AttrNumber	parent_attno;
-
-		relation = heap_openrv(parent, AccessShareLock);
-
-		if (relation->rd_rel->relkind != RELKIND_RELATION)
-			elog(ERROR, "CREATE TABLE: inherited relation \"%s\" is not a table",
-				 parent->relname);
-		/* Permanent rels cannot inherit from temporary ones */
-		if (!istemp && isTempNamespace(RelationGetNamespace(relation)))
-			elog(ERROR, "CREATE TABLE: cannot inherit from temp relation \"%s\"",
-				 parent->relname);
-
-		/*
-		 * We should have an UNDER permission flag for this, but for now,
-		 * demand that creator of a child table own the parent.
-		 */
-		if (!pg_class_ownercheck(RelationGetRelid(relation), GetUserId()))
-			elog(ERROR, "you do not own table \"%s\"",
-				 parent->relname);
-
-		/*
-		 * Reject duplications in the list of parents.
-		 */
-		if (intMember(RelationGetRelid(relation), parentOids))
-			elog(ERROR, "CREATE TABLE: inherited relation \"%s\" duplicated",
-				 parent->relname);
-
-		parentOids = lappendi(parentOids, RelationGetRelid(relation));
-		setRelhassubclassInRelation(RelationGetRelid(relation), true);
-
-		parentHasOids |= relation->rd_rel->relhasoids;
-
-		tupleDesc = RelationGetDescr(relation);
-		constr = tupleDesc->constr;
-
-		/*
-		 * newattno[] will contain the child-table attribute numbers for
-		 * the attributes of this parent table.  (They are not the same
-		 * for parents after the first one.)
-		 */
-		newattno = (AttrNumber *) palloc(tupleDesc->natts * sizeof(AttrNumber));
-
-		for (parent_attno = 1; parent_attno <= tupleDesc->natts;
-			 parent_attno++)
-		{
-			Form_pg_attribute attribute = tupleDesc->attrs[parent_attno - 1];
-			char	   *attributeName = NameStr(attribute->attname);
-			int			exist_attno;
-			ColumnDef  *def;
-			TypeName   *typename;
-
-			/*
-			 * Does it conflict with some previously inherited column?
-			 */
-			exist_attno = findAttrByName(attributeName, inhSchema);
-			if (exist_attno > 0)
-			{
-				/*
-				 * Yes, try to merge the two column definitions. They must
-				 * have the same type and typmod.
-				 */
-				elog(NOTICE, "CREATE TABLE: merging multiple inherited definitions of attribute \"%s\"",
-					 attributeName);
-				def = (ColumnDef *) nth(exist_attno - 1, inhSchema);
-				if (typenameTypeId(def->typename) != attribute->atttypid ||
-					def->typename->typmod != attribute->atttypmod)
-					elog(ERROR, "CREATE TABLE: inherited attribute \"%s\" type conflict (%s and %s)",
-						 attributeName,
-						 TypeNameToString(def->typename),
-						 typeidTypeName(attribute->atttypid));
-				/* Merge of NOT NULL constraints = OR 'em together */
-				def->is_not_null |= attribute->attnotnull;
-				/* Default and other constraints are handled below */
-				newattno[parent_attno - 1] = exist_attno;
-			}
-			else
-			{
-				/*
-				 * No, create a new inherited column
-				 */
-				def = makeNode(ColumnDef);
-				def->colname = pstrdup(attributeName);
-				typename = makeNode(TypeName);
-				typename->typeid = attribute->atttypid;
-				typename->typmod = attribute->atttypmod;
-				def->typename = typename;
-				def->is_not_null = attribute->attnotnull;
-				def->raw_default = NULL;
-				def->cooked_default = NULL;
-				def->constraints = NIL;
-				inhSchema = lappend(inhSchema, def);
-				newattno[parent_attno - 1] = ++child_attno;
-			}
-
-			/*
-			 * Copy default if any
-			 */
-			if (attribute->atthasdef)
-			{
-				char	   *this_default = NULL;
-				AttrDefault *attrdef;
-				int			i;
-
-				/* Find default in constraint structure */
-				Assert(constr != NULL);
-				attrdef = constr->defval;
-				for (i = 0; i < constr->num_defval; i++)
-				{
-					if (attrdef[i].adnum == parent_attno)
-					{
-						this_default = attrdef[i].adbin;
-						break;
-					}
-				}
-				Assert(this_default != NULL);
-
-				/*
-				 * If default expr could contain any vars, we'd need to
-				 * fix 'em, but it can't; so default is ready to apply to
-				 * child.
-				 *
-				 * If we already had a default from some prior parent, check
-				 * to see if they are the same.  If so, no problem; if
-				 * not, mark the column as having a bogus default. Below,
-				 * we will complain if the bogus default isn't overridden
-				 * by the child schema.
-				 */
-				Assert(def->raw_default == NULL);
-				if (def->cooked_default == NULL)
-					def->cooked_default = pstrdup(this_default);
-				else if (strcmp(def->cooked_default, this_default) != 0)
-				{
-					def->cooked_default = bogus_marker;
-					have_bogus_defaults = true;
-				}
-			}
-		}
-
-		/*
-		 * Now copy the constraints of this parent, adjusting attnos using
-		 * the completed newattno[] map
-		 */
-		if (constr && constr->num_check > 0)
-		{
-			ConstrCheck *check = constr->check;
-			int			i;
-
-			for (i = 0; i < constr->num_check; i++)
-			{
-				Constraint *cdef = makeNode(Constraint);
-				Node	   *expr;
-
-				cdef->contype = CONSTR_CHECK;
-				if (check[i].ccname[0] == '$')
-					cdef->name = NULL;
-				else
-					cdef->name = pstrdup(check[i].ccname);
-				cdef->raw_expr = NULL;
-				/* adjust varattnos of ccbin here */
-				expr = stringToNode(check[i].ccbin);
-				change_varattnos_of_a_node(expr, newattno);
-				cdef->cooked_expr = nodeToString(expr);
-				constraints = lappend(constraints, cdef);
-			}
-		}
-
-		pfree(newattno);
-
-		/*
-		 * Close the parent rel, but keep our AccessShareLock on it until
-		 * xact commit.  That will prevent someone else from deleting or
-		 * ALTERing the parent before the child is committed.
-		 */
-		heap_close(relation, NoLock);
-	}
-
-	/*
-	 * If we had no inherited attributes, the result schema is just the
-	 * explicitly declared columns.  Otherwise, we need to merge the
-	 * declared columns into the inherited schema list.
-	 */
-	if (inhSchema != NIL)
-	{
-		foreach(entry, schema)
-		{
-			ColumnDef  *newdef = lfirst(entry);
-			char	   *attributeName = newdef->colname;
-			int			exist_attno;
-
-			/*
-			 * Does it conflict with some previously inherited column?
-			 */
-			exist_attno = findAttrByName(attributeName, inhSchema);
-			if (exist_attno > 0)
-			{
-				ColumnDef  *def;
-
-				/*
-				 * Yes, try to merge the two column definitions. They must
-				 * have the same type and typmod.
-				 */
-				elog(NOTICE, "CREATE TABLE: merging attribute \"%s\" with inherited definition",
-					 attributeName);
-				def = (ColumnDef *) nth(exist_attno - 1, inhSchema);
-				if (typenameTypeId(def->typename) != typenameTypeId(newdef->typename) ||
-					def->typename->typmod != newdef->typename->typmod)
-					elog(ERROR, "CREATE TABLE: attribute \"%s\" type conflict (%s and %s)",
-						 attributeName,
-						 TypeNameToString(def->typename),
-						 TypeNameToString(newdef->typename));
-				/* Merge of NOT NULL constraints = OR 'em together */
-				def->is_not_null |= newdef->is_not_null;
-				/* If new def has a default, override previous default */
-				if (newdef->raw_default != NULL)
-				{
-					def->raw_default = newdef->raw_default;
-					def->cooked_default = newdef->cooked_default;
-				}
-			}
-			else
-			{
-				/*
-				 * No, attach new column to result schema
-				 */
-				inhSchema = lappend(inhSchema, newdef);
-			}
-		}
-
-		schema = inhSchema;
-	}
-
-	/*
-	 * If we found any conflicting parent default values, check to make
-	 * sure they were overridden by the child.
-	 */
-	if (have_bogus_defaults)
-	{
-		foreach(entry, schema)
-		{
-			ColumnDef  *def = lfirst(entry);
-
-			if (def->cooked_default == bogus_marker)
-				elog(ERROR, "CREATE TABLE: attribute \"%s\" inherits conflicting default values"
-					 "\n\tTo resolve the conflict, specify a default explicitly",
-					 def->colname);
-		}
-	}
-
-	*supOids = parentOids;
-	*supconstr = constraints;
-	*supHasOids = parentHasOids;
-	return schema;
-}
-
-/*
- * complementary static functions for MergeAttributes().
- *
- * Varattnos of pg_relcheck.rcbin must be rewritten when subclasses inherit
- * constraints from parent classes, since the inherited attributes could
- * be given different column numbers in multiple-inheritance cases.
- *
- * Note that the passed node tree is modified in place!
- */
-static bool
-change_varattnos_walker(Node *node, const AttrNumber *newattno)
-{
-	if (node == NULL)
-		return false;
-	if (IsA(node, Var))
-	{
-		Var		   *var = (Var *) node;
-
-		if (var->varlevelsup == 0 && var->varno == 1 &&
-			var->varattno > 0)
-		{
-			/*
-			 * ??? the following may be a problem when the node is
-			 * multiply referenced though stringToNode() doesn't create
-			 * such a node currently.
-			 */
-			Assert(newattno[var->varattno - 1] > 0);
-			var->varattno = newattno[var->varattno - 1];
-		}
-		return false;
-	}
-	return expression_tree_walker(node, change_varattnos_walker,
-								  (void *) newattno);
-}
-
-static bool
-change_varattnos_of_a_node(Node *node, const AttrNumber *newattno)
-{
-	return change_varattnos_walker(node, newattno);
-}
-
-/*
- * StoreCatalogInheritance
- *		Updates the system catalogs with proper inheritance information.
- *
- * supers is an integer list of the OIDs of the new relation's direct
- * ancestors.  NB: it is destructively changed to include indirect ancestors.
- */
-static void
-StoreCatalogInheritance(Oid relationId, List *supers)
-{
-	Relation	relation;
-	TupleDesc	desc;
-	int16		seqNumber;
-	List	   *entry;
-	HeapTuple	tuple;
-
-	/*
-	 * sanity checks
-	 */
-	AssertArg(OidIsValid(relationId));
-
-	if (supers == NIL)
-		return;
-
-	/*
-	 * Catalog INHERITS information using direct ancestors only.
-	 */
-	relation = heap_openr(InheritsRelationName, RowExclusiveLock);
-	desc = RelationGetDescr(relation);
-
-	seqNumber = 1;
-	foreach(entry, supers)
-	{
-		Oid			entryOid = lfirsti(entry);
-		Datum		datum[Natts_pg_inherits];
-		char		nullarr[Natts_pg_inherits];
-
-		datum[0] = ObjectIdGetDatum(relationId);		/* inhrel */
-		datum[1] = ObjectIdGetDatum(entryOid);	/* inhparent */
-		datum[2] = Int16GetDatum(seqNumber);	/* inhseqno */
-
-		nullarr[0] = ' ';
-		nullarr[1] = ' ';
-		nullarr[2] = ' ';
-
-		tuple = heap_formtuple(desc, datum, nullarr);
-
-		heap_insert(relation, tuple);
-
-		if (RelationGetForm(relation)->relhasindex)
-		{
-			Relation	idescs[Num_pg_inherits_indices];
-
-			CatalogOpenIndices(Num_pg_inherits_indices, Name_pg_inherits_indices, idescs);
-			CatalogIndexInsert(idescs, Num_pg_inherits_indices, relation, tuple);
-			CatalogCloseIndices(Num_pg_inherits_indices, idescs);
-		}
-
-		heap_freetuple(tuple);
-
-		seqNumber += 1;
-	}
-
-	heap_close(relation, RowExclusiveLock);
-
-	/* ----------------
-	 * Expand supers list to include indirect ancestors as well.
-	 *
-	 * Algorithm:
-	 *	0. begin with list of direct superclasses.
-	 *	1. append after each relationId, its superclasses, recursively.
-	 *	2. remove all but last of duplicates.
-	 * ----------------
-	 */
-
-	/*
-	 * 1. append after each relationId, its superclasses, recursively.
-	 */
-	foreach(entry, supers)
-	{
-		HeapTuple	tuple;
-		Oid			id;
-		int16		number;
-		List	   *next;
-		List	   *current;
-
-		id = (Oid) lfirsti(entry);
-		current = entry;
-		next = lnext(entry);
-
-		for (number = 1;; number += 1)
-		{
-			tuple = SearchSysCache(INHRELID,
-								   ObjectIdGetDatum(id),
-								   Int16GetDatum(number),
-								   0, 0);
-			if (!HeapTupleIsValid(tuple))
-				break;
-
-			lnext(current) = lconsi(((Form_pg_inherits)
-									 GETSTRUCT(tuple))->inhparent,
-									NIL);
-
-			ReleaseSysCache(tuple);
-
-			current = lnext(current);
-		}
-		lnext(current) = next;
-	}
-
-	/*
-	 * 2. remove all but last of duplicates.
-	 */
-	foreach(entry, supers)
-	{
-		Oid			thisone;
-		bool		found;
-		List	   *rest;
-
-again:
-		thisone = lfirsti(entry);
-		found = false;
-		foreach(rest, lnext(entry))
-		{
-			if (thisone == lfirsti(rest))
-			{
-				found = true;
-				break;
-			}
-		}
-		if (found)
-		{
-			/*
-			 * found a later duplicate, so remove this entry.
-			 */
-			lfirsti(entry) = lfirsti(lnext(entry));
-			lnext(entry) = lnext(lnext(entry));
-
-			goto again;
-		}
-	}
-}
-
-/*
- * Look for an existing schema entry with the given name.
- *
- * Returns the index (starting with 1) if attribute already exists in schema,
- * 0 if it doesn't.
- */
-static int
-findAttrByName(const char *attributeName, List *schema)
-{
-	List	   *s;
-	int			i = 0;
-
-	foreach(s, schema)
-	{
-		ColumnDef  *def = lfirst(s);
-
-		++i;
-		if (strcmp(attributeName, def->colname) == 0)
-			return i;
-	}
-	return 0;
-}
-
-/*
- * Update a relation's pg_class.relhassubclass entry to the given value
- */
-static void
-setRelhassubclassInRelation(Oid relationId, bool relhassubclass)
-{
-	Relation	relationRelation;
-	HeapTuple	tuple;
-	Relation	idescs[Num_pg_class_indices];
-
-	/*
-	 * Fetch a modifiable copy of the tuple, modify it, update pg_class.
-	 */
-	relationRelation = heap_openr(RelationRelationName, RowExclusiveLock);
-	tuple = SearchSysCacheCopy(RELOID,
-							   ObjectIdGetDatum(relationId),
-							   0, 0, 0);
-	if (!HeapTupleIsValid(tuple))
-		elog(ERROR, "setRelhassubclassInRelation: cache lookup failed for relation %u", relationId);
-
-	((Form_pg_class) GETSTRUCT(tuple))->relhassubclass = relhassubclass;
-	simple_heap_update(relationRelation, &tuple->t_self, tuple);
-
-	/* keep the catalog indices up to date */
-	CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, idescs);
-	CatalogIndexInsert(idescs, Num_pg_class_indices, relationRelation, tuple);
-	CatalogCloseIndices(Num_pg_class_indices, idescs);
-
-	heap_freetuple(tuple);
-	heap_close(relationRelation, RowExclusiveLock);
-}
diff --git a/src/backend/commands/define.c b/src/backend/commands/define.c
index 692fc9f957c4a389dd1536d1d2deb1c6c1c9f10c..889ddd0f44026a578d78c8cfb1d67d890cd0ec54 100644
--- a/src/backend/commands/define.c
+++ b/src/backend/commands/define.c
@@ -1,16 +1,15 @@
 /*-------------------------------------------------------------------------
  *
  * define.c
+ *	  Support routines for various kinds of object creation.
  *
- *	  These routines execute some of the CREATE statements.  In an earlier
- *	  version of Postgres, these were "define" statements.
  *
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/commands/define.c,v 1.75 2002/04/11 19:59:57 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/define.c,v 1.76 2002/04/15 05:22:03 tgl Exp $
  *
  * DESCRIPTION
  *	  The "DefineFoo" routines take the parse tree and pick out the
@@ -28,8 +27,6 @@
  *		"create operator":
  *				operators
  *
- *		Most of the parse-tree manipulation routines are defined in
- *		commands/manip.c.
  *
  *-------------------------------------------------------------------------
  */
@@ -38,42 +35,16 @@
 #include <ctype.h>
 #include <math.h>
 
-#include "access/heapam.h"
-#include "catalog/catname.h"
-#include "catalog/heap.h"
-#include "catalog/namespace.h"
-#include "catalog/pg_aggregate.h"
-#include "catalog/pg_language.h"
-#include "catalog/pg_operator.h"
-#include "catalog/pg_proc.h"
-#include "catalog/pg_type.h"
 #include "commands/defrem.h"
-#include "fmgr.h"
-#include "miscadmin.h"
-#include "optimizer/cost.h"
-#include "parser/parse_func.h"
 #include "parser/parse_type.h"
-#include "utils/acl.h"
-#include "utils/builtins.h"
-#include "utils/fmgroids.h"
-#include "utils/lsyscache.h"
-#include "utils/syscache.h"
-
-
-static Oid	findTypeIOFunction(List *procname, bool isOutput);
-static char *defGetString(DefElem *def);
-static double defGetNumeric(DefElem *def);
-static List *defGetQualifiedName(DefElem *def);
-static TypeName *defGetTypeName(DefElem *def);
-static int	defGetTypeLength(DefElem *def);
-
-#define DEFAULT_TYPDELIM		','
 
 
 /*
  * Translate the input language name to lower case.
+ *
+ * Output buffer should be NAMEDATALEN long.
  */
-static void
+void
 case_translate_language_name(const char *input, char *output)
 {
 	int			i;
@@ -86,1021 +57,9 @@ case_translate_language_name(const char *input, char *output)
 
 
 /*
- *	 Examine the "returns" clause returnType of the CREATE FUNCTION statement
- *	 and return information about it as *prorettype_p and *returnsSet.
- *
- * This is more complex than the average typename lookup because we want to
- * allow a shell type to be used, or even created if the specified return type
- * doesn't exist yet.  (Without this, there's no way to define the I/O procs
- * for a new type.)  But SQL function creation won't cope, so error out if
- * the target language is SQL.
- */
-static void
-compute_return_type(TypeName *returnType, Oid languageOid,
-					Oid *prorettype_p, bool *returnsSet_p)
-{
-	Oid		rettype;
-
-	rettype = LookupTypeName(returnType);
-
-	if (OidIsValid(rettype))
-	{
-		if (!get_typisdefined(rettype))
-		{
-			if (languageOid == SQLlanguageId)
-				elog(ERROR, "SQL functions cannot return shell types");
-			else
-				elog(WARNING, "Return type \"%s\" is only a shell",
-					 TypeNameToString(returnType));
-		}
-	}
-	else
-	{
-		char      *typnam = TypeNameToString(returnType);
-
-		if (strcmp(typnam, "opaque") == 0)
-			rettype = InvalidOid;
-		else
-		{
-			Oid			namespaceId;
-			char	   *typname;
-
-			if (languageOid == SQLlanguageId)
-				elog(ERROR, "Type \"%s\" does not exist", typnam);
-			elog(WARNING, "ProcedureCreate: type %s is not yet defined",
-				 typnam);
-			namespaceId = QualifiedNameGetCreationNamespace(returnType->names,
-															&typname);
-			rettype = TypeShellMake(typname, namespaceId);
-			if (!OidIsValid(rettype))
-				elog(ERROR, "could not create type %s", typnam);
-		}
-	}
-
-	*prorettype_p = rettype;
-	*returnsSet_p = returnType->setof;
-}
-
-/*
- * Interpret the argument-types list of the CREATE FUNCTION statement.
- */
-static int
-compute_parameter_types(List *argTypes, Oid languageOid,
-						Oid *parameterTypes)
-{
-	int			parameterCount = 0;
-	List	   *x;
-
-	MemSet(parameterTypes, 0, FUNC_MAX_ARGS * sizeof(Oid));
-	foreach(x, argTypes)
-	{
-		TypeName   *t = (TypeName *) lfirst(x);
-		Oid			toid;
-
-		if (parameterCount >= FUNC_MAX_ARGS)
-			elog(ERROR, "functions cannot have more than %d arguments",
-				 FUNC_MAX_ARGS);
-
-		toid = LookupTypeName(t);
-		if (OidIsValid(toid))
-		{
-			if (!get_typisdefined(toid))
-				elog(WARNING, "Argument type \"%s\" is only a shell",
-					 TypeNameToString(t));
-		}
-		else
-		{
-			char      *typnam = TypeNameToString(t);
-
-			if (strcmp(typnam, "opaque") == 0)
-			{
-				if (languageOid == SQLlanguageId)
-					elog(ERROR, "SQL functions cannot have arguments of type \"opaque\"");
-				toid = InvalidOid;
-			}
-			else
-				elog(ERROR, "Type \"%s\" does not exist", typnam);
-		}
-
-		if (t->setof)
-			elog(ERROR, "functions cannot accept set arguments");
-
-		parameterTypes[parameterCount++] = toid;
-	}
-
-	return parameterCount;
-}
-
-/*-------------
- *	 Interpret the parameters *parameters and return their contents as
- *	 *byte_pct_p, etc.
- *
- *	These parameters supply optional information about a function.
- *	All have defaults if not specified.
- *
- *	Note: currently, only three of these parameters actually do anything:
- *
- *	 * isImplicit means the function may be used as an implicit type
- *	   coercion.
- *
- *	 * isStrict means the function should not be called when any NULL
- *	   inputs are present; instead a NULL result value should be assumed.
- *
- *	 * volatility tells the optimizer whether the function's result can
- *	   be assumed to be repeatable over multiple evaluations.
- *
- *	The other four parameters are not used anywhere.	They used to be
- *	used in the "expensive functions" optimizer, but that's been dead code
- *	for a long time.
- *------------
- */
-static void
-compute_full_attributes(List *parameters,
-						int32 *byte_pct_p, int32 *perbyte_cpu_p,
-						int32 *percall_cpu_p, int32 *outin_ratio_p,
-						bool *isImplicit_p, bool *isStrict_p,
-						char *volatility_p)
-{
-	List	   *pl;
-
-	/* the defaults */
-	*byte_pct_p = BYTE_PCT;
-	*perbyte_cpu_p = PERBYTE_CPU;
-	*percall_cpu_p = PERCALL_CPU;
-	*outin_ratio_p = OUTIN_RATIO;
-	*isImplicit_p = false;
-	*isStrict_p = false;
-	*volatility_p = PROVOLATILE_VOLATILE;
-
-	foreach(pl, parameters)
-	{
-		DefElem    *param = (DefElem *) lfirst(pl);
-
-		if (strcasecmp(param->defname, "implicitcoercion") == 0)
-			*isImplicit_p = true;
-		else if (strcasecmp(param->defname, "isstrict") == 0)
-			*isStrict_p = true;
-		else if (strcasecmp(param->defname, "isimmutable") == 0)
-			*volatility_p = PROVOLATILE_IMMUTABLE;
-		else if (strcasecmp(param->defname, "isstable") == 0)
-			*volatility_p = PROVOLATILE_STABLE;
-		else if (strcasecmp(param->defname, "isvolatile") == 0)
-			*volatility_p = PROVOLATILE_VOLATILE;
-		else if (strcasecmp(param->defname, "iscachable") == 0)
-		{
-			/* obsolete spelling of isImmutable */
-			*volatility_p = PROVOLATILE_IMMUTABLE;
-		}
-		else if (strcasecmp(param->defname, "trusted") == 0)
-		{
-			/*
-			 * we don't have untrusted functions any more. The 4.2
-			 * implementation is lousy anyway so I took it out. -ay 10/94
-			 */
-			elog(ERROR, "untrusted function has been decommissioned.");
-		}
-		else if (strcasecmp(param->defname, "byte_pct") == 0)
-			*byte_pct_p = (int) defGetNumeric(param);
-		else if (strcasecmp(param->defname, "perbyte_cpu") == 0)
-			*perbyte_cpu_p = (int) defGetNumeric(param);
-		else if (strcasecmp(param->defname, "percall_cpu") == 0)
-			*percall_cpu_p = (int) defGetNumeric(param);
-		else if (strcasecmp(param->defname, "outin_ratio") == 0)
-			*outin_ratio_p = (int) defGetNumeric(param);
-		else
-			elog(WARNING, "Unrecognized function attribute '%s' ignored",
-				 param->defname);
-	}
-}
-
-
-/*
- * For a dynamically linked C language object, the form of the clause is
- *
- *	   AS <object file name> [, <link symbol name> ]
- *
- * In all other cases
- *
- *	   AS <object reference, or sql code>
- *
- */
-
-static void
-interpret_AS_clause(Oid languageOid, const char *languageName, const List *as,
-					char **prosrc_str_p, char **probin_str_p)
-{
-	Assert(as != NIL);
-
-	if (languageOid == ClanguageId)
-	{
-		/*
-		 * For "C" language, store the file name in probin and, when
-		 * given, the link symbol name in prosrc.
-		 */
-		*probin_str_p = strVal(lfirst(as));
-		if (lnext(as) == NULL)
-			*prosrc_str_p = "-";
-		else
-			*prosrc_str_p = strVal(lsecond(as));
-	}
-	else
-	{
-		/* Everything else wants the given string in prosrc. */
-		*prosrc_str_p = strVal(lfirst(as));
-		*probin_str_p = "-";
-
-		if (lnext(as) != NIL)
-			elog(ERROR, "CREATE FUNCTION: only one AS item needed for %s language",
-				 languageName);
-	}
-}
-
-
-
-/*
- * CreateFunction
- *	 Execute a CREATE FUNCTION utility statement.
- */
-void
-CreateFunction(ProcedureStmt *stmt)
-{
-	char	   *probin_str;
-	char	   *prosrc_str;
-	Oid			prorettype;
-	bool		returnsSet;
-	char		languageName[NAMEDATALEN];
-	Oid			languageOid;
-	char	   *funcname;
-	Oid			namespaceId;
-	int			parameterCount;
-	Oid			parameterTypes[FUNC_MAX_ARGS];
-	int32		byte_pct,
-				perbyte_cpu,
-				percall_cpu,
-				outin_ratio;
-	bool		isImplicit,
-				isStrict;
-	char		volatility;
-	HeapTuple	languageTuple;
-	Form_pg_language languageStruct;
-
-	/* Convert list of names to a name and namespace */
-	namespaceId = QualifiedNameGetCreationNamespace(stmt->funcname,
-													&funcname);
-
-	/* Convert language name to canonical case */
-	case_translate_language_name(stmt->language, languageName);
-
-	/* Look up the language and validate permissions */
-	languageTuple = SearchSysCache(LANGNAME,
-								   PointerGetDatum(languageName),
-								   0, 0, 0);
-	if (!HeapTupleIsValid(languageTuple))
-		elog(ERROR, "language \"%s\" does not exist", languageName);
-
-	languageOid = languageTuple->t_data->t_oid;
-	languageStruct = (Form_pg_language) GETSTRUCT(languageTuple);
-
-	if (!((languageStruct->lanpltrusted
-		   && pg_language_aclcheck(languageOid, GetUserId()) == ACLCHECK_OK)
-		  || superuser()))
-		elog(ERROR, "permission denied");
-
-	ReleaseSysCache(languageTuple);
-
-	/*
-	 * Convert remaining parameters of CREATE to form wanted by
-	 * ProcedureCreate.
-	 */
-	compute_return_type(stmt->returnType, languageOid,
-						&prorettype, &returnsSet);
-
-	parameterCount = compute_parameter_types(stmt->argTypes, languageOid,
-											 parameterTypes);
-
-	compute_full_attributes(stmt->withClause,
-							&byte_pct, &perbyte_cpu, &percall_cpu,
-							&outin_ratio, &isImplicit, &isStrict,
-							&volatility);
-
-	interpret_AS_clause(languageOid, languageName, stmt->as,
-						&prosrc_str, &probin_str);
-
-	/*
-	 * And now that we have all the parameters, and know we're permitted
-	 * to do so, go ahead and create the function.
-	 */
-	ProcedureCreate(funcname,
-					namespaceId,
-					stmt->replace,
-					returnsSet,
-					prorettype,
-					languageOid,
-					prosrc_str, /* converted to text later */
-					probin_str, /* converted to text later */
-					false,		/* not an aggregate */
-					true,		/* (obsolete "trusted") */
-					isImplicit,
-					isStrict,
-					volatility,
-					byte_pct,
-					perbyte_cpu,
-					percall_cpu,
-					outin_ratio,
-					parameterCount,
-					parameterTypes);
-}
-
-
-/*
- * DefineOperator
- *		this function extracts all the information from the
- *		parameter list generated by the parser and then has
- *		OperatorCreate() do all the actual work.
- *
- * 'parameters' is a list of DefElem
- */
-void
-DefineOperator(List *names, List *parameters)
-{
-	char	   *oprName;
-	Oid			oprNamespace;
-	uint16		precedence = 0; /* operator precedence */
-	bool		canHash = false;	/* operator hashes */
-	bool		isLeftAssociative = true;		/* operator is left
-												 * associative */
-	char	   *functionName = NULL;	/* function for operator */
-	TypeName   *typeName1 = NULL;		/* first type name */
-	TypeName   *typeName2 = NULL;		/* second type name */
-	Oid			typeId1 = InvalidOid;	/* types converted to OID */
-	Oid			typeId2 = InvalidOid;
-	char	   *commutatorName = NULL;	/* optional commutator operator
-										 * name */
-	char	   *negatorName = NULL;		/* optional negator operator name */
-	char	   *restrictionName = NULL; /* optional restrict. sel.
-										 * procedure */
-	char	   *joinName = NULL;	/* optional join sel. procedure name */
-	char	   *sortName1 = NULL;		/* optional first sort operator */
-	char	   *sortName2 = NULL;		/* optional second sort operator */
-	List	   *pl;
-
-	/* Convert list of names to a name and namespace */
-	oprNamespace = QualifiedNameGetCreationNamespace(names, &oprName);
-
-	/*
-	 * loop over the definition list and extract the information we need.
-	 */
-	foreach(pl, parameters)
-	{
-		DefElem    *defel = (DefElem *) lfirst(pl);
-
-		if (strcasecmp(defel->defname, "leftarg") == 0)
-		{
-			typeName1 = defGetTypeName(defel);
-			if (typeName1->setof)
-				elog(ERROR, "setof type not implemented for leftarg");
-		}
-		else if (strcasecmp(defel->defname, "rightarg") == 0)
-		{
-			typeName2 = defGetTypeName(defel);
-			if (typeName2->setof)
-				elog(ERROR, "setof type not implemented for rightarg");
-		}
-		else if (strcasecmp(defel->defname, "procedure") == 0)
-			functionName = defGetString(defel);
-		else if (strcasecmp(defel->defname, "precedence") == 0)
-		{
-			/* NOT IMPLEMENTED (never worked in v4.2) */
-			elog(NOTICE, "CREATE OPERATOR: precedence not implemented");
-		}
-		else if (strcasecmp(defel->defname, "associativity") == 0)
-		{
-			/* NOT IMPLEMENTED (never worked in v4.2) */
-			elog(NOTICE, "CREATE OPERATOR: associativity not implemented");
-		}
-		else if (strcasecmp(defel->defname, "commutator") == 0)
-			commutatorName = defGetString(defel);
-		else if (strcasecmp(defel->defname, "negator") == 0)
-			negatorName = defGetString(defel);
-		else if (strcasecmp(defel->defname, "restrict") == 0)
-			restrictionName = defGetString(defel);
-		else if (strcasecmp(defel->defname, "join") == 0)
-			joinName = defGetString(defel);
-		else if (strcasecmp(defel->defname, "hashes") == 0)
-			canHash = TRUE;
-		else if (strcasecmp(defel->defname, "sort1") == 0)
-			sortName1 = defGetString(defel);
-		else if (strcasecmp(defel->defname, "sort2") == 0)
-			sortName2 = defGetString(defel);
-		else
-		{
-			elog(WARNING, "DefineOperator: attribute \"%s\" not recognized",
-				 defel->defname);
-		}
-	}
-
-	/*
-	 * make sure we have our required definitions
-	 */
-	if (functionName == NULL)
-		elog(ERROR, "Define: \"procedure\" unspecified");
-
-	/* Transform type names to type OIDs */
-	if (typeName1)
-		typeId1 = typenameTypeId(typeName1);
-	if (typeName2)
-		typeId2 = typenameTypeId(typeName2);
-
-	/*
-	 * now have OperatorCreate do all the work..
-	 */
-	OperatorCreate(oprName,		/* operator name */
-				   typeId1,		/* left type id */
-				   typeId2,		/* right type id */
-				   functionName,	/* function for operator */
-				   precedence,	/* operator precedence */
-				   isLeftAssociative,	/* operator is left associative */
-				   commutatorName,		/* optional commutator operator
-										 * name */
-				   negatorName, /* optional negator operator name */
-				   restrictionName,		/* optional restrict. sel.
-										 * procedure */
-				   joinName,	/* optional join sel. procedure name */
-				   canHash,		/* operator hashes */
-				   sortName1,	/* optional first sort operator */
-				   sortName2);	/* optional second sort operator */
-
-}
-
-/*
- *	DefineAggregate
- */
-void
-DefineAggregate(List *names, List *parameters)
-{
-	char	   *aggName;
-	Oid			aggNamespace;
-	List	   *transfuncName = NIL;
-	List	   *finalfuncName = NIL;
-	TypeName   *baseType = NULL;
-	TypeName   *transType = NULL;
-	char	   *initval = NULL;
-	Oid			baseTypeId;
-	Oid			transTypeId;
-	List	   *pl;
-
-	/* Convert list of names to a name and namespace */
-	aggNamespace = QualifiedNameGetCreationNamespace(names, &aggName);
-
-	foreach(pl, parameters)
-	{
-		DefElem    *defel = (DefElem *) lfirst(pl);
-
-		/*
-		 * sfunc1, stype1, and initcond1 are accepted as obsolete
-		 * spellings for sfunc, stype, initcond.
-		 */
-		if (strcasecmp(defel->defname, "sfunc") == 0)
-			transfuncName = defGetQualifiedName(defel);
-		else if (strcasecmp(defel->defname, "sfunc1") == 0)
-			transfuncName = defGetQualifiedName(defel);
-		else if (strcasecmp(defel->defname, "finalfunc") == 0)
-			finalfuncName = defGetQualifiedName(defel);
-		else if (strcasecmp(defel->defname, "basetype") == 0)
-			baseType = defGetTypeName(defel);
-		else if (strcasecmp(defel->defname, "stype") == 0)
-			transType = defGetTypeName(defel);
-		else if (strcasecmp(defel->defname, "stype1") == 0)
-			transType = defGetTypeName(defel);
-		else if (strcasecmp(defel->defname, "initcond") == 0)
-			initval = defGetString(defel);
-		else if (strcasecmp(defel->defname, "initcond1") == 0)
-			initval = defGetString(defel);
-		else
-			elog(WARNING, "DefineAggregate: attribute \"%s\" not recognized",
-				 defel->defname);
-	}
-
-	/*
-	 * make sure we have our required definitions
-	 */
-	if (baseType == NULL)
-		elog(ERROR, "Define: \"basetype\" unspecified");
-	if (transType == NULL)
-		elog(ERROR, "Define: \"stype\" unspecified");
-	if (transfuncName == NIL)
-		elog(ERROR, "Define: \"sfunc\" unspecified");
-
-	/*
-	 * Handle the aggregate's base type (input data type).  This can be
-	 * specified as 'ANY' for a data-independent transition function, such
-	 * as COUNT(*).
-	 */
-	baseTypeId = LookupTypeName(baseType);
-	if (OidIsValid(baseTypeId))
-	{
-		/* no need to allow aggregates on as-yet-undefined types */
-		if (!get_typisdefined(baseTypeId))
-			elog(ERROR, "Type \"%s\" is only a shell",
-				 TypeNameToString(baseType));
-	}
-	else
-	{
-		char      *typnam = TypeNameToString(baseType);
-
-		if (strcasecmp(typnam, "ANY") != 0)
-			elog(ERROR, "Type \"%s\" does not exist", typnam);
-		baseTypeId = InvalidOid;
-	}
-
-	/* handle transtype --- no special cases here */
-	transTypeId = typenameTypeId(transType);
-
-	/*
-	 * Most of the argument-checking is done inside of AggregateCreate
-	 */
-	AggregateCreate(aggName,	/* aggregate name */
-					aggNamespace,	/* namespace */
-					transfuncName,		/* step function name */
-					finalfuncName,		/* final function name */
-					baseTypeId,	/* type of data being aggregated */
-					transTypeId,	/* transition data type */
-					initval);	/* initial condition */
-}
-
-/*
- * DefineDomain
- *		Registers a new domain.
- */
-void
-DefineDomain(CreateDomainStmt *stmt)
-{
-	char	   *domainName;
-	Oid			domainNamespace;
-	int16		internalLength;
-	int16		externalLength;
-	Oid			inputProcedure;
-	Oid			outputProcedure;
-	Oid			receiveProcedure;
-	Oid			sendProcedure;
-	bool		byValue;
-	char		delimiter;
-	char		alignment;
-	char		storage;
-	char		typtype;
-	Datum		datum;
-	bool		isnull;
-	char	   *defaultValue = NULL;
-	char	   *defaultValueBin = NULL;
-	bool		typNotNull = false;
-	Oid			basetypelem;
-	int32		typNDims = length(stmt->typename->arrayBounds);
-	HeapTuple	typeTup;
-	List	   *schema = stmt->constraints;
-	List	   *listptr;
-
-	/* Convert list of names to a name and namespace */
-	domainNamespace = QualifiedNameGetCreationNamespace(stmt->domainname,
-														&domainName);
-
-	/*
-	 * Domainnames, unlike typenames don't need to account for the '_'
-	 * prefix.  So they can be one character longer.
-	 */
-	if (strlen(domainName) > (NAMEDATALEN - 1))
-		elog(ERROR, "CREATE DOMAIN: domain names must be %d characters or less",
-			 NAMEDATALEN - 1);
-
-	/*
-	 * Look up the base type.
-	 */
-	typeTup = typenameType(stmt->typename);
-
-	/*
-	 * What we really don't want is domains of domains.  This could cause all sorts
-	 * of neat issues if we allow that.
-	 *
-	 * With testing, we may determine complex types should be allowed
-	 */
-	typtype = ((Form_pg_type) GETSTRUCT(typeTup))->typtype;
-	if (typtype != 'b')
-		elog(ERROR, "DefineDomain: %s is not a basetype",
-			 TypeNameToString(stmt->typename));
-
-	/* passed by value */
-	byValue = ((Form_pg_type) GETSTRUCT(typeTup))->typbyval;
-
-	/* Required Alignment */
-	alignment = ((Form_pg_type) GETSTRUCT(typeTup))->typalign;
-
-	/* TOAST Strategy */
-	storage = ((Form_pg_type) GETSTRUCT(typeTup))->typstorage;
-
-	/* Storage Length */
-	internalLength = ((Form_pg_type) GETSTRUCT(typeTup))->typlen;
-
-	/* External Length (unused) */
-	externalLength = ((Form_pg_type) GETSTRUCT(typeTup))->typprtlen;
-
-	/* Array element Delimiter */
-	delimiter = ((Form_pg_type) GETSTRUCT(typeTup))->typdelim;
-
-	/* I/O Functions */
-	inputProcedure = ((Form_pg_type) GETSTRUCT(typeTup))->typinput;
-	outputProcedure = ((Form_pg_type) GETSTRUCT(typeTup))->typoutput;
-	receiveProcedure = ((Form_pg_type) GETSTRUCT(typeTup))->typreceive;
-	sendProcedure = ((Form_pg_type) GETSTRUCT(typeTup))->typsend;
-
-	/* Inherited default value */
-	datum =	SysCacheGetAttr(TYPEOID, typeTup,
-							Anum_pg_type_typdefault, &isnull);
-	if (!isnull)
-		defaultValue = DatumGetCString(DirectFunctionCall1(textout, datum));
-
-	/* Inherited default binary value */
-	datum =	SysCacheGetAttr(TYPEOID, typeTup,
-							Anum_pg_type_typdefaultbin, &isnull);
-	if (!isnull)
-		defaultValueBin = DatumGetCString(DirectFunctionCall1(textout, datum));
-
-	/*
-	 * Pull out the typelem name of the parent OID.
-	 *
-	 * This is what enables us to make a domain of an array
-	 */
-	basetypelem = ((Form_pg_type) GETSTRUCT(typeTup))->typelem;
-
-	/*
-	 * Run through constraints manually to avoid the additional
-	 * processing conducted by DefineRelation() and friends.
-	 *
-	 * Besides, we don't want any constraints to be cooked.  We'll
-	 * do that when the table is created via MergeDomainAttributes().
-	 */
-	foreach(listptr, schema)
-	{
-		Constraint *colDef = lfirst(listptr);
-		bool nullDefined = false;
-		Node	   *expr;
-		ParseState *pstate;
-
-		switch (colDef->contype)
-		{
-			/*
-	 		 * The inherited default value may be overridden by the user
-			 * with the DEFAULT <expr> statement.
-			 *
-	 		 * We have to search the entire constraint tree returned as we
-			 * don't want to cook or fiddle too much.
-			 */
-			case CONSTR_DEFAULT:
-				/* Create a dummy ParseState for transformExpr */
-				pstate = make_parsestate(NULL);
-				/*
-				 * Cook the colDef->raw_expr into an expression.
-				 * Note: Name is strictly for error message
-				 */
-				expr = cookDefault(pstate, colDef->raw_expr,
-								   typeTup->t_data->t_oid,
-								   stmt->typename->typmod,
-								   domainName);
-				/*
-				 * Expression must be stored as a nodeToString result,
-				 * but we also require a valid textual representation
-				 * (mainly to make life easier for pg_dump).
-				 */
-				defaultValue = deparse_expression(expr,
-								deparse_context_for(domainName,
-													InvalidOid),
-												   false);
-				defaultValueBin = nodeToString(expr);
-				break;
-
-			/*
-			 * Find the NULL constraint.
-			 */
-			case CONSTR_NOTNULL:
-				if (nullDefined) {
-					elog(ERROR, "CREATE DOMAIN has conflicting NULL / NOT NULL constraint");
-				} else {
-					typNotNull = true;
-					nullDefined = true;
-				}
-		  		break;
-
-			case CONSTR_NULL:
-				if (nullDefined) {
-					elog(ERROR, "CREATE DOMAIN has conflicting NULL / NOT NULL constraint");
-				} else {
-					typNotNull = false;
-					nullDefined = true;
-				}
-		  		break;
-
-		  	case CONSTR_UNIQUE:
-		  		elog(ERROR, "CREATE DOMAIN / UNIQUE indexes not supported");
-		  		break;
-
-		  	case CONSTR_PRIMARY:
-		  		elog(ERROR, "CREATE DOMAIN / PRIMARY KEY indexes not supported");
-		  		break;
-
-		  	case CONSTR_CHECK:
-		  		elog(ERROR, "DefineDomain: CHECK Constraints not supported");
-		  		break;
-
-		  	case CONSTR_ATTR_DEFERRABLE:
-		  	case CONSTR_ATTR_NOT_DEFERRABLE:
-		  	case CONSTR_ATTR_DEFERRED:
-		  	case CONSTR_ATTR_IMMEDIATE:
-		  		elog(ERROR, "DefineDomain: DEFERRABLE, NON DEFERRABLE, DEFERRED and IMMEDIATE not supported");
-		  		break;
-
-			default:
-		  		elog(ERROR, "DefineDomain: unrecognized constraint node type");
-		  		break;
-		}
-	}
-
-	/*
-	 * Have TypeCreate do all the real work.
-	 */
-	TypeCreate(domainName,			/* type name */
-			   domainNamespace,		/* namespace */
-			   InvalidOid,			/* preassigned type oid (not done here) */
-			   InvalidOid,			/* relation oid (n/a here) */
-			   internalLength,		/* internal size */
-			   externalLength,		/* external size */
-			   'd',					/* type-type (domain type) */
-			   delimiter,			/* array element delimiter */
-			   inputProcedure,		/* input procedure */
-			   outputProcedure,		/* output procedure */
-			   receiveProcedure,	/* receive procedure */
-			   sendProcedure,		/* send procedure */
-			   basetypelem,			/* element type ID */
-			   typeTup->t_data->t_oid,	/* base type ID */
-			   defaultValue,		/* default type value (text) */
-			   defaultValueBin,		/* default type value (binary) */
-			   byValue,				/* passed by value */
-			   alignment,			/* required alignment */
-			   storage,				/* TOAST strategy */
-			   stmt->typename->typmod, /* typeMod value */
-			   typNDims,			/* Array dimensions for base type */
-			   typNotNull);			/* Type NOT NULL */
-
-	/*
-	 * Now we can clean up.
-	 */
-	ReleaseSysCache(typeTup);
-}
-
-/*
- * DefineType
- *		Registers a new type.
+ * Extract a string value (otherwise uninterpreted) from a DefElem.
  */
-void
-DefineType(List *names, List *parameters)
-{
-	char	   *typeName;
-	Oid			typeNamespace;
-	int16		internalLength = -1;	/* int2 */
-	int16		externalLength = -1;	/* int2 */
-	Oid			elemType = InvalidOid;
-	List	   *inputName = NIL;
-	List	   *outputName = NIL;
-	List	   *sendName = NIL;
-	List	   *receiveName = NIL;
-	char	   *defaultValue = NULL;
-	bool		byValue = false;
-	char		delimiter = DEFAULT_TYPDELIM;
-	char		alignment = 'i';	/* default alignment */
-	char		storage = 'p';	/* default TOAST storage method */
-	Oid			inputOid;
-	Oid			outputOid;
-	Oid			sendOid;
-	Oid			receiveOid;
-	char	   *shadow_type;
-	List	   *pl;
-	Oid			typoid;
-
-	/* Convert list of names to a name and namespace */
-	typeNamespace = QualifiedNameGetCreationNamespace(names, &typeName);
-
-	/*
-	 * Type names must be one character shorter than other names, allowing
-	 * room to create the corresponding array type name with prepended
-	 * "_".
-	 */
-	if (strlen(typeName) > (NAMEDATALEN - 2))
-		elog(ERROR, "DefineType: type names must be %d characters or less",
-			 NAMEDATALEN - 2);
-
-	foreach(pl, parameters)
-	{
-		DefElem    *defel = (DefElem *) lfirst(pl);
-
-		if (strcasecmp(defel->defname, "internallength") == 0)
-			internalLength = defGetTypeLength(defel);
-		else if (strcasecmp(defel->defname, "externallength") == 0)
-			externalLength = defGetTypeLength(defel);
-		else if (strcasecmp(defel->defname, "input") == 0)
-			inputName = defGetQualifiedName(defel);
-		else if (strcasecmp(defel->defname, "output") == 0)
-			outputName = defGetQualifiedName(defel);
-		else if (strcasecmp(defel->defname, "send") == 0)
-			sendName = defGetQualifiedName(defel);
-		else if (strcasecmp(defel->defname, "receive") == 0)
-			receiveName = defGetQualifiedName(defel);
-		else if (strcasecmp(defel->defname, "delimiter") == 0)
-		{
-			char	   *p = defGetString(defel);
-
-			delimiter = p[0];
-		}
-		else if (strcasecmp(defel->defname, "element") == 0)
-			elemType = typenameTypeId(defGetTypeName(defel));
-		else if (strcasecmp(defel->defname, "default") == 0)
-			defaultValue = defGetString(defel);
-		else if (strcasecmp(defel->defname, "passedbyvalue") == 0)
-			byValue = true;
-		else if (strcasecmp(defel->defname, "alignment") == 0)
-		{
-			char	   *a = defGetString(defel);
-
-			/*
-			 * Note: if argument was an unquoted identifier, parser will
-			 * have applied xlateSqlType() to it, so be prepared to
-			 * recognize translated type names as well as the nominal
-			 * form.
-			 */
-			if (strcasecmp(a, "double") == 0)
-				alignment = 'd';
-			else if (strcasecmp(a, "float8") == 0)
-				alignment = 'd';
-			else if (strcasecmp(a, "int4") == 0)
-				alignment = 'i';
-			else if (strcasecmp(a, "int2") == 0)
-				alignment = 's';
-			else if (strcasecmp(a, "char") == 0)
-				alignment = 'c';
-			else if (strcasecmp(a, "bpchar") == 0)
-				alignment = 'c';
-			else
-				elog(ERROR, "DefineType: \"%s\" alignment not recognized",
-					 a);
-		}
-		else if (strcasecmp(defel->defname, "storage") == 0)
-		{
-			char	   *a = defGetString(defel);
-
-			if (strcasecmp(a, "plain") == 0)
-				storage = 'p';
-			else if (strcasecmp(a, "external") == 0)
-				storage = 'e';
-			else if (strcasecmp(a, "extended") == 0)
-				storage = 'x';
-			else if (strcasecmp(a, "main") == 0)
-				storage = 'm';
-			else
-				elog(ERROR, "DefineType: \"%s\" storage not recognized",
-					 a);
-		}
-		else
-		{
-			elog(WARNING, "DefineType: attribute \"%s\" not recognized",
-				 defel->defname);
-		}
-	}
-
-	/*
-	 * make sure we have our required definitions
-	 */
-	if (inputName == NIL)
-		elog(ERROR, "Define: \"input\" unspecified");
-	if (outputName == NIL)
-		elog(ERROR, "Define: \"output\" unspecified");
-
-	/* Convert I/O proc names to OIDs */
-	inputOid = findTypeIOFunction(inputName, false);
-	outputOid = findTypeIOFunction(outputName, true);
-	if (sendName)
-		sendOid = findTypeIOFunction(sendName, true);
-	else
-		sendOid = outputOid;
-	if (receiveName)
-		receiveOid = findTypeIOFunction(receiveName, false);
-	else
-		receiveOid = inputOid;
-
-	/*
-	 * now have TypeCreate do all the real work.
-	 */
-	typoid =
-		TypeCreate(typeName,		/* type name */
-				   typeNamespace,	/* namespace */
-				   InvalidOid,		/* preassigned type oid (not done here) */
-				   InvalidOid,		/* relation oid (n/a here) */
-				   internalLength,	/* internal size */
-				   externalLength,	/* external size */
-				   'b',				/* type-type (base type) */
-				   delimiter,		/* array element delimiter */
-				   inputOid,		/* input procedure */
-				   outputOid,		/* output procedure */
-				   receiveOid,		/* receive procedure */
-				   sendOid,			/* send procedure */
-				   elemType,		/* element type ID */
-				   InvalidOid,		/* base type ID (only for domains) */
-				   defaultValue,	/* default type value */
-				   NULL,			/* no binary form available */
-				   byValue,			/* passed by value */
-				   alignment,		/* required alignment */
-				   storage,			/* TOAST strategy */
-				   -1,				/* typMod (Domains only) */
-				   0,				/* Array Dimensions of typbasetype */
-				   false);			/* Type NOT NULL */
-
-	/*
-	 * When we create a base type (as opposed to a complex type) we need
-	 * to have an array entry for it in pg_type as well.
-	 */
-	shadow_type = makeArrayTypeName(typeName);
-
-	/* alignment must be 'i' or 'd' for arrays */
-	alignment = (alignment == 'd') ? 'd' : 'i';
-
-	TypeCreate(shadow_type,		/* type name */
-			   typeNamespace,	/* namespace */
-			   InvalidOid,		/* preassigned type oid (not done here) */
-			   InvalidOid,		/* relation oid (n/a here) */
-			   -1,				/* internal size */
-			   -1,				/* external size */
-			   'b',				/* type-type (base type) */
-			   DEFAULT_TYPDELIM,	/* array element delimiter */
-			   F_ARRAY_IN,		/* input procedure */
-			   F_ARRAY_OUT,		/* output procedure */
-			   F_ARRAY_IN,		/* receive procedure */
-			   F_ARRAY_OUT,		/* send procedure */
-			   typoid,			/* element type ID */
-			   InvalidOid,		/* base type ID */
-			   NULL,			/* never a default type value */
-			   NULL,			/* binary default isn't sent either */
-			   false,			/* never passed by value */
-			   alignment,		/* see above */
-			   'x',				/* ARRAY is always toastable */
-			   -1,				/* typMod (Domains only) */
-			   0,				/* Array dimensions of typbasetype */
-			   false);			/* Type NOT NULL */
-
-	pfree(shadow_type);
-}
-
-static Oid
-findTypeIOFunction(List *procname, bool isOutput)
-{
-	Oid			argList[FUNC_MAX_ARGS];
-	int			nargs;
-	Oid			procOid;
-
-	/*
-	 * First look for a 1-argument func with all argtypes 0. This is
-	 * valid for all kinds of procedure.
-	 */
-	MemSet(argList, 0, FUNC_MAX_ARGS * sizeof(Oid));
-
-	procOid = LookupFuncName(procname, 1, argList);
-
-	if (!OidIsValid(procOid))
-	{
-		/*
-		 * Alternatively, input procedures may take 3 args (data
-		 * value, element OID, atttypmod); the pg_proc argtype
-		 * signature is 0,OIDOID,INT4OID.  Output procedures may
-		 * take 2 args (data value, element OID).
-		 */
-		if (isOutput)
-		{
-			/* output proc */
-			nargs = 2;
-			argList[1] = OIDOID;
-		}
-		else
-		{
-			/* input proc */
-			nargs = 3;
-			argList[1] = OIDOID;
-			argList[2] = INT4OID;
-		}
-		procOid = LookupFuncName(procname, nargs, argList);
-
-		if (!OidIsValid(procOid))
-			func_error("TypeCreate", procname, 1, argList, NULL);
-	}
-
-	return procOid;
-}
-
-
-static char *
+char *
 defGetString(DefElem *def)
 {
 	if (def->arg == NULL)
@@ -1133,7 +92,10 @@ defGetString(DefElem *def)
 	return NULL;				/* keep compiler quiet */
 }
 
-static double
+/*
+ * Extract a numeric value (actually double) from a DefElem.
+ */
+double
 defGetNumeric(DefElem *def)
 {
 	if (def->arg == NULL)
@@ -1152,7 +114,10 @@ defGetNumeric(DefElem *def)
 	return 0;					/* keep compiler quiet */
 }
 
-static List *
+/*
+ * Extract a possibly-qualified name (as a List of Strings) from a DefElem.
+ */
+List *
 defGetQualifiedName(DefElem *def)
 {
 	if (def->arg == NULL)
@@ -1172,7 +137,10 @@ defGetQualifiedName(DefElem *def)
 	return NIL;					/* keep compiler quiet */
 }
 
-static TypeName *
+/*
+ * Extract a TypeName from a DefElem.
+ */
+TypeName *
 defGetTypeName(DefElem *def)
 {
 	if (def->arg == NULL)
@@ -1198,7 +166,11 @@ defGetTypeName(DefElem *def)
 	return NULL;				/* keep compiler quiet */
 }
 
-static int
+/*
+ * Extract a type length indicator (either absolute bytes, or
+ * -1 for "variable") from a DefElem.
+ */
+int
 defGetTypeLength(DefElem *def)
 {
 	if (def->arg == NULL)
diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c
new file mode 100644
index 0000000000000000000000000000000000000000..0bee7cdced1c55db71b2a781b347829b51c47db7
--- /dev/null
+++ b/src/backend/commands/functioncmds.c
@@ -0,0 +1,431 @@
+/*-------------------------------------------------------------------------
+ *
+ * functioncmds.c
+ *
+ *	  Routines for CREATE and DROP FUNCTION commands
+ *
+ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/functioncmds.c,v 1.1 2002/04/15 05:22:03 tgl Exp $
+ *
+ * DESCRIPTION
+ *	  These routines take the parse tree and pick out the
+ *	  appropriate arguments/flags, and pass the results to the
+ *	  corresponding "FooDefine" routines (in src/catalog) that do
+ *	  the actual catalog-munging.  These routines also verify permission
+ *	  of the user to execute the command.
+ *
+ * NOTES
+ *	  These things must be defined and committed in the following order:
+ *		"create function":
+ *				input/output, recv/send procedures
+ *		"create type":
+ *				type
+ *		"create operator":
+ *				operators
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "access/heapam.h"
+#include "catalog/catname.h"
+#include "catalog/namespace.h"
+#include "catalog/pg_language.h"
+#include "catalog/pg_proc.h"
+#include "catalog/pg_type.h"
+#include "commands/comment.h"
+#include "commands/defrem.h"
+#include "miscadmin.h"
+#include "optimizer/cost.h"
+#include "parser/parse_func.h"
+#include "parser/parse_type.h"
+#include "utils/acl.h"
+#include "utils/lsyscache.h"
+#include "utils/syscache.h"
+
+
+/*
+ *	 Examine the "returns" clause returnType of the CREATE FUNCTION statement
+ *	 and return information about it as *prorettype_p and *returnsSet.
+ *
+ * This is more complex than the average typename lookup because we want to
+ * allow a shell type to be used, or even created if the specified return type
+ * doesn't exist yet.  (Without this, there's no way to define the I/O procs
+ * for a new type.)  But SQL function creation won't cope, so error out if
+ * the target language is SQL.
+ */
+static void
+compute_return_type(TypeName *returnType, Oid languageOid,
+					Oid *prorettype_p, bool *returnsSet_p)
+{
+	Oid		rettype;
+
+	rettype = LookupTypeName(returnType);
+
+	if (OidIsValid(rettype))
+	{
+		if (!get_typisdefined(rettype))
+		{
+			if (languageOid == SQLlanguageId)
+				elog(ERROR, "SQL functions cannot return shell types");
+			else
+				elog(WARNING, "Return type \"%s\" is only a shell",
+					 TypeNameToString(returnType));
+		}
+	}
+	else
+	{
+		char      *typnam = TypeNameToString(returnType);
+
+		if (strcmp(typnam, "opaque") == 0)
+			rettype = InvalidOid;
+		else
+		{
+			Oid			namespaceId;
+			char	   *typname;
+
+			if (languageOid == SQLlanguageId)
+				elog(ERROR, "Type \"%s\" does not exist", typnam);
+			elog(WARNING, "ProcedureCreate: type %s is not yet defined",
+				 typnam);
+			namespaceId = QualifiedNameGetCreationNamespace(returnType->names,
+															&typname);
+			rettype = TypeShellMake(typname, namespaceId);
+			if (!OidIsValid(rettype))
+				elog(ERROR, "could not create type %s", typnam);
+		}
+	}
+
+	*prorettype_p = rettype;
+	*returnsSet_p = returnType->setof;
+}
+
+/*
+ * Interpret the argument-types list of the CREATE FUNCTION statement.
+ */
+static int
+compute_parameter_types(List *argTypes, Oid languageOid,
+						Oid *parameterTypes)
+{
+	int			parameterCount = 0;
+	List	   *x;
+
+	MemSet(parameterTypes, 0, FUNC_MAX_ARGS * sizeof(Oid));
+	foreach(x, argTypes)
+	{
+		TypeName   *t = (TypeName *) lfirst(x);
+		Oid			toid;
+
+		if (parameterCount >= FUNC_MAX_ARGS)
+			elog(ERROR, "functions cannot have more than %d arguments",
+				 FUNC_MAX_ARGS);
+
+		toid = LookupTypeName(t);
+		if (OidIsValid(toid))
+		{
+			if (!get_typisdefined(toid))
+				elog(WARNING, "Argument type \"%s\" is only a shell",
+					 TypeNameToString(t));
+		}
+		else
+		{
+			char      *typnam = TypeNameToString(t);
+
+			if (strcmp(typnam, "opaque") == 0)
+			{
+				if (languageOid == SQLlanguageId)
+					elog(ERROR, "SQL functions cannot have arguments of type \"opaque\"");
+				toid = InvalidOid;
+			}
+			else
+				elog(ERROR, "Type \"%s\" does not exist", typnam);
+		}
+
+		if (t->setof)
+			elog(ERROR, "functions cannot accept set arguments");
+
+		parameterTypes[parameterCount++] = toid;
+	}
+
+	return parameterCount;
+}
+
+/*-------------
+ *	 Interpret the parameters *parameters and return their contents as
+ *	 *byte_pct_p, etc.
+ *
+ *	These parameters supply optional information about a function.
+ *	All have defaults if not specified.
+ *
+ *	Note: currently, only three of these parameters actually do anything:
+ *
+ *	 * isImplicit means the function may be used as an implicit type
+ *	   coercion.
+ *
+ *	 * isStrict means the function should not be called when any NULL
+ *	   inputs are present; instead a NULL result value should be assumed.
+ *
+ *	 * volatility tells the optimizer whether the function's result can
+ *	   be assumed to be repeatable over multiple evaluations.
+ *
+ *	The other four parameters are not used anywhere.	They used to be
+ *	used in the "expensive functions" optimizer, but that's been dead code
+ *	for a long time.
+ *------------
+ */
+static void
+compute_full_attributes(List *parameters,
+						int32 *byte_pct_p, int32 *perbyte_cpu_p,
+						int32 *percall_cpu_p, int32 *outin_ratio_p,
+						bool *isImplicit_p, bool *isStrict_p,
+						char *volatility_p)
+{
+	List	   *pl;
+
+	/* the defaults */
+	*byte_pct_p = BYTE_PCT;
+	*perbyte_cpu_p = PERBYTE_CPU;
+	*percall_cpu_p = PERCALL_CPU;
+	*outin_ratio_p = OUTIN_RATIO;
+	*isImplicit_p = false;
+	*isStrict_p = false;
+	*volatility_p = PROVOLATILE_VOLATILE;
+
+	foreach(pl, parameters)
+	{
+		DefElem    *param = (DefElem *) lfirst(pl);
+
+		if (strcasecmp(param->defname, "implicitcoercion") == 0)
+			*isImplicit_p = true;
+		else if (strcasecmp(param->defname, "isstrict") == 0)
+			*isStrict_p = true;
+		else if (strcasecmp(param->defname, "isimmutable") == 0)
+			*volatility_p = PROVOLATILE_IMMUTABLE;
+		else if (strcasecmp(param->defname, "isstable") == 0)
+			*volatility_p = PROVOLATILE_STABLE;
+		else if (strcasecmp(param->defname, "isvolatile") == 0)
+			*volatility_p = PROVOLATILE_VOLATILE;
+		else if (strcasecmp(param->defname, "iscachable") == 0)
+		{
+			/* obsolete spelling of isImmutable */
+			*volatility_p = PROVOLATILE_IMMUTABLE;
+		}
+		else if (strcasecmp(param->defname, "trusted") == 0)
+		{
+			/*
+			 * we don't have untrusted functions any more. The 4.2
+			 * implementation is lousy anyway so I took it out. -ay 10/94
+			 */
+			elog(ERROR, "untrusted function has been decommissioned.");
+		}
+		else if (strcasecmp(param->defname, "byte_pct") == 0)
+			*byte_pct_p = (int) defGetNumeric(param);
+		else if (strcasecmp(param->defname, "perbyte_cpu") == 0)
+			*perbyte_cpu_p = (int) defGetNumeric(param);
+		else if (strcasecmp(param->defname, "percall_cpu") == 0)
+			*percall_cpu_p = (int) defGetNumeric(param);
+		else if (strcasecmp(param->defname, "outin_ratio") == 0)
+			*outin_ratio_p = (int) defGetNumeric(param);
+		else
+			elog(WARNING, "Unrecognized function attribute '%s' ignored",
+				 param->defname);
+	}
+}
+
+
+/*
+ * For a dynamically linked C language object, the form of the clause is
+ *
+ *	   AS <object file name> [, <link symbol name> ]
+ *
+ * In all other cases
+ *
+ *	   AS <object reference, or sql code>
+ *
+ */
+
+static void
+interpret_AS_clause(Oid languageOid, const char *languageName, const List *as,
+					char **prosrc_str_p, char **probin_str_p)
+{
+	Assert(as != NIL);
+
+	if (languageOid == ClanguageId)
+	{
+		/*
+		 * For "C" language, store the file name in probin and, when
+		 * given, the link symbol name in prosrc.
+		 */
+		*probin_str_p = strVal(lfirst(as));
+		if (lnext(as) == NULL)
+			*prosrc_str_p = "-";
+		else
+			*prosrc_str_p = strVal(lsecond(as));
+	}
+	else
+	{
+		/* Everything else wants the given string in prosrc. */
+		*prosrc_str_p = strVal(lfirst(as));
+		*probin_str_p = "-";
+
+		if (lnext(as) != NIL)
+			elog(ERROR, "CREATE FUNCTION: only one AS item needed for %s language",
+				 languageName);
+	}
+}
+
+
+
+/*
+ * CreateFunction
+ *	 Execute a CREATE FUNCTION utility statement.
+ */
+void
+CreateFunction(ProcedureStmt *stmt)
+{
+	char	   *probin_str;
+	char	   *prosrc_str;
+	Oid			prorettype;
+	bool		returnsSet;
+	char		languageName[NAMEDATALEN];
+	Oid			languageOid;
+	char	   *funcname;
+	Oid			namespaceId;
+	int			parameterCount;
+	Oid			parameterTypes[FUNC_MAX_ARGS];
+	int32		byte_pct,
+				perbyte_cpu,
+				percall_cpu,
+				outin_ratio;
+	bool		isImplicit,
+				isStrict;
+	char		volatility;
+	HeapTuple	languageTuple;
+	Form_pg_language languageStruct;
+
+	/* Convert list of names to a name and namespace */
+	namespaceId = QualifiedNameGetCreationNamespace(stmt->funcname,
+													&funcname);
+
+	/* Convert language name to canonical case */
+	case_translate_language_name(stmt->language, languageName);
+
+	/* Look up the language and validate permissions */
+	languageTuple = SearchSysCache(LANGNAME,
+								   PointerGetDatum(languageName),
+								   0, 0, 0);
+	if (!HeapTupleIsValid(languageTuple))
+		elog(ERROR, "language \"%s\" does not exist", languageName);
+
+	languageOid = languageTuple->t_data->t_oid;
+	languageStruct = (Form_pg_language) GETSTRUCT(languageTuple);
+
+	if (!((languageStruct->lanpltrusted
+		   && pg_language_aclcheck(languageOid, GetUserId()) == ACLCHECK_OK)
+		  || superuser()))
+		elog(ERROR, "permission denied");
+
+	ReleaseSysCache(languageTuple);
+
+	/*
+	 * Convert remaining parameters of CREATE to form wanted by
+	 * ProcedureCreate.
+	 */
+	compute_return_type(stmt->returnType, languageOid,
+						&prorettype, &returnsSet);
+
+	parameterCount = compute_parameter_types(stmt->argTypes, languageOid,
+											 parameterTypes);
+
+	compute_full_attributes(stmt->withClause,
+							&byte_pct, &perbyte_cpu, &percall_cpu,
+							&outin_ratio, &isImplicit, &isStrict,
+							&volatility);
+
+	interpret_AS_clause(languageOid, languageName, stmt->as,
+						&prosrc_str, &probin_str);
+
+	/*
+	 * And now that we have all the parameters, and know we're permitted
+	 * to do so, go ahead and create the function.
+	 */
+	ProcedureCreate(funcname,
+					namespaceId,
+					stmt->replace,
+					returnsSet,
+					prorettype,
+					languageOid,
+					prosrc_str, /* converted to text later */
+					probin_str, /* converted to text later */
+					false,		/* not an aggregate */
+					true,		/* (obsolete "trusted") */
+					isImplicit,
+					isStrict,
+					volatility,
+					byte_pct,
+					perbyte_cpu,
+					percall_cpu,
+					outin_ratio,
+					parameterCount,
+					parameterTypes);
+}
+
+
+/*
+ * RemoveFunction
+ *		Deletes a function.
+ *
+ * Exceptions:
+ *		BadArg if name is invalid.
+ *		"ERROR" if function nonexistent.
+ *		...
+ */
+void
+RemoveFunction(List *functionName,		/* function name to be removed */
+			   List *argTypes)	/* list of TypeName nodes */
+{
+	Oid			funcOid;
+	Relation	relation;
+	HeapTuple	tup;
+
+	funcOid = LookupFuncNameTypeNames(functionName, argTypes, 
+									  true, "RemoveFunction");
+
+	relation = heap_openr(ProcedureRelationName, RowExclusiveLock);
+
+	tup = SearchSysCache(PROCOID,
+						 ObjectIdGetDatum(funcOid),
+						 0, 0, 0);
+	if (!HeapTupleIsValid(tup))	/* should not happen */
+		elog(ERROR, "RemoveFunction: couldn't find tuple for function %s",
+			 NameListToString(functionName));
+
+	if (!pg_proc_ownercheck(funcOid, GetUserId()))
+		elog(ERROR, "RemoveFunction: function '%s': permission denied",
+			 NameListToString(functionName));
+
+	if (((Form_pg_proc) GETSTRUCT(tup))->proisagg)
+		elog(ERROR, "RemoveFunction: function '%s' is an aggregate"
+			 "\n\tUse DROP AGGREGATE to remove it",
+			 NameListToString(functionName));
+
+	if (((Form_pg_proc) GETSTRUCT(tup))->prolang == INTERNALlanguageId)
+	{
+		/* "Helpful" WARNING when removing a builtin function ... */
+		elog(WARNING, "Removing built-in function \"%s\"",
+			 NameListToString(functionName));
+	}
+
+	/* Delete any comments associated with this function */
+	DeleteComments(funcOid, RelationGetRelid(relation));
+
+	simple_heap_delete(relation, &tup->t_self);
+
+	ReleaseSysCache(tup);
+
+	heap_close(relation, RowExclusiveLock);
+}
diff --git a/src/backend/commands/lockcmds.c b/src/backend/commands/lockcmds.c
new file mode 100644
index 0000000000000000000000000000000000000000..c91669572ef4a989904cf195bca1e87a140f0f8a
--- /dev/null
+++ b/src/backend/commands/lockcmds.c
@@ -0,0 +1,69 @@
+/*-------------------------------------------------------------------------
+ *
+ * lockcmds.c
+ *	  Lock command support code
+ *
+ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/lockcmds.c,v 1.1 2002/04/15 05:22:03 tgl Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "access/heapam.h"
+#include "catalog/namespace.h"
+#include "commands/lockcmds.h"
+#include "miscadmin.h"
+#include "utils/acl.h"
+
+
+/*
+ * LOCK TABLE
+ */
+void
+LockTableCommand(LockStmt *lockstmt)
+{
+	List	   *p;
+
+	/*
+	 * Iterate over the list and open, lock, and close the relations one
+	 * at a time
+	 */
+
+	foreach(p, lockstmt->relations)
+	{
+		RangeVar   *relation = lfirst(p);
+		Oid			reloid;
+		int32		aclresult;
+		Relation	rel;
+
+		/*
+		 * We don't want to open the relation until we've checked privilege.
+		 * So, manually get the relation OID.
+		 */
+		reloid = RangeVarGetRelid(relation, false);
+
+		if (lockstmt->mode == AccessShareLock)
+			aclresult = pg_class_aclcheck(reloid, GetUserId(),
+										  ACL_SELECT);
+		else
+			aclresult = pg_class_aclcheck(reloid, GetUserId(),
+										  ACL_UPDATE | ACL_DELETE);
+
+		if (aclresult != ACLCHECK_OK)
+			elog(ERROR, "LOCK TABLE: permission denied");
+
+		rel = relation_open(reloid, lockstmt->mode);
+
+		/* Currently, we only allow plain tables to be locked */
+		if (rel->rd_rel->relkind != RELKIND_RELATION)
+			elog(ERROR, "LOCK TABLE: %s is not a table",
+				 relation->relname);
+
+		relation_close(rel, NoLock);	/* close rel, keep lock */
+	}
+}
diff --git a/src/backend/commands/operatorcmds.c b/src/backend/commands/operatorcmds.c
new file mode 100644
index 0000000000000000000000000000000000000000..54f48928b41e631726d9868411dae3aa13d14fd2
--- /dev/null
+++ b/src/backend/commands/operatorcmds.c
@@ -0,0 +1,247 @@
+/*-------------------------------------------------------------------------
+ *
+ * operatorcmds.c
+ *
+ *	  Routines for operator manipulation commands
+ *
+ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/operatorcmds.c,v 1.1 2002/04/15 05:22:03 tgl Exp $
+ *
+ * DESCRIPTION
+ *	  The "DefineFoo" routines take the parse tree and pick out the
+ *	  appropriate arguments/flags, passing the results to the
+ *	  corresponding "FooDefine" routines (in src/catalog) that do
+ *	  the actual catalog-munging.  These routines also verify permission
+ *	  of the user to execute the command.
+ *
+ * NOTES
+ *	  These things must be defined and committed in the following order:
+ *		"create function":
+ *				input/output, recv/send procedures
+ *		"create type":
+ *				type
+ *		"create operator":
+ *				operators
+ *
+ *		Most of the parse-tree manipulation routines are defined in
+ *		commands/manip.c.
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "access/heapam.h"
+#include "catalog/catname.h"
+#include "catalog/namespace.h"
+#include "catalog/pg_operator.h"
+#include "commands/comment.h"
+#include "commands/defrem.h"
+#include "miscadmin.h"
+#include "parser/parse_type.h"
+#include "utils/acl.h"
+#include "utils/syscache.h"
+
+
+/*
+ * DefineOperator
+ *		this function extracts all the information from the
+ *		parameter list generated by the parser and then has
+ *		OperatorCreate() do all the actual work.
+ *
+ * 'parameters' is a list of DefElem
+ */
+void
+DefineOperator(List *names, List *parameters)
+{
+	char	   *oprName;
+	Oid			oprNamespace;
+	uint16		precedence = 0; /* operator precedence */
+	bool		canHash = false;	/* operator hashes */
+	bool		isLeftAssociative = true;		/* operator is left
+												 * associative */
+	char	   *functionName = NULL;	/* function for operator */
+	TypeName   *typeName1 = NULL;		/* first type name */
+	TypeName   *typeName2 = NULL;		/* second type name */
+	Oid			typeId1 = InvalidOid;	/* types converted to OID */
+	Oid			typeId2 = InvalidOid;
+	char	   *commutatorName = NULL;	/* optional commutator operator
+										 * name */
+	char	   *negatorName = NULL;		/* optional negator operator name */
+	char	   *restrictionName = NULL; /* optional restrict. sel.
+										 * procedure */
+	char	   *joinName = NULL;	/* optional join sel. procedure name */
+	char	   *sortName1 = NULL;		/* optional first sort operator */
+	char	   *sortName2 = NULL;		/* optional second sort operator */
+	List	   *pl;
+
+	/* Convert list of names to a name and namespace */
+	oprNamespace = QualifiedNameGetCreationNamespace(names, &oprName);
+
+	/*
+	 * loop over the definition list and extract the information we need.
+	 */
+	foreach(pl, parameters)
+	{
+		DefElem    *defel = (DefElem *) lfirst(pl);
+
+		if (strcasecmp(defel->defname, "leftarg") == 0)
+		{
+			typeName1 = defGetTypeName(defel);
+			if (typeName1->setof)
+				elog(ERROR, "setof type not implemented for leftarg");
+		}
+		else if (strcasecmp(defel->defname, "rightarg") == 0)
+		{
+			typeName2 = defGetTypeName(defel);
+			if (typeName2->setof)
+				elog(ERROR, "setof type not implemented for rightarg");
+		}
+		else if (strcasecmp(defel->defname, "procedure") == 0)
+			functionName = defGetString(defel);
+		else if (strcasecmp(defel->defname, "precedence") == 0)
+		{
+			/* NOT IMPLEMENTED (never worked in v4.2) */
+			elog(NOTICE, "CREATE OPERATOR: precedence not implemented");
+		}
+		else if (strcasecmp(defel->defname, "associativity") == 0)
+		{
+			/* NOT IMPLEMENTED (never worked in v4.2) */
+			elog(NOTICE, "CREATE OPERATOR: associativity not implemented");
+		}
+		else if (strcasecmp(defel->defname, "commutator") == 0)
+			commutatorName = defGetString(defel);
+		else if (strcasecmp(defel->defname, "negator") == 0)
+			negatorName = defGetString(defel);
+		else if (strcasecmp(defel->defname, "restrict") == 0)
+			restrictionName = defGetString(defel);
+		else if (strcasecmp(defel->defname, "join") == 0)
+			joinName = defGetString(defel);
+		else if (strcasecmp(defel->defname, "hashes") == 0)
+			canHash = TRUE;
+		else if (strcasecmp(defel->defname, "sort1") == 0)
+			sortName1 = defGetString(defel);
+		else if (strcasecmp(defel->defname, "sort2") == 0)
+			sortName2 = defGetString(defel);
+		else
+		{
+			elog(WARNING, "DefineOperator: attribute \"%s\" not recognized",
+				 defel->defname);
+		}
+	}
+
+	/*
+	 * make sure we have our required definitions
+	 */
+	if (functionName == NULL)
+		elog(ERROR, "Define: \"procedure\" unspecified");
+
+	/* Transform type names to type OIDs */
+	if (typeName1)
+		typeId1 = typenameTypeId(typeName1);
+	if (typeName2)
+		typeId2 = typenameTypeId(typeName2);
+
+	/*
+	 * now have OperatorCreate do all the work..
+	 */
+	OperatorCreate(oprName,		/* operator name */
+				   typeId1,		/* left type id */
+				   typeId2,		/* right type id */
+				   functionName,	/* function for operator */
+				   precedence,	/* operator precedence */
+				   isLeftAssociative,	/* operator is left associative */
+				   commutatorName,		/* optional commutator operator
+										 * name */
+				   negatorName, /* optional negator operator name */
+				   restrictionName,		/* optional restrict. sel.
+										 * procedure */
+				   joinName,	/* optional join sel. procedure name */
+				   canHash,		/* operator hashes */
+				   sortName1,	/* optional first sort operator */
+				   sortName2);	/* optional second sort operator */
+
+}
+
+
+/*
+ * RemoveOperator
+ *		Deletes an operator.
+ *
+ * Exceptions:
+ *		BadArg if name is invalid.
+ *		BadArg if type1 is invalid.
+ *		"ERROR" if operator nonexistent.
+ *		...
+ */
+void
+RemoveOperator(char *operatorName,		/* operator name */
+			   TypeName *typeName1, /* left argument type name */
+			   TypeName *typeName2) /* right argument type name */
+{
+	Relation	relation;
+	HeapTuple	tup;
+	Oid			typeId1 = InvalidOid;
+	Oid			typeId2 = InvalidOid;
+	char		oprtype;
+
+	if (typeName1)
+		typeId1 = typenameTypeId(typeName1);
+
+	if (typeName2)
+		typeId2 = typenameTypeId(typeName2);
+
+	if (OidIsValid(typeId1) && OidIsValid(typeId2))
+		oprtype = 'b';
+	else if (OidIsValid(typeId1))
+		oprtype = 'r';
+	else
+		oprtype = 'l';
+
+	relation = heap_openr(OperatorRelationName, RowExclusiveLock);
+
+	tup = SearchSysCacheCopy(OPERNAME,
+							 PointerGetDatum(operatorName),
+							 ObjectIdGetDatum(typeId1),
+							 ObjectIdGetDatum(typeId2),
+							 CharGetDatum(oprtype));
+
+	if (HeapTupleIsValid(tup))
+	{
+		if (!pg_oper_ownercheck(tup->t_data->t_oid, GetUserId()))
+			elog(ERROR, "RemoveOperator: operator '%s': permission denied",
+				 operatorName);
+
+		/* Delete any comments associated with this operator */
+		DeleteComments(tup->t_data->t_oid, RelationGetRelid(relation));
+
+		simple_heap_delete(relation, &tup->t_self);
+	}
+	else
+	{
+		if (OidIsValid(typeId1) && OidIsValid(typeId2))
+		{
+			elog(ERROR, "RemoveOperator: binary operator '%s' taking '%s' and '%s' does not exist",
+				 operatorName,
+				 TypeNameToString(typeName1),
+				 TypeNameToString(typeName2));
+		}
+		else if (OidIsValid(typeId1))
+		{
+			elog(ERROR, "RemoveOperator: right unary operator '%s' taking '%s' does not exist",
+				 operatorName,
+				 TypeNameToString(typeName1));
+		}
+		else
+		{
+			elog(ERROR, "RemoveOperator: left unary operator '%s' taking '%s' does not exist",
+				 operatorName,
+				 TypeNameToString(typeName2));
+		}
+	}
+	heap_freetuple(tup);
+	heap_close(relation, RowExclusiveLock);
+}
diff --git a/src/backend/commands/portalcmds.c b/src/backend/commands/portalcmds.c
new file mode 100644
index 0000000000000000000000000000000000000000..6f690c0927ce5357fff37439f83f6aaa081c72b8
--- /dev/null
+++ b/src/backend/commands/portalcmds.c
@@ -0,0 +1,234 @@
+/*-------------------------------------------------------------------------
+ *
+ * portalcmds.c
+ *	  portal support code
+ *
+ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/portalcmds.c,v 1.1 2002/04/15 05:22:03 tgl Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "postgres.h"
+
+#include "commands/portalcmds.h"
+#include "executor/executor.h"
+
+
+/*
+ * PortalCleanup
+ */
+void
+PortalCleanup(Portal portal)
+{
+	MemoryContext oldcontext;
+
+	/*
+	 * sanity checks
+	 */
+	AssertArg(PortalIsValid(portal));
+	AssertArg(portal->cleanup == PortalCleanup);
+
+	/*
+	 * set proper portal-executor context before calling ExecMain.
+	 */
+	oldcontext = MemoryContextSwitchTo(PortalGetHeapMemory(portal));
+
+	/*
+	 * tell the executor to shutdown the query
+	 */
+	ExecutorEnd(PortalGetQueryDesc(portal), PortalGetState(portal));
+
+	/*
+	 * switch back to previous context
+	 */
+	MemoryContextSwitchTo(oldcontext);
+}
+
+
+/*
+ * PerformPortalFetch
+ *
+ *	name: name of portal
+ *	forward: forward or backward fetch?
+ *	count: # of tuples to fetch (0 implies all)
+ *	dest: where to send results
+ *	completionTag: points to a buffer of size COMPLETION_TAG_BUFSIZE
+ *		in which to store a command completion status string.
+ *
+ * completionTag may be NULL if caller doesn't want a status string.
+ */
+void
+PerformPortalFetch(char *name,
+				   bool forward,
+				   int count,
+				   CommandDest dest,
+				   char *completionTag)
+{
+	Portal		portal;
+	QueryDesc  *queryDesc;
+	EState	   *estate;
+	MemoryContext oldcontext;
+	ScanDirection direction;
+	CommandId	savedId;
+	bool		temp_desc = false;
+
+	/* initialize completion status in case of early exit */
+	if (completionTag)
+		strcpy(completionTag, (dest == None) ? "MOVE 0" : "FETCH 0");
+
+	/*
+	 * sanity checks
+	 */
+	if (name == NULL)
+	{
+		elog(WARNING, "PerformPortalFetch: missing portal name");
+		return;
+	}
+
+	/*
+	 * get the portal from the portal name
+	 */
+	portal = GetPortalByName(name);
+	if (!PortalIsValid(portal))
+	{
+		elog(WARNING, "PerformPortalFetch: portal \"%s\" not found",
+			 name);
+		return;
+	}
+
+	/*
+	 * switch into the portal context
+	 */
+	oldcontext = MemoryContextSwitchTo(PortalGetHeapMemory(portal));
+
+	queryDesc = PortalGetQueryDesc(portal);
+	estate = PortalGetState(portal);
+
+	/*
+	 * If the requested destination is not the same as the query's
+	 * original destination, make a temporary QueryDesc with the proper
+	 * destination.  This supports MOVE, for example, which will pass in
+	 * dest = None.
+	 *
+	 * EXCEPTION: if the query's original dest is RemoteInternal (ie, it's a
+	 * binary cursor) and the request is Remote, we do NOT override the
+	 * original dest.  This is necessary since a FETCH command will pass
+	 * dest = Remote, not knowing whether the cursor is binary or not.
+	 */
+	if (dest != queryDesc->dest &&
+		!(queryDesc->dest == RemoteInternal && dest == Remote))
+	{
+		QueryDesc  *qdesc = (QueryDesc *) palloc(sizeof(QueryDesc));
+
+		memcpy(qdesc, queryDesc, sizeof(QueryDesc));
+		qdesc->dest = dest;
+		queryDesc = qdesc;
+		temp_desc = true;
+	}
+
+	/*
+	 * Restore the scanCommandId that was current when the cursor was
+	 * opened.  This ensures that we see the same tuples throughout the
+	 * execution of the cursor.
+	 */
+	savedId = GetScanCommandId();
+	SetScanCommandId(PortalGetCommandId(portal));
+
+	/*
+	 * Determine which direction to go in, and check to see if we're
+	 * already at the end of the available tuples in that direction.  If
+	 * so, set the direction to NoMovement to avoid trying to fetch any
+	 * tuples.  (This check exists because not all plan node types
+	 * are robust about being called again if they've already returned
+	 * NULL once.)  Then call the executor (we must not skip this, because
+	 * the destination needs to see a setup and shutdown even if no tuples
+	 * are available).  Finally, update the atStart/atEnd state depending
+	 * on the number of tuples that were retrieved.
+	 */
+	if (forward)
+	{
+		if (portal->atEnd)
+			direction = NoMovementScanDirection;
+		else
+			direction = ForwardScanDirection;
+
+		ExecutorRun(queryDesc, estate, direction, (long) count);
+
+		if (estate->es_processed > 0)
+			portal->atStart = false; /* OK to back up now */
+		if (count <= 0 || (int) estate->es_processed < count)
+			portal->atEnd = true;	/* we retrieved 'em all */
+	}
+	else
+	{
+		if (portal->atStart)
+			direction = NoMovementScanDirection;
+		else
+			direction = BackwardScanDirection;
+
+		ExecutorRun(queryDesc, estate, direction, (long) count);
+
+		if (estate->es_processed > 0)
+			portal->atEnd = false;	/* OK to go forward now */
+		if (count <= 0 || (int) estate->es_processed < count)
+			portal->atStart = true; /* we retrieved 'em all */
+	}
+
+	/* Return command status if wanted */
+	if (completionTag)
+		snprintf(completionTag, COMPLETION_TAG_BUFSIZE, "%s %u",
+				 (dest == None) ? "MOVE" : "FETCH",
+				 estate->es_processed);
+
+	/*
+	 * Restore outer command ID.
+	 */
+	SetScanCommandId(savedId);
+
+	/*
+	 * Clean up and switch back to old context.
+	 */
+	if (temp_desc)
+		pfree(queryDesc);
+
+	MemoryContextSwitchTo(oldcontext);
+}
+
+/*
+ * PerformPortalClose
+ */
+void
+PerformPortalClose(char *name, CommandDest dest)
+{
+	Portal		portal;
+
+	/*
+	 * sanity checks
+	 */
+	if (name == NULL)
+	{
+		elog(WARNING, "PerformPortalClose: missing portal name");
+		return;
+	}
+
+	/*
+	 * get the portal from the portal name
+	 */
+	portal = GetPortalByName(name);
+	if (!PortalIsValid(portal))
+	{
+		elog(WARNING, "PerformPortalClose: portal \"%s\" not found",
+			 name);
+		return;
+	}
+
+	/*
+	 * Note: PortalCleanup is called as a side-effect
+	 */
+	PortalDrop(portal);
+}
diff --git a/src/backend/commands/proclang.c b/src/backend/commands/proclang.c
index 4ef8d8f72a0bee3b3a69cab019cd467181aa6bd2..2ad25fdbd4f2cf977f9cd78175e99cd70b7a40b9 100644
--- a/src/backend/commands/proclang.c
+++ b/src/backend/commands/proclang.c
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/commands/proclang.c,v 1.30 2002/04/09 20:35:48 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/proclang.c,v 1.31 2002/04/15 05:22:03 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -22,6 +22,7 @@
 #include "catalog/pg_language.h"
 #include "catalog/pg_proc.h"
 #include "commands/proclang.h"
+#include "commands/defrem.h"
 #include "fmgr.h"
 #include "miscadmin.h"
 #include "parser/parse_func.h"
@@ -30,21 +31,6 @@
 #include "utils/syscache.h"
 
 
-/*
- * Translate the input language name to lower case.
- */
-static void
-case_translate_language_name(const char *input, char *output)
-{
-	int			i;
-
-	for (i = 0; i < NAMEDATALEN && input[i]; ++i)
-		output[i] = tolower((unsigned char) input[i]);
-
-	output[i] = '\0';
-}
-
-
 /* ---------------------------------------------------------------------
  * CREATE PROCEDURAL LANGUAGE
  * ---------------------------------------------------------------------
diff --git a/src/backend/commands/remove.c b/src/backend/commands/remove.c
deleted file mode 100644
index c32d2b215c5163f64990d0fdb6f0436b1341114c..0000000000000000000000000000000000000000
--- a/src/backend/commands/remove.c
+++ /dev/null
@@ -1,476 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * remove.c
- *	  POSTGRES remove (domain | function | type | operator ) utilty code.
- *
- * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- *
- * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/commands/Attic/remove.c,v 1.74 2002/04/11 19:59:58 tgl Exp $
- *
- *-------------------------------------------------------------------------
- */
-#include "postgres.h"
-
-#include "access/heapam.h"
-#include "catalog/catname.h"
-#include "catalog/namespace.h"
-#include "catalog/pg_language.h"
-#include "catalog/pg_proc.h"
-#include "catalog/pg_type.h"
-#include "commands/comment.h"
-#include "commands/defrem.h"
-#include "miscadmin.h"
-#include "parser/parse.h"
-#include "parser/parse_func.h"
-#include "parser/parse_type.h"
-#include "utils/acl.h"
-#include "utils/builtins.h"
-#include "utils/syscache.h"
-
-
-/*
- * RemoveOperator
- *		Deletes an operator.
- *
- * Exceptions:
- *		BadArg if name is invalid.
- *		BadArg if type1 is invalid.
- *		"ERROR" if operator nonexistent.
- *		...
- */
-void
-RemoveOperator(char *operatorName,		/* operator name */
-			   TypeName *typeName1, /* left argument type name */
-			   TypeName *typeName2) /* right argument type name */
-{
-	Relation	relation;
-	HeapTuple	tup;
-	Oid			typeId1 = InvalidOid;
-	Oid			typeId2 = InvalidOid;
-	char		oprtype;
-
-	if (typeName1)
-		typeId1 = typenameTypeId(typeName1);
-
-	if (typeName2)
-		typeId2 = typenameTypeId(typeName2);
-
-	if (OidIsValid(typeId1) && OidIsValid(typeId2))
-		oprtype = 'b';
-	else if (OidIsValid(typeId1))
-		oprtype = 'r';
-	else
-		oprtype = 'l';
-
-	relation = heap_openr(OperatorRelationName, RowExclusiveLock);
-
-	tup = SearchSysCacheCopy(OPERNAME,
-							 PointerGetDatum(operatorName),
-							 ObjectIdGetDatum(typeId1),
-							 ObjectIdGetDatum(typeId2),
-							 CharGetDatum(oprtype));
-
-	if (HeapTupleIsValid(tup))
-	{
-		if (!pg_oper_ownercheck(tup->t_data->t_oid, GetUserId()))
-			elog(ERROR, "RemoveOperator: operator '%s': permission denied",
-				 operatorName);
-
-		/* Delete any comments associated with this operator */
-		DeleteComments(tup->t_data->t_oid, RelationGetRelid(relation));
-
-		simple_heap_delete(relation, &tup->t_self);
-	}
-	else
-	{
-		if (OidIsValid(typeId1) && OidIsValid(typeId2))
-		{
-			elog(ERROR, "RemoveOperator: binary operator '%s' taking '%s' and '%s' does not exist",
-				 operatorName,
-				 TypeNameToString(typeName1),
-				 TypeNameToString(typeName2));
-		}
-		else if (OidIsValid(typeId1))
-		{
-			elog(ERROR, "RemoveOperator: right unary operator '%s' taking '%s' does not exist",
-				 operatorName,
-				 TypeNameToString(typeName1));
-		}
-		else
-		{
-			elog(ERROR, "RemoveOperator: left unary operator '%s' taking '%s' does not exist",
-				 operatorName,
-				 TypeNameToString(typeName2));
-		}
-	}
-	heap_freetuple(tup);
-	heap_close(relation, RowExclusiveLock);
-}
-
-#ifdef NOTYET
-/*
- * this stuff is to support removing all reference to a type
- * don't use it  - pma 2/1/94
- */
-/*
- *	SingleOpOperatorRemove
- *		Removes all operators that have operands or a result of type 'typeOid'.
- */
-static void
-SingleOpOperatorRemove(Oid typeOid)
-{
-	Relation	rel;
-	ScanKeyData key[3];
-	HeapScanDesc scan;
-	HeapTuple	tup;
-	static		attnums[3] = {7, 8, 9}; /* left, right, return */
-	int			i;
-
-	ScanKeyEntryInitialize(&key[0],
-						   0, 0, F_OIDEQ, (Datum) typeOid);
-	rel = heap_openr(OperatorRelationName, RowExclusiveLock);
-	for (i = 0; i < 3; ++i)
-	{
-		key[0].sk_attno = attnums[i];
-		scan = heap_beginscan(rel, 0, SnapshotNow, 1, key);
-		while (HeapTupleIsValid(tup = heap_getnext(scan, 0)))
-		{
-			/* Delete any comments associated with this operator */
-			DeleteComments(tup->t_data->t_oid, RelationGetRelid(rel));
-
-			simple_heap_delete(rel, &tup->t_self);
-		}
-
-		heap_endscan(scan);
-	}
-	heap_close(rel, RowExclusiveLock);
-}
-
-/*
- *	AttributeAndRelationRemove
- *		Removes all entries in the attribute and relation relations
- *		that contain entries of type 'typeOid'.
- *		Currently nothing calls this code, it is untested.
- */
-static void
-AttributeAndRelationRemove(Oid typeOid)
-{
-	struct oidlist
-	{
-		Oid			reloid;
-		struct oidlist *next;
-	};
-	struct oidlist *oidptr,
-			   *optr;
-	Relation	rel;
-	ScanKeyData key[1];
-	HeapScanDesc scan;
-	HeapTuple	tup;
-
-	/*
-	 * Get the oid's of the relations to be removed by scanning the entire
-	 * attribute relation. We don't need to remove the attributes here,
-	 * because amdestroy will remove all attributes of the relation. XXX
-	 * should check for duplicate relations
-	 */
-
-	ScanKeyEntryInitialize(&key[0],
-						   0, 3, F_OIDEQ, (Datum) typeOid);
-
-	oidptr = (struct oidlist *) palloc(sizeof(*oidptr));
-	oidptr->next = NULL;
-	optr = oidptr;
-	rel = heap_openr(AttributeRelationName, AccessShareLock);
-	scan = heap_beginscan(rel, 0, SnapshotNow, 1, key);
-	while (HeapTupleIsValid(tup = heap_getnext(scan, 0)))
-	{
-		optr->reloid = ((Form_pg_attribute) GETSTRUCT(tup))->attrelid;
-		optr->next = (struct oidlist *) palloc(sizeof(*oidptr));
-		optr = optr->next;
-	}
-	optr->next = NULL;
-	heap_endscan(scan);
-	heap_close(rel, AccessShareLock);
-
-	optr = oidptr;
-
-	ScanKeyEntryInitialize(&key[0], 0,
-						   ObjectIdAttributeNumber,
-						   F_OIDEQ, (Datum) 0);
-	/* get RowExclusiveLock because heap_destroy will need it */
-	rel = heap_openr(RelationRelationName, RowExclusiveLock);
-	while (PointerIsValid((char *) optr->next))
-	{
-		Oid		relOid = (optr++)->reloid;
-
-		key[0].sk_argument = ObjectIdGetDatum(relOid);
-		scan = heap_beginscan(rel, 0, SnapshotNow, 1, key);
-		tup = heap_getnext(scan, 0);
-		if (HeapTupleIsValid(tup))
-			heap_drop_with_catalog(relOid, allowSystemTableMods);
-		heap_endscan(scan);
-	}
-	heap_close(rel, RowExclusiveLock);
-}
-#endif   /* NOTYET */
-
-/*
- *	TypeRemove
- *		Removes a datatype.
- *
- * NOTE: since this tries to remove the associated array type too, it'll
- * only work on scalar types.
- */
-void
-RemoveType(List *names)
-{
-	TypeName   *typename;
-	Relation	relation;
-	Oid			typeoid;
-	HeapTuple	tup;
-
-	/* Make a TypeName so we can use standard type lookup machinery */
-	typename = makeNode(TypeName);
-	typename->names = names;
-	typename->typmod = -1;
-	typename->arrayBounds = NIL;
-
-	relation = heap_openr(TypeRelationName, RowExclusiveLock);
-
-	/* Use LookupTypeName here so that shell types can be removed. */
-	typeoid = LookupTypeName(typename);
-	if (!OidIsValid(typeoid))
-		elog(ERROR, "Type \"%s\" does not exist",
-			 TypeNameToString(typename));
-
-	tup = SearchSysCache(TYPEOID,
-						 ObjectIdGetDatum(typeoid),
-						 0, 0, 0);
-	if (!HeapTupleIsValid(tup))
-		elog(ERROR, "Type \"%s\" does not exist",
-			 TypeNameToString(typename));
-
-	if (!pg_type_ownercheck(typeoid, GetUserId()))
-		elog(ERROR, "RemoveType: type '%s': permission denied",
-			 TypeNameToString(typename));
-
-	/* Delete any comments associated with this type */
-	DeleteComments(typeoid, RelationGetRelid(relation));
-
-	/* Remove the type tuple from pg_type */
-	simple_heap_delete(relation, &tup->t_self);
-
-	ReleaseSysCache(tup);
-
-	/* Now, delete the "array of" that type */
-	typename->arrayBounds = makeList1(makeInteger(1));
-
-	typeoid = LookupTypeName(typename);
-	if (!OidIsValid(typeoid))
-		elog(ERROR, "Type \"%s\" does not exist",
-			 TypeNameToString(typename));
-
-	tup = SearchSysCache(TYPEOID,
-						 ObjectIdGetDatum(typeoid),
-						 0, 0, 0);
-	if (!HeapTupleIsValid(tup))
-		elog(ERROR, "Type \"%s\" does not exist",
-			 TypeNameToString(typename));
-
-	DeleteComments(typeoid, RelationGetRelid(relation));
-
-	simple_heap_delete(relation, &tup->t_self);
-
-	ReleaseSysCache(tup);
-
-	heap_close(relation, RowExclusiveLock);
-}
-
-/*
- *	RemoveDomain
- *		Removes a domain.
- */
-void
-RemoveDomain(List *names, int behavior)
-{
-	TypeName   *typename;
-	Relation	relation;
-	Oid			typeoid;
-	HeapTuple	tup;
-	char		typtype;
-
-	/* CASCADE unsupported */
-	if (behavior == CASCADE)
-		elog(ERROR, "DROP DOMAIN does not support the CASCADE keyword");
-
-	/* Make a TypeName so we can use standard type lookup machinery */
-	typename = makeNode(TypeName);
-	typename->names = names;
-	typename->typmod = -1;
-	typename->arrayBounds = NIL;
-
-	relation = heap_openr(TypeRelationName, RowExclusiveLock);
-
-	typeoid = typenameTypeId(typename);
-
-	tup = SearchSysCache(TYPEOID,
-						 ObjectIdGetDatum(typeoid),
-						 0, 0, 0);
-	if (!HeapTupleIsValid(tup))
-		elog(ERROR, "RemoveDomain: type '%s' does not exist",
-			 TypeNameToString(typename));
-
-	if (!pg_type_ownercheck(typeoid, GetUserId()))
-		elog(ERROR, "RemoveDomain: type '%s': permission denied",
-			 TypeNameToString(typename));
-
-	/* Check that this is actually a domain */
-	typtype = ((Form_pg_type) GETSTRUCT(tup))->typtype;
-
-	if (typtype != 'd')
-		elog(ERROR, "%s is not a domain",
-			 TypeNameToString(typename));
-
-	/* Delete any comments associated with this type */
-	DeleteComments(typeoid, RelationGetRelid(relation));
-
-	/* Remove the type tuple from pg_type */
-	simple_heap_delete(relation, &tup->t_self);
-
-	ReleaseSysCache(tup);
-
-	/* At present, domains don't have associated array types */
-
-	heap_close(relation, RowExclusiveLock);
-}
-
-/*
- * RemoveFunction
- *		Deletes a function.
- *
- * Exceptions:
- *		BadArg if name is invalid.
- *		"ERROR" if function nonexistent.
- *		...
- */
-void
-RemoveFunction(List *functionName,		/* function name to be removed */
-			   List *argTypes)	/* list of TypeName nodes */
-{
-	Oid			funcOid;
-	Relation	relation;
-	HeapTuple	tup;
-
-	funcOid = LookupFuncNameTypeNames(functionName, argTypes, 
-									  true, "RemoveFunction");
-
-	relation = heap_openr(ProcedureRelationName, RowExclusiveLock);
-
-	tup = SearchSysCache(PROCOID,
-						 ObjectIdGetDatum(funcOid),
-						 0, 0, 0);
-	if (!HeapTupleIsValid(tup))	/* should not happen */
-		elog(ERROR, "RemoveFunction: couldn't find tuple for function %s",
-			 NameListToString(functionName));
-
-	if (!pg_proc_ownercheck(funcOid, GetUserId()))
-		elog(ERROR, "RemoveFunction: function '%s': permission denied",
-			 NameListToString(functionName));
-
-	if (((Form_pg_proc) GETSTRUCT(tup))->proisagg)
-		elog(ERROR, "RemoveFunction: function '%s' is an aggregate"
-			 "\n\tUse DROP AGGREGATE to remove it",
-			 NameListToString(functionName));
-
-	if (((Form_pg_proc) GETSTRUCT(tup))->prolang == INTERNALlanguageId)
-	{
-		/* "Helpful" WARNING when removing a builtin function ... */
-		elog(WARNING, "Removing built-in function \"%s\"",
-			 NameListToString(functionName));
-	}
-
-	/* Delete any comments associated with this function */
-	DeleteComments(funcOid, RelationGetRelid(relation));
-
-	simple_heap_delete(relation, &tup->t_self);
-
-	ReleaseSysCache(tup);
-
-	heap_close(relation, RowExclusiveLock);
-}
-
-void
-RemoveAggregate(List *aggName, TypeName *aggType)
-{
-	Relation	relation;
-	HeapTuple	tup;
-	Oid			basetypeID;
-	Oid			procOid;
-
-	/*
-	 * if a basetype is passed in, then attempt to find an aggregate for
-	 * that specific type.
-	 *
-	 * else if the basetype is blank, then attempt to find an aggregate with
-	 * a basetype of zero.	This is valid. It means that the aggregate is
-	 * to apply to all basetypes (eg, COUNT).
-	 */
-	if (aggType)
-		basetypeID = typenameTypeId(aggType);
-	else
-		basetypeID = InvalidOid;
-
-	procOid = find_aggregate_func("RemoveAggregate", aggName, basetypeID);
-
-	/* Permission check */
-
-	if (!pg_proc_ownercheck(procOid, GetUserId()))
-	{
-		if (basetypeID == InvalidOid)
-			elog(ERROR, "RemoveAggregate: aggregate %s for all types: permission denied",
-				 NameListToString(aggName));
-		else
-			elog(ERROR, "RemoveAggregate: aggregate %s for type %s: permission denied",
-				 NameListToString(aggName), format_type_be(basetypeID));
-	}
-
-	/* Remove the pg_proc tuple */
-
-	relation = heap_openr(ProcedureRelationName, RowExclusiveLock);
-
-	tup = SearchSysCache(PROCOID,
-						 ObjectIdGetDatum(procOid),
-						 0, 0, 0);
-	if (!HeapTupleIsValid(tup))	/* should not happen */
-		elog(ERROR, "RemoveAggregate: couldn't find pg_proc tuple for %s",
-			 NameListToString(aggName));
-
-	/* Delete any comments associated with this function */
-	DeleteComments(procOid, RelationGetRelid(relation));
-
-	simple_heap_delete(relation, &tup->t_self);
-
-	ReleaseSysCache(tup);
-
-	heap_close(relation, RowExclusiveLock);
-
-	/* Remove the pg_aggregate tuple */
-
-	relation = heap_openr(AggregateRelationName, RowExclusiveLock);
-
-	tup = SearchSysCache(AGGFNOID,
-						 ObjectIdGetDatum(procOid),
-						 0, 0, 0);
-	if (!HeapTupleIsValid(tup))	/* should not happen */
-		elog(ERROR, "RemoveAggregate: couldn't find pg_aggregate tuple for %s",
-			 NameListToString(aggName));
-
-	simple_heap_delete(relation, &tup->t_self);
-
-	ReleaseSysCache(tup);
-
-	heap_close(relation, RowExclusiveLock);
-}
diff --git a/src/backend/commands/rename.c b/src/backend/commands/rename.c
deleted file mode 100644
index 21db59b7f6b0102ba443f23279440b11d302fa9d..0000000000000000000000000000000000000000
--- a/src/backend/commands/rename.c
+++ /dev/null
@@ -1,591 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * rename.c
- *	  renameatt() and renamerel() reside here.
- *
- * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- *
- * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/commands/Attic/rename.c,v 1.70 2002/04/12 20:38:24 tgl Exp $
- *
- *-------------------------------------------------------------------------
- */
-#include "postgres.h"
-
-#include <errno.h>
-
-#include "access/genam.h"
-#include "access/heapam.h"
-#include "access/itup.h"
-#include "catalog/catname.h"
-#include "catalog/pg_index.h"
-#include "catalog/pg_trigger.h"
-#include "catalog/pg_type.h"
-#include "catalog/heap.h"
-#include "catalog/indexing.h"
-#include "catalog/catalog.h"
-#include "commands/rename.h"
-#include "commands/trigger.h"
-#include "miscadmin.h"
-#include "storage/smgr.h"
-#include "optimizer/prep.h"
-#include "rewrite/rewriteDefine.h"
-#include "rewrite/rewriteSupport.h"
-#include "utils/acl.h"
-#include "utils/builtins.h"
-#include "utils/fmgroids.h"
-#include "utils/lsyscache.h"
-#include "utils/relcache.h"
-#include "utils/syscache.h"
-
-
-#define RI_TRIGGER_PK	1		/* is a trigger on the PK relation */
-#define RI_TRIGGER_FK	2		/* is a trigger on the FK relation */
-#define RI_TRIGGER_NONE 0		/* is not an RI trigger function */
-
-static int	ri_trigger_type(Oid tgfoid);
-static void update_ri_trigger_args(Oid relid,
-					   const char *oldname,
-					   const char *newname,
-					   bool fk_scan,
-					   bool update_relname);
-
-
-/*
- *		renameatt		- changes the name of a attribute in a relation
- *
- *		Attname attribute is changed in attribute catalog.
- *		No record of the previous attname is kept (correct?).
- *
- *		get proper relrelation from relation catalog (if not arg)
- *		scan attribute catalog
- *				for name conflict (within rel)
- *				for original attribute (if not arg)
- *		modify attname in attribute tuple
- *		insert modified attribute in attribute catalog
- *		delete original attribute from attribute catalog
- */
-void
-renameatt(Oid relid,
-		  const char *oldattname,
-		  const char *newattname,
-		  bool recurse)
-{
-	Relation	targetrelation;
-	Relation	attrelation;
-	HeapTuple	atttup;
-	List	   *indexoidlist;
-	List	   *indexoidscan;
-
-	/*
-	 * Grab an exclusive lock on the target table, which we will NOT
-	 * release until end of transaction.
-	 */
-	targetrelation = heap_open(relid, AccessExclusiveLock);
-
-	/*
-	 * permissions checking.  this would normally be done in utility.c,
-	 * but this particular routine is recursive.
-	 *
-	 * normally, only the owner of a class can change its schema.
-	 */
-	if (!allowSystemTableMods 
-		&& IsSystemRelation(targetrelation))
-		elog(ERROR, "renameatt: class \"%s\" is a system catalog",
-			 RelationGetRelationName(targetrelation));
-	if (!pg_class_ownercheck(relid, GetUserId()))
-		elog(ERROR, "renameatt: you do not own class \"%s\"",
-			 RelationGetRelationName(targetrelation));
-
-	/*
-	 * if the 'recurse' flag is set then we are supposed to rename this
-	 * attribute in all classes that inherit from 'relname' (as well as in
-	 * 'relname').
-	 *
-	 * any permissions or problems with duplicate attributes will cause the
-	 * whole transaction to abort, which is what we want -- all or
-	 * nothing.
-	 */
-	if (recurse)
-	{
-		List	   *child,
-				   *children;
-
-		/* this routine is actually in the planner */
-		children = find_all_inheritors(relid);
-
-		/*
-		 * find_all_inheritors does the recursive search of the
-		 * inheritance hierarchy, so all we have to do is process all of
-		 * the relids in the list that it returns.
-		 */
-		foreach(child, children)
-		{
-			Oid			childrelid = lfirsti(child);
-
-			if (childrelid == relid)
-				continue;
-			/* note we need not recurse again! */
-			renameatt(childrelid, oldattname, newattname, false);
-		}
-	}
-
-	attrelation = heap_openr(AttributeRelationName, RowExclusiveLock);
-
-	atttup = SearchSysCacheCopy(ATTNAME,
-								ObjectIdGetDatum(relid),
-								PointerGetDatum(oldattname),
-								0, 0);
-	if (!HeapTupleIsValid(atttup))
-		elog(ERROR, "renameatt: attribute \"%s\" does not exist", oldattname);
-
-	if (((Form_pg_attribute) GETSTRUCT(atttup))->attnum < 0)
-		elog(ERROR, "renameatt: system attribute \"%s\" not renamed", oldattname);
-
-	/* should not already exist */
-	if (SearchSysCacheExists(ATTNAME,
-							 ObjectIdGetDatum(relid),
-							 PointerGetDatum(newattname),
-							 0, 0))
-		elog(ERROR, "renameatt: attribute \"%s\" exists", newattname);
-
-	StrNCpy(NameStr(((Form_pg_attribute) GETSTRUCT(atttup))->attname),
-			newattname, NAMEDATALEN);
-
-	simple_heap_update(attrelation, &atttup->t_self, atttup);
-
-	/* keep system catalog indices current */
-	{
-		Relation	irelations[Num_pg_attr_indices];
-
-		CatalogOpenIndices(Num_pg_attr_indices, Name_pg_attr_indices, irelations);
-		CatalogIndexInsert(irelations, Num_pg_attr_indices, attrelation, atttup);
-		CatalogCloseIndices(Num_pg_attr_indices, irelations);
-	}
-
-	heap_freetuple(atttup);
-
-	/*
-	 * Update column names of indexes that refer to the column being
-	 * renamed.
-	 */
-	indexoidlist = RelationGetIndexList(targetrelation);
-
-	foreach(indexoidscan, indexoidlist)
-	{
-		Oid			indexoid = lfirsti(indexoidscan);
-		HeapTuple	indextup;
-
-		/*
-		 * First check to see if index is a functional index. If so, its
-		 * column name is a function name and shouldn't be renamed here.
-		 */
-		indextup = SearchSysCache(INDEXRELID,
-								  ObjectIdGetDatum(indexoid),
-								  0, 0, 0);
-		if (!HeapTupleIsValid(indextup))
-			elog(ERROR, "renameatt: can't find index id %u", indexoid);
-		if (OidIsValid(((Form_pg_index) GETSTRUCT(indextup))->indproc))
-		{
-			ReleaseSysCache(indextup);
-			continue;
-		}
-		ReleaseSysCache(indextup);
-
-		/*
-		 * Okay, look to see if any column name of the index matches the
-		 * old attribute name.
-		 */
-		atttup = SearchSysCacheCopy(ATTNAME,
-									ObjectIdGetDatum(indexoid),
-									PointerGetDatum(oldattname),
-									0, 0);
-		if (!HeapTupleIsValid(atttup))
-			continue;			/* Nope, so ignore it */
-
-		/*
-		 * Update the (copied) attribute tuple.
-		 */
-		StrNCpy(NameStr(((Form_pg_attribute) GETSTRUCT(atttup))->attname),
-				newattname, NAMEDATALEN);
-
-		simple_heap_update(attrelation, &atttup->t_self, atttup);
-
-		/* keep system catalog indices current */
-		{
-			Relation	irelations[Num_pg_attr_indices];
-
-			CatalogOpenIndices(Num_pg_attr_indices, Name_pg_attr_indices, irelations);
-			CatalogIndexInsert(irelations, Num_pg_attr_indices, attrelation, atttup);
-			CatalogCloseIndices(Num_pg_attr_indices, irelations);
-		}
-		heap_freetuple(atttup);
-	}
-
-	freeList(indexoidlist);
-
-	heap_close(attrelation, RowExclusiveLock);
-
-	/*
-	 * Update att name in any RI triggers associated with the relation.
-	 */
-	if (targetrelation->rd_rel->reltriggers > 0)
-	{
-		/* update tgargs column reference where att is primary key */
-		update_ri_trigger_args(RelationGetRelid(targetrelation),
-							   oldattname, newattname,
-							   false, false);
-		/* update tgargs column reference where att is foreign key */
-		update_ri_trigger_args(RelationGetRelid(targetrelation),
-							   oldattname, newattname,
-							   true, false);
-	}
-
-	heap_close(targetrelation, NoLock); /* close rel but keep lock! */
-}
-
-/*
- *		renamerel		- change the name of a relation
- *
- *		XXX - When renaming sequences, we don't bother to modify the
- *			  sequence name that is stored within the sequence itself
- *			  (this would cause problems with MVCC). In the future,
- *			  the sequence name should probably be removed from the
- *			  sequence, AFAIK there's no need for it to be there.
- */
-void
-renamerel(Oid relid, const char *newrelname)
-{
-	Relation	targetrelation;
-	Relation	relrelation;	/* for RELATION relation */
-	HeapTuple	reltup;
-	Oid			namespaceId;
-	char		relkind;
-	bool		relhastriggers;
-	Relation	irelations[Num_pg_class_indices];
-
-	/*
-	 * Grab an exclusive lock on the target table or index, which we will
-	 * NOT release until end of transaction.
-	 */
-	targetrelation = relation_open(relid, AccessExclusiveLock);
-
-	namespaceId = RelationGetNamespace(targetrelation);
-
-	/* Validity checks */
-	if (!allowSystemTableMods &&
-		IsSystemRelation(targetrelation))
-		elog(ERROR, "renamerel: system relation \"%s\" may not be renamed",
-			 RelationGetRelationName(targetrelation));
-
-	relkind = targetrelation->rd_rel->relkind;
-	relhastriggers = (targetrelation->rd_rel->reltriggers > 0);
-
-	/*
-	 * Find relation's pg_class tuple, and make sure newrelname isn't in
-	 * use.
-	 */
-	relrelation = heap_openr(RelationRelationName, RowExclusiveLock);
-
-	reltup = SearchSysCacheCopy(RELOID,
-								PointerGetDatum(relid),
-								0, 0, 0);
-	if (!HeapTupleIsValid(reltup))
-		elog(ERROR, "renamerel: relation \"%s\" does not exist",
-			 RelationGetRelationName(targetrelation));
-
-	if (get_relname_relid(newrelname, namespaceId) != InvalidOid)
-		elog(ERROR, "renamerel: relation \"%s\" exists", newrelname);
-
-	/*
-	 * Update pg_class tuple with new relname.	(Scribbling on reltup is
-	 * OK because it's a copy...)
-	 */
-	StrNCpy(NameStr(((Form_pg_class) GETSTRUCT(reltup))->relname),
-			newrelname, NAMEDATALEN);
-
-	simple_heap_update(relrelation, &reltup->t_self, reltup);
-
-	/* keep the system catalog indices current */
-	CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, irelations);
-	CatalogIndexInsert(irelations, Num_pg_class_indices, relrelation, reltup);
-	CatalogCloseIndices(Num_pg_class_indices, irelations);
-
-	heap_close(relrelation, NoLock);
-	heap_freetuple(reltup);
-
-	/*
-	 * Also rename the associated type, if any.
-	 */
-	if (relkind != RELKIND_INDEX)
-		TypeRename(RelationGetRelationName(targetrelation), namespaceId,
-				   newrelname);
-
-	/*
-	 * If it's a view, must also rename the associated ON SELECT rule.
-	 */
-	if (relkind == RELKIND_VIEW)
-	{
-		char	   *oldrulename,
-				   *newrulename;
-
-		oldrulename = MakeRetrieveViewRuleName(RelationGetRelationName(targetrelation));
-		newrulename = MakeRetrieveViewRuleName(newrelname);
-		RenameRewriteRule(oldrulename, newrulename);
-	}
-
-	/*
-	 * Update rel name in any RI triggers associated with the relation.
-	 */
-	if (relhastriggers)
-	{
-		/* update tgargs where relname is primary key */
-		update_ri_trigger_args(relid,
-							   RelationGetRelationName(targetrelation),
-							   newrelname,
-							   false, true);
-		/* update tgargs where relname is foreign key */
-		update_ri_trigger_args(relid,
-							   RelationGetRelationName(targetrelation),
-							   newrelname,
-							   true, true);
-	}
-
-	/*
-	 * Close rel, but keep exclusive lock!
-	 */
-	relation_close(targetrelation, NoLock);
-}
-
-/*
- * Given a trigger function OID, determine whether it is an RI trigger,
- * and if so whether it is attached to PK or FK relation.
- *
- * XXX this probably doesn't belong here; should be exported by
- * ri_triggers.c
- */
-static int
-ri_trigger_type(Oid tgfoid)
-{
-	switch (tgfoid)
-	{
-		case F_RI_FKEY_CASCADE_DEL:
-		case F_RI_FKEY_CASCADE_UPD:
-		case F_RI_FKEY_RESTRICT_DEL:
-		case F_RI_FKEY_RESTRICT_UPD:
-		case F_RI_FKEY_SETNULL_DEL:
-		case F_RI_FKEY_SETNULL_UPD:
-		case F_RI_FKEY_SETDEFAULT_DEL:
-		case F_RI_FKEY_SETDEFAULT_UPD:
-		case F_RI_FKEY_NOACTION_DEL:
-		case F_RI_FKEY_NOACTION_UPD:
-			return RI_TRIGGER_PK;
-
-		case F_RI_FKEY_CHECK_INS:
-		case F_RI_FKEY_CHECK_UPD:
-			return RI_TRIGGER_FK;
-	}
-
-	return RI_TRIGGER_NONE;
-}
-
-/*
- * Scan pg_trigger for RI triggers that are on the specified relation
- * (if fk_scan is false) or have it as the tgconstrrel (if fk_scan
- * is true).  Update RI trigger args fields matching oldname to contain
- * newname instead.  If update_relname is true, examine the relname
- * fields; otherwise examine the attname fields.
- */
-static void
-update_ri_trigger_args(Oid relid,
-					   const char *oldname,
-					   const char *newname,
-					   bool fk_scan,
-					   bool update_relname)
-{
-	Relation	tgrel;
-	Relation	irel;
-	ScanKeyData skey[1];
-	IndexScanDesc idxtgscan;
-	RetrieveIndexResult idxres;
-	Datum		values[Natts_pg_trigger];
-	char		nulls[Natts_pg_trigger];
-	char		replaces[Natts_pg_trigger];
-
-	tgrel = heap_openr(TriggerRelationName, RowExclusiveLock);
-	if (fk_scan)
-		irel = index_openr(TriggerConstrRelidIndex);
-	else
-		irel = index_openr(TriggerRelidIndex);
-
-	ScanKeyEntryInitialize(&skey[0], 0x0,
-						   1,	/* always column 1 of index */
-						   F_OIDEQ,
-						   ObjectIdGetDatum(relid));
-	idxtgscan = index_beginscan(irel, false, 1, skey);
-
-	while ((idxres = index_getnext(idxtgscan, ForwardScanDirection)) != NULL)
-	{
-		HeapTupleData tupledata;
-		Buffer		buffer;
-		HeapTuple	tuple;
-		Form_pg_trigger pg_trigger;
-		bytea	   *val;
-		bytea	   *newtgargs;
-		bool		isnull;
-		int			tg_type;
-		bool		examine_pk;
-		bool		changed;
-		int			tgnargs;
-		int			i;
-		int			newlen;
-		const char *arga[RI_MAX_ARGUMENTS];
-		const char *argp;
-
-		tupledata.t_self = idxres->heap_iptr;
-		heap_fetch(tgrel, SnapshotNow, &tupledata, &buffer, idxtgscan);
-		pfree(idxres);
-		if (!tupledata.t_data)
-			continue;
-		tuple = &tupledata;
-		pg_trigger = (Form_pg_trigger) GETSTRUCT(tuple);
-		tg_type = ri_trigger_type(pg_trigger->tgfoid);
-		if (tg_type == RI_TRIGGER_NONE)
-		{
-			/* Not an RI trigger, forget it */
-			ReleaseBuffer(buffer);
-			continue;
-		}
-
-		/*
-		 * It is an RI trigger, so parse the tgargs bytea.
-		 *
-		 * NB: we assume the field will never be compressed or moved out of
-		 * line; so does trigger.c ...
-		 */
-		tgnargs = pg_trigger->tgnargs;
-		val = (bytea *) fastgetattr(tuple,
-									Anum_pg_trigger_tgargs,
-									tgrel->rd_att, &isnull);
-		if (isnull || tgnargs < RI_FIRST_ATTNAME_ARGNO ||
-			tgnargs > RI_MAX_ARGUMENTS)
-		{
-			/* This probably shouldn't happen, but ignore busted triggers */
-			ReleaseBuffer(buffer);
-			continue;
-		}
-		argp = (const char *) VARDATA(val);
-		for (i = 0; i < tgnargs; i++)
-		{
-			arga[i] = argp;
-			argp += strlen(argp) + 1;
-		}
-
-		/*
-		 * Figure out which item(s) to look at.  If the trigger is
-		 * primary-key type and attached to my rel, I should look at the
-		 * PK fields; if it is foreign-key type and attached to my rel, I
-		 * should look at the FK fields.  But the opposite rule holds when
-		 * examining triggers found by tgconstrrel search.
-		 */
-		examine_pk = (tg_type == RI_TRIGGER_PK) == (!fk_scan);
-
-		changed = false;
-		if (update_relname)
-		{
-			/* Change the relname if needed */
-			i = examine_pk ? RI_PK_RELNAME_ARGNO : RI_FK_RELNAME_ARGNO;
-			if (strcmp(arga[i], oldname) == 0)
-			{
-				arga[i] = newname;
-				changed = true;
-			}
-		}
-		else
-		{
-			/* Change attname(s) if needed */
-			i = examine_pk ? RI_FIRST_ATTNAME_ARGNO + RI_KEYPAIR_PK_IDX :
-				RI_FIRST_ATTNAME_ARGNO + RI_KEYPAIR_FK_IDX;
-			for (; i < tgnargs; i += 2)
-			{
-				if (strcmp(arga[i], oldname) == 0)
-				{
-					arga[i] = newname;
-					changed = true;
-				}
-			}
-		}
-
-		if (!changed)
-		{
-			/* Don't need to update this tuple */
-			ReleaseBuffer(buffer);
-			continue;
-		}
-
-		/*
-		 * Construct modified tgargs bytea.
-		 */
-		newlen = VARHDRSZ;
-		for (i = 0; i < tgnargs; i++)
-			newlen += strlen(arga[i]) + 1;
-		newtgargs = (bytea *) palloc(newlen);
-		VARATT_SIZEP(newtgargs) = newlen;
-		newlen = VARHDRSZ;
-		for (i = 0; i < tgnargs; i++)
-		{
-			strcpy(((char *) newtgargs) + newlen, arga[i]);
-			newlen += strlen(arga[i]) + 1;
-		}
-
-		/*
-		 * Build modified tuple.
-		 */
-		for (i = 0; i < Natts_pg_trigger; i++)
-		{
-			values[i] = (Datum) 0;
-			replaces[i] = ' ';
-			nulls[i] = ' ';
-		}
-		values[Anum_pg_trigger_tgargs - 1] = PointerGetDatum(newtgargs);
-		replaces[Anum_pg_trigger_tgargs - 1] = 'r';
-
-		tuple = heap_modifytuple(tuple, tgrel, values, nulls, replaces);
-
-		/*
-		 * Now we can release hold on original tuple.
-		 */
-		ReleaseBuffer(buffer);
-
-		/*
-		 * Update pg_trigger and its indexes
-		 */
-		simple_heap_update(tgrel, &tuple->t_self, tuple);
-
-		{
-			Relation	irelations[Num_pg_attr_indices];
-
-			CatalogOpenIndices(Num_pg_trigger_indices, Name_pg_trigger_indices, irelations);
-			CatalogIndexInsert(irelations, Num_pg_trigger_indices, tgrel, tuple);
-			CatalogCloseIndices(Num_pg_trigger_indices, irelations);
-		}
-
-		/* free up our scratch memory */
-		pfree(newtgargs);
-		heap_freetuple(tuple);
-	}
-
-	index_endscan(idxtgscan);
-	index_close(irel);
-
-	heap_close(tgrel, RowExclusiveLock);
-
-	/*
-	 * Increment cmd counter to make updates visible; this is needed in
-	 * case the same tuple has to be updated again by next pass (can
-	 * happen in case of a self-referential FK relationship).
-	 */
-	CommandCounterIncrement();
-}
diff --git a/src/backend/commands/schemacmds.c b/src/backend/commands/schemacmds.c
new file mode 100644
index 0000000000000000000000000000000000000000..191d5e329b8a9ced0c198cbf411865f78c6b92c8
--- /dev/null
+++ b/src/backend/commands/schemacmds.c
@@ -0,0 +1,116 @@
+/*-------------------------------------------------------------------------
+ *
+ * schemacmds.c
+ *	  schema creation command support code
+ *
+ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/schemacmds.c,v 1.1 2002/04/15 05:22:03 tgl Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "catalog/catalog.h"
+#include "catalog/pg_namespace.h"
+#include "commands/schemacmds.h"
+#include "miscadmin.h"
+#include "parser/analyze.h"
+#include "tcop/utility.h"
+#include "utils/lsyscache.h"
+
+
+/*
+ * CREATE SCHEMA
+ */
+void
+CreateSchemaCommand(CreateSchemaStmt *stmt)
+{
+	const char *schemaName = stmt->schemaname;
+	const char *authId = stmt->authid;
+	List	   *parsetree_list;
+	List	   *parsetree_item;
+	const char *owner_name;
+	Oid			owner_userid;
+	Oid			saved_userid;
+
+	saved_userid = GetUserId();
+
+	if (!authId)
+	{
+		owner_userid = saved_userid;
+		owner_name = GetUserName(owner_userid);
+	}
+	else if (superuser())
+	{
+		owner_name = authId;
+		/* The following will error out if user does not exist */
+		owner_userid = get_usesysid(owner_name);
+		/*
+		 * Set the current user to the requested authorization so
+		 * that objects created in the statement have the requested
+		 * owner.  (This will revert to session user on error or at
+		 * the end of this routine.)
+		 */
+		SetUserId(owner_userid);
+	}
+	else /* not superuser */
+	{
+		owner_userid = saved_userid;
+		owner_name = GetUserName(owner_userid);
+		if (strcmp(authId, owner_name) != 0)
+			elog(ERROR, "CREATE SCHEMA: permission denied"
+				 "\n\t\"%s\" is not a superuser, so cannot create a schema for \"%s\"",
+				 owner_name, authId);
+	}
+
+	if (!allowSystemTableMods && IsReservedName(schemaName))
+		elog(ERROR, "CREATE SCHEMA: Illegal schema name: \"%s\" -- pg_ is reserved for system schemas",
+			 schemaName);
+
+	/* Create the schema's namespace */
+	NamespaceCreate(schemaName, owner_userid);
+
+	/* Let commands in the schema-element-list know about the schema */
+	CommandCounterIncrement();
+
+	/*
+	 * Examine the list of commands embedded in the CREATE SCHEMA command,
+	 * and reorganize them into a sequentially executable order with no
+	 * forward references.  Note that the result is still a list of raw
+	 * parsetrees in need of parse analysis --- we cannot, in general,
+	 * run analyze.c on one statement until we have actually executed the
+	 * prior ones.
+	 */
+	parsetree_list = analyzeCreateSchemaStmt(stmt);
+
+	/*
+	 * Analyze and execute each command contained in the CREATE SCHEMA
+	 */
+	foreach(parsetree_item, parsetree_list)
+	{
+		Node	   *parsetree = (Node *) lfirst(parsetree_item);
+		List	   *querytree_list,
+				   *querytree_item;
+
+		querytree_list = parse_analyze(parsetree, NULL);
+
+		foreach(querytree_item, querytree_list)
+		{
+			Query	   *querytree = (Query *) lfirst(querytree_item);
+
+			/* schemas should contain only utility stmts */
+			Assert(querytree->commandType == CMD_UTILITY);
+			/* do this step */
+			ProcessUtility(querytree->utilityStmt, None, NULL);
+			/* make sure later steps can see the object created here */
+			CommandCounterIncrement();
+		}
+	}
+
+	/* Reset current user */
+	SetUserId(saved_userid);
+}
diff --git a/src/backend/commands/sequence.c b/src/backend/commands/sequence.c
index a7678c5ce38484567e7ff38c25a27bf3f463947c..0fa56fcfb7db7fdba605fade2ae2ecc978069076 100644
--- a/src/backend/commands/sequence.c
+++ b/src/backend/commands/sequence.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/commands/sequence.c,v 1.76 2002/03/30 01:02:41 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/sequence.c,v 1.77 2002/04/15 05:22:03 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -17,7 +17,7 @@
 #include "access/heapam.h"
 #include "catalog/namespace.h"
 #include "catalog/pg_type.h"
-#include "commands/creatinh.h"
+#include "commands/tablecmds.h"
 #include "commands/sequence.h"
 #include "miscadmin.h"
 #include "utils/acl.h"
diff --git a/src/backend/commands/command.c b/src/backend/commands/tablecmds.c
similarity index 52%
rename from src/backend/commands/command.c
rename to src/backend/commands/tablecmds.c
index 9a20d8329ad9a60e7680c32ac936f10320f745a7..18cea28df12f79028abd87bb87f8631b3483a40e 100644
--- a/src/backend/commands/command.c
+++ b/src/backend/commands/tablecmds.c
@@ -1,19 +1,14 @@
 /*-------------------------------------------------------------------------
  *
- * command.c
- *	  random postgres portal and utility support code
+ * tablecmds.c
+ *	  Commands for altering table structures and settings
  *
- * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.175 2002/04/14 16:47:16 momjian Exp $
- *
- * NOTES
- *	  The PerformAddAttribute() code, like most of the relation
- *	  manipulating code in the commands/ directory, should go
- *	  someplace closer to the lib/catalog code.
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.1 2002/04/15 05:22:03 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -28,27 +23,25 @@
 #include "catalog/indexing.h"
 #include "catalog/namespace.h"
 #include "catalog/pg_attrdef.h"
-#include "catalog/pg_index.h"
+#include "catalog/pg_inherits.h"
 #include "catalog/pg_namespace.h"
 #include "catalog/pg_opclass.h"
-#include "catalog/pg_relcheck.h"
+#include "catalog/pg_trigger.h"
 #include "catalog/pg_type.h"
-#include "commands/command.h"
+#include "commands/tablecmds.h"
 #include "commands/trigger.h"
-#include "executor/execdefs.h"
 #include "executor/executor.h"
 #include "miscadmin.h"
 #include "nodes/makefuncs.h"
 #include "optimizer/clauses.h"
 #include "optimizer/planmain.h"
 #include "optimizer/prep.h"
-#include "parser/analyze.h"
 #include "parser/parse.h"
 #include "parser/parse_expr.h"
-#include "parser/parse_oper.h"
 #include "parser/parse_relation.h"
 #include "parser/parse_type.h"
-#include "tcop/utility.h"
+#include "rewrite/rewriteDefine.h"
+#include "rewrite/rewriteSupport.h"
 #include "utils/acl.h"
 #include "utils/builtins.h"
 #include "utils/fmgroids.h"
@@ -61,220 +54,27 @@ static void drop_default(Oid relid, int16 attnum);
 static bool needs_toast_table(Relation rel);
 static void CheckTupleType(Form_pg_class tuple_class);
 
+static List *MergeAttributes(List *schema, List *supers, bool istemp,
+				List **supOids, List **supconstr, bool *supHasOids);
+static bool change_varattnos_of_a_node(Node *node, const AttrNumber *newattno);
+static void StoreCatalogInheritance(Oid relationId, List *supers);
+static int	findAttrByName(const char *attributeName, List *schema);
+static void setRelhassubclassInRelation(Oid relationId, bool relhassubclass);
+static List *MergeDomainAttributes(List *schema);
 
-/*
- *		PortalCleanup
- */
-void
-PortalCleanup(Portal portal)
-{
-	MemoryContext oldcontext;
-
-	/*
-	 * sanity checks
-	 */
-	AssertArg(PortalIsValid(portal));
-	AssertArg(portal->cleanup == PortalCleanup);
-
-	/*
-	 * set proper portal-executor context before calling ExecMain.
-	 */
-	oldcontext = MemoryContextSwitchTo(PortalGetHeapMemory(portal));
-
-	/*
-	 * tell the executor to shutdown the query
-	 */
-	ExecutorEnd(PortalGetQueryDesc(portal), PortalGetState(portal));
-
-	/*
-	 * switch back to previous context
-	 */
-	MemoryContextSwitchTo(oldcontext);
-}
-
-
-/*
- * PerformPortalFetch
- *
- *	name: name of portal
- *	forward: forward or backward fetch?
- *	count: # of tuples to fetch (0 implies all)
- *	dest: where to send results
- *	completionTag: points to a buffer of size COMPLETION_TAG_BUFSIZE
- *		in which to store a command completion status string.
- *
- * completionTag may be NULL if caller doesn't want a status string.
- */
-void
-PerformPortalFetch(char *name,
-				   bool forward,
-				   int count,
-				   CommandDest dest,
-				   char *completionTag)
-{
-	Portal		portal;
-	QueryDesc  *queryDesc;
-	EState	   *estate;
-	MemoryContext oldcontext;
-	ScanDirection direction;
-	CommandId	savedId;
-	bool		temp_desc = false;
-
-	/* initialize completion status in case of early exit */
-	if (completionTag)
-		strcpy(completionTag, (dest == None) ? "MOVE 0" : "FETCH 0");
-
-	/*
-	 * sanity checks
-	 */
-	if (name == NULL)
-	{
-		elog(WARNING, "PerformPortalFetch: missing portal name");
-		return;
-	}
-
-	/*
-	 * get the portal from the portal name
-	 */
-	portal = GetPortalByName(name);
-	if (!PortalIsValid(portal))
-	{
-		elog(WARNING, "PerformPortalFetch: portal \"%s\" not found",
-			 name);
-		return;
-	}
-
-	/*
-	 * switch into the portal context
-	 */
-	oldcontext = MemoryContextSwitchTo(PortalGetHeapMemory(portal));
-
-	queryDesc = PortalGetQueryDesc(portal);
-	estate = PortalGetState(portal);
-
-	/*
-	 * If the requested destination is not the same as the query's
-	 * original destination, make a temporary QueryDesc with the proper
-	 * destination.  This supports MOVE, for example, which will pass in
-	 * dest = None.
-	 *
-	 * EXCEPTION: if the query's original dest is RemoteInternal (ie, it's a
-	 * binary cursor) and the request is Remote, we do NOT override the
-	 * original dest.  This is necessary since a FETCH command will pass
-	 * dest = Remote, not knowing whether the cursor is binary or not.
-	 */
-	if (dest != queryDesc->dest &&
-		!(queryDesc->dest == RemoteInternal && dest == Remote))
-	{
-		QueryDesc  *qdesc = (QueryDesc *) palloc(sizeof(QueryDesc));
-
-		memcpy(qdesc, queryDesc, sizeof(QueryDesc));
-		qdesc->dest = dest;
-		queryDesc = qdesc;
-		temp_desc = true;
-	}
-
-	/*
-	 * Restore the scanCommandId that was current when the cursor was
-	 * opened.  This ensures that we see the same tuples throughout the
-	 * execution of the cursor.
-	 */
-	savedId = GetScanCommandId();
-	SetScanCommandId(PortalGetCommandId(portal));
-
-	/*
-	 * Determine which direction to go in, and check to see if we're
-	 * already at the end of the available tuples in that direction.  If
-	 * so, set the direction to NoMovement to avoid trying to fetch any
-	 * tuples.  (This check exists because not all plan node types
-	 * are robust about being called again if they've already returned
-	 * NULL once.)  Then call the executor (we must not skip this, because
-	 * the destination needs to see a setup and shutdown even if no tuples
-	 * are available).  Finally, update the atStart/atEnd state depending
-	 * on the number of tuples that were retrieved.
-	 */
-	if (forward)
-	{
-		if (portal->atEnd)
-			direction = NoMovementScanDirection;
-		else
-			direction = ForwardScanDirection;
-
-		ExecutorRun(queryDesc, estate, direction, (long) count);
-
-		if (estate->es_processed > 0)
-			portal->atStart = false; /* OK to back up now */
-		if (count <= 0 || (int) estate->es_processed < count)
-			portal->atEnd = true;	/* we retrieved 'em all */
-	}
-	else
-	{
-		if (portal->atStart)
-			direction = NoMovementScanDirection;
-		else
-			direction = BackwardScanDirection;
-
-		ExecutorRun(queryDesc, estate, direction, (long) count);
-
-		if (estate->es_processed > 0)
-			portal->atEnd = false;	/* OK to go forward now */
-		if (count <= 0 || (int) estate->es_processed < count)
-			portal->atStart = true; /* we retrieved 'em all */
-	}
-
-	/* Return command status if wanted */
-	if (completionTag)
-		snprintf(completionTag, COMPLETION_TAG_BUFSIZE, "%s %u",
-				 (dest == None) ? "MOVE" : "FETCH",
-				 estate->es_processed);
-
-	/*
-	 * Restore outer command ID.
-	 */
-	SetScanCommandId(savedId);
-
-	/*
-	 * Clean up and switch back to old context.
-	 */
-	if (temp_desc)
-		pfree(queryDesc);
-
-	MemoryContextSwitchTo(oldcontext);
-}
-
-/*
- *		PerformPortalClose
- */
-void
-PerformPortalClose(char *name, CommandDest dest)
-{
-	Portal		portal;
+/* Used by attribute and relation renaming routines: */
 
-	/*
-	 * sanity checks
-	 */
-	if (name == NULL)
-	{
-		elog(WARNING, "PerformPortalClose: missing portal name");
-		return;
-	}
+#define RI_TRIGGER_PK	1		/* is a trigger on the PK relation */
+#define RI_TRIGGER_FK	2		/* is a trigger on the FK relation */
+#define RI_TRIGGER_NONE 0		/* is not an RI trigger function */
 
-	/*
-	 * get the portal from the portal name
-	 */
-	portal = GetPortalByName(name);
-	if (!PortalIsValid(portal))
-	{
-		elog(WARNING, "PerformPortalClose: portal \"%s\" not found",
-			 name);
-		return;
-	}
+static int	ri_trigger_type(Oid tgfoid);
+static void update_ri_trigger_args(Oid relid,
+					   const char *oldname,
+					   const char *newname,
+					   bool fk_scan,
+					   bool update_relname);
 
-	/*
-	 * Note: PortalCleanup is called as a side-effect
-	 */
-	PortalDrop(portal);
-}
 
 /* ----------------
  *		AlterTableAddColumn
@@ -1856,142 +1656,1427 @@ needs_toast_table(Relation rel)
 	return (tuple_length > TOAST_TUPLE_THRESHOLD);
 }
 
-/*
- * LOCK TABLE
+
+/* ----------------------------------------------------------------
+ *		DefineRelation
+ *				Creates a new relation.
+ *
+ * If successful, returns the OID of the new relation.
+ * ----------------------------------------------------------------
  */
-void
-LockTableCommand(LockStmt *lockstmt)
+Oid
+DefineRelation(CreateStmt *stmt, char relkind)
 {
-	List	   *p;
+	char	   *relname = palloc(NAMEDATALEN);
+	Oid			namespaceId;
+	List	   *schema = stmt->tableElts;
+	int			numberOfAttributes;
+	Oid			relationId;
+	Relation	rel;
+	TupleDesc	descriptor;
+	List	   *inheritOids;
+	List	   *old_constraints;
+	bool		parentHasOids;
+	List	   *rawDefaults;
+	List	   *listptr;
+	int			i;
+	AttrNumber	attnum;
+
+	/*
+	 * Truncate relname to appropriate length (probably a waste of time,
+	 * as parser should have done this already).
+	 */
+	StrNCpy(relname, (stmt->relation)->relname, NAMEDATALEN);
+
+	/*
+	 * Look up the namespace in which we are supposed to create the
+	 * relation.
+	 */
+	namespaceId = RangeVarGetCreationNamespace(stmt->relation);
+
+	/*
+	 * Merge domain attributes into the known columns before processing table
+	 * inheritance.  Otherwise we risk adding double constraints to a
+	 * domain-type column that's inherited.
+	 */
+	schema = MergeDomainAttributes(schema);
+
+	/*
+	 * Look up inheritance ancestors and generate relation schema,
+	 * including inherited attributes.
+	 */
+	schema = MergeAttributes(schema, stmt->inhRelations,
+							 stmt->relation->istemp,
+							 &inheritOids, &old_constraints, &parentHasOids);
+
+	numberOfAttributes = length(schema);
+	if (numberOfAttributes <= 0)
+		elog(ERROR, "DefineRelation: please inherit from a relation or define an attribute");
 
 	/*
-	 * Iterate over the list and open, lock, and close the relations one
-	 * at a time
+	 * Create a relation descriptor from the relation schema and create
+	 * the relation.  Note that in this stage only inherited (pre-cooked)
+	 * defaults and constraints will be included into the new relation.
+	 * (BuildDescForRelation takes care of the inherited defaults, but we
+	 * have to copy inherited constraints here.)
 	 */
+	descriptor = BuildDescForRelation(schema);
 
-	foreach(p, lockstmt->relations)
+	if (old_constraints != NIL)
 	{
-		RangeVar   *relation = lfirst(p);
-		Oid			reloid;
-		int32		aclresult;
-		Relation	rel;
+		ConstrCheck *check = (ConstrCheck *) palloc(length(old_constraints) *
+													sizeof(ConstrCheck));
+		int			ncheck = 0;
 
-		/*
-		 * We don't want to open the relation until we've checked privilege.
-		 * So, manually get the relation OID.
-		 */
-		reloid = RangeVarGetRelid(relation, false);
+		foreach(listptr, old_constraints)
+		{
+			Constraint *cdef = (Constraint *) lfirst(listptr);
 
-		if (lockstmt->mode == AccessShareLock)
-			aclresult = pg_class_aclcheck(reloid, GetUserId(),
-										  ACL_SELECT);
-		else
-			aclresult = pg_class_aclcheck(reloid, GetUserId(),
-										  ACL_UPDATE | ACL_DELETE);
+			if (cdef->contype != CONSTR_CHECK)
+				continue;
+
+			if (cdef->name != NULL)
+			{
+				for (i = 0; i < ncheck; i++)
+				{
+					if (strcmp(check[i].ccname, cdef->name) == 0)
+						elog(ERROR, "Duplicate CHECK constraint name: '%s'",
+							 cdef->name);
+				}
+				check[ncheck].ccname = cdef->name;
+			}
+			else
+			{
+				check[ncheck].ccname = (char *) palloc(NAMEDATALEN);
+				snprintf(check[ncheck].ccname, NAMEDATALEN, "$%d", ncheck + 1);
+			}
+			Assert(cdef->raw_expr == NULL && cdef->cooked_expr != NULL);
+			check[ncheck].ccbin = pstrdup(cdef->cooked_expr);
+			ncheck++;
+		}
+		if (ncheck > 0)
+		{
+			if (descriptor->constr == NULL)
+			{
+				descriptor->constr = (TupleConstr *) palloc(sizeof(TupleConstr));
+				descriptor->constr->defval = NULL;
+				descriptor->constr->num_defval = 0;
+				descriptor->constr->has_not_null = false;
+			}
+			descriptor->constr->num_check = ncheck;
+			descriptor->constr->check = check;
+		}
+	}
+
+	relationId = heap_create_with_catalog(relname,
+										  namespaceId,
+										  descriptor,
+										  relkind,
+										  stmt->hasoids || parentHasOids,
+										  allowSystemTableMods);
+
+	StoreCatalogInheritance(relationId, inheritOids);
+
+	/*
+	 * We must bump the command counter to make the newly-created relation
+	 * tuple visible for opening.
+	 */
+	CommandCounterIncrement();
+
+	/*
+	 * Open the new relation and acquire exclusive lock on it.	This isn't
+	 * really necessary for locking out other backends (since they can't
+	 * see the new rel anyway until we commit), but it keeps the lock
+	 * manager from complaining about deadlock risks.
+	 */
+	rel = heap_open(relationId, AccessExclusiveLock);
+
+	/*
+	 * Now add any newly specified column default values and CHECK
+	 * constraints to the new relation.  These are passed to us in the
+	 * form of raw parsetrees; we need to transform them to executable
+	 * expression trees before they can be added. The most convenient way
+	 * to do that is to apply the parser's transformExpr routine, but
+	 * transformExpr doesn't work unless we have a pre-existing relation.
+	 * So, the transformation has to be postponed to this final step of
+	 * CREATE TABLE.
+	 *
+	 * First, scan schema to find new column defaults.
+	 */
+	rawDefaults = NIL;
+	attnum = 0;
 
-		if (aclresult != ACLCHECK_OK)
-			elog(ERROR, "LOCK TABLE: permission denied");
+	foreach(listptr, schema)
+	{
+		ColumnDef  *colDef = lfirst(listptr);
+		RawColumnDefault *rawEnt;
 
-		rel = relation_open(reloid, lockstmt->mode);
+		attnum++;
 
-		/* Currently, we only allow plain tables to be locked */
-		if (rel->rd_rel->relkind != RELKIND_RELATION)
-			elog(ERROR, "LOCK TABLE: %s is not a table",
-				 relation->relname);
+		if (colDef->raw_default == NULL)
+			continue;
+		Assert(colDef->cooked_default == NULL);
 
-		relation_close(rel, NoLock);	/* close rel, keep lock */
+		rawEnt = (RawColumnDefault *) palloc(sizeof(RawColumnDefault));
+		rawEnt->attnum = attnum;
+		rawEnt->raw_default = colDef->raw_default;
+		rawDefaults = lappend(rawDefaults, rawEnt);
 	}
+
+	/*
+	 * Parse and add the defaults/constraints, if any.
+	 */
+	if (rawDefaults || stmt->constraints)
+		AddRelationRawConstraints(rel, rawDefaults, stmt->constraints);
+
+	/*
+	 * Clean up.  We keep lock on new relation (although it shouldn't be
+	 * visible to anyone else anyway, until commit).
+	 */
+	heap_close(rel, NoLock);
+
+	return relationId;
 }
 
+/*
+ * RemoveRelation
+ *		Deletes a relation.
+ *
+ * Exceptions:
+ *		BadArg if name is invalid.
+ *
+ * Note:
+ *		If the relation has indices defined on it, then the index relations
+ * themselves will be destroyed, too.
+ */
+void
+RemoveRelation(const RangeVar *relation)
+{
+	Oid			relOid;
+
+	relOid = RangeVarGetRelid(relation, false);
+	heap_drop_with_catalog(relOid, allowSystemTableMods);
+}
 
 /*
- * CREATE SCHEMA
+ * TruncateRelation
+ *				  Removes all the rows from a relation
+ *
+ * Exceptions:
+ *				  BadArg if name is invalid
+ *
+ * Note:
+ *				  Rows are removed, indices are truncated and reconstructed.
  */
 void
-CreateSchemaCommand(CreateSchemaStmt *stmt)
+TruncateRelation(const RangeVar *relation)
 {
-	const char *schemaName = stmt->schemaname;
-	const char *authId = stmt->authid;
-	List	   *parsetree_list;
-	List	   *parsetree_item;
-	const char *owner_name;
-	Oid			owner_userid;
-	Oid			saved_userid;
+	Relation	rel;
+	Oid			relid;
 
-	saved_userid = GetUserId();
+	/* Grab exclusive lock in preparation for truncate */
+	rel = heap_openrv(relation, AccessExclusiveLock);
+	relid = RelationGetRelid(rel);
 
-	if (!authId)
-	{
-		owner_userid = saved_userid;
-		owner_name = GetUserName(owner_userid);
-	}
-	else if (superuser())
-	{
-		owner_name = authId;
-		/* The following will error out if user does not exist */
-		owner_userid = get_usesysid(owner_name);
-		/*
-		 * Set the current user to the requested authorization so
-		 * that objects created in the statement have the requested
-		 * owner.  (This will revert to session user on error or at
-		 * the end of this routine.)
-		 */
-		SetUserId(owner_userid);
-	}
-	else /* not superuser */
-	{
-		owner_userid = saved_userid;
-		owner_name = GetUserName(owner_userid);
-		if (strcmp(authId, owner_name) != 0)
-			elog(ERROR, "CREATE SCHEMA: permission denied"
-				 "\n\t\"%s\" is not a superuser, so cannot create a schema for \"%s\"",
-				 owner_name, authId);
-	}
+	if (rel->rd_rel->relkind == RELKIND_SEQUENCE)
+		elog(ERROR, "TRUNCATE cannot be used on sequences. '%s' is a sequence",
+			 RelationGetRelationName(rel));
+
+	if (rel->rd_rel->relkind == RELKIND_VIEW)
+		elog(ERROR, "TRUNCATE cannot be used on views. '%s' is a view",
+			 RelationGetRelationName(rel));
 
-	if (!allowSystemTableMods && IsReservedName(schemaName))
-		elog(ERROR, "CREATE SCHEMA: Illegal schema name: \"%s\" -- pg_ is reserved for system schemas",
-			 schemaName);
+	if (!allowSystemTableMods && IsSystemRelation(rel))
+		elog(ERROR, "TRUNCATE cannot be used on system tables. '%s' is a system table",
+			 RelationGetRelationName(rel));
 
-	/* Create the schema's namespace */
-	NamespaceCreate(schemaName, owner_userid);
+	if (!pg_class_ownercheck(relid, GetUserId()))
+		elog(ERROR, "you do not own relation \"%s\"",
+			 RelationGetRelationName(rel));
 
-	/* Let commands in the schema-element-list know about the schema */
-	CommandCounterIncrement();
+	/* Keep the lock until transaction commit */
+	heap_close(rel, NoLock);
+
+	heap_truncate(relid);
+}
+
+
+/*
+ * MergeDomainAttributes
+ *      Returns a new table schema with the constraints, types, and other
+ *      attributes of domains resolved for fields using a domain as
+ *      their type.
+ */
+static List *
+MergeDomainAttributes(List *schema)
+{
+	List	   *entry;
 
 	/*
-	 * Examine the list of commands embedded in the CREATE SCHEMA command,
-	 * and reorganize them into a sequentially executable order with no
-	 * forward references.  Note that the result is still a list of raw
-	 * parsetrees in need of parse analysis --- we cannot, in general,
-	 * run analyze.c on one statement until we have actually executed the
-	 * prior ones.
+	 * Loop through the table elements supplied. These should
+	 * never include inherited domains else they'll be
+	 * double (or more) processed.
 	 */
-	parsetree_list = analyzeCreateSchemaStmt(stmt);
+	foreach(entry, schema)
+	{
+		ColumnDef  *coldef = lfirst(entry);
+		HeapTuple  tuple;
+		Form_pg_type typeTup;
+
+		tuple = typenameType(coldef->typename);
+		typeTup = (Form_pg_type) GETSTRUCT(tuple);
+
+		if (typeTup->typtype == 'd')
+		{
+			/* Force the column to have the correct typmod. */
+			coldef->typename->typmod = typeTup->typtypmod;
+			/* XXX more to do here? */
+		}
+
+		/* Enforce type NOT NULL || column definition NOT NULL -> NOT NULL */
+		/* Currently only used for domains, but could be valid for all */
+		coldef->is_not_null |= typeTup->typnotnull;
+
+		ReleaseSysCache(tuple);
+	}
+
+	return schema;
+}
+
+/*----------
+ * MergeAttributes
+ *		Returns new schema given initial schema and superclasses.
+ *
+ * Input arguments:
+ * 'schema' is the column/attribute definition for the table. (It's a list
+ *		of ColumnDef's.) It is destructively changed.
+ * 'supers' is a list of names (as RangeVar nodes) of parent relations.
+ * 'istemp' is TRUE if we are creating a temp relation.
+ *
+ * Output arguments:
+ * 'supOids' receives an integer list of the OIDs of the parent relations.
+ * 'supconstr' receives a list of constraints belonging to the parents,
+ *		updated as necessary to be valid for the child.
+ * 'supHasOids' is set TRUE if any parent has OIDs, else it is set FALSE.
+ *
+ * Return value:
+ * Completed schema list.
+ *
+ * Notes:
+ *	  The order in which the attributes are inherited is very important.
+ *	  Intuitively, the inherited attributes should come first. If a table
+ *	  inherits from multiple parents, the order of those attributes are
+ *	  according to the order of the parents specified in CREATE TABLE.
+ *
+ *	  Here's an example:
+ *
+ *		create table person (name text, age int4, location point);
+ *		create table emp (salary int4, manager text) inherits(person);
+ *		create table student (gpa float8) inherits (person);
+ *		create table stud_emp (percent int4) inherits (emp, student);
+ *
+ *	  The order of the attributes of stud_emp is:
+ *
+ *							person {1:name, 2:age, 3:location}
+ *							/	 \
+ *			   {6:gpa}	student   emp {4:salary, 5:manager}
+ *							\	 /
+ *						   stud_emp {7:percent}
+ *
+ *	   If the same attribute name appears multiple times, then it appears
+ *	   in the result table in the proper location for its first appearance.
+ *
+ *	   Constraints (including NOT NULL constraints) for the child table
+ *	   are the union of all relevant constraints, from both the child schema
+ *	   and parent tables.
+ *
+ *	   The default value for a child column is defined as:
+ *		(1) If the child schema specifies a default, that value is used.
+ *		(2) If neither the child nor any parent specifies a default, then
+ *			the column will not have a default.
+ *		(3) If conflicting defaults are inherited from different parents
+ *			(and not overridden by the child), an error is raised.
+ *		(4) Otherwise the inherited default is used.
+ *		Rule (3) is new in Postgres 7.1; in earlier releases you got a
+ *		rather arbitrary choice of which parent default to use.
+ *----------
+ */
+static List *
+MergeAttributes(List *schema, List *supers, bool istemp,
+				List **supOids, List **supconstr, bool *supHasOids)
+{
+	List	   *entry;
+	List	   *inhSchema = NIL;
+	List	   *parentOids = NIL;
+	List	   *constraints = NIL;
+	bool		parentHasOids = false;
+	bool		have_bogus_defaults = false;
+	char	   *bogus_marker = "Bogus!";		/* marks conflicting
+												 * defaults */
+	int			child_attno;
 
 	/*
-	 * Analyze and execute each command contained in the CREATE SCHEMA
+	 * Check for duplicate names in the explicit list of attributes.
+	 *
+	 * Although we might consider merging such entries in the same way that
+	 * we handle name conflicts for inherited attributes, it seems to make
+	 * more sense to assume such conflicts are errors.
 	 */
-	foreach(parsetree_item, parsetree_list)
+	foreach(entry, schema)
 	{
-		Node	   *parsetree = (Node *) lfirst(parsetree_item);
-		List	   *querytree_list,
-				   *querytree_item;
+		ColumnDef  *coldef = lfirst(entry);
+		List	   *rest;
 
-		querytree_list = parse_analyze(parsetree, NULL);
-
-		foreach(querytree_item, querytree_list)
+		foreach(rest, lnext(entry))
 		{
-			Query	   *querytree = (Query *) lfirst(querytree_item);
-
-			/* schemas should contain only utility stmts */
-			Assert(querytree->commandType == CMD_UTILITY);
-			/* do this step */
-			ProcessUtility(querytree->utilityStmt, None, NULL);
-			/* make sure later steps can see the object created here */
-			CommandCounterIncrement();
+			ColumnDef  *restdef = lfirst(rest);
+
+			if (strcmp(coldef->colname, restdef->colname) == 0)
+				elog(ERROR, "CREATE TABLE: attribute \"%s\" duplicated",
+					 coldef->colname);
 		}
 	}
 
-	/* Reset current user */
-	SetUserId(saved_userid);
+	/*
+	 * Scan the parents left-to-right, and merge their attributes to form
+	 * a list of inherited attributes (inhSchema).	Also check to see if
+	 * we need to inherit an OID column.
+	 */
+	child_attno = 0;
+	foreach(entry, supers)
+	{
+		RangeVar   *parent = (RangeVar *) lfirst(entry);
+		Relation	relation;
+		TupleDesc	tupleDesc;
+		TupleConstr *constr;
+		AttrNumber *newattno;
+		AttrNumber	parent_attno;
+
+		relation = heap_openrv(parent, AccessShareLock);
+
+		if (relation->rd_rel->relkind != RELKIND_RELATION)
+			elog(ERROR, "CREATE TABLE: inherited relation \"%s\" is not a table",
+				 parent->relname);
+		/* Permanent rels cannot inherit from temporary ones */
+		if (!istemp && isTempNamespace(RelationGetNamespace(relation)))
+			elog(ERROR, "CREATE TABLE: cannot inherit from temp relation \"%s\"",
+				 parent->relname);
+
+		/*
+		 * We should have an UNDER permission flag for this, but for now,
+		 * demand that creator of a child table own the parent.
+		 */
+		if (!pg_class_ownercheck(RelationGetRelid(relation), GetUserId()))
+			elog(ERROR, "you do not own table \"%s\"",
+				 parent->relname);
+
+		/*
+		 * Reject duplications in the list of parents.
+		 */
+		if (intMember(RelationGetRelid(relation), parentOids))
+			elog(ERROR, "CREATE TABLE: inherited relation \"%s\" duplicated",
+				 parent->relname);
+
+		parentOids = lappendi(parentOids, RelationGetRelid(relation));
+		setRelhassubclassInRelation(RelationGetRelid(relation), true);
+
+		parentHasOids |= relation->rd_rel->relhasoids;
+
+		tupleDesc = RelationGetDescr(relation);
+		constr = tupleDesc->constr;
+
+		/*
+		 * newattno[] will contain the child-table attribute numbers for
+		 * the attributes of this parent table.  (They are not the same
+		 * for parents after the first one.)
+		 */
+		newattno = (AttrNumber *) palloc(tupleDesc->natts * sizeof(AttrNumber));
+
+		for (parent_attno = 1; parent_attno <= tupleDesc->natts;
+			 parent_attno++)
+		{
+			Form_pg_attribute attribute = tupleDesc->attrs[parent_attno - 1];
+			char	   *attributeName = NameStr(attribute->attname);
+			int			exist_attno;
+			ColumnDef  *def;
+			TypeName   *typename;
+
+			/*
+			 * Does it conflict with some previously inherited column?
+			 */
+			exist_attno = findAttrByName(attributeName, inhSchema);
+			if (exist_attno > 0)
+			{
+				/*
+				 * Yes, try to merge the two column definitions. They must
+				 * have the same type and typmod.
+				 */
+				elog(NOTICE, "CREATE TABLE: merging multiple inherited definitions of attribute \"%s\"",
+					 attributeName);
+				def = (ColumnDef *) nth(exist_attno - 1, inhSchema);
+				if (typenameTypeId(def->typename) != attribute->atttypid ||
+					def->typename->typmod != attribute->atttypmod)
+					elog(ERROR, "CREATE TABLE: inherited attribute \"%s\" type conflict (%s and %s)",
+						 attributeName,
+						 TypeNameToString(def->typename),
+						 typeidTypeName(attribute->atttypid));
+				/* Merge of NOT NULL constraints = OR 'em together */
+				def->is_not_null |= attribute->attnotnull;
+				/* Default and other constraints are handled below */
+				newattno[parent_attno - 1] = exist_attno;
+			}
+			else
+			{
+				/*
+				 * No, create a new inherited column
+				 */
+				def = makeNode(ColumnDef);
+				def->colname = pstrdup(attributeName);
+				typename = makeNode(TypeName);
+				typename->typeid = attribute->atttypid;
+				typename->typmod = attribute->atttypmod;
+				def->typename = typename;
+				def->is_not_null = attribute->attnotnull;
+				def->raw_default = NULL;
+				def->cooked_default = NULL;
+				def->constraints = NIL;
+				inhSchema = lappend(inhSchema, def);
+				newattno[parent_attno - 1] = ++child_attno;
+			}
+
+			/*
+			 * Copy default if any
+			 */
+			if (attribute->atthasdef)
+			{
+				char	   *this_default = NULL;
+				AttrDefault *attrdef;
+				int			i;
+
+				/* Find default in constraint structure */
+				Assert(constr != NULL);
+				attrdef = constr->defval;
+				for (i = 0; i < constr->num_defval; i++)
+				{
+					if (attrdef[i].adnum == parent_attno)
+					{
+						this_default = attrdef[i].adbin;
+						break;
+					}
+				}
+				Assert(this_default != NULL);
+
+				/*
+				 * If default expr could contain any vars, we'd need to
+				 * fix 'em, but it can't; so default is ready to apply to
+				 * child.
+				 *
+				 * If we already had a default from some prior parent, check
+				 * to see if they are the same.  If so, no problem; if
+				 * not, mark the column as having a bogus default. Below,
+				 * we will complain if the bogus default isn't overridden
+				 * by the child schema.
+				 */
+				Assert(def->raw_default == NULL);
+				if (def->cooked_default == NULL)
+					def->cooked_default = pstrdup(this_default);
+				else if (strcmp(def->cooked_default, this_default) != 0)
+				{
+					def->cooked_default = bogus_marker;
+					have_bogus_defaults = true;
+				}
+			}
+		}
+
+		/*
+		 * Now copy the constraints of this parent, adjusting attnos using
+		 * the completed newattno[] map
+		 */
+		if (constr && constr->num_check > 0)
+		{
+			ConstrCheck *check = constr->check;
+			int			i;
+
+			for (i = 0; i < constr->num_check; i++)
+			{
+				Constraint *cdef = makeNode(Constraint);
+				Node	   *expr;
+
+				cdef->contype = CONSTR_CHECK;
+				if (check[i].ccname[0] == '$')
+					cdef->name = NULL;
+				else
+					cdef->name = pstrdup(check[i].ccname);
+				cdef->raw_expr = NULL;
+				/* adjust varattnos of ccbin here */
+				expr = stringToNode(check[i].ccbin);
+				change_varattnos_of_a_node(expr, newattno);
+				cdef->cooked_expr = nodeToString(expr);
+				constraints = lappend(constraints, cdef);
+			}
+		}
+
+		pfree(newattno);
+
+		/*
+		 * Close the parent rel, but keep our AccessShareLock on it until
+		 * xact commit.  That will prevent someone else from deleting or
+		 * ALTERing the parent before the child is committed.
+		 */
+		heap_close(relation, NoLock);
+	}
+
+	/*
+	 * If we had no inherited attributes, the result schema is just the
+	 * explicitly declared columns.  Otherwise, we need to merge the
+	 * declared columns into the inherited schema list.
+	 */
+	if (inhSchema != NIL)
+	{
+		foreach(entry, schema)
+		{
+			ColumnDef  *newdef = lfirst(entry);
+			char	   *attributeName = newdef->colname;
+			int			exist_attno;
+
+			/*
+			 * Does it conflict with some previously inherited column?
+			 */
+			exist_attno = findAttrByName(attributeName, inhSchema);
+			if (exist_attno > 0)
+			{
+				ColumnDef  *def;
+
+				/*
+				 * Yes, try to merge the two column definitions. They must
+				 * have the same type and typmod.
+				 */
+				elog(NOTICE, "CREATE TABLE: merging attribute \"%s\" with inherited definition",
+					 attributeName);
+				def = (ColumnDef *) nth(exist_attno - 1, inhSchema);
+				if (typenameTypeId(def->typename) != typenameTypeId(newdef->typename) ||
+					def->typename->typmod != newdef->typename->typmod)
+					elog(ERROR, "CREATE TABLE: attribute \"%s\" type conflict (%s and %s)",
+						 attributeName,
+						 TypeNameToString(def->typename),
+						 TypeNameToString(newdef->typename));
+				/* Merge of NOT NULL constraints = OR 'em together */
+				def->is_not_null |= newdef->is_not_null;
+				/* If new def has a default, override previous default */
+				if (newdef->raw_default != NULL)
+				{
+					def->raw_default = newdef->raw_default;
+					def->cooked_default = newdef->cooked_default;
+				}
+			}
+			else
+			{
+				/*
+				 * No, attach new column to result schema
+				 */
+				inhSchema = lappend(inhSchema, newdef);
+			}
+		}
+
+		schema = inhSchema;
+	}
+
+	/*
+	 * If we found any conflicting parent default values, check to make
+	 * sure they were overridden by the child.
+	 */
+	if (have_bogus_defaults)
+	{
+		foreach(entry, schema)
+		{
+			ColumnDef  *def = lfirst(entry);
+
+			if (def->cooked_default == bogus_marker)
+				elog(ERROR, "CREATE TABLE: attribute \"%s\" inherits conflicting default values"
+					 "\n\tTo resolve the conflict, specify a default explicitly",
+					 def->colname);
+		}
+	}
+
+	*supOids = parentOids;
+	*supconstr = constraints;
+	*supHasOids = parentHasOids;
+	return schema;
+}
+
+/*
+ * complementary static functions for MergeAttributes().
+ *
+ * Varattnos of pg_relcheck.rcbin must be rewritten when subclasses inherit
+ * constraints from parent classes, since the inherited attributes could
+ * be given different column numbers in multiple-inheritance cases.
+ *
+ * Note that the passed node tree is modified in place!
+ */
+static bool
+change_varattnos_walker(Node *node, const AttrNumber *newattno)
+{
+	if (node == NULL)
+		return false;
+	if (IsA(node, Var))
+	{
+		Var		   *var = (Var *) node;
+
+		if (var->varlevelsup == 0 && var->varno == 1 &&
+			var->varattno > 0)
+		{
+			/*
+			 * ??? the following may be a problem when the node is
+			 * multiply referenced though stringToNode() doesn't create
+			 * such a node currently.
+			 */
+			Assert(newattno[var->varattno - 1] > 0);
+			var->varattno = newattno[var->varattno - 1];
+		}
+		return false;
+	}
+	return expression_tree_walker(node, change_varattnos_walker,
+								  (void *) newattno);
+}
+
+static bool
+change_varattnos_of_a_node(Node *node, const AttrNumber *newattno)
+{
+	return change_varattnos_walker(node, newattno);
+}
+
+/*
+ * StoreCatalogInheritance
+ *		Updates the system catalogs with proper inheritance information.
+ *
+ * supers is an integer list of the OIDs of the new relation's direct
+ * ancestors.  NB: it is destructively changed to include indirect ancestors.
+ */
+static void
+StoreCatalogInheritance(Oid relationId, List *supers)
+{
+	Relation	relation;
+	TupleDesc	desc;
+	int16		seqNumber;
+	List	   *entry;
+	HeapTuple	tuple;
+
+	/*
+	 * sanity checks
+	 */
+	AssertArg(OidIsValid(relationId));
+
+	if (supers == NIL)
+		return;
+
+	/*
+	 * Catalog INHERITS information using direct ancestors only.
+	 */
+	relation = heap_openr(InheritsRelationName, RowExclusiveLock);
+	desc = RelationGetDescr(relation);
+
+	seqNumber = 1;
+	foreach(entry, supers)
+	{
+		Oid			entryOid = lfirsti(entry);
+		Datum		datum[Natts_pg_inherits];
+		char		nullarr[Natts_pg_inherits];
+
+		datum[0] = ObjectIdGetDatum(relationId);		/* inhrel */
+		datum[1] = ObjectIdGetDatum(entryOid);	/* inhparent */
+		datum[2] = Int16GetDatum(seqNumber);	/* inhseqno */
+
+		nullarr[0] = ' ';
+		nullarr[1] = ' ';
+		nullarr[2] = ' ';
+
+		tuple = heap_formtuple(desc, datum, nullarr);
+
+		heap_insert(relation, tuple);
+
+		if (RelationGetForm(relation)->relhasindex)
+		{
+			Relation	idescs[Num_pg_inherits_indices];
+
+			CatalogOpenIndices(Num_pg_inherits_indices, Name_pg_inherits_indices, idescs);
+			CatalogIndexInsert(idescs, Num_pg_inherits_indices, relation, tuple);
+			CatalogCloseIndices(Num_pg_inherits_indices, idescs);
+		}
+
+		heap_freetuple(tuple);
+
+		seqNumber += 1;
+	}
+
+	heap_close(relation, RowExclusiveLock);
+
+	/* ----------------
+	 * Expand supers list to include indirect ancestors as well.
+	 *
+	 * Algorithm:
+	 *	0. begin with list of direct superclasses.
+	 *	1. append after each relationId, its superclasses, recursively.
+	 *	2. remove all but last of duplicates.
+	 * ----------------
+	 */
+
+	/*
+	 * 1. append after each relationId, its superclasses, recursively.
+	 */
+	foreach(entry, supers)
+	{
+		HeapTuple	tuple;
+		Oid			id;
+		int16		number;
+		List	   *next;
+		List	   *current;
+
+		id = (Oid) lfirsti(entry);
+		current = entry;
+		next = lnext(entry);
+
+		for (number = 1;; number += 1)
+		{
+			tuple = SearchSysCache(INHRELID,
+								   ObjectIdGetDatum(id),
+								   Int16GetDatum(number),
+								   0, 0);
+			if (!HeapTupleIsValid(tuple))
+				break;
+
+			lnext(current) = lconsi(((Form_pg_inherits)
+									 GETSTRUCT(tuple))->inhparent,
+									NIL);
+
+			ReleaseSysCache(tuple);
+
+			current = lnext(current);
+		}
+		lnext(current) = next;
+	}
+
+	/*
+	 * 2. remove all but last of duplicates.
+	 */
+	foreach(entry, supers)
+	{
+		Oid			thisone;
+		bool		found;
+		List	   *rest;
+
+again:
+		thisone = lfirsti(entry);
+		found = false;
+		foreach(rest, lnext(entry))
+		{
+			if (thisone == lfirsti(rest))
+			{
+				found = true;
+				break;
+			}
+		}
+		if (found)
+		{
+			/*
+			 * found a later duplicate, so remove this entry.
+			 */
+			lfirsti(entry) = lfirsti(lnext(entry));
+			lnext(entry) = lnext(lnext(entry));
+
+			goto again;
+		}
+	}
+}
+
+/*
+ * Look for an existing schema entry with the given name.
+ *
+ * Returns the index (starting with 1) if attribute already exists in schema,
+ * 0 if it doesn't.
+ */
+static int
+findAttrByName(const char *attributeName, List *schema)
+{
+	List	   *s;
+	int			i = 0;
+
+	foreach(s, schema)
+	{
+		ColumnDef  *def = lfirst(s);
+
+		++i;
+		if (strcmp(attributeName, def->colname) == 0)
+			return i;
+	}
+	return 0;
+}
+
+/*
+ * Update a relation's pg_class.relhassubclass entry to the given value
+ */
+static void
+setRelhassubclassInRelation(Oid relationId, bool relhassubclass)
+{
+	Relation	relationRelation;
+	HeapTuple	tuple;
+	Relation	idescs[Num_pg_class_indices];
+
+	/*
+	 * Fetch a modifiable copy of the tuple, modify it, update pg_class.
+	 */
+	relationRelation = heap_openr(RelationRelationName, RowExclusiveLock);
+	tuple = SearchSysCacheCopy(RELOID,
+							   ObjectIdGetDatum(relationId),
+							   0, 0, 0);
+	if (!HeapTupleIsValid(tuple))
+		elog(ERROR, "setRelhassubclassInRelation: cache lookup failed for relation %u", relationId);
+
+	((Form_pg_class) GETSTRUCT(tuple))->relhassubclass = relhassubclass;
+	simple_heap_update(relationRelation, &tuple->t_self, tuple);
+
+	/* keep the catalog indices up to date */
+	CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, idescs);
+	CatalogIndexInsert(idescs, Num_pg_class_indices, relationRelation, tuple);
+	CatalogCloseIndices(Num_pg_class_indices, idescs);
+
+	heap_freetuple(tuple);
+	heap_close(relationRelation, RowExclusiveLock);
+}
+
+
+/*
+ *		renameatt		- changes the name of a attribute in a relation
+ *
+ *		Attname attribute is changed in attribute catalog.
+ *		No record of the previous attname is kept (correct?).
+ *
+ *		get proper relrelation from relation catalog (if not arg)
+ *		scan attribute catalog
+ *				for name conflict (within rel)
+ *				for original attribute (if not arg)
+ *		modify attname in attribute tuple
+ *		insert modified attribute in attribute catalog
+ *		delete original attribute from attribute catalog
+ */
+void
+renameatt(Oid relid,
+		  const char *oldattname,
+		  const char *newattname,
+		  bool recurse)
+{
+	Relation	targetrelation;
+	Relation	attrelation;
+	HeapTuple	atttup;
+	List	   *indexoidlist;
+	List	   *indexoidscan;
+
+	/*
+	 * Grab an exclusive lock on the target table, which we will NOT
+	 * release until end of transaction.
+	 */
+	targetrelation = heap_open(relid, AccessExclusiveLock);
+
+	/*
+	 * permissions checking.  this would normally be done in utility.c,
+	 * but this particular routine is recursive.
+	 *
+	 * normally, only the owner of a class can change its schema.
+	 */
+	if (!allowSystemTableMods 
+		&& IsSystemRelation(targetrelation))
+		elog(ERROR, "renameatt: class \"%s\" is a system catalog",
+			 RelationGetRelationName(targetrelation));
+	if (!pg_class_ownercheck(relid, GetUserId()))
+		elog(ERROR, "renameatt: you do not own class \"%s\"",
+			 RelationGetRelationName(targetrelation));
+
+	/*
+	 * if the 'recurse' flag is set then we are supposed to rename this
+	 * attribute in all classes that inherit from 'relname' (as well as in
+	 * 'relname').
+	 *
+	 * any permissions or problems with duplicate attributes will cause the
+	 * whole transaction to abort, which is what we want -- all or
+	 * nothing.
+	 */
+	if (recurse)
+	{
+		List	   *child,
+				   *children;
+
+		/* this routine is actually in the planner */
+		children = find_all_inheritors(relid);
+
+		/*
+		 * find_all_inheritors does the recursive search of the
+		 * inheritance hierarchy, so all we have to do is process all of
+		 * the relids in the list that it returns.
+		 */
+		foreach(child, children)
+		{
+			Oid			childrelid = lfirsti(child);
+
+			if (childrelid == relid)
+				continue;
+			/* note we need not recurse again! */
+			renameatt(childrelid, oldattname, newattname, false);
+		}
+	}
+
+	attrelation = heap_openr(AttributeRelationName, RowExclusiveLock);
+
+	atttup = SearchSysCacheCopy(ATTNAME,
+								ObjectIdGetDatum(relid),
+								PointerGetDatum(oldattname),
+								0, 0);
+	if (!HeapTupleIsValid(atttup))
+		elog(ERROR, "renameatt: attribute \"%s\" does not exist", oldattname);
+
+	if (((Form_pg_attribute) GETSTRUCT(atttup))->attnum < 0)
+		elog(ERROR, "renameatt: system attribute \"%s\" not renamed", oldattname);
+
+	/* should not already exist */
+	if (SearchSysCacheExists(ATTNAME,
+							 ObjectIdGetDatum(relid),
+							 PointerGetDatum(newattname),
+							 0, 0))
+		elog(ERROR, "renameatt: attribute \"%s\" exists", newattname);
+
+	StrNCpy(NameStr(((Form_pg_attribute) GETSTRUCT(atttup))->attname),
+			newattname, NAMEDATALEN);
+
+	simple_heap_update(attrelation, &atttup->t_self, atttup);
+
+	/* keep system catalog indices current */
+	{
+		Relation	irelations[Num_pg_attr_indices];
+
+		CatalogOpenIndices(Num_pg_attr_indices, Name_pg_attr_indices, irelations);
+		CatalogIndexInsert(irelations, Num_pg_attr_indices, attrelation, atttup);
+		CatalogCloseIndices(Num_pg_attr_indices, irelations);
+	}
+
+	heap_freetuple(atttup);
+
+	/*
+	 * Update column names of indexes that refer to the column being
+	 * renamed.
+	 */
+	indexoidlist = RelationGetIndexList(targetrelation);
+
+	foreach(indexoidscan, indexoidlist)
+	{
+		Oid			indexoid = lfirsti(indexoidscan);
+		HeapTuple	indextup;
+
+		/*
+		 * First check to see if index is a functional index. If so, its
+		 * column name is a function name and shouldn't be renamed here.
+		 */
+		indextup = SearchSysCache(INDEXRELID,
+								  ObjectIdGetDatum(indexoid),
+								  0, 0, 0);
+		if (!HeapTupleIsValid(indextup))
+			elog(ERROR, "renameatt: can't find index id %u", indexoid);
+		if (OidIsValid(((Form_pg_index) GETSTRUCT(indextup))->indproc))
+		{
+			ReleaseSysCache(indextup);
+			continue;
+		}
+		ReleaseSysCache(indextup);
+
+		/*
+		 * Okay, look to see if any column name of the index matches the
+		 * old attribute name.
+		 */
+		atttup = SearchSysCacheCopy(ATTNAME,
+									ObjectIdGetDatum(indexoid),
+									PointerGetDatum(oldattname),
+									0, 0);
+		if (!HeapTupleIsValid(atttup))
+			continue;			/* Nope, so ignore it */
+
+		/*
+		 * Update the (copied) attribute tuple.
+		 */
+		StrNCpy(NameStr(((Form_pg_attribute) GETSTRUCT(atttup))->attname),
+				newattname, NAMEDATALEN);
+
+		simple_heap_update(attrelation, &atttup->t_self, atttup);
+
+		/* keep system catalog indices current */
+		{
+			Relation	irelations[Num_pg_attr_indices];
+
+			CatalogOpenIndices(Num_pg_attr_indices, Name_pg_attr_indices, irelations);
+			CatalogIndexInsert(irelations, Num_pg_attr_indices, attrelation, atttup);
+			CatalogCloseIndices(Num_pg_attr_indices, irelations);
+		}
+		heap_freetuple(atttup);
+	}
+
+	freeList(indexoidlist);
+
+	heap_close(attrelation, RowExclusiveLock);
+
+	/*
+	 * Update att name in any RI triggers associated with the relation.
+	 */
+	if (targetrelation->rd_rel->reltriggers > 0)
+	{
+		/* update tgargs column reference where att is primary key */
+		update_ri_trigger_args(RelationGetRelid(targetrelation),
+							   oldattname, newattname,
+							   false, false);
+		/* update tgargs column reference where att is foreign key */
+		update_ri_trigger_args(RelationGetRelid(targetrelation),
+							   oldattname, newattname,
+							   true, false);
+	}
+
+	heap_close(targetrelation, NoLock); /* close rel but keep lock! */
+}
+
+/*
+ *		renamerel		- change the name of a relation
+ *
+ *		XXX - When renaming sequences, we don't bother to modify the
+ *			  sequence name that is stored within the sequence itself
+ *			  (this would cause problems with MVCC). In the future,
+ *			  the sequence name should probably be removed from the
+ *			  sequence, AFAIK there's no need for it to be there.
+ */
+void
+renamerel(Oid relid, const char *newrelname)
+{
+	Relation	targetrelation;
+	Relation	relrelation;	/* for RELATION relation */
+	HeapTuple	reltup;
+	Oid			namespaceId;
+	char		relkind;
+	bool		relhastriggers;
+	Relation	irelations[Num_pg_class_indices];
+
+	/*
+	 * Grab an exclusive lock on the target table or index, which we will
+	 * NOT release until end of transaction.
+	 */
+	targetrelation = relation_open(relid, AccessExclusiveLock);
+
+	namespaceId = RelationGetNamespace(targetrelation);
+
+	/* Validity checks */
+	if (!allowSystemTableMods &&
+		IsSystemRelation(targetrelation))
+		elog(ERROR, "renamerel: system relation \"%s\" may not be renamed",
+			 RelationGetRelationName(targetrelation));
+
+	relkind = targetrelation->rd_rel->relkind;
+	relhastriggers = (targetrelation->rd_rel->reltriggers > 0);
+
+	/*
+	 * Find relation's pg_class tuple, and make sure newrelname isn't in
+	 * use.
+	 */
+	relrelation = heap_openr(RelationRelationName, RowExclusiveLock);
+
+	reltup = SearchSysCacheCopy(RELOID,
+								PointerGetDatum(relid),
+								0, 0, 0);
+	if (!HeapTupleIsValid(reltup))
+		elog(ERROR, "renamerel: relation \"%s\" does not exist",
+			 RelationGetRelationName(targetrelation));
+
+	if (get_relname_relid(newrelname, namespaceId) != InvalidOid)
+		elog(ERROR, "renamerel: relation \"%s\" exists", newrelname);
+
+	/*
+	 * Update pg_class tuple with new relname.	(Scribbling on reltup is
+	 * OK because it's a copy...)
+	 */
+	StrNCpy(NameStr(((Form_pg_class) GETSTRUCT(reltup))->relname),
+			newrelname, NAMEDATALEN);
+
+	simple_heap_update(relrelation, &reltup->t_self, reltup);
+
+	/* keep the system catalog indices current */
+	CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, irelations);
+	CatalogIndexInsert(irelations, Num_pg_class_indices, relrelation, reltup);
+	CatalogCloseIndices(Num_pg_class_indices, irelations);
+
+	heap_close(relrelation, NoLock);
+	heap_freetuple(reltup);
+
+	/*
+	 * Also rename the associated type, if any.
+	 */
+	if (relkind != RELKIND_INDEX)
+		TypeRename(RelationGetRelationName(targetrelation), namespaceId,
+				   newrelname);
+
+	/*
+	 * If it's a view, must also rename the associated ON SELECT rule.
+	 */
+	if (relkind == RELKIND_VIEW)
+	{
+		char	   *oldrulename,
+				   *newrulename;
+
+		oldrulename = MakeRetrieveViewRuleName(RelationGetRelationName(targetrelation));
+		newrulename = MakeRetrieveViewRuleName(newrelname);
+		RenameRewriteRule(oldrulename, newrulename);
+	}
+
+	/*
+	 * Update rel name in any RI triggers associated with the relation.
+	 */
+	if (relhastriggers)
+	{
+		/* update tgargs where relname is primary key */
+		update_ri_trigger_args(relid,
+							   RelationGetRelationName(targetrelation),
+							   newrelname,
+							   false, true);
+		/* update tgargs where relname is foreign key */
+		update_ri_trigger_args(relid,
+							   RelationGetRelationName(targetrelation),
+							   newrelname,
+							   true, true);
+	}
+
+	/*
+	 * Close rel, but keep exclusive lock!
+	 */
+	relation_close(targetrelation, NoLock);
+}
+
+/*
+ * Given a trigger function OID, determine whether it is an RI trigger,
+ * and if so whether it is attached to PK or FK relation.
+ *
+ * XXX this probably doesn't belong here; should be exported by
+ * ri_triggers.c
+ */
+static int
+ri_trigger_type(Oid tgfoid)
+{
+	switch (tgfoid)
+	{
+		case F_RI_FKEY_CASCADE_DEL:
+		case F_RI_FKEY_CASCADE_UPD:
+		case F_RI_FKEY_RESTRICT_DEL:
+		case F_RI_FKEY_RESTRICT_UPD:
+		case F_RI_FKEY_SETNULL_DEL:
+		case F_RI_FKEY_SETNULL_UPD:
+		case F_RI_FKEY_SETDEFAULT_DEL:
+		case F_RI_FKEY_SETDEFAULT_UPD:
+		case F_RI_FKEY_NOACTION_DEL:
+		case F_RI_FKEY_NOACTION_UPD:
+			return RI_TRIGGER_PK;
+
+		case F_RI_FKEY_CHECK_INS:
+		case F_RI_FKEY_CHECK_UPD:
+			return RI_TRIGGER_FK;
+	}
+
+	return RI_TRIGGER_NONE;
+}
+
+/*
+ * Scan pg_trigger for RI triggers that are on the specified relation
+ * (if fk_scan is false) or have it as the tgconstrrel (if fk_scan
+ * is true).  Update RI trigger args fields matching oldname to contain
+ * newname instead.  If update_relname is true, examine the relname
+ * fields; otherwise examine the attname fields.
+ */
+static void
+update_ri_trigger_args(Oid relid,
+					   const char *oldname,
+					   const char *newname,
+					   bool fk_scan,
+					   bool update_relname)
+{
+	Relation	tgrel;
+	Relation	irel;
+	ScanKeyData skey[1];
+	IndexScanDesc idxtgscan;
+	RetrieveIndexResult idxres;
+	Datum		values[Natts_pg_trigger];
+	char		nulls[Natts_pg_trigger];
+	char		replaces[Natts_pg_trigger];
+
+	tgrel = heap_openr(TriggerRelationName, RowExclusiveLock);
+	if (fk_scan)
+		irel = index_openr(TriggerConstrRelidIndex);
+	else
+		irel = index_openr(TriggerRelidIndex);
+
+	ScanKeyEntryInitialize(&skey[0], 0x0,
+						   1,	/* always column 1 of index */
+						   F_OIDEQ,
+						   ObjectIdGetDatum(relid));
+	idxtgscan = index_beginscan(irel, false, 1, skey);
+
+	while ((idxres = index_getnext(idxtgscan, ForwardScanDirection)) != NULL)
+	{
+		HeapTupleData tupledata;
+		Buffer		buffer;
+		HeapTuple	tuple;
+		Form_pg_trigger pg_trigger;
+		bytea	   *val;
+		bytea	   *newtgargs;
+		bool		isnull;
+		int			tg_type;
+		bool		examine_pk;
+		bool		changed;
+		int			tgnargs;
+		int			i;
+		int			newlen;
+		const char *arga[RI_MAX_ARGUMENTS];
+		const char *argp;
+
+		tupledata.t_self = idxres->heap_iptr;
+		heap_fetch(tgrel, SnapshotNow, &tupledata, &buffer, idxtgscan);
+		pfree(idxres);
+		if (!tupledata.t_data)
+			continue;
+		tuple = &tupledata;
+		pg_trigger = (Form_pg_trigger) GETSTRUCT(tuple);
+		tg_type = ri_trigger_type(pg_trigger->tgfoid);
+		if (tg_type == RI_TRIGGER_NONE)
+		{
+			/* Not an RI trigger, forget it */
+			ReleaseBuffer(buffer);
+			continue;
+		}
+
+		/*
+		 * It is an RI trigger, so parse the tgargs bytea.
+		 *
+		 * NB: we assume the field will never be compressed or moved out of
+		 * line; so does trigger.c ...
+		 */
+		tgnargs = pg_trigger->tgnargs;
+		val = (bytea *) fastgetattr(tuple,
+									Anum_pg_trigger_tgargs,
+									tgrel->rd_att, &isnull);
+		if (isnull || tgnargs < RI_FIRST_ATTNAME_ARGNO ||
+			tgnargs > RI_MAX_ARGUMENTS)
+		{
+			/* This probably shouldn't happen, but ignore busted triggers */
+			ReleaseBuffer(buffer);
+			continue;
+		}
+		argp = (const char *) VARDATA(val);
+		for (i = 0; i < tgnargs; i++)
+		{
+			arga[i] = argp;
+			argp += strlen(argp) + 1;
+		}
+
+		/*
+		 * Figure out which item(s) to look at.  If the trigger is
+		 * primary-key type and attached to my rel, I should look at the
+		 * PK fields; if it is foreign-key type and attached to my rel, I
+		 * should look at the FK fields.  But the opposite rule holds when
+		 * examining triggers found by tgconstrrel search.
+		 */
+		examine_pk = (tg_type == RI_TRIGGER_PK) == (!fk_scan);
+
+		changed = false;
+		if (update_relname)
+		{
+			/* Change the relname if needed */
+			i = examine_pk ? RI_PK_RELNAME_ARGNO : RI_FK_RELNAME_ARGNO;
+			if (strcmp(arga[i], oldname) == 0)
+			{
+				arga[i] = newname;
+				changed = true;
+			}
+		}
+		else
+		{
+			/* Change attname(s) if needed */
+			i = examine_pk ? RI_FIRST_ATTNAME_ARGNO + RI_KEYPAIR_PK_IDX :
+				RI_FIRST_ATTNAME_ARGNO + RI_KEYPAIR_FK_IDX;
+			for (; i < tgnargs; i += 2)
+			{
+				if (strcmp(arga[i], oldname) == 0)
+				{
+					arga[i] = newname;
+					changed = true;
+				}
+			}
+		}
+
+		if (!changed)
+		{
+			/* Don't need to update this tuple */
+			ReleaseBuffer(buffer);
+			continue;
+		}
+
+		/*
+		 * Construct modified tgargs bytea.
+		 */
+		newlen = VARHDRSZ;
+		for (i = 0; i < tgnargs; i++)
+			newlen += strlen(arga[i]) + 1;
+		newtgargs = (bytea *) palloc(newlen);
+		VARATT_SIZEP(newtgargs) = newlen;
+		newlen = VARHDRSZ;
+		for (i = 0; i < tgnargs; i++)
+		{
+			strcpy(((char *) newtgargs) + newlen, arga[i]);
+			newlen += strlen(arga[i]) + 1;
+		}
+
+		/*
+		 * Build modified tuple.
+		 */
+		for (i = 0; i < Natts_pg_trigger; i++)
+		{
+			values[i] = (Datum) 0;
+			replaces[i] = ' ';
+			nulls[i] = ' ';
+		}
+		values[Anum_pg_trigger_tgargs - 1] = PointerGetDatum(newtgargs);
+		replaces[Anum_pg_trigger_tgargs - 1] = 'r';
+
+		tuple = heap_modifytuple(tuple, tgrel, values, nulls, replaces);
+
+		/*
+		 * Now we can release hold on original tuple.
+		 */
+		ReleaseBuffer(buffer);
+
+		/*
+		 * Update pg_trigger and its indexes
+		 */
+		simple_heap_update(tgrel, &tuple->t_self, tuple);
+
+		{
+			Relation	irelations[Num_pg_attr_indices];
+
+			CatalogOpenIndices(Num_pg_trigger_indices, Name_pg_trigger_indices, irelations);
+			CatalogIndexInsert(irelations, Num_pg_trigger_indices, tgrel, tuple);
+			CatalogCloseIndices(Num_pg_trigger_indices, irelations);
+		}
+
+		/* free up our scratch memory */
+		pfree(newtgargs);
+		heap_freetuple(tuple);
+	}
+
+	index_endscan(idxtgscan);
+	index_close(irel);
+
+	heap_close(tgrel, RowExclusiveLock);
+
+	/*
+	 * Increment cmd counter to make updates visible; this is needed in
+	 * case the same tuple has to be updated again by next pass (can
+	 * happen in case of a self-referential FK relationship).
+	 */
+	CommandCounterIncrement();
 }
diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c
new file mode 100644
index 0000000000000000000000000000000000000000..13dbf04aaacf6e30b9e2007a652521aeebd56092
--- /dev/null
+++ b/src/backend/commands/typecmds.c
@@ -0,0 +1,660 @@
+/*-------------------------------------------------------------------------
+ *
+ * typecmds.c
+ *	  Routines for SQL commands that manipulate types (and domains).
+ *
+ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/typecmds.c,v 1.1 2002/04/15 05:22:03 tgl Exp $
+ *
+ * DESCRIPTION
+ *	  The "DefineFoo" routines take the parse tree and pick out the
+ *	  appropriate arguments/flags, passing the results to the
+ *	  corresponding "FooDefine" routines (in src/catalog) that do
+ *	  the actual catalog-munging.  These routines also verify permission
+ *	  of the user to execute the command.
+ *
+ * NOTES
+ *	  These things must be defined and committed in the following order:
+ *		"create function":
+ *				input/output, recv/send procedures
+ *		"create type":
+ *				type
+ *		"create operator":
+ *				operators
+ *
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "access/heapam.h"
+#include "catalog/catname.h"
+#include "catalog/heap.h"
+#include "catalog/namespace.h"
+#include "catalog/pg_type.h"
+#include "commands/comment.h"
+#include "commands/defrem.h"
+#include "miscadmin.h"
+#include "parser/parse.h"
+#include "parser/parse_func.h"
+#include "parser/parse_type.h"
+#include "utils/acl.h"
+#include "utils/builtins.h"
+#include "utils/fmgroids.h"
+#include "utils/syscache.h"
+
+
+static Oid findTypeIOFunction(List *procname, bool isOutput);
+
+
+/*
+ * DefineType
+ *		Registers a new type.
+ */
+void
+DefineType(List *names, List *parameters)
+{
+	char	   *typeName;
+	Oid			typeNamespace;
+	int16		internalLength = -1;	/* int2 */
+	int16		externalLength = -1;	/* int2 */
+	Oid			elemType = InvalidOid;
+	List	   *inputName = NIL;
+	List	   *outputName = NIL;
+	List	   *sendName = NIL;
+	List	   *receiveName = NIL;
+	char	   *defaultValue = NULL;
+	bool		byValue = false;
+	char		delimiter = DEFAULT_TYPDELIM;
+	char		alignment = 'i';	/* default alignment */
+	char		storage = 'p';	/* default TOAST storage method */
+	Oid			inputOid;
+	Oid			outputOid;
+	Oid			sendOid;
+	Oid			receiveOid;
+	char	   *shadow_type;
+	List	   *pl;
+	Oid			typoid;
+
+	/* Convert list of names to a name and namespace */
+	typeNamespace = QualifiedNameGetCreationNamespace(names, &typeName);
+
+	/*
+	 * Type names must be one character shorter than other names, allowing
+	 * room to create the corresponding array type name with prepended
+	 * "_".
+	 */
+	if (strlen(typeName) > (NAMEDATALEN - 2))
+		elog(ERROR, "DefineType: type names must be %d characters or less",
+			 NAMEDATALEN - 2);
+
+	foreach(pl, parameters)
+	{
+		DefElem    *defel = (DefElem *) lfirst(pl);
+
+		if (strcasecmp(defel->defname, "internallength") == 0)
+			internalLength = defGetTypeLength(defel);
+		else if (strcasecmp(defel->defname, "externallength") == 0)
+			externalLength = defGetTypeLength(defel);
+		else if (strcasecmp(defel->defname, "input") == 0)
+			inputName = defGetQualifiedName(defel);
+		else if (strcasecmp(defel->defname, "output") == 0)
+			outputName = defGetQualifiedName(defel);
+		else if (strcasecmp(defel->defname, "send") == 0)
+			sendName = defGetQualifiedName(defel);
+		else if (strcasecmp(defel->defname, "receive") == 0)
+			receiveName = defGetQualifiedName(defel);
+		else if (strcasecmp(defel->defname, "delimiter") == 0)
+		{
+			char	   *p = defGetString(defel);
+
+			delimiter = p[0];
+		}
+		else if (strcasecmp(defel->defname, "element") == 0)
+			elemType = typenameTypeId(defGetTypeName(defel));
+		else if (strcasecmp(defel->defname, "default") == 0)
+			defaultValue = defGetString(defel);
+		else if (strcasecmp(defel->defname, "passedbyvalue") == 0)
+			byValue = true;
+		else if (strcasecmp(defel->defname, "alignment") == 0)
+		{
+			char	   *a = defGetString(defel);
+
+			/*
+			 * Note: if argument was an unquoted identifier, parser will
+			 * have applied xlateSqlType() to it, so be prepared to
+			 * recognize translated type names as well as the nominal
+			 * form.
+			 */
+			if (strcasecmp(a, "double") == 0)
+				alignment = 'd';
+			else if (strcasecmp(a, "float8") == 0)
+				alignment = 'd';
+			else if (strcasecmp(a, "int4") == 0)
+				alignment = 'i';
+			else if (strcasecmp(a, "int2") == 0)
+				alignment = 's';
+			else if (strcasecmp(a, "char") == 0)
+				alignment = 'c';
+			else if (strcasecmp(a, "bpchar") == 0)
+				alignment = 'c';
+			else
+				elog(ERROR, "DefineType: \"%s\" alignment not recognized",
+					 a);
+		}
+		else if (strcasecmp(defel->defname, "storage") == 0)
+		{
+			char	   *a = defGetString(defel);
+
+			if (strcasecmp(a, "plain") == 0)
+				storage = 'p';
+			else if (strcasecmp(a, "external") == 0)
+				storage = 'e';
+			else if (strcasecmp(a, "extended") == 0)
+				storage = 'x';
+			else if (strcasecmp(a, "main") == 0)
+				storage = 'm';
+			else
+				elog(ERROR, "DefineType: \"%s\" storage not recognized",
+					 a);
+		}
+		else
+		{
+			elog(WARNING, "DefineType: attribute \"%s\" not recognized",
+				 defel->defname);
+		}
+	}
+
+	/*
+	 * make sure we have our required definitions
+	 */
+	if (inputName == NIL)
+		elog(ERROR, "Define: \"input\" unspecified");
+	if (outputName == NIL)
+		elog(ERROR, "Define: \"output\" unspecified");
+
+	/* Convert I/O proc names to OIDs */
+	inputOid = findTypeIOFunction(inputName, false);
+	outputOid = findTypeIOFunction(outputName, true);
+	if (sendName)
+		sendOid = findTypeIOFunction(sendName, true);
+	else
+		sendOid = outputOid;
+	if (receiveName)
+		receiveOid = findTypeIOFunction(receiveName, false);
+	else
+		receiveOid = inputOid;
+
+	/*
+	 * now have TypeCreate do all the real work.
+	 */
+	typoid =
+		TypeCreate(typeName,		/* type name */
+				   typeNamespace,	/* namespace */
+				   InvalidOid,		/* preassigned type oid (not done here) */
+				   InvalidOid,		/* relation oid (n/a here) */
+				   internalLength,	/* internal size */
+				   externalLength,	/* external size */
+				   'b',				/* type-type (base type) */
+				   delimiter,		/* array element delimiter */
+				   inputOid,		/* input procedure */
+				   outputOid,		/* output procedure */
+				   receiveOid,		/* receive procedure */
+				   sendOid,			/* send procedure */
+				   elemType,		/* element type ID */
+				   InvalidOid,		/* base type ID (only for domains) */
+				   defaultValue,	/* default type value */
+				   NULL,			/* no binary form available */
+				   byValue,			/* passed by value */
+				   alignment,		/* required alignment */
+				   storage,			/* TOAST strategy */
+				   -1,				/* typMod (Domains only) */
+				   0,				/* Array Dimensions of typbasetype */
+				   false);			/* Type NOT NULL */
+
+	/*
+	 * When we create a base type (as opposed to a complex type) we need
+	 * to have an array entry for it in pg_type as well.
+	 */
+	shadow_type = makeArrayTypeName(typeName);
+
+	/* alignment must be 'i' or 'd' for arrays */
+	alignment = (alignment == 'd') ? 'd' : 'i';
+
+	TypeCreate(shadow_type,		/* type name */
+			   typeNamespace,	/* namespace */
+			   InvalidOid,		/* preassigned type oid (not done here) */
+			   InvalidOid,		/* relation oid (n/a here) */
+			   -1,				/* internal size */
+			   -1,				/* external size */
+			   'b',				/* type-type (base type) */
+			   DEFAULT_TYPDELIM,	/* array element delimiter */
+			   F_ARRAY_IN,		/* input procedure */
+			   F_ARRAY_OUT,		/* output procedure */
+			   F_ARRAY_IN,		/* receive procedure */
+			   F_ARRAY_OUT,		/* send procedure */
+			   typoid,			/* element type ID */
+			   InvalidOid,		/* base type ID */
+			   NULL,			/* never a default type value */
+			   NULL,			/* binary default isn't sent either */
+			   false,			/* never passed by value */
+			   alignment,		/* see above */
+			   'x',				/* ARRAY is always toastable */
+			   -1,				/* typMod (Domains only) */
+			   0,				/* Array dimensions of typbasetype */
+			   false);			/* Type NOT NULL */
+
+	pfree(shadow_type);
+}
+
+
+/*
+ *	RemoveType
+ *		Removes a datatype.
+ *
+ * NOTE: since this tries to remove the associated array type too, it'll
+ * only work on scalar types.
+ */
+void
+RemoveType(List *names)
+{
+	TypeName   *typename;
+	Relation	relation;
+	Oid			typeoid;
+	HeapTuple	tup;
+
+	/* Make a TypeName so we can use standard type lookup machinery */
+	typename = makeNode(TypeName);
+	typename->names = names;
+	typename->typmod = -1;
+	typename->arrayBounds = NIL;
+
+	relation = heap_openr(TypeRelationName, RowExclusiveLock);
+
+	/* Use LookupTypeName here so that shell types can be removed. */
+	typeoid = LookupTypeName(typename);
+	if (!OidIsValid(typeoid))
+		elog(ERROR, "Type \"%s\" does not exist",
+			 TypeNameToString(typename));
+
+	tup = SearchSysCache(TYPEOID,
+						 ObjectIdGetDatum(typeoid),
+						 0, 0, 0);
+	if (!HeapTupleIsValid(tup))
+		elog(ERROR, "Type \"%s\" does not exist",
+			 TypeNameToString(typename));
+
+	if (!pg_type_ownercheck(typeoid, GetUserId()))
+		elog(ERROR, "RemoveType: type '%s': permission denied",
+			 TypeNameToString(typename));
+
+	/* Delete any comments associated with this type */
+	DeleteComments(typeoid, RelationGetRelid(relation));
+
+	/* Remove the type tuple from pg_type */
+	simple_heap_delete(relation, &tup->t_self);
+
+	ReleaseSysCache(tup);
+
+	/* Now, delete the "array of" that type */
+	typename->arrayBounds = makeList1(makeInteger(1));
+
+	typeoid = LookupTypeName(typename);
+	if (!OidIsValid(typeoid))
+		elog(ERROR, "Type \"%s\" does not exist",
+			 TypeNameToString(typename));
+
+	tup = SearchSysCache(TYPEOID,
+						 ObjectIdGetDatum(typeoid),
+						 0, 0, 0);
+	if (!HeapTupleIsValid(tup))
+		elog(ERROR, "Type \"%s\" does not exist",
+			 TypeNameToString(typename));
+
+	DeleteComments(typeoid, RelationGetRelid(relation));
+
+	simple_heap_delete(relation, &tup->t_self);
+
+	ReleaseSysCache(tup);
+
+	heap_close(relation, RowExclusiveLock);
+}
+
+
+/*
+ * DefineDomain
+ *		Registers a new domain.
+ */
+void
+DefineDomain(CreateDomainStmt *stmt)
+{
+	char	   *domainName;
+	Oid			domainNamespace;
+	int16		internalLength;
+	int16		externalLength;
+	Oid			inputProcedure;
+	Oid			outputProcedure;
+	Oid			receiveProcedure;
+	Oid			sendProcedure;
+	bool		byValue;
+	char		delimiter;
+	char		alignment;
+	char		storage;
+	char		typtype;
+	Datum		datum;
+	bool		isnull;
+	char	   *defaultValue = NULL;
+	char	   *defaultValueBin = NULL;
+	bool		typNotNull = false;
+	Oid			basetypelem;
+	int32		typNDims = length(stmt->typename->arrayBounds);
+	HeapTuple	typeTup;
+	List	   *schema = stmt->constraints;
+	List	   *listptr;
+
+	/* Convert list of names to a name and namespace */
+	domainNamespace = QualifiedNameGetCreationNamespace(stmt->domainname,
+														&domainName);
+
+	/*
+	 * Domainnames, unlike typenames don't need to account for the '_'
+	 * prefix.  So they can be one character longer.
+	 */
+	if (strlen(domainName) > (NAMEDATALEN - 1))
+		elog(ERROR, "CREATE DOMAIN: domain names must be %d characters or less",
+			 NAMEDATALEN - 1);
+
+	/*
+	 * Look up the base type.
+	 */
+	typeTup = typenameType(stmt->typename);
+
+	/*
+	 * What we really don't want is domains of domains.  This could cause all sorts
+	 * of neat issues if we allow that.
+	 *
+	 * With testing, we may determine complex types should be allowed
+	 */
+	typtype = ((Form_pg_type) GETSTRUCT(typeTup))->typtype;
+	if (typtype != 'b')
+		elog(ERROR, "DefineDomain: %s is not a basetype",
+			 TypeNameToString(stmt->typename));
+
+	/* passed by value */
+	byValue = ((Form_pg_type) GETSTRUCT(typeTup))->typbyval;
+
+	/* Required Alignment */
+	alignment = ((Form_pg_type) GETSTRUCT(typeTup))->typalign;
+
+	/* TOAST Strategy */
+	storage = ((Form_pg_type) GETSTRUCT(typeTup))->typstorage;
+
+	/* Storage Length */
+	internalLength = ((Form_pg_type) GETSTRUCT(typeTup))->typlen;
+
+	/* External Length (unused) */
+	externalLength = ((Form_pg_type) GETSTRUCT(typeTup))->typprtlen;
+
+	/* Array element Delimiter */
+	delimiter = ((Form_pg_type) GETSTRUCT(typeTup))->typdelim;
+
+	/* I/O Functions */
+	inputProcedure = ((Form_pg_type) GETSTRUCT(typeTup))->typinput;
+	outputProcedure = ((Form_pg_type) GETSTRUCT(typeTup))->typoutput;
+	receiveProcedure = ((Form_pg_type) GETSTRUCT(typeTup))->typreceive;
+	sendProcedure = ((Form_pg_type) GETSTRUCT(typeTup))->typsend;
+
+	/* Inherited default value */
+	datum =	SysCacheGetAttr(TYPEOID, typeTup,
+							Anum_pg_type_typdefault, &isnull);
+	if (!isnull)
+		defaultValue = DatumGetCString(DirectFunctionCall1(textout, datum));
+
+	/* Inherited default binary value */
+	datum =	SysCacheGetAttr(TYPEOID, typeTup,
+							Anum_pg_type_typdefaultbin, &isnull);
+	if (!isnull)
+		defaultValueBin = DatumGetCString(DirectFunctionCall1(textout, datum));
+
+	/*
+	 * Pull out the typelem name of the parent OID.
+	 *
+	 * This is what enables us to make a domain of an array
+	 */
+	basetypelem = ((Form_pg_type) GETSTRUCT(typeTup))->typelem;
+
+	/*
+	 * Run through constraints manually to avoid the additional
+	 * processing conducted by DefineRelation() and friends.
+	 *
+	 * Besides, we don't want any constraints to be cooked.  We'll
+	 * do that when the table is created via MergeDomainAttributes().
+	 */
+	foreach(listptr, schema)
+	{
+		Constraint *colDef = lfirst(listptr);
+		bool nullDefined = false;
+		Node	   *expr;
+		ParseState *pstate;
+
+		switch (colDef->contype)
+		{
+			/*
+	 		 * The inherited default value may be overridden by the user
+			 * with the DEFAULT <expr> statement.
+			 *
+	 		 * We have to search the entire constraint tree returned as we
+			 * don't want to cook or fiddle too much.
+			 */
+			case CONSTR_DEFAULT:
+				/* Create a dummy ParseState for transformExpr */
+				pstate = make_parsestate(NULL);
+				/*
+				 * Cook the colDef->raw_expr into an expression.
+				 * Note: Name is strictly for error message
+				 */
+				expr = cookDefault(pstate, colDef->raw_expr,
+								   typeTup->t_data->t_oid,
+								   stmt->typename->typmod,
+								   domainName);
+				/*
+				 * Expression must be stored as a nodeToString result,
+				 * but we also require a valid textual representation
+				 * (mainly to make life easier for pg_dump).
+				 */
+				defaultValue = deparse_expression(expr,
+								deparse_context_for(domainName,
+													InvalidOid),
+												   false);
+				defaultValueBin = nodeToString(expr);
+				break;
+
+			/*
+			 * Find the NULL constraint.
+			 */
+			case CONSTR_NOTNULL:
+				if (nullDefined) {
+					elog(ERROR, "CREATE DOMAIN has conflicting NULL / NOT NULL constraint");
+				} else {
+					typNotNull = true;
+					nullDefined = true;
+				}
+		  		break;
+
+			case CONSTR_NULL:
+				if (nullDefined) {
+					elog(ERROR, "CREATE DOMAIN has conflicting NULL / NOT NULL constraint");
+				} else {
+					typNotNull = false;
+					nullDefined = true;
+				}
+		  		break;
+
+		  	case CONSTR_UNIQUE:
+		  		elog(ERROR, "CREATE DOMAIN / UNIQUE indexes not supported");
+		  		break;
+
+		  	case CONSTR_PRIMARY:
+		  		elog(ERROR, "CREATE DOMAIN / PRIMARY KEY indexes not supported");
+		  		break;
+
+		  	case CONSTR_CHECK:
+		  		elog(ERROR, "DefineDomain: CHECK Constraints not supported");
+		  		break;
+
+		  	case CONSTR_ATTR_DEFERRABLE:
+		  	case CONSTR_ATTR_NOT_DEFERRABLE:
+		  	case CONSTR_ATTR_DEFERRED:
+		  	case CONSTR_ATTR_IMMEDIATE:
+		  		elog(ERROR, "DefineDomain: DEFERRABLE, NON DEFERRABLE, DEFERRED and IMMEDIATE not supported");
+		  		break;
+
+			default:
+		  		elog(ERROR, "DefineDomain: unrecognized constraint node type");
+		  		break;
+		}
+	}
+
+	/*
+	 * Have TypeCreate do all the real work.
+	 */
+	TypeCreate(domainName,			/* type name */
+			   domainNamespace,		/* namespace */
+			   InvalidOid,			/* preassigned type oid (not done here) */
+			   InvalidOid,			/* relation oid (n/a here) */
+			   internalLength,		/* internal size */
+			   externalLength,		/* external size */
+			   'd',					/* type-type (domain type) */
+			   delimiter,			/* array element delimiter */
+			   inputProcedure,		/* input procedure */
+			   outputProcedure,		/* output procedure */
+			   receiveProcedure,	/* receive procedure */
+			   sendProcedure,		/* send procedure */
+			   basetypelem,			/* element type ID */
+			   typeTup->t_data->t_oid,	/* base type ID */
+			   defaultValue,		/* default type value (text) */
+			   defaultValueBin,		/* default type value (binary) */
+			   byValue,				/* passed by value */
+			   alignment,			/* required alignment */
+			   storage,				/* TOAST strategy */
+			   stmt->typename->typmod, /* typeMod value */
+			   typNDims,			/* Array dimensions for base type */
+			   typNotNull);			/* Type NOT NULL */
+
+	/*
+	 * Now we can clean up.
+	 */
+	ReleaseSysCache(typeTup);
+}
+
+
+/*
+ *	RemoveDomain
+ *		Removes a domain.
+ */
+void
+RemoveDomain(List *names, int behavior)
+{
+	TypeName   *typename;
+	Relation	relation;
+	Oid			typeoid;
+	HeapTuple	tup;
+	char		typtype;
+
+	/* CASCADE unsupported */
+	if (behavior == CASCADE)
+		elog(ERROR, "DROP DOMAIN does not support the CASCADE keyword");
+
+	/* Make a TypeName so we can use standard type lookup machinery */
+	typename = makeNode(TypeName);
+	typename->names = names;
+	typename->typmod = -1;
+	typename->arrayBounds = NIL;
+
+	relation = heap_openr(TypeRelationName, RowExclusiveLock);
+
+	typeoid = typenameTypeId(typename);
+
+	tup = SearchSysCache(TYPEOID,
+						 ObjectIdGetDatum(typeoid),
+						 0, 0, 0);
+	if (!HeapTupleIsValid(tup))
+		elog(ERROR, "RemoveDomain: type '%s' does not exist",
+			 TypeNameToString(typename));
+
+	if (!pg_type_ownercheck(typeoid, GetUserId()))
+		elog(ERROR, "RemoveDomain: type '%s': permission denied",
+			 TypeNameToString(typename));
+
+	/* Check that this is actually a domain */
+	typtype = ((Form_pg_type) GETSTRUCT(tup))->typtype;
+
+	if (typtype != 'd')
+		elog(ERROR, "%s is not a domain",
+			 TypeNameToString(typename));
+
+	/* Delete any comments associated with this type */
+	DeleteComments(typeoid, RelationGetRelid(relation));
+
+	/* Remove the type tuple from pg_type */
+	simple_heap_delete(relation, &tup->t_self);
+
+	ReleaseSysCache(tup);
+
+	/* At present, domains don't have associated array types */
+
+	heap_close(relation, RowExclusiveLock);
+}
+
+
+/*
+ * Find a suitable I/O function for a type.
+ */
+static Oid
+findTypeIOFunction(List *procname, bool isOutput)
+{
+	Oid			argList[FUNC_MAX_ARGS];
+	int			nargs;
+	Oid			procOid;
+
+	/*
+	 * First look for a 1-argument func with all argtypes 0. This is
+	 * valid for all kinds of procedure.
+	 */
+	MemSet(argList, 0, FUNC_MAX_ARGS * sizeof(Oid));
+
+	procOid = LookupFuncName(procname, 1, argList);
+
+	if (!OidIsValid(procOid))
+	{
+		/*
+		 * Alternatively, input procedures may take 3 args (data
+		 * value, element OID, atttypmod); the pg_proc argtype
+		 * signature is 0,OIDOID,INT4OID.  Output procedures may
+		 * take 2 args (data value, element OID).
+		 */
+		if (isOutput)
+		{
+			/* output proc */
+			nargs = 2;
+			argList[1] = OIDOID;
+		}
+		else
+		{
+			/* input proc */
+			nargs = 3;
+			argList[1] = OIDOID;
+			argList[2] = INT4OID;
+		}
+		procOid = LookupFuncName(procname, nargs, argList);
+
+		if (!OidIsValid(procOid))
+			func_error("TypeCreate", procname, 1, argList, NULL);
+	}
+
+	return procOid;
+}
diff --git a/src/backend/commands/view.c b/src/backend/commands/view.c
index 6b8652db5b72e5c4adba96046a00dad33917600c..bb4f2185b08baac403fedd2e693812864714a18c 100644
--- a/src/backend/commands/view.c
+++ b/src/backend/commands/view.c
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- *	$Id: view.c,v 1.61 2002/03/29 19:06:08 tgl Exp $
+ *	$Id: view.c,v 1.62 2002/04/15 05:22:03 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -15,7 +15,7 @@
 #include "access/xact.h"
 #include "catalog/heap.h"
 #include "catalog/namespace.h"
-#include "commands/creatinh.h"
+#include "commands/tablecmds.h"
 #include "commands/view.h"
 #include "miscadmin.h"
 #include "nodes/makefuncs.h"
diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c
index 659ab63f5536dfd4ff2f65b6b95e50123ba6bfa4..a2045a9eb80e2dc808020df999865d9932defdd5 100644
--- a/src/backend/executor/execMain.c
+++ b/src/backend/executor/execMain.c
@@ -27,7 +27,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.157 2002/04/08 22:42:18 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.158 2002/04/15 05:22:04 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -36,7 +36,7 @@
 #include "access/heapam.h"
 #include "catalog/heap.h"
 #include "catalog/namespace.h"
-#include "commands/command.h"
+#include "commands/tablecmds.h"
 #include "commands/trigger.h"
 #include "executor/execdebug.h"
 #include "executor/execdefs.h"
diff --git a/src/backend/executor/spi.c b/src/backend/executor/spi.c
index f09f90744e8fcae68cf416368dccadc3295d56af..b9bcce30e29acab992940a0f59ff650b7d638349 100644
--- a/src/backend/executor/spi.c
+++ b/src/backend/executor/spi.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/executor/spi.c,v 1.68 2002/03/21 16:00:38 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/executor/spi.c,v 1.69 2002/04/15 05:22:04 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -16,7 +16,7 @@
 
 #include "access/printtup.h"
 #include "catalog/heap.h"
-#include "commands/command.h"
+#include "commands/portalcmds.h"
 #include "executor/spi_priv.h"
 #include "tcop/tcopprot.h"
 #include "utils/lsyscache.h"
diff --git a/src/backend/tcop/pquery.c b/src/backend/tcop/pquery.c
index 4599a27a6428512fd8c4b634270373e8c621299b..e8df96a53defeb4bc6e26b6a6674f36f0745a2a3 100644
--- a/src/backend/tcop/pquery.c
+++ b/src/backend/tcop/pquery.c
@@ -8,14 +8,14 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/tcop/pquery.c,v 1.51 2002/03/21 16:01:27 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/tcop/pquery.c,v 1.52 2002/04/15 05:22:04 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 
 #include "postgres.h"
 
-#include "commands/command.h"
+#include "commands/portalcmds.h"
 #include "executor/execdefs.h"
 #include "executor/executor.h"
 #include "tcop/pquery.h"
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
index 77dfe4a23651b9124ea60ce1bfb3673ae81dc3af..63e6b5dd9b2184ccc8a453b0d2c6bade4644696b 100644
--- a/src/backend/tcop/utility.c
+++ b/src/backend/tcop/utility.c
@@ -10,7 +10,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.148 2002/04/12 20:38:27 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.149 2002/04/15 05:22:04 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -22,16 +22,17 @@
 #include "catalog/pg_shadow.h"
 #include "commands/async.h"
 #include "commands/cluster.h"
-#include "commands/command.h"
 #include "commands/comment.h"
 #include "commands/copy.h"
-#include "commands/creatinh.h"
 #include "commands/dbcommands.h"
 #include "commands/defrem.h"
 #include "commands/explain.h"
+#include "commands/lockcmds.h"
+#include "commands/portalcmds.h"
 #include "commands/proclang.h"
-#include "commands/rename.h"
+#include "commands/schemacmds.h"
 #include "commands/sequence.h"
+#include "commands/tablecmds.h"
 #include "commands/trigger.h"
 #include "commands/user.h"
 #include "commands/vacuum.h"
diff --git a/src/include/commands/command.h b/src/include/commands/command.h
deleted file mode 100644
index cfb8f20890eb7117e7aa0099ee9db56ff2ab66f9..0000000000000000000000000000000000000000
--- a/src/include/commands/command.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * command.h
- *	  prototypes for command.c.
- *
- *
- * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- * $Id: command.h,v 1.37 2002/04/01 04:35:39 tgl Exp $
- *
- *-------------------------------------------------------------------------
- */
-#ifndef COMMAND_H
-#define COMMAND_H
-
-#include "utils/portal.h"
-
-
-/*
- * PerformPortalFetch
- *		Performs the POSTQUEL function FETCH.  Fetches count (or all if 0)
- * tuples in portal with name in the forward direction iff goForward.
- *
- * Exceptions:
- *		BadArg if forward invalid.
- *		"ERROR" if portal not found.
- */
-extern void PerformPortalFetch(char *name, bool forward, int count,
-							   CommandDest dest, char *completionTag);
-
-/*
- * PerformPortalClose
- *		Performs the POSTQUEL function CLOSE.
- */
-extern void PerformPortalClose(char *name, CommandDest dest);
-
-extern void PortalCleanup(Portal portal);
-
-/*
- * ALTER TABLE variants
- */
-extern void AlterTableAddColumn(Oid myrelid, bool inherits, ColumnDef *colDef);
-
-extern void AlterTableAlterColumnDefault(Oid myrelid, bool inh,
-										 const char *colName, Node *newDefault);
-
-extern void AlterTableAlterColumnDropNotNull(Oid myrelid,
-							 bool inh, const char *colName);
-
-extern void AlterTableAlterColumnSetNotNull(Oid myrelid,
-							 bool inh, const char *colName);
-
-extern void AlterTableAlterColumnFlags(Oid myrelid,
-									   bool inh, const char *colName,
-									   Node *flagValue, const char *flagType);
-
-extern void AlterTableDropColumn(Oid myrelid, bool inh,
-					 			 const char *colName, int behavior);
-
-extern void AlterTableAddConstraint(Oid myrelid,
-									bool inh, List *newConstraints);
-
-extern void AlterTableDropConstraint(Oid myrelid,
-									 bool inh, const char *constrName, int behavior);
-
-extern void AlterTableCreateToastTable(Oid relOid, bool silent);
-
-extern void AlterTableOwner(Oid relationOid, int32 newOwnerSysId);
-
-/*
- * LOCK
- */
-extern void LockTableCommand(LockStmt *lockstmt);
-
-/*
- * SCHEMA
- */
-extern void CreateSchemaCommand(CreateSchemaStmt *parsetree);
-
-#endif   /* COMMAND_H */
diff --git a/src/include/commands/creatinh.h b/src/include/commands/creatinh.h
deleted file mode 100644
index fe0f2bc35128a16f6e7c2664f149f460a089236d..0000000000000000000000000000000000000000
--- a/src/include/commands/creatinh.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * creatinh.h
- *	  prototypes for creatinh.c.
- *
- *
- * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- * $Id: creatinh.h,v 1.20 2002/03/29 19:06:22 tgl Exp $
- *
- *-------------------------------------------------------------------------
- */
-#ifndef CREATINH_H
-#define CREATINH_H
-
-#include "nodes/parsenodes.h"
-
-extern Oid	DefineRelation(CreateStmt *stmt, char relkind);
-extern void RemoveRelation(const RangeVar *relation);
-extern void TruncateRelation(const RangeVar *relation);
-
-#endif   /* CREATINH_H */
diff --git a/src/include/commands/defrem.h b/src/include/commands/defrem.h
index 83b8fec6d77cb05cc6e06f9561186fcf7231181d..711bc91f57993f3a37e29795635e466e698bc35b 100644
--- a/src/include/commands/defrem.h
+++ b/src/include/commands/defrem.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: defrem.h,v 1.34 2002/04/09 20:35:54 tgl Exp $
+ * $Id: defrem.h,v 1.35 2002/04/15 05:22:03 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -16,6 +16,8 @@
 
 #include "nodes/parsenodes.h"
 
+#define DEFAULT_TYPDELIM		','
+
 /*
  * prototypes in indexcmds.c
  */
@@ -33,22 +35,33 @@ extern void ReindexTable(RangeVar *relation, bool force);
 extern void ReindexDatabase(const char *databaseName, bool force, bool all);
 
 /*
- * prototypes in define.c
+ * DefineFoo and RemoveFoo are now both in foocmds.c
  */
+
 extern void CreateFunction(ProcedureStmt *stmt);
+extern void RemoveFunction(List *functionName, List *argTypes);
+
 extern void DefineOperator(List *names, List *parameters);
+extern void RemoveOperator(char *operatorName,
+						   TypeName *typeName1, TypeName *typeName2);
+
 extern void DefineAggregate(List *names, List *parameters);
+extern void RemoveAggregate(List *aggName, TypeName *aggType);
+
 extern void DefineType(List *names, List *parameters);
+extern void RemoveType(List *names);
 extern void DefineDomain(CreateDomainStmt *stmt);
-
-/*
- * prototypes in remove.c
- */
 extern void RemoveDomain(List *names, int behavior);
-extern void RemoveFunction(List *functionName, List *argTypes);
-extern void RemoveOperator(char *operatorName,
-			   TypeName *typeName1, TypeName *typeName2);
-extern void RemoveType(List *names);
-extern void RemoveAggregate(List *aggName, TypeName *aggType);
+
+
+/* support routines in define.c */
+
+extern void case_translate_language_name(const char *input, char *output);
+
+extern char *defGetString(DefElem *def);
+extern double defGetNumeric(DefElem *def);
+extern List *defGetQualifiedName(DefElem *def);
+extern TypeName *defGetTypeName(DefElem *def);
+extern int	defGetTypeLength(DefElem *def);
 
 #endif   /* DEFREM_H */
diff --git a/src/include/commands/lockcmds.h b/src/include/commands/lockcmds.h
new file mode 100644
index 0000000000000000000000000000000000000000..04335c31c4e01ba7c56ba767ad6749dc2dc493d1
--- /dev/null
+++ b/src/include/commands/lockcmds.h
@@ -0,0 +1,24 @@
+/*-------------------------------------------------------------------------
+ *
+ * lockcmds.h
+ *	  prototypes for lockcmds.c.
+ *
+ *
+ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * $Id: lockcmds.h,v 1.1 2002/04/15 05:22:03 tgl Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef LOCKCMDS_H
+#define LOCKCMDS_H
+
+#include "nodes/parsenodes.h"
+
+/*
+ * LOCK
+ */
+extern void LockTableCommand(LockStmt *lockstmt);
+
+#endif  /* LOCKCMDS_H */
diff --git a/src/include/commands/portalcmds.h b/src/include/commands/portalcmds.h
new file mode 100644
index 0000000000000000000000000000000000000000..b62e3638a9133b0c7faa124c161d31f72132a7ea
--- /dev/null
+++ b/src/include/commands/portalcmds.h
@@ -0,0 +1,39 @@
+/*-------------------------------------------------------------------------
+ *
+ * portalcmds.h
+ *	  prototypes for portalcmds.c.
+ *
+ *
+ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * $Id: portalcmds.h,v 1.1 2002/04/15 05:22:03 tgl Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PORTALCMDS_H
+#define PORTALCMDS_H
+
+#include "utils/portal.h"
+
+/*
+ * PerformPortalFetch
+ *		Performs the POSTQUEL function FETCH.  Fetches count (or all if 0)
+ * tuples in portal with name in the forward direction iff goForward.
+ *
+ * Exceptions:
+ *		BadArg if forward invalid.
+ *		"ERROR" if portal not found.
+ */
+extern void PerformPortalFetch(char *name, bool forward, int count,
+							   CommandDest dest, char *completionTag);
+
+/*
+ * PerformPortalClose
+ *		Performs the POSTQUEL function CLOSE.
+ */
+extern void PerformPortalClose(char *name, CommandDest dest);
+
+extern void PortalCleanup(Portal portal);
+
+#endif  /* PORTALCMDS_H */
diff --git a/src/include/commands/rename.h b/src/include/commands/rename.h
deleted file mode 100644
index 48e1a1cbe0dbfb205f85a3e7a83d166996d3790a..0000000000000000000000000000000000000000
--- a/src/include/commands/rename.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * rename.h
- *
- *
- *
- * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- * $Id: rename.h,v 1.16 2002/03/31 07:49:30 tgl Exp $
- *
- *-------------------------------------------------------------------------
- */
-#ifndef RENAME_H
-#define RENAME_H
-
-extern void renameatt(Oid relid,
-		  const char *oldattname,
-		  const char *newattname,
-		  bool recurse);
-
-extern void renamerel(Oid relid,
-		  const char *newrelname);
-
-#endif   /* RENAME_H */
diff --git a/src/include/commands/schemacmds.h b/src/include/commands/schemacmds.h
new file mode 100644
index 0000000000000000000000000000000000000000..6adf9a4517ea0357520cb7858d8957b0d8171865
--- /dev/null
+++ b/src/include/commands/schemacmds.h
@@ -0,0 +1,22 @@
+/*-------------------------------------------------------------------------
+ *
+ * schemacmds.h
+ *	  prototypes for schemacmds.c.
+ *
+ *
+ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * $Id: schemacmds.h,v 1.1 2002/04/15 05:22:04 tgl Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef SCHEMACMDS_H
+#define SCHEMACMDS_H
+
+#include "nodes/parsenodes.h"
+
+extern void CreateSchemaCommand(CreateSchemaStmt *parsetree);
+
+#endif  /* SCHEMACMDS_H */
diff --git a/src/include/commands/tablecmds.h b/src/include/commands/tablecmds.h
new file mode 100644
index 0000000000000000000000000000000000000000..5d895972f5b069fbabcbf521ff366a594ecdb906
--- /dev/null
+++ b/src/include/commands/tablecmds.h
@@ -0,0 +1,63 @@
+/*-------------------------------------------------------------------------
+ *
+ * tablecmds.h
+ *	  prototypes for tablecmds.c.
+ *
+ *
+ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * $Id: tablecmds.h,v 1.1 2002/04/15 05:22:04 tgl Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef TABLECMDS_H
+#define TABLECMDS_H
+
+#include "nodes/parsenodes.h"
+
+extern void AlterTableAddColumn(Oid myrelid, bool inherits,
+								ColumnDef *colDef);
+
+extern void AlterTableAlterColumnDefault(Oid myrelid, bool inh,
+										 const char *colName,
+										 Node *newDefault);
+
+extern void AlterTableAlterColumnDropNotNull(Oid myrelid, bool inh,
+											 const char *colName);
+
+extern void AlterTableAlterColumnSetNotNull(Oid myrelid, bool inh,
+											const char *colName);
+
+extern void AlterTableAlterColumnFlags(Oid myrelid, bool inh,
+									   const char *colName,
+									   Node *flagValue, const char *flagType);
+
+extern void AlterTableDropColumn(Oid myrelid, bool inh,
+					 			 const char *colName, int behavior);
+
+extern void AlterTableAddConstraint(Oid myrelid, bool inh,
+									List *newConstraints);
+
+extern void AlterTableDropConstraint(Oid myrelid, bool inh,
+									 const char *constrName, int behavior);
+
+extern void AlterTableCreateToastTable(Oid relOid, bool silent);
+
+extern void AlterTableOwner(Oid relationOid, int32 newOwnerSysId);
+
+extern Oid	DefineRelation(CreateStmt *stmt, char relkind);
+
+extern void RemoveRelation(const RangeVar *relation);
+
+extern void TruncateRelation(const RangeVar *relation);
+
+extern void renameatt(Oid relid,
+		  const char *oldattname,
+		  const char *newattname,
+		  bool recurse);
+
+extern void renamerel(Oid relid,
+		  const char *newrelname);
+
+#endif   /* TABLECMDS_H */