From 1dbf8aa7a8159875bb46f6ee6ab0116eee76869b Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Tue, 26 Mar 2002 19:17:02 +0000
Subject: [PATCH] pg_class has a relnamespace column.  You can create and
 access tables in schemas other than the system namespace; however, there's no
 search path yet, and not all operations work yet on tables outside the system
 namespace.

---
 doc/src/sgml/catalogs.sgml          |  11 +-
 src/backend/access/heap/heapam.c    | 101 +++++++++---
 src/backend/access/index/indexam.c  |  37 ++++-
 src/backend/bootstrap/bootparse.y   |  13 +-
 src/backend/bootstrap/bootstrap.c   |  18 +--
 src/backend/catalog/Makefile        |   4 +-
 src/backend/catalog/aclchk.c        |  22 +--
 src/backend/catalog/genbki.sh       |  11 +-
 src/backend/catalog/heap.c          | 118 ++++----------
 src/backend/catalog/index.c         |  88 ++++-------
 src/backend/catalog/indexing.c      |   4 +-
 src/backend/catalog/namespace.c     | 126 +++++++++++++++
 src/backend/commands/cluster.c      |  59 ++++---
 src/backend/commands/command.c      | 118 +++++++-------
 src/backend/commands/comment.c      |  29 ++--
 src/backend/commands/creatinh.c     |  62 ++++----
 src/backend/commands/indexcmds.c    |  74 +++++----
 src/backend/commands/rename.c       |  32 ++--
 src/backend/commands/trigger.c      |  18 +--
 src/backend/commands/user.c         |   8 +-
 src/backend/executor/execMain.c     |  16 +-
 src/backend/parser/analyze.c        |  33 ++--
 src/backend/parser/parse_clause.c   |   4 +-
 src/backend/parser/parse_relation.c |   4 +-
 src/backend/rewrite/rewriteDefine.c |   4 +-
 src/backend/tcop/utility.c          | 118 +++++++-------
 src/backend/utils/adt/acl.c         |  29 ++--
 src/backend/utils/cache/catcache.c  |   8 +-
 src/backend/utils/cache/lsyscache.c |  23 ++-
 src/backend/utils/cache/relcache.c  | 232 ++++++++++++++--------------
 src/backend/utils/cache/syscache.c  |  18 +--
 src/include/access/genam.h          |   6 +-
 src/include/access/heapam.h         |   9 +-
 src/include/bootstrap/bootstrap.h   |   4 +-
 src/include/catalog/catversion.h    |   4 +-
 src/include/catalog/heap.h          |  11 +-
 src/include/catalog/index.h         |   5 +-
 src/include/catalog/indexing.h      |   6 +-
 src/include/catalog/namespace.h     |  26 ++++
 src/include/catalog/pg_attribute.h  |  92 +++++------
 src/include/catalog/pg_class.h      |  68 ++++----
 src/include/commands/cluster.h      |   4 +-
 src/include/commands/command.h      |   7 +-
 src/include/commands/comment.h      |   4 +-
 src/include/commands/defrem.h       |  10 +-
 src/include/commands/rename.h       |   4 +-
 src/include/nodes/parsenodes.h      |  45 +-----
 src/include/nodes/primnodes.h       |  45 +++++-
 src/include/utils/catcache.h        |  10 +-
 src/include/utils/lsyscache.h       |   3 +-
 src/include/utils/rel.h             |  10 +-
 src/include/utils/relcache.h        |   8 +-
 src/include/utils/syscache.h        |   4 +-
 src/pl/plpgsql/src/pl_comp.c        |  43 +++---
 54 files changed, 1062 insertions(+), 808 deletions(-)
 create mode 100644 src/backend/catalog/namespace.c
 create mode 100644 src/include/catalog/namespace.h

diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml
index 5371da7ee7e..950d2016df6 100644
--- a/doc/src/sgml/catalogs.sgml
+++ b/doc/src/sgml/catalogs.sgml
@@ -1,6 +1,6 @@
 <!--
  Documentation of the system catalogs, directed toward PostgreSQL developers
- $Header: /cvsroot/pgsql/doc/src/sgml/catalogs.sgml,v 2.37 2002/03/22 21:34:43 tgl Exp $
+ $Header: /cvsroot/pgsql/doc/src/sgml/catalogs.sgml,v 2.38 2002/03/26 19:15:10 tgl Exp $
  -->
 
 <chapter id="catalogs">
@@ -568,6 +568,15 @@
       <entry>Name of the table, index, view, etc.</entry>
      </row>
 
+     <row>
+      <entry>relnamespace</entry>
+      <entry><type>oid</type></entry>
+      <entry>pg_namespace.oid</entry>
+      <entry>
+       The OID of the namespace that contains this relation
+      </entry>
+     </row>
+
      <row>
       <entry>reltype</entry>
       <entry><type>oid</type></entry>
diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index adcf9bc6cb6..86c62e4fdb1 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -8,15 +8,17 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.131 2002/03/03 17:47:53 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.132 2002/03/26 19:15:11 tgl Exp $
  *
  *
  * INTERFACE ROUTINES
  *		relation_open	- open any relation by relation OID
- *		relation_openr	- open any relation by name
+ *		relation_openrv	- open any relation specified by a RangeVar
+ *		relation_openr	- open a system relation by name
  *		relation_close	- close any relation
  *		heap_open		- open a heap relation by relation OID
- *		heap_openr		- open a heap relation by name
+ *		heap_openrv		- open a heap relation specified by a RangeVar
+ *		heap_openr		- open a system heap relation by name
  *		heap_close		- (now just a macro for relation_close)
  *		heap_beginscan	- begin relation scan
  *		heap_rescan		- restart a relation scan
@@ -44,6 +46,7 @@
 #include "access/valid.h"
 #include "access/xlogutils.h"
 #include "catalog/catalog.h"
+#include "catalog/namespace.h"
 #include "miscadmin.h"
 #include "utils/inval.h"
 #include "utils/relcache.h"
@@ -481,29 +484,30 @@ relation_open(Oid relationId, LOCKMODE lockmode)
 }
 
 /* ----------------
- *		relation_openr - open any relation by name
+ *		relation_openrv - open any relation specified by a RangeVar
  *
- *		As above, but lookup by name instead of OID.
+ *		As above, but the relation is specified by a RangeVar.
  * ----------------
  */
 Relation
-relation_openr(const char *relationName, LOCKMODE lockmode)
+relation_openrv(const RangeVar *relation, LOCKMODE lockmode)
 {
-	Relation	r;
-
-	Assert(lockmode >= NoLock && lockmode < MAX_LOCKMODES);
+	Oid			relOid;
 
 	/*
-	 * increment access statistics
+	 * In bootstrap mode, don't do any namespace processing.
 	 */
-	IncrHeapAccessStat(local_openr);
-	IncrHeapAccessStat(global_openr);
+	if (IsBootstrapProcessingMode())
+	{
+		Assert(relation->schemaname == NULL);
+		return relation_openr(relation->relname, lockmode);
+	}
 
 	/*
 	 * Check for shared-cache-inval messages before trying to open the
 	 * relation.  This is needed to cover the case where the name
 	 * identifies a rel that has been dropped and recreated since the
-	 * start of our transaction: if we don't flush the old relcache entry
+	 * start of our transaction: if we don't flush the old syscache entry
 	 * then we'll latch onto that entry and suffer an error when we do
 	 * LockRelation. Note that relation_open does not need to do this,
 	 * since a relation's OID never changes.
@@ -514,11 +518,43 @@ relation_openr(const char *relationName, LOCKMODE lockmode)
 	if (lockmode != NoLock)
 		AcceptInvalidationMessages();
 
+	/* Look up the appropriate relation using namespace search */
+	relOid = RangeVarGetRelid(relation, false);
+
+	/* Let relation_open do the rest */
+	return relation_open(relOid, lockmode);
+}
+
+/* ----------------
+ *		relation_openr - open a system relation specified by name.
+ *
+ *		As above, but the relation is specified by an unqualified name;
+ *		it is assumed to live in the system catalog namespace.
+ * ----------------
+ */
+Relation
+relation_openr(const char *sysRelationName, LOCKMODE lockmode)
+{
+	Relation	r;
+
+	Assert(lockmode >= NoLock && lockmode < MAX_LOCKMODES);
+
+	/*
+	 * increment access statistics
+	 */
+	IncrHeapAccessStat(local_openr);
+	IncrHeapAccessStat(global_openr);
+
+	/*
+	 * We assume we should not need to worry about the rel's OID changing,
+	 * hence no need for AcceptInvalidationMessages here.
+	 */
+
 	/* The relcache does all the real work... */
-	r = RelationNameGetRelation(relationName);
+	r = RelationSysNameGetRelation(sysRelationName);
 
 	if (!RelationIsValid(r))
-		elog(ERROR, "Relation \"%s\" does not exist", relationName);
+		elog(ERROR, "Relation \"%s\" does not exist", sysRelationName);
 
 	if (lockmode != NoLock)
 		LockRelation(r, lockmode);
@@ -582,17 +618,44 @@ heap_open(Oid relationId, LOCKMODE lockmode)
 }
 
 /* ----------------
- *		heap_openr - open a heap relation by name
+ *		heap_openrv - open a heap relation specified
+ *		by a RangeVar node
+ *
+ *		As above, but relation is specified by a RangeVar.
+ * ----------------
+ */
+Relation
+heap_openrv(const RangeVar *relation, LOCKMODE lockmode)
+{
+	Relation	r;
+
+	r = relation_openrv(relation, lockmode);
+
+	if (r->rd_rel->relkind == RELKIND_INDEX)
+		elog(ERROR, "%s is an index relation",
+			 RelationGetRelationName(r));
+	else if (r->rd_rel->relkind == RELKIND_SPECIAL)
+		elog(ERROR, "%s is a special relation",
+			 RelationGetRelationName(r));
+
+	pgstat_initstats(&r->pgstat_info, r);
+
+	return r;
+}
+
+/* ----------------
+ *		heap_openr - open a system heap relation specified by name.
  *
- *		As above, but lookup by name instead of OID.
+ *		As above, but the relation is specified by an unqualified name;
+ *		it is assumed to live in the system catalog namespace.
  * ----------------
  */
 Relation
-heap_openr(const char *relationName, LOCKMODE lockmode)
+heap_openr(const char *sysRelationName, LOCKMODE lockmode)
 {
 	Relation	r;
 
-	r = relation_openr(relationName, lockmode);
+	r = relation_openr(sysRelationName, lockmode);
 
 	if (r->rd_rel->relkind == RELKIND_INDEX)
 		elog(ERROR, "%s is an index relation",
diff --git a/src/backend/access/index/indexam.c b/src/backend/access/index/indexam.c
index 523349ebdb5..ea043afb341 100644
--- a/src/backend/access/index/indexam.c
+++ b/src/backend/access/index/indexam.c
@@ -8,11 +8,12 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/access/index/indexam.c,v 1.55 2001/11/02 16:30:29 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/access/index/indexam.c,v 1.56 2002/03/26 19:15:14 tgl Exp $
  *
  * INTERFACE ROUTINES
  *		index_open		- open an index relation by relation OID
- *		index_openr		- open an index relation by name
+ *		index_openrv	- open an index relation specified by a RangeVar
+ *		index_openr		- open a system index relation by name
  *		index_close		- close an index relation
  *		index_beginscan - start a scan of an index
  *		index_rescan	- restart a scan of an index
@@ -136,17 +137,41 @@ index_open(Oid relationId)
 }
 
 /* ----------------
- *		index_openr - open an index relation by name
+ *		index_openrv - open an index relation specified
+ *		by a RangeVar node
  *
- *		As above, but lookup by name instead of OID.
+ *		As above, but relation is specified by a RangeVar.
  * ----------------
  */
 Relation
-index_openr(const char *relationName)
+index_openrv(const RangeVar *relation)
 {
 	Relation	r;
 
-	r = relation_openr(relationName, NoLock);
+	r = relation_openrv(relation, NoLock);
+
+	if (r->rd_rel->relkind != RELKIND_INDEX)
+		elog(ERROR, "%s is not an index relation",
+			 RelationGetRelationName(r));
+
+	pgstat_initstats(&r->pgstat_info, r);
+
+	return r;
+}
+
+/* ----------------
+ *		index_openr - open a system index relation specified by name.
+ *
+ *		As above, but the relation is specified by an unqualified name;
+ *		it is assumed to live in the system catalog namespace.
+ * ----------------
+ */
+Relation
+index_openr(const char *sysRelationName)
+{
+	Relation	r;
+
+	r = relation_openr(sysRelationName, NoLock);
 
 	if (r->rd_rel->relkind != RELKIND_INDEX)
 		elog(ERROR, "%s is not an index relation",
diff --git a/src/backend/bootstrap/bootparse.y b/src/backend/bootstrap/bootparse.y
index 04f68adee7f..3b0d34f9fcd 100644
--- a/src/backend/bootstrap/bootparse.y
+++ b/src/backend/bootstrap/bootparse.y
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/bootstrap/bootparse.y,v 1.40 2002/03/02 21:39:20 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/bootstrap/bootparse.y,v 1.41 2002/03/26 19:15:16 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -32,8 +32,10 @@
 #include "catalog/pg_am.h"
 #include "catalog/pg_attribute.h"
 #include "catalog/pg_class.h"
+#include "catalog/pg_namespace.h"
 #include "commands/defrem.h"
 #include "miscadmin.h"
+#include "nodes/makefuncs.h"
 #include "nodes/nodes.h"
 #include "nodes/parsenodes.h"
 #include "nodes/pg_list.h"
@@ -179,7 +181,9 @@ Boot_CreateStmt:
 						}
 
 						tupdesc = CreateTupleDesc(numattr, attrtypes);
-						reldesc = heap_create(LexIDStr($4), tupdesc,
+						reldesc = heap_create(LexIDStr($4),
+											  PG_CATALOG_NAMESPACE,
+											  tupdesc,
 											  false, true, true);
 						reldesc->rd_rel->relhasoids = ! ($3);
 						elog(DEBUG3, "bootstrap relation created");
@@ -191,6 +195,7 @@ Boot_CreateStmt:
 
 						tupdesc = CreateTupleDesc(numattr,attrtypes);
 						id = heap_create_with_catalog(LexIDStr($4),
+													  PG_CATALOG_NAMESPACE,
 													  tupdesc,
 													  RELKIND_RELATION,
 													  ! ($3),
@@ -232,7 +237,7 @@ Boot_DeclareIndexStmt:
 				{
 					do_start();
 
-					DefineIndex(LexIDStr($5),
+					DefineIndex(makeRangeVar(NULL, LexIDStr($5)),
 								LexIDStr($3),
 								LexIDStr($7),
 								$9, false, false, NULL, NIL);
@@ -245,7 +250,7 @@ Boot_DeclareUniqueIndexStmt:
 				{
 					do_start();
 
-					DefineIndex(LexIDStr($6),
+					DefineIndex(makeRangeVar(NULL, LexIDStr($6)),
 								LexIDStr($4),
 								LexIDStr($8),
 								$10, true, false, NULL, NIL);
diff --git a/src/backend/bootstrap/bootstrap.c b/src/backend/bootstrap/bootstrap.c
index 275b0579ffa..a4ab6fce614 100644
--- a/src/backend/bootstrap/bootstrap.c
+++ b/src/backend/bootstrap/bootstrap.c
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/bootstrap/bootstrap.c,v 1.124 2002/03/15 19:20:34 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/bootstrap/bootstrap.c,v 1.125 2002/03/26 19:15:16 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -153,8 +153,8 @@ extern char *optarg;
 
 typedef struct _IndexList
 {
-	char	   *il_heap;
-	char	   *il_ind;
+	Oid			il_heap;
+	Oid			il_ind;
 	IndexInfo  *il_info;
 	struct _IndexList *il_next;
 } IndexList;
@@ -1080,8 +1080,8 @@ AddStr(char *str, int strlength, int mderef)
  *		are present in the index.
  */
 void
-index_register(char *heap,
-			   char *ind,
+index_register(Oid heap,
+			   Oid ind,
 			   IndexInfo *indexInfo)
 {
 	IndexList  *newind;
@@ -1103,8 +1103,8 @@ index_register(char *heap,
 	oldcxt = MemoryContextSwitchTo(nogc);
 
 	newind = (IndexList *) palloc(sizeof(IndexList));
-	newind->il_heap = pstrdup(heap);
-	newind->il_ind = pstrdup(ind);
+	newind->il_heap = heap;
+	newind->il_ind = ind;
 	newind->il_info = (IndexInfo *) palloc(sizeof(IndexInfo));
 
 	memcpy(newind->il_info, indexInfo, sizeof(IndexInfo));
@@ -1126,8 +1126,8 @@ build_indices()
 		Relation	heap;
 		Relation	ind;
 
-		heap = heap_openr(ILHead->il_heap, NoLock);
-		ind = index_openr(ILHead->il_ind);
+		heap = heap_open(ILHead->il_heap, NoLock);
+		ind = index_open(ILHead->il_ind);
 		index_build(heap, ind, ILHead->il_info);
 
 		/*
diff --git a/src/backend/catalog/Makefile b/src/backend/catalog/Makefile
index d0bc7b37267..3d1126bf01f 100644
--- a/src/backend/catalog/Makefile
+++ b/src/backend/catalog/Makefile
@@ -2,7 +2,7 @@
 #
 # Makefile for backend/catalog
 #
-# $Header: /cvsroot/pgsql/src/backend/catalog/Makefile,v 1.38 2002/03/22 21:34:43 tgl Exp $
+# $Header: /cvsroot/pgsql/src/backend/catalog/Makefile,v 1.39 2002/03/26 19:15:22 tgl Exp $
 #
 #-------------------------------------------------------------------------
 
@@ -10,7 +10,7 @@ subdir = src/backend/catalog
 top_builddir = ../../..
 include $(top_builddir)/src/Makefile.global
 
-OBJS = catalog.o heap.o index.o indexing.o aclchk.o \
+OBJS = catalog.o heap.o index.o indexing.o namespace.o aclchk.o \
        pg_aggregate.o pg_largeobject.o pg_namespace.o \
        pg_operator.o pg_proc.o pg_type.o
 
diff --git a/src/backend/catalog/aclchk.c b/src/backend/catalog/aclchk.c
index 2225dc3a14e..bead0959d93 100644
--- a/src/backend/catalog/aclchk.c
+++ b/src/backend/catalog/aclchk.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/catalog/aclchk.c,v 1.58 2002/03/21 23:27:19 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/catalog/aclchk.c,v 1.59 2002/03/26 19:15:22 tgl Exp $
  *
  * NOTES
  *	  See acl.h.
@@ -22,6 +22,7 @@
 #include "catalog/catalog.h"
 #include "catalog/catname.h"
 #include "catalog/indexing.h"
+#include "catalog/namespace.h"
 #include "catalog/pg_aggregate.h"
 #include "catalog/pg_group.h"
 #include "catalog/pg_language.h"
@@ -200,7 +201,8 @@ ExecuteGrantStmt_Table(GrantStmt *stmt)
 
 	foreach(i, stmt->objects)
 	{
-		char	   *relname = ((RangeVar *) lfirst(i))->relname;
+		RangeVar   *relvar = (RangeVar *) lfirst(i);
+		Oid			relOid;
 		Relation	relation;
 		HeapTuple	tuple;
 		Form_pg_class pg_class_tuple;
@@ -216,27 +218,27 @@ ExecuteGrantStmt_Table(GrantStmt *stmt)
 
 		/* open pg_class */
 		relation = heap_openr(RelationRelationName, RowExclusiveLock);
-		tuple = SearchSysCache(RELNAME,
-							   PointerGetDatum(relname),
+		relOid = RangeVarGetRelid(relvar, false);
+		tuple = SearchSysCache(RELOID,
+							   ObjectIdGetDatum(relOid),
 							   0, 0, 0);
 		if (!HeapTupleIsValid(tuple))
-			elog(ERROR, "relation \"%s\" not found",
-				 relname);
+			elog(ERROR, "relation %u not found", relOid);
 		pg_class_tuple = (Form_pg_class) GETSTRUCT(tuple);
 
-		if (!pg_class_ownercheck(tuple->t_data->t_oid, GetUserId()))
+		if (!pg_class_ownercheck(relOid, GetUserId()))
 			elog(ERROR, "%s: permission denied",
-				 relname);
+				 relvar->relname);
 
 		if (pg_class_tuple->relkind == RELKIND_INDEX)
 			elog(ERROR, "\"%s\" is an index",
-				 relname);
+				 relvar->relname);
 
 		/*
 		 * If there's no ACL, create a default using the pg_class.relowner
 		 * field.
 		 */
-		aclDatum = SysCacheGetAttr(RELNAME, tuple, Anum_pg_class_relacl,
+		aclDatum = SysCacheGetAttr(RELOID, tuple, Anum_pg_class_relacl,
 								   &isNull);
 		if (isNull)
 			old_acl = acldefault(pg_class_tuple->relowner);
diff --git a/src/backend/catalog/genbki.sh b/src/backend/catalog/genbki.sh
index 6324d906286..4edb86cdba9 100644
--- a/src/backend/catalog/genbki.sh
+++ b/src/backend/catalog/genbki.sh
@@ -10,7 +10,7 @@
 #
 #
 # IDENTIFICATION
-#    $Header: /cvsroot/pgsql/src/backend/catalog/Attic/genbki.sh,v 1.25 2001/11/30 20:21:06 tgl Exp $
+#    $Header: /cvsroot/pgsql/src/backend/catalog/Attic/genbki.sh,v 1.26 2002/03/26 19:15:24 tgl Exp $
 #
 # NOTES
 #    non-essential whitespace is removed from the generated file.
@@ -136,6 +136,14 @@ for dir in $INCLUDE_DIRS; do
     fi
 done
 
+# Get PG_CATALOG_NAMESPACE from catalog/pg_namespace.h
+for dir in $INCLUDE_DIRS; do
+    if [ -f "$dir/catalog/pg_namespace.h" ]; then
+        PG_CATALOG_NAMESPACE=`grep '^#define[ 	]*PG_CATALOG_NAMESPACE' $dir/catalog/pg_namespace.h | $AWK '{ print $3 }'`
+        break
+    fi
+done
+
 # Get FirstGenBKIObjectId from access/transam.h
 for dir in $INCLUDE_DIRS; do
     if [ -f "$dir/access/transam.h" ]; then
@@ -185,6 +193,7 @@ sed -e "s/;[ 	]*$//g" \
     -e "s/(TransactionId/(xid/g" \
     -e "s/PGUID/1/g" \
     -e "s/NAMEDATALEN/$NAMEDATALEN/g" \
+    -e "s/PGNSP/$PG_CATALOG_NAMESPACE/g" \
     -e "s/DEFAULT_ATTSTATTARGET/$DEFAULTATTSTATTARGET/g" \
     -e "s/INDEX_MAX_KEYS\*2/$INDEXMAXKEYS2/g" \
     -e "s/INDEX_MAX_KEYS\*4/$INDEXMAXKEYS4/g" \
diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c
index 9df788406a9..0b367e3daba 100644
--- a/src/backend/catalog/heap.c
+++ b/src/backend/catalog/heap.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.191 2002/03/22 02:56:30 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.192 2002/03/26 19:15:25 tgl Exp $
  *
  *
  * INTERFACE ROUTINES
@@ -38,7 +38,7 @@
 #include "catalog/indexing.h"
 #include "catalog/pg_attrdef.h"
 #include "catalog/pg_inherits.h"
-#include "catalog/pg_index.h"
+#include "catalog/pg_namespace.h"
 #include "catalog/pg_relcheck.h"
 #include "catalog/pg_statistic.h"
 #include "catalog/pg_type.h"
@@ -50,11 +50,9 @@
 #include "optimizer/planmain.h"
 #include "optimizer/prep.h"
 #include "optimizer/var.h"
-#include "parser/parse_coerce.h"
 #include "parser/parse_expr.h"
 #include "parser/parse_relation.h"
 #include "parser/parse_target.h"
-#include "parser/parse_type.h"
 #include "rewrite/rewriteRemove.h"
 #include "storage/smgr.h"
 #include "utils/builtins.h"
@@ -214,6 +212,7 @@ SystemAttributeByName(const char *attname, bool relhasoids)
  */
 Relation
 heap_create(char *relname,
+			Oid relnamespace,
 			TupleDesc tupDesc,
 			bool istemp,
 			bool storage_create,
@@ -222,7 +221,8 @@ heap_create(char *relname,
 	static unsigned int uniqueId = 0;
 
 	Oid			relid;
-	Oid			tblNode = MyDatabaseId;
+	Oid			dbid = MyDatabaseId;
+	RelFileNode	rnode;
 	bool		nailme = false;
 	Relation	rel;
 
@@ -238,9 +238,11 @@ heap_create(char *relname,
 	/*
 	 * Real ugly stuff to assign the proper relid in the relation
 	 * descriptor follows.	Note that only "bootstrapped" relations whose
-	 * OIDs are hard-coded in pg_class.h need be listed here.
+	 * OIDs are hard-coded in pg_class.h need be listed here.  We also
+	 * have to take special care for those rels that should be nailed
+	 * in cache and/or are shared across databases.
 	 */
-	if (relname && IsSystemRelationName(relname))
+	if (relname && relnamespace == PG_CATALOG_NAMESPACE)
 	{
 		if (strcmp(TypeRelationName, relname) == 0)
 		{
@@ -264,24 +266,24 @@ heap_create(char *relname,
 		}
 		else if (strcmp(ShadowRelationName, relname) == 0)
 		{
-			tblNode = InvalidOid;
+			dbid = InvalidOid;
 			relid = RelOid_pg_shadow;
 		}
 		else if (strcmp(GroupRelationName, relname) == 0)
 		{
-			tblNode = InvalidOid;
+			dbid = InvalidOid;
 			relid = RelOid_pg_group;
 		}
 		else if (strcmp(DatabaseRelationName, relname) == 0)
 		{
-			tblNode = InvalidOid;
+			dbid = InvalidOid;
 			relid = RelOid_pg_database;
 		}
 		else
 		{
 			relid = newoid();
 			if (IsSharedSystemRelationName(relname))
-				tblNode = InvalidOid;
+				dbid = InvalidOid;
 		}
 	}
 	else
@@ -297,11 +299,21 @@ heap_create(char *relname,
 				 PG_TEMP_REL_PREFIX, (int) MyProcPid, uniqueId++);
 	}
 
+	/*
+	 * For now, the physical identifier of the relation is the same as the
+	 * logical identifier.
+	 */
+	rnode.tblNode = dbid;
+	rnode.relNode = relid;
+
 	/*
 	 * build the relcache entry.
 	 */
-	rel = RelationBuildLocalRelation(relname, tupDesc,
-									 relid, tblNode,
+	rel = RelationBuildLocalRelation(relname,
+									 relnamespace,
+									 tupDesc,
+									 relid, dbid,
+									 rnode,
 									 nailme);
 
 	/*
@@ -329,7 +341,7 @@ heap_storage_create(Relation rel)
  *		1) CheckAttributeNames() is used to make certain the tuple
  *		   descriptor contains a valid set of attribute names
  *
- *		2) pg_class is opened and RelationFindRelid()
+ *		2) pg_class is opened and get_relname_relid()
  *		   performs a scan to ensure that no relation with the
  *		   same name already exists.
  *
@@ -400,73 +412,6 @@ CheckAttributeNames(TupleDesc tupdesc, bool relhasoids)
 	}
 }
 
-/* --------------------------------
- *		RelnameFindRelid
- *
- *		Find any existing relation of the given name.
- * --------------------------------
- */
-Oid
-RelnameFindRelid(const char *relname)
-{
-	Oid			relid;
-
-	/*
-	 * If this is not bootstrap (initdb) time, use the catalog index on
-	 * pg_class.
-	 */
-	if (!IsBootstrapProcessingMode())
-	{
-		relid = GetSysCacheOid(RELNAME,
-							   PointerGetDatum(relname),
-							   0, 0, 0);
-	}
-	else
-	{
-		Relation	pg_class_desc;
-		ScanKeyData key;
-		HeapScanDesc pg_class_scan;
-		HeapTuple	tuple;
-
-		pg_class_desc = heap_openr(RelationRelationName, AccessShareLock);
-
-		/*
-		 * At bootstrap time, we have to do this the hard way.	Form the
-		 * scan key.
-		 */
-		ScanKeyEntryInitialize(&key,
-							   0,
-							   (AttrNumber) Anum_pg_class_relname,
-							   (RegProcedure) F_NAMEEQ,
-							   PointerGetDatum(relname));
-
-		/*
-		 * begin the scan
-		 */
-		pg_class_scan = heap_beginscan(pg_class_desc,
-									   0,
-									   SnapshotNow,
-									   1,
-									   &key);
-
-		/*
-		 * get a tuple.  if the tuple is NULL then it means we didn't find
-		 * an existing relation.
-		 */
-		tuple = heap_getnext(pg_class_scan, 0);
-
-		if (HeapTupleIsValid(tuple))
-			relid = tuple->t_data->t_oid;
-		else
-			relid = InvalidOid;
-
-		heap_endscan(pg_class_scan);
-
-		heap_close(pg_class_desc, AccessShareLock);
-	}
-	return relid;
-}
-
 /* --------------------------------
  *		AddNewAttributeTuples
  *
@@ -719,6 +664,7 @@ AddNewRelationType(char *typeName, Oid new_rel_oid, Oid new_type_oid)
  */
 Oid
 heap_create_with_catalog(char *relname,
+						 Oid relnamespace,
 						 TupleDesc tupdesc,
 						 char relkind,
 						 bool relhasoids,
@@ -742,7 +688,7 @@ heap_create_with_catalog(char *relname,
 	CheckAttributeNames(tupdesc, relhasoids);
 
 	/* temp tables can mask non-temp tables */
-	if ((!istemp && RelnameFindRelid(relname)) ||
+	if ((!istemp && get_relname_relid(relname, relnamespace)) ||
 		(istemp && is_temp_rel_name(relname)))
 		elog(ERROR, "Relation '%s' already exists", relname);
 
@@ -765,8 +711,8 @@ heap_create_with_catalog(char *relname,
 	 * heap_storage_create() does all the "real" work of creating the disk
 	 * file for the relation.
 	 */
-	new_rel_desc = heap_create(relname, tupdesc, istemp, false,
-							   allow_system_table_mods);
+	new_rel_desc = heap_create(relname, relnamespace, tupdesc,
+							   istemp, false, allow_system_table_mods);
 
 	/* Fetch the relation OID assigned by heap_create */
 	new_rel_oid = new_rel_desc->rd_att->attrs[0]->attrelid;
@@ -916,10 +862,8 @@ RelationRemoveInheritance(Relation relation)
 	heap_close(catalogRelation, RowExclusiveLock);
 }
 
-/* --------------------------------
+/*
  *		RelationRemoveIndexes
- *
- * --------------------------------
  */
 static void
 RelationRemoveIndexes(Relation relation)
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index ce63a0fd548..17d290f84eb 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.173 2002/03/03 17:47:54 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.174 2002/03/26 19:15:28 tgl Exp $
  *
  *
  * INTERFACE ROUTINES
@@ -48,10 +48,12 @@
 #include "utils/catcache.h"
 #include "utils/fmgroids.h"
 #include "utils/inval.h"
+#include "utils/lsyscache.h"
 #include "utils/relcache.h"
 #include "utils/syscache.h"
 #include "utils/temprel.h"
 
+
 /*
  * macros used in guessing how many tuples are on a page.
  */
@@ -61,15 +63,13 @@
 	((natts) * AVG_ATTR_SIZE + MAXALIGN(sizeof(HeapTupleHeaderData))))
 
 /* non-export function prototypes */
-static Oid GetHeapRelationOid(char *heapRelationName, char *indexRelationName,
-				   bool istemp);
 static TupleDesc BuildFuncTupleDesc(Oid funcOid,
 				   Oid *classObjectId);
 static TupleDesc ConstructTupleDescriptor(Relation heapRelation,
 						 int numatts, AttrNumber *attNums,
 						 Oid *classObjectId);
 static void ConstructIndexReldesc(Relation indexRelation, Oid amoid);
-static Oid	UpdateRelationRelation(Relation indexRelation, char *temp_relname);
+static void UpdateRelationRelation(Relation indexRelation, char *temp_relname);
 static void InitializeAttributeOids(Relation indexRelation,
 						int numatts, Oid indexoid);
 static void AppendAttributeTuples(Relation indexRelation, int numatts);
@@ -99,33 +99,6 @@ IsReindexProcessing(void)
 	return reindexing;
 }
 
-/* ----------------------------------------------------------------
- *		GetHeapRelationOid
- * ----------------------------------------------------------------
- */
-static Oid
-GetHeapRelationOid(char *heapRelationName, char *indexRelationName, bool istemp)
-{
-	Oid			indoid;
-	Oid			heapoid;
-
-
-	indoid = RelnameFindRelid(indexRelationName);
-
-	if ((!istemp && OidIsValid(indoid)) ||
-		(istemp && is_temp_rel_name(indexRelationName)))
-		elog(ERROR, "index named \"%s\" already exists",
-			 indexRelationName);
-
-	heapoid = RelnameFindRelid(heapRelationName);
-
-	if (!OidIsValid(heapoid))
-		elog(ERROR, "cannot create index on non-existent relation \"%s\"",
-			 heapRelationName);
-
-	return heapoid;
-}
-
 static TupleDesc
 BuildFuncTupleDesc(Oid funcOid,
 				   Oid *classObjectId)
@@ -356,12 +329,11 @@ ConstructIndexReldesc(Relation indexRelation, Oid amoid)
  *		UpdateRelationRelation
  * ----------------------------------------------------------------
  */
-static Oid
+static void
 UpdateRelationRelation(Relation indexRelation, char *temp_relname)
 {
 	Relation	pg_class;
 	HeapTuple	tuple;
-	Oid			tupleOid;
 	Relation	idescs[Num_pg_class_indices];
 
 	pg_class = heap_openr(RelationRelationName, RowExclusiveLock);
@@ -372,9 +344,8 @@ UpdateRelationRelation(Relation indexRelation, char *temp_relname)
 						   (void *) indexRelation->rd_rel);
 
 	/*
-	 * the new tuple must have the same oid as the relcache entry for the
-	 * index.  sure would be embarrassing to do this sort of thing in
-	 * polite company.
+	 * the new tuple must have the oid already chosen for the index.
+	 * sure would be embarrassing to do this sort of thing in polite company.
 	 */
 	tuple->t_data->t_oid = RelationGetRelid(indexRelation);
 	heap_insert(pg_class, tuple);
@@ -396,11 +367,8 @@ UpdateRelationRelation(Relation indexRelation, char *temp_relname)
 		CatalogCloseIndices(Num_pg_class_indices, idescs);
 	}
 
-	tupleOid = tuple->t_data->t_oid;
 	heap_freetuple(tuple);
 	heap_close(pg_class, RowExclusiveLock);
-
-	return tupleOid;
 }
 
 /* ----------------------------------------------------------------
@@ -586,24 +554,31 @@ UpdateIndexRelation(Oid indexoid,
  * ----------------------------------------------------------------
  */
 Oid
-index_create(char *heapRelationName,
+index_create(Oid heapRelationId,
 			 char *indexRelationName,
 			 IndexInfo *indexInfo,
 			 Oid accessMethodObjectId,
 			 Oid *classObjectId,
+			 bool istemp,
 			 bool primary,
 			 bool allow_system_table_mods)
 {
 	Relation	heapRelation;
 	Relation	indexRelation;
 	TupleDesc	indexTupDesc;
-	Oid			heapoid;
+	Oid			namespaceId;
 	Oid			indexoid;
-	bool		istemp = is_temp_rel_name(heapRelationName);
 	char	   *temp_relname = NULL;
 
 	SetReindexProcessing(false);
 
+	/*
+	 * Only SELECT ... FOR UPDATE are allowed while doing this
+	 */
+	heapRelation = heap_open(heapRelationId, ShareLock);
+
+	namespaceId = RelationGetNamespace(heapRelation);
+
 	/*
 	 * check parameters
 	 */
@@ -611,19 +586,15 @@ index_create(char *heapRelationName,
 		indexInfo->ii_NumKeyAttrs < 1)
 		elog(ERROR, "must index at least one column");
 
-	if (heapRelationName && !allow_system_table_mods &&
-	  IsSystemRelationName(heapRelationName) && IsNormalProcessingMode())
+	if (!allow_system_table_mods &&
+		IsSystemRelationName(RelationGetRelationName(heapRelation)) &&
+		IsNormalProcessingMode())
 		elog(ERROR, "User-defined indexes on system catalogs are not supported");
 
-	/*
-	 * get heap relation oid and open the heap relation
-	 */
-	heapoid = GetHeapRelationOid(heapRelationName, indexRelationName, istemp);
-
-	/*
-	 * Only SELECT ... FOR UPDATE are allowed while doing this
-	 */
-	heapRelation = heap_open(heapoid, ShareLock);
+	if ((!istemp && get_relname_relid(indexRelationName, namespaceId)) ||
+		(istemp && is_temp_rel_name(indexRelationName)))
+		elog(ERROR, "index named \"%s\" already exists",
+			 indexRelationName);
 
 	/*
 	 * construct tuple descriptor for index tuples
@@ -649,8 +620,11 @@ index_create(char *heapRelationName,
 	/*
 	 * create the index relation
 	 */
-	indexRelation = heap_create(indexRelationName, indexTupDesc,
+	indexRelation = heap_create(indexRelationName,
+								namespaceId,
+								indexTupDesc,
 								istemp, false, allow_system_table_mods);
+	indexoid = RelationGetRelid(indexRelation);
 
 	/*
 	 * Obtain exclusive lock on it.  Although no other backends can see it
@@ -671,7 +645,7 @@ index_create(char *heapRelationName,
 	 *	  (append RELATION tuple)
 	 * ----------------
 	 */
-	indexoid = UpdateRelationRelation(indexRelation, temp_relname);
+	UpdateRelationRelation(indexRelation, temp_relname);
 
 	/*
 	 * We create the disk file for this relation here
@@ -699,7 +673,7 @@ index_create(char *heapRelationName,
 	 *	  (Or, could define a rule to maintain the predicate) --Nels, Feb '92
 	 * ----------------
 	 */
-	UpdateIndexRelation(indexoid, heapoid, indexInfo,
+	UpdateIndexRelation(indexoid, heapRelationId, indexInfo,
 						classObjectId, primary);
 
 	/*
@@ -725,7 +699,7 @@ index_create(char *heapRelationName,
 	 */
 	if (IsBootstrapProcessingMode())
 	{
-		index_register(heapRelationName, indexRelationName, indexInfo);
+		index_register(heapRelationId, indexoid, indexInfo);
 		/* XXX shouldn't we close the heap and index rels here? */
 	}
 	else
diff --git a/src/backend/catalog/indexing.c b/src/backend/catalog/indexing.c
index fcad116e99d..da269d28415 100644
--- a/src/backend/catalog/indexing.c
+++ b/src/backend/catalog/indexing.c
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/catalog/indexing.c,v 1.84 2002/03/22 21:34:44 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/catalog/indexing.c,v 1.85 2002/03/26 19:15:30 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -44,7 +44,7 @@ char	   *Name_pg_attr_indices[Num_pg_attr_indices] =
 char	   *Name_pg_attrdef_indices[Num_pg_attrdef_indices] =
 {AttrDefaultIndex};
 char	   *Name_pg_class_indices[Num_pg_class_indices] =
-{ClassNameIndex, ClassOidIndex};
+{ClassNameNspIndex, ClassOidIndex};
 char	   *Name_pg_database_indices[Num_pg_database_indices] =
 {DatabaseNameIndex, DatabaseOidIndex};
 char	   *Name_pg_group_indices[Num_pg_group_indices] =
diff --git a/src/backend/catalog/namespace.c b/src/backend/catalog/namespace.c
new file mode 100644
index 00000000000..c9d8d21f929
--- /dev/null
+++ b/src/backend/catalog/namespace.c
@@ -0,0 +1,126 @@
+/*-------------------------------------------------------------------------
+ *
+ * namespace.c
+ *	  code to support accessing and searching namespaces
+ *
+ * This is separate from pg_namespace.c, which contains the routines that
+ * directly manipulate the pg_namespace system catalog.  This module
+ * provides routines associated with defining a "namespace search path"
+ * and implementing search-path-controlled searches.
+ *
+ *
+ * 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/catalog/namespace.c,v 1.1 2002/03/26 19:15:32 tgl Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "catalog/namespace.h"
+#include "catalog/pg_namespace.h"
+#include "miscadmin.h"
+#include "utils/lsyscache.h"
+#include "utils/syscache.h"
+
+
+/*
+ * RangeVarGetRelid
+ *		Given a RangeVar describing an existing relation,
+ *		select the proper namespace and look up the relation OID.
+ *
+ * If the relation is not found, return InvalidOid if failOK = true,
+ * otherwise raise an error.
+ */
+Oid
+RangeVarGetRelid(const RangeVar *relation, bool failOK)
+{
+	Oid			namespaceId;
+	Oid			relId;
+
+	/*
+	 * We check the catalog name and then ignore it.
+	 */
+	if (relation->catalogname)
+	{
+		if (strcmp(relation->catalogname, DatabaseName) != 0)
+			elog(ERROR, "Cross-database references are not implemented");
+	}
+
+	if (relation->schemaname)
+	{
+		namespaceId = GetSysCacheOid(NAMESPACENAME,
+									 CStringGetDatum(relation->schemaname),
+									 0, 0, 0);
+		if (!OidIsValid(namespaceId))
+			elog(ERROR, "Namespace \"%s\" does not exist",
+				 relation->schemaname);
+		relId = get_relname_relid(relation->relname, namespaceId);
+	}
+	else
+	{
+		relId = RelnameGetRelid(relation->relname);
+	}
+
+	if (!OidIsValid(relId) && !failOK)
+	{
+		if (relation->schemaname)
+			elog(ERROR, "Relation \"%s\".\"%s\" does not exist",
+				 relation->schemaname, relation->relname);
+		else
+			elog(ERROR, "Relation \"%s\" does not exist",
+				 relation->relname);
+	}
+	return relId;
+}
+
+/*
+ * RangeVarGetCreationNamespace
+ *		Given a RangeVar describing a to-be-created relation,
+ *		choose which namespace to create it in.
+ */
+Oid
+RangeVarGetCreationNamespace(const RangeVar *newRelation)
+{
+	Oid			namespaceId;
+
+	/*
+	 * We check the catalog name and then ignore it.
+	 */
+	if (newRelation->catalogname)
+	{
+		if (strcmp(newRelation->catalogname, DatabaseName) != 0)
+			elog(ERROR, "Cross-database references are not implemented");
+	}
+
+	if (newRelation->schemaname)
+	{
+		namespaceId = GetSysCacheOid(NAMESPACENAME,
+									 CStringGetDatum(newRelation->schemaname),
+									 0, 0, 0);
+		if (!OidIsValid(namespaceId))
+			elog(ERROR, "Namespace \"%s\" does not exist",
+				 newRelation->schemaname);
+	}
+	else
+	{
+		/* XXX Wrong!  Need to get a default schema from somewhere */
+		namespaceId = PG_CATALOG_NAMESPACE;
+	}
+
+	return namespaceId;
+}
+
+/*
+ * RelnameGetRelid
+ *		Try to resolve an unqualified relation name.
+ *		Returns OID if relation found in search path, else InvalidOid.
+ */
+Oid
+RelnameGetRelid(const char *relname)
+{
+	/* XXX Wrong!  must search search path */
+	return get_relname_relid(relname, PG_CATALOG_NAMESPACE);
+}
diff --git a/src/backend/commands/cluster.c b/src/backend/commands/cluster.c
index f3739487426..0bd64232d1a 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.72 2002/02/19 20:11:12 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/cluster.c,v 1.73 2002/03/26 19:15:35 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -38,7 +38,8 @@
 
 
 static Oid	copy_heap(Oid OIDOldHeap, char *NewName, bool istemp);
-static void copy_index(Oid OIDOldIndex, Oid OIDNewHeap, char *NewIndexName);
+static void copy_index(Oid OIDOldIndex, Oid OIDNewHeap, char *NewIndexName,
+					   bool istemp);
 static void rebuildheap(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex);
 
 /*
@@ -54,7 +55,7 @@ static void rebuildheap(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex);
  *	 hand, re-creating n indexes may blow out the space.
  */
 void
-cluster(char *oldrelname, char *oldindexname)
+cluster(RangeVar *oldrelation, char *oldindexname)
 {
 	Oid			OIDOldHeap,
 				OIDOldIndex,
@@ -64,34 +65,40 @@ cluster(char *oldrelname, char *oldindexname)
 	bool		istemp;
 	char		NewHeapName[NAMEDATALEN];
 	char		NewIndexName[NAMEDATALEN];
-	char		saveoldrelname[NAMEDATALEN];
-	char		saveoldindexname[NAMEDATALEN];
+	RangeVar   *saveoldrelation;
+	RangeVar   *saveoldindex;
+	RangeVar   *NewHeap;
+	RangeVar   *NewIndex;
 
 	/*
-	 * Copy the arguments into local storage, just to be safe.
+	 * FIXME SCHEMAS: The old code had the comment:
+	 * "Copy the arguments into local storage, just to be safe."
+	 * By using copyObject we are not using local storage.
+	 * Was that really necessary?
 	 */
-	StrNCpy(saveoldrelname, oldrelname, NAMEDATALEN);
-	StrNCpy(saveoldindexname, oldindexname, NAMEDATALEN);
+	saveoldrelation = copyObject(oldrelation);
+	saveoldindex = copyObject(oldrelation);
+	saveoldindex->relname = pstrdup(oldindexname);
 
 	/*
 	 * We grab exclusive access to the target rel and index for the
 	 * duration of the transaction.
 	 */
-	OldHeap = heap_openr(saveoldrelname, AccessExclusiveLock);
+	OldHeap = heap_openrv(saveoldrelation, AccessExclusiveLock);
 	OIDOldHeap = RelationGetRelid(OldHeap);
 
-	OldIndex = index_openr(saveoldindexname);
+	OldIndex = index_openrv(saveoldindex);
 	LockRelation(OldIndex, AccessExclusiveLock);
 	OIDOldIndex = RelationGetRelid(OldIndex);
 
-	istemp = is_temp_rel_name(saveoldrelname);
+	istemp = is_temp_rel_name(saveoldrelation->relname);
 
 	/*
 	 * Check that index is in fact an index on the given relation
 	 */
 	if (OldIndex->rd_index->indrelid != OIDOldHeap)
 		elog(ERROR, "CLUSTER: \"%s\" is not an index for table \"%s\"",
-			 saveoldindexname, saveoldrelname);
+			 saveoldindex->relname, saveoldrelation->relname);
 
 	/* Drop relcache refcnts, but do NOT give up the locks */
 	heap_close(OldHeap, NoLock);
@@ -117,21 +124,26 @@ cluster(char *oldrelname, char *oldindexname)
 	/* Create new index over the tuples of the new heap. */
 	snprintf(NewIndexName, NAMEDATALEN, "temp_%u", OIDOldIndex);
 
-	copy_index(OIDOldIndex, OIDNewHeap, NewIndexName);
+	copy_index(OIDOldIndex, OIDNewHeap, NewIndexName, istemp);
 
 	CommandCounterIncrement();
 
 	/* Destroy old heap (along with its index) and rename new. */
-	heap_drop_with_catalog(saveoldrelname, allowSystemTableMods);
+	heap_drop_with_catalog(saveoldrelation->relname, allowSystemTableMods);
 
 	CommandCounterIncrement();
 
-	renamerel(NewHeapName, saveoldrelname);
+	NewHeap = copyObject(saveoldrelation);
+	NewHeap->relname = NewHeapName;
+	NewIndex = copyObject(saveoldindex);
+	NewIndex->relname = NewIndexName;
+	
+	renamerel(NewHeap, saveoldrelation->relname);
 
 	/* This one might be unnecessary, but let's be safe. */
 	CommandCounterIncrement();
 
-	renamerel(NewIndexName, saveoldindexname);
+	renamerel(NewIndex, saveoldindex->relname);
 }
 
 static Oid
@@ -151,7 +163,9 @@ copy_heap(Oid OIDOldHeap, char *NewName, bool istemp)
 	 */
 	tupdesc = CreateTupleDescCopyConstr(OldHeapDesc);
 
-	OIDNewHeap = heap_create_with_catalog(NewName, tupdesc,
+	OIDNewHeap = heap_create_with_catalog(NewName,
+										  RelationGetNamespace(OldHeap),
+										  tupdesc,
 										  OldHeap->rd_rel->relkind,
 										  OldHeap->rd_rel->relhasoids,
 										  istemp,
@@ -168,7 +182,7 @@ copy_heap(Oid OIDOldHeap, char *NewName, bool istemp)
 	 * AlterTableCreateToastTable ends with CommandCounterIncrement(), so
 	 * that the TOAST table will be visible for insertion.
 	 */
-	AlterTableCreateToastTable(NewName, true);
+	AlterTableCreateToastTable(OIDNewHeap, true);
 
 	heap_close(OldHeap, NoLock);
 
@@ -176,7 +190,7 @@ copy_heap(Oid OIDOldHeap, char *NewName, bool istemp)
 }
 
 static void
-copy_index(Oid OIDOldIndex, Oid OIDNewHeap, char *NewIndexName)
+copy_index(Oid OIDOldIndex, Oid OIDNewHeap, char *NewIndexName, bool istemp)
 {
 	Relation	OldIndex,
 				NewHeap;
@@ -189,18 +203,15 @@ copy_index(Oid OIDOldIndex, Oid OIDNewHeap, char *NewIndexName)
 	 * Create a new index like the old one.  To do this I get the info
 	 * from pg_index, and add a new index with a temporary name (that will
 	 * be changed later).
-	 *
-	 * NOTE: index_create will cause the new index to be a temp relation if
-	 * its parent table is, so we don't need to do anything special for
-	 * the temp-table case here.
 	 */
 	indexInfo = BuildIndexInfo(OldIndex->rd_index);
 
-	index_create(RelationGetRelationName(NewHeap),
+	index_create(OIDNewHeap,
 				 NewIndexName,
 				 indexInfo,
 				 OldIndex->rd_rel->relam,
 				 OldIndex->rd_index->indclass,
+				 istemp,
 				 OldIndex->rd_index->indisprimary,
 				 allowSystemTableMods);
 
diff --git a/src/backend/commands/command.c b/src/backend/commands/command.c
index af9e76e2791..bf7980d42c8 100644
--- a/src/backend/commands/command.c
+++ b/src/backend/commands/command.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.165 2002/03/22 21:34:44 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.166 2002/03/26 19:15:36 tgl Exp $
  *
  * NOTES
  *	  The PerformAddAttribute() code, like most of the relation
@@ -26,6 +26,7 @@
 #include "catalog/heap.h"
 #include "catalog/index.h"
 #include "catalog/indexing.h"
+#include "catalog/namespace.h"
 #include "catalog/pg_attrdef.h"
 #include "catalog/pg_index.h"
 #include "catalog/pg_namespace.h"
@@ -34,7 +35,6 @@
 #include "catalog/pg_type.h"
 #include "commands/command.h"
 #include "commands/trigger.h"
-#include "commands/defrem.h"
 #include "executor/execdefs.h"
 #include "executor/executor.h"
 #include "miscadmin.h"
@@ -415,8 +415,8 @@ AlterTableAddColumn(const char *relationName,
 
 	rel = heap_openr(RelationRelationName, RowExclusiveLock);
 
-	reltup = SearchSysCache(RELNAME,
-							PointerGetDatum(relationName),
+	reltup = SearchSysCache(RELOID,
+							ObjectIdGetDatum(myrelid),
 							0, 0, 0);
 
 	if (!HeapTupleIsValid(reltup))
@@ -424,7 +424,7 @@ AlterTableAddColumn(const char *relationName,
 			 relationName);
 
 	if (SearchSysCacheExists(ATTNAME,
-							 ObjectIdGetDatum(reltup->t_data->t_oid),
+							 ObjectIdGetDatum(myrelid),
 							 PointerGetDatum(colDef->colname),
 							 0, 0))
 		elog(ERROR, "ALTER TABLE: column name \"%s\" already exists in table \"%s\"",
@@ -463,7 +463,7 @@ AlterTableAddColumn(const char *relationName,
 
 	attribute = (Form_pg_attribute) GETSTRUCT(attributeTuple);
 
-	attribute->attrelid = reltup->t_data->t_oid;
+	attribute->attrelid = myrelid;
 	namestrcpy(&(attribute->attname), colDef->colname);
 	attribute->atttypid = typeTuple->t_data->t_oid;
 	attribute->attstattarget = DEFAULT_ATTSTATTARGET;
@@ -532,7 +532,7 @@ AlterTableAddColumn(const char *relationName,
 	 */
 	if (colDef->constraints != NIL)
 	{
-		rel = heap_openr(relationName, AccessExclusiveLock);
+		rel = heap_open(myrelid, AccessExclusiveLock);
 		AddRelationRawConstraints(rel, NIL, colDef->constraints);
 		heap_close(rel, NoLock);
 	}
@@ -541,7 +541,7 @@ AlterTableAddColumn(const char *relationName,
 	 * Automatically create the secondary relation for TOAST if it
 	 * formerly had no such but now has toastable attributes.
 	 */
-	AlterTableCreateToastTable(relationName, true);
+	AlterTableCreateToastTable(myrelid, true);
 }
 
 
@@ -989,11 +989,7 @@ RemoveColumnReferences(Oid reloid, int attnum, bool checkonly, HeapTuple reltup)
 				}
 				else
 				{
-					htup = SearchSysCache(RELOID,
-									 ObjectIdGetDatum(index->indexrelid),
-										  0, 0, 0);
-					RemoveIndex(NameStr(((Form_pg_class) GETSTRUCT(htup))->relname));
-					ReleaseSysCache(htup);
+					index_drop(index->indexrelid);
 				}
 				break;
 			}
@@ -1066,8 +1062,8 @@ AlterTableDropColumn(const char *relationName,
 	 * lock the pg_class tuple for update
 	 */
 	rel = heap_openr(RelationRelationName, RowExclusiveLock);
-	reltup = SearchSysCache(RELNAME,
-							PointerGetDatum(relationName),
+	reltup = SearchSysCache(RELOID,
+							ObjectIdGetDatum(myrelid),
 							0, 0, 0);
 	if (!HeapTupleIsValid(reltup))
 		elog(ERROR, "ALTER TABLE: relation \"%s\" not found",
@@ -1092,7 +1088,7 @@ AlterTableDropColumn(const char *relationName,
 	 * Get the target pg_attribute tuple and make a modifiable copy
 	 */
 	tup = SearchSysCacheCopy(ATTNAME,
-							 ObjectIdGetDatum(reltup->t_data->t_oid),
+							 ObjectIdGetDatum(myrelid),
 							 PointerGetDatum(colName),
 							 0, 0);
 	if (!HeapTupleIsValid(tup))
@@ -1370,7 +1366,8 @@ AlterTableAddConstraint(char *relationName,
 					 * someone doesn't delete rows out from under us.
 					 */
 
-					pkrel = heap_openr(fkconstraint->pktable->relname, AccessExclusiveLock);
+					pkrel = heap_openrv(fkconstraint->pktable,
+										AccessExclusiveLock);
 					if (pkrel->rd_rel->relkind != RELKIND_RELATION)
 						elog(ERROR, "referenced table \"%s\" not a relation",
 							 fkconstraint->pktable->relname);
@@ -1557,43 +1554,48 @@ AlterTableDropConstraint(const char *relationName,
  * ALTER TABLE OWNER
  */
 void
-AlterTableOwner(const char *relationName, const char *newOwnerName)
+AlterTableOwner(const RangeVar *tgtrel, const char *newOwnerName)
 {
-	Oid relationOid;
-	Relation relation;
-	int32 newOwnerSysId;
+	Relation	rel;
+	Oid			myrelid;
+	int32		newOwnerSysId;
 
 	/* check that we are the superuser */
 	if (!superuser())
 		elog(ERROR, "ALTER TABLE: permission denied");
 
 	/* lookup the OID of the target relation */
-	relation = RelationNameGetRelation(relationName);
-	relationOid = relation->rd_id;
-	RelationClose(relation);
+	rel = relation_openrv(tgtrel, AccessExclusiveLock);
+	myrelid = RelationGetRelid(rel);
+	heap_close(rel, NoLock);	/* close rel but keep lock! */
 
 	/* lookup the sysid of the new owner */
 	newOwnerSysId = get_usesysid(newOwnerName);
 
 	/* do all the actual work */
-	AlterTableOwnerId(relationOid, newOwnerSysId);
+	AlterTableOwnerId(myrelid, newOwnerSysId);
 }
 
 static void
 AlterTableOwnerId(Oid relationOid, int32 newOwnerSysId)
 {
+	Relation		target_rel;
 	Relation		class_rel;
 	HeapTuple		tuple;
 	Relation		idescs[Num_pg_class_indices];
 	Form_pg_class	tuple_class;
 
+	/* Get exclusive lock till end of transaction on the target table */
+	target_rel = heap_open(relationOid, AccessExclusiveLock);
+
+	/* Get its pg_class tuple, too */
+	class_rel = heap_openr(RelationRelationName, RowExclusiveLock);
+
 	tuple = SearchSysCacheCopy(RELOID,
 							   ObjectIdGetDatum(relationOid),
 							   0, 0, 0);
 	if (!HeapTupleIsValid(tuple))
-		elog(ERROR, "ALTER TABLE: object ID %hd not found",
-				relationOid);
-
+		elog(ERROR, "ALTER TABLE: relation %u not found", relationOid);
 	tuple_class = (Form_pg_class) GETSTRUCT(tuple);
 
 	/* Can we change the ownership of this tuple? */
@@ -1603,7 +1605,6 @@ AlterTableOwnerId(Oid relationOid, int32 newOwnerSysId)
 	 * Okay, this is a valid tuple: change its ownership and
 	 * write to the heap.
 	 */
-	class_rel = heap_openr(RelationRelationName, RowExclusiveLock);
 	tuple_class->relowner = newOwnerSysId;
 	simple_heap_update(class_rel, &tuple->t_self, tuple);
 
@@ -1617,25 +1618,25 @@ AlterTableOwnerId(Oid relationOid, int32 newOwnerSysId)
 	 * indexes that belong to the table, as well as the table's toast
 	 * table (if it has one)
 	 */
-	if (tuple_class->relkind == RELKIND_RELATION)
+	if (tuple_class->relkind == RELKIND_RELATION ||
+		tuple_class->relkind == RELKIND_TOASTVALUE)
 	{
-		/* Search for indexes belonging to this table */
-		Relation target_rel;
 		List *index_oid_list, *i;
 
 		/* Find all the indexes belonging to this relation */
-		target_rel = heap_open(relationOid, RowExclusiveLock);
 		index_oid_list = RelationGetIndexList(target_rel);
-		heap_close(target_rel, RowExclusiveLock);
 
 		/* For each index, recursively change its ownership */
-		foreach (i, index_oid_list)
+		foreach(i, index_oid_list)
 		{
 			AlterTableOwnerId(lfirsti(i), newOwnerSysId);
 		}
 
 		freeList(index_oid_list);
+	}
 
+	if (tuple_class->relkind == RELKIND_RELATION)
+	{
 		/* If it has a toast table, recurse to change its ownership */
 		if (tuple_class->reltoastrelid != InvalidOid)
 		{
@@ -1644,7 +1645,8 @@ AlterTableOwnerId(Oid relationOid, int32 newOwnerSysId)
 	}
 
 	heap_freetuple(tuple);
-	heap_close(class_rel, NoLock);
+	heap_close(class_rel, RowExclusiveLock);
+	heap_close(target_rel, NoLock);
 }
 
 static void
@@ -1669,10 +1671,9 @@ CheckTupleType(Form_pg_class tuple_class)
  * ALTER TABLE CREATE TOAST TABLE
  */
 void
-AlterTableCreateToastTable(const char *relationName, bool silent)
+AlterTableCreateToastTable(Oid relOid, bool silent)
 {
 	Relation	rel;
-	Oid			myrelid;
 	HeapTuple	reltup;
 	HeapTupleData classtuple;
 	TupleDesc	tupdesc;
@@ -1690,14 +1691,13 @@ AlterTableCreateToastTable(const char *relationName, bool silent)
 	 * Grab an exclusive lock on the target table, which we will NOT
 	 * release until end of transaction.
 	 */
-	rel = heap_openr(relationName, AccessExclusiveLock);
-	myrelid = RelationGetRelid(rel);
+	rel = heap_open(relOid, AccessExclusiveLock);
 
 	if (rel->rd_rel->relkind != RELKIND_RELATION)
 		elog(ERROR, "ALTER TABLE: relation \"%s\" is not a table",
-			 relationName);
+			 RelationGetRelationName(rel));
 
-	if (!pg_class_ownercheck(myrelid, GetUserId()))
+	if (!pg_class_ownercheck(relOid, GetUserId()))
 		elog(ERROR, "ALTER TABLE: permission denied");
 
 	/*
@@ -1705,12 +1705,12 @@ AlterTableCreateToastTable(const char *relationName, bool silent)
 	 */
 	class_rel = heap_openr(RelationRelationName, RowExclusiveLock);
 
-	reltup = SearchSysCache(RELNAME,
-							PointerGetDatum(relationName),
+	reltup = SearchSysCache(RELOID,
+							ObjectIdGetDatum(relOid),
 							0, 0, 0);
 	if (!HeapTupleIsValid(reltup))
 		elog(ERROR, "ALTER TABLE: relation \"%s\" not found",
-			 relationName);
+			 RelationGetRelationName(rel));
 	classtuple.t_self = reltup->t_self;
 	ReleaseSysCache(reltup);
 
@@ -1739,7 +1739,7 @@ AlterTableCreateToastTable(const char *relationName, bool silent)
 		}
 
 		elog(ERROR, "ALTER TABLE: relation \"%s\" already has a toast table",
-			 relationName);
+			 RelationGetRelationName(rel));
 	}
 
 	/*
@@ -1756,14 +1756,14 @@ AlterTableCreateToastTable(const char *relationName, bool silent)
 		}
 
 		elog(ERROR, "ALTER TABLE: relation \"%s\" does not need a toast table",
-			 relationName);
+			 RelationGetRelationName(rel));
 	}
 
 	/*
 	 * Create the toast table and its index
 	 */
-	sprintf(toast_relname, "pg_toast_%u", myrelid);
-	sprintf(toast_idxname, "pg_toast_%u_idx", myrelid);
+	sprintf(toast_relname, "pg_toast_%u", relOid);
+	sprintf(toast_idxname, "pg_toast_%u_idx", relOid);
 
 	/* this is pretty painful...  need a tuple descriptor */
 	tupdesc = CreateTemplateTupleDesc(3);
@@ -1795,7 +1795,9 @@ AlterTableCreateToastTable(const char *relationName, bool silent)
 	 * collision, and the toast rel will be destroyed when its master is,
 	 * so there's no need to handle the toast rel as temp.
 	 */
-	toast_relid = heap_create_with_catalog(toast_relname, tupdesc,
+	toast_relid = heap_create_with_catalog(toast_relname,
+										   RelationGetNamespace(rel),
+										   tupdesc,
 										   RELKIND_TOASTVALUE, false,
 										   false, true);
 
@@ -1825,9 +1827,9 @@ AlterTableCreateToastTable(const char *relationName, bool silent)
 	classObjectId[0] = OID_BTREE_OPS_OID;
 	classObjectId[1] = INT4_BTREE_OPS_OID;
 
-	toast_idxid = index_create(toast_relname, toast_idxname, indexInfo,
+	toast_idxid = index_create(toast_relid, toast_idxname, indexInfo,
 							   BTREE_AM_OID, classObjectId,
-							   true, true);
+							   false, true, true);
 
 	/*
 	 * Update toast rel's pg_class entry to show that it has an index. The
@@ -1927,21 +1929,15 @@ LockTableCommand(LockStmt *lockstmt)
 	foreach(p, lockstmt->relations)
 	{
 		RangeVar   *relation = lfirst(p);
-		char	   *relname = relation->relname;
 		Oid			reloid;
-		int			aclresult;
+		int32		aclresult;
 		Relation	rel;
 
 		/*
 		 * We don't want to open the relation until we've checked privilege.
 		 * So, manually get the relation OID.
 		 */
-		reloid = GetSysCacheOid(RELNAME,
-								PointerGetDatum(relname),
-								0, 0, 0);
-		if (!OidIsValid(reloid))
-			elog(ERROR, "LOCK TABLE: relation \"%s\" does not exist",
-				 relname);
+		reloid = RangeVarGetRelid(relation, false);
 
 		if (lockstmt->mode == AccessShareLock)
 			aclresult = pg_class_aclcheck(reloid, GetUserId(),
@@ -1958,7 +1954,7 @@ LockTableCommand(LockStmt *lockstmt)
 		/* 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",
-				 relname);
+				 relation->relname);
 
 		relation_close(rel, NoLock);	/* close rel, keep lock */
 	}
diff --git a/src/backend/commands/comment.c b/src/backend/commands/comment.c
index 4ad49581629..cdc8ce35be3 100644
--- a/src/backend/commands/comment.c
+++ b/src/backend/commands/comment.c
@@ -7,7 +7,7 @@
  * Copyright (c) 1999-2001, PostgreSQL Global Development Group
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/commands/comment.c,v 1.36 2002/03/21 23:27:20 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/comment.c,v 1.37 2002/03/26 19:15:38 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -20,6 +20,7 @@
 #include "catalog/indexing.h"
 #include "catalog/pg_database.h"
 #include "catalog/pg_description.h"
+#include "catalog/pg_namespace.h"
 #include "catalog/pg_operator.h"
 #include "catalog/pg_rewrite.h"
 #include "catalog/pg_trigger.h"
@@ -48,7 +49,8 @@
  *------------------------------------------------------------------
  */
 
-static void CommentRelation(int objtype, char *relation, char *comment);
+static void CommentRelation(int objtype, char * schemaname, char *relation,
+							char *comment);
 static void CommentAttribute(char *relation, char *attrib, char *comment);
 static void CommentDatabase(char *database, char *comment);
 static void CommentRewrite(char *rule, char *comment);
@@ -74,7 +76,7 @@ static void CommentTrigger(char *trigger, char *relation, char *comments);
 */
 
 void
-CommentObject(int objtype, char *objname, char *objproperty,
+CommentObject(int objtype, char *schemaname, char *objname, char *objproperty,
 			  List *objlist, char *comment)
 {
 	switch (objtype)
@@ -83,7 +85,7 @@ CommentObject(int objtype, char *objname, char *objproperty,
 		case SEQUENCE:
 		case TABLE:
 		case VIEW:
-			CommentRelation(objtype, objname, comment);
+			CommentRelation(objtype, schemaname, objname, comment);
 			break;
 		case COLUMN:
 			CommentAttribute(objname, objproperty, comment);
@@ -323,9 +325,16 @@ DeleteComments(Oid oid, Oid classoid)
  */
 
 static void
-CommentRelation(int reltype, char *relname, char *comment)
+CommentRelation(int reltype, char *schemaname, char *relname, char *comment)
 {
 	Relation	relation;
+	RangeVar   *tgtrel = makeNode(RangeVar);
+	
+	
+	tgtrel->relname = relname;
+	tgtrel->schemaname = schemaname;
+	/* FIXME SCHEMA: Can we add comments to temp relations? */
+	tgtrel->istemp = false;
 
 	/*
 	 * Open the relation.  We do this mainly to acquire a lock that
@@ -333,7 +342,7 @@ CommentRelation(int reltype, char *relname, char *comment)
 	 * did, they'd fail to remove the entry we are about to make in
 	 * pg_description.)
 	 */
-	relation = relation_openr(relname, AccessShareLock);
+	relation = relation_openrv(tgtrel, AccessShareLock);
 
 	/* Check object security */
 	if (!pg_class_ownercheck(RelationGetRelid(relation), GetUserId()))
@@ -504,9 +513,7 @@ CommentRewrite(char *rule, char *comment)
 
 	/* pg_rewrite doesn't have a hard-coded OID, so must look it up */
 
-	classoid = GetSysCacheOid(RELNAME,
-							  PointerGetDatum(RewriteRelationName),
-							  0, 0, 0);
+	classoid = get_relname_relid(RewriteRelationName, PG_CATALOG_NAMESPACE);
 	Assert(OidIsValid(classoid));
 
 	/* Call CreateComments() to create/drop the comments */
@@ -604,9 +611,7 @@ CommentAggregate(char *aggregate, List *arguments, char *comment)
 
 	/* pg_aggregate doesn't have a hard-coded OID, so must look it up */
 
-	classoid = GetSysCacheOid(RELNAME,
-							  PointerGetDatum(AggregateRelationName),
-							  0, 0, 0);
+	classoid = get_relname_relid(AggregateRelationName, PG_CATALOG_NAMESPACE);
 	Assert(OidIsValid(classoid));
 
 	/* Call CreateComments() to create/drop the comments */
diff --git a/src/backend/commands/creatinh.c b/src/backend/commands/creatinh.c
index 0f9bf525ef3..2d68d5d6e7f 100644
--- a/src/backend/commands/creatinh.c
+++ b/src/backend/commands/creatinh.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/commands/Attic/creatinh.c,v 1.91 2002/03/22 02:56:31 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/Attic/creatinh.c,v 1.92 2002/03/26 19:15:40 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -18,9 +18,11 @@
 #include "access/heapam.h"
 #include "catalog/catalog.h"
 #include "catalog/catname.h"
-#include "catalog/indexing.h"
 #include "catalog/heap.h"
+#include "catalog/indexing.h"
+#include "catalog/namespace.h"
 #include "catalog/pg_inherits.h"
+#include "catalog/pg_namespace.h"
 #include "catalog/pg_type.h"
 #include "commands/creatinh.h"
 #include "miscadmin.h"
@@ -54,6 +56,7 @@ Oid
 DefineRelation(CreateStmt *stmt, char relkind)
 {
 	char	   *relname = palloc(NAMEDATALEN);
+	Oid			namespaceId;
 	List	   *schema = stmt->tableElts;
 	int			numberOfAttributes;
 	Oid			relationId;
@@ -73,6 +76,12 @@ DefineRelation(CreateStmt *stmt, char relkind)
 	 */
 	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
@@ -147,7 +156,8 @@ DefineRelation(CreateStmt *stmt, char relkind)
 		}
 	}
 
-	relationId = heap_create_with_catalog(relname, descriptor,
+	relationId = heap_create_with_catalog(relname, namespaceId,
+										  descriptor,
 										  relkind,
 										  stmt->hasoids || parentHasOids,
 										  stmt->relation->istemp,
@@ -330,7 +340,7 @@ MergeDomainAttributes(List *schema)
  * 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 Value objects) of parent relations.
+ * 'supers' is a list of names (as RangeVar nodes) of parent relations.
  * 'istemp' is TRUE if we are creating a temp relation.
  *
  * Output arguments:
@@ -417,24 +427,6 @@ MergeAttributes(List *schema, List *supers, bool istemp,
 		}
 	}
 
-	/*
-	 * Reject duplicate names in the list of parents, too.
-	 *
-	 * XXX needs to be smarter about schema-qualified table names.
-	 */
-	foreach(entry, supers)
-	{
-		List	   *rest;
-
-		foreach(rest, lnext(entry))
-		{
-			if (strcmp(((RangeVar *) lfirst(entry))->relname, 
-					   ((RangeVar *) lfirst(rest))->relname) == 0)
-				elog(ERROR, "CREATE TABLE: inherited relation \"%s\" duplicated",
-					 ((RangeVar *) lfirst(entry))->relname);
-		}
-	}
-
 	/*
 	 * Scan the parents left-to-right, and merge their attributes to form
 	 * a list of inherited attributes (inhSchema).	Also check to see if
@@ -443,30 +435,40 @@ MergeAttributes(List *schema, List *supers, bool istemp,
 	child_attno = 0;
 	foreach(entry, supers)
 	{
-		char	   *name = ((RangeVar *) lfirst(entry))->relname;
+		RangeVar   *parent = (RangeVar *) lfirst(entry);
 		Relation	relation;
 		TupleDesc	tupleDesc;
 		TupleConstr *constr;
 		AttrNumber *newattno;
 		AttrNumber	parent_attno;
 
-		relation = heap_openr(name, AccessShareLock);
+		relation = heap_openrv(parent, AccessShareLock);
 
 		if (relation->rd_rel->relkind != RELKIND_RELATION)
-			elog(ERROR, "CREATE TABLE: inherited relation \"%s\" is not a table", name);
+			elog(ERROR, "CREATE TABLE: inherited relation \"%s\" is not a table",
+				 parent->relname);
 		/* Permanent rels cannot inherit from temporary ones */
-		if (!istemp && is_temp_rel_name(name))
-			elog(ERROR, "CREATE TABLE: cannot inherit from temp relation \"%s\"", name);
+		if (!istemp && is_temp_rel_name(parent->relname))
+			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\"", name);
+			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, relation->rd_id);
-		setRelhassubclassInRelation(relation->rd_id, true);
+		parentOids = lappendi(parentOids, RelationGetRelid(relation));
+		setRelhassubclassInRelation(RelationGetRelid(relation), true);
 
 		parentHasOids |= relation->rd_rel->relhasoids;
 
diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index 677f1306376..ae3476efb24 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.64 2002/03/20 19:43:47 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.65 2002/03/26 19:15:41 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -18,8 +18,8 @@
 #include "access/heapam.h"
 #include "catalog/catalog.h"
 #include "catalog/catname.h"
-#include "catalog/heap.h"
 #include "catalog/index.h"
+#include "catalog/namespace.h"
 #include "catalog/pg_opclass.h"
 #include "commands/defrem.h"
 #include "miscadmin.h"
@@ -33,6 +33,7 @@
 #include "utils/fmgroids.h"
 #include "utils/lsyscache.h"
 #include "utils/syscache.h"
+#include "utils/temprel.h"
 
 
 #define IsFuncIndex(ATTR_LIST) (((IndexElem*)lfirst(ATTR_LIST))->args != NIL)
@@ -61,7 +62,7 @@ static Oid	GetDefaultOpClass(Oid attrType, Oid accessMethodId);
  * 'rangetable' is needed to interpret the predicate.
  */
 void
-DefineIndex(char *heapRelationName,
+DefineIndex(RangeVar *heapRelation,
 			char *indexRelationName,
 			char *accessMethodName,
 			List *attributeList,
@@ -73,6 +74,7 @@ DefineIndex(char *heapRelationName,
 	Oid		   *classObjectId;
 	Oid			accessMethodId;
 	Oid			relationId;
+	bool		istemp = is_temp_rel_name(heapRelation->relname);
 	Relation	rel;
 	HeapTuple	tuple;
 	Form_pg_am	accessMethodForm;
@@ -93,20 +95,20 @@ DefineIndex(char *heapRelationName,
 	/*
 	 * Open heap relation, acquire a suitable lock on it, remember its OID
 	 */
-	rel = heap_openr(heapRelationName, ShareLock);
+	rel = heap_openrv(heapRelation, ShareLock);
 
 	/* Note: during bootstrap may see uncataloged relation */
 	if (rel->rd_rel->relkind != RELKIND_RELATION &&
 		rel->rd_rel->relkind != RELKIND_UNCATALOGED)
 		elog(ERROR, "DefineIndex: relation \"%s\" is not a table",
-			 heapRelationName);
+			 heapRelation->relname);
 
 	relationId = RelationGetRelid(rel);
 
 	heap_close(rel, NoLock);
 
 	if (!IsBootstrapProcessingMode() &&
-		IsSystemRelationName(heapRelationName) &&
+		IsSystemRelationName(heapRelation->relname) &&
 		!IndexesAreActive(relationId, false))
 		elog(ERROR, "Existing indexes are inactive. REINDEX first");
 
@@ -187,9 +189,9 @@ DefineIndex(char *heapRelationName,
 					   relationId, accessMethodName, accessMethodId);
 	}
 
-	index_create(heapRelationName, indexRelationName,
+	index_create(relationId, indexRelationName,
 				 indexInfo, accessMethodId, classObjectId,
-				 primary, allowSystemTableMods);
+				 istemp, primary, allowSystemTableMods);
 
 	/*
 	 * We update the relation's pg_class tuple even if it already has
@@ -500,23 +502,25 @@ GetDefaultOpClass(Oid attrType, Oid accessMethodId)
  *		...
  */
 void
-RemoveIndex(char *name)
+RemoveIndex(RangeVar *relation)
 {
+	Oid			indOid;
 	HeapTuple	tuple;
 
-	tuple = SearchSysCache(RELNAME,
-						   PointerGetDatum(name),
+	indOid = RangeVarGetRelid(relation, false);
+	tuple = SearchSysCache(RELOID,
+						   ObjectIdGetDatum(indOid),
 						   0, 0, 0);
 	if (!HeapTupleIsValid(tuple))
-		elog(ERROR, "index \"%s\" does not exist", name);
+		elog(ERROR, "index \"%s\" does not exist", relation->relname);
 
 	if (((Form_pg_class) GETSTRUCT(tuple))->relkind != RELKIND_INDEX)
 		elog(ERROR, "relation \"%s\" is of type \"%c\"",
-			 name, ((Form_pg_class) GETSTRUCT(tuple))->relkind);
-
-	index_drop(tuple->t_data->t_oid);
+			 relation->relname, ((Form_pg_class) GETSTRUCT(tuple))->relkind);
 
 	ReleaseSysCache(tuple);
+
+	index_drop(indOid);
 }
 
 /*
@@ -528,8 +532,9 @@ RemoveIndex(char *name)
  *		...
  */
 void
-ReindexIndex(const char *name, bool force /* currently unused */ )
+ReindexIndex(RangeVar *indexRelation, bool force /* currently unused */ )
 {
+	Oid			indOid;
 	HeapTuple	tuple;
 	bool		overwrite = false;
 
@@ -541,22 +546,24 @@ ReindexIndex(const char *name, bool force /* currently unused */ )
 	if (IsTransactionBlock())
 		elog(ERROR, "REINDEX cannot run inside a BEGIN/END block");
 
-	tuple = SearchSysCache(RELNAME,
-						   PointerGetDatum(name),
+	indOid = RangeVarGetRelid(indexRelation, false);
+	tuple = SearchSysCache(RELOID,
+						   ObjectIdGetDatum(indOid),
 						   0, 0, 0);
 	if (!HeapTupleIsValid(tuple))
-		elog(ERROR, "index \"%s\" does not exist", name);
+		elog(ERROR, "index \"%s\" does not exist", indexRelation->relname);
 
 	if (((Form_pg_class) GETSTRUCT(tuple))->relkind != RELKIND_INDEX)
 		elog(ERROR, "relation \"%s\" is of type \"%c\"",
-			 name, ((Form_pg_class) GETSTRUCT(tuple))->relkind);
+			 indexRelation->relname,
+			 ((Form_pg_class) GETSTRUCT(tuple))->relkind);
+
+	ReleaseSysCache(tuple);
 
 	if (IsIgnoringSystemIndexes())
 		overwrite = true;
-	if (!reindex_index(tuple->t_data->t_oid, force, overwrite))
-		elog(WARNING, "index \"%s\" wasn't reindexed", name);
-
-	ReleaseSysCache(tuple);
+	if (!reindex_index(indOid, force, overwrite))
+		elog(WARNING, "index \"%s\" wasn't reindexed", indexRelation->relname);
 }
 
 /*
@@ -568,8 +575,9 @@ ReindexIndex(const char *name, bool force /* currently unused */ )
  *		...
  */
 void
-ReindexTable(const char *name, bool force)
+ReindexTable(RangeVar *relation, bool force)
 {
+	Oid			heapOid;
 	HeapTuple	tuple;
 
 	/*
@@ -580,20 +588,22 @@ ReindexTable(const char *name, bool force)
 	if (IsTransactionBlock())
 		elog(ERROR, "REINDEX cannot run inside a BEGIN/END block");
 
-	tuple = SearchSysCache(RELNAME,
-						   PointerGetDatum(name),
+	heapOid = RangeVarGetRelid(relation, false);
+	tuple = SearchSysCache(RELOID,
+						   ObjectIdGetDatum(heapOid),
 						   0, 0, 0);
 	if (!HeapTupleIsValid(tuple))
-		elog(ERROR, "table \"%s\" does not exist", name);
+		elog(ERROR, "table \"%s\" does not exist", relation->relname);
 
 	if (((Form_pg_class) GETSTRUCT(tuple))->relkind != RELKIND_RELATION)
 		elog(ERROR, "relation \"%s\" is of type \"%c\"",
-			 name, ((Form_pg_class) GETSTRUCT(tuple))->relkind);
-
-	if (!reindex_relation(tuple->t_data->t_oid, force))
-		elog(WARNING, "table \"%s\" wasn't reindexed", name);
+			 relation->relname,
+			 ((Form_pg_class) GETSTRUCT(tuple))->relkind);
 
 	ReleaseSysCache(tuple);
+
+	if (!reindex_relation(heapOid, force))
+		elog(WARNING, "table \"%s\" wasn't reindexed", relation->relname);
 }
 
 /*
diff --git a/src/backend/commands/rename.c b/src/backend/commands/rename.c
index 0ce475303a7..f050aa9f7fc 100644
--- a/src/backend/commands/rename.c
+++ b/src/backend/commands/rename.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/commands/Attic/rename.c,v 1.64 2002/03/21 23:27:21 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/Attic/rename.c,v 1.65 2002/03/26 19:15:43 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -36,6 +36,7 @@
 #include "utils/acl.h"
 #include "utils/builtins.h"
 #include "utils/fmgroids.h"
+#include "utils/lsyscache.h"
 #include "utils/relcache.h"
 #include "utils/syscache.h"
 #include "utils/temprel.h"
@@ -266,19 +267,20 @@ renameatt(char *relname,
  *		renamerel		- change the name of a relation
  */
 void
-renamerel(const char *oldrelname, const char *newrelname)
+renamerel(const RangeVar *relation, const char *newrelname)
 {
 	Relation	targetrelation;
 	Relation	relrelation;	/* for RELATION relation */
 	HeapTuple	reltup;
+	Oid			namespaceId;
 	Oid			reloid;
 	char		relkind;
 	bool		relhastriggers;
 	Relation	irelations[Num_pg_class_indices];
 
-	if (!allowSystemTableMods && IsSystemRelationName(oldrelname))
+	if (!allowSystemTableMods && IsSystemRelationName(relation->relname))
 		elog(ERROR, "renamerel: system relation \"%s\" may not be renamed",
-			 oldrelname);
+			 relation->relname);
 
 	if (!allowSystemTableMods && IsSystemRelationName(newrelname))
 		elog(ERROR, "renamerel: Illegal class name: \"%s\" -- pg_ is reserved for system catalogs",
@@ -288,15 +290,16 @@ renamerel(const char *oldrelname, const char *newrelname)
 	 * Check for renaming a temp table, which only requires altering the
 	 * temp-table mapping, not the underlying table.
 	 */
-	if (rename_temp_relation(oldrelname, newrelname))
+	if (rename_temp_relation(relation->relname, newrelname))
 		return;					/* all done... */
 
 	/*
 	 * Grab an exclusive lock on the target table or index, which we will
 	 * NOT release until end of transaction.
 	 */
-	targetrelation = relation_openr(oldrelname, AccessExclusiveLock);
+	targetrelation = relation_openrv(relation, AccessExclusiveLock);
 
+	namespaceId = RelationGetNamespace(targetrelation);
 	reloid = RelationGetRelid(targetrelation);
 	relkind = targetrelation->rd_rel->relkind;
 	relhastriggers = (targetrelation->rd_rel->reltriggers > 0);
@@ -323,13 +326,14 @@ renamerel(const char *oldrelname, const char *newrelname)
 	 */
 	relrelation = heap_openr(RelationRelationName, RowExclusiveLock);
 
-	reltup = SearchSysCacheCopy(RELNAME,
-								PointerGetDatum(oldrelname),
+	reltup = SearchSysCacheCopy(RELOID,
+								PointerGetDatum(reloid),
 								0, 0, 0);
 	if (!HeapTupleIsValid(reltup))
-		elog(ERROR, "renamerel: relation \"%s\" does not exist", oldrelname);
+		elog(ERROR, "renamerel: relation \"%s\" does not exist",
+			 relation->relname);
 
-	if (RelnameFindRelid(newrelname) != InvalidOid)
+	if (get_relname_relid(newrelname, namespaceId) != InvalidOid)
 		elog(ERROR, "renamerel: relation \"%s\" exists", newrelname);
 
 	/*
@@ -352,7 +356,7 @@ renamerel(const char *oldrelname, const char *newrelname)
 	 * Also rename the associated type, if any.
 	 */
 	if (relkind != RELKIND_INDEX)
-		TypeRename(oldrelname, newrelname);
+		TypeRename(relation->relname, newrelname);
 
 	/*
 	 * If it's a view, must also rename the associated ON SELECT rule.
@@ -362,7 +366,7 @@ renamerel(const char *oldrelname, const char *newrelname)
 		char	   *oldrulename,
 				   *newrulename;
 
-		oldrulename = MakeRetrieveViewRuleName(oldrelname);
+		oldrulename = MakeRetrieveViewRuleName(relation->relname);
 		newrulename = MakeRetrieveViewRuleName(newrelname);
 		RenameRewriteRule(oldrulename, newrulename);
 	}
@@ -374,11 +378,11 @@ renamerel(const char *oldrelname, const char *newrelname)
 	{
 		/* update tgargs where relname is primary key */
 		update_ri_trigger_args(reloid,
-							   oldrelname, newrelname,
+							   relation->relname, newrelname,
 							   false, true);
 		/* update tgargs where relname is foreign key */
 		update_ri_trigger_args(reloid,
-							   oldrelname, newrelname,
+							   relation->relname, newrelname,
 							   true, true);
 	}
 }
diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c
index 2fa17612e37..931ddeae7b0 100644
--- a/src/backend/commands/trigger.c
+++ b/src/backend/commands/trigger.c
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.107 2002/03/21 23:27:22 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.108 2002/03/26 19:15:45 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -71,7 +71,7 @@ CreateTrigger(CreateTrigStmt *stmt)
 	char	   *constrname = "";
 	Oid			constrrelid = InvalidOid;
 
-	rel = heap_openr(stmt->relation->relname, AccessExclusiveLock);
+	rel = heap_openrv(stmt->relation, AccessExclusiveLock);
 
 	if (rel->rd_rel->relkind != RELKIND_RELATION)
 		elog(ERROR, "CreateTrigger: relation \"%s\" is not a table",
@@ -106,7 +106,7 @@ CreateTrigger(CreateTrigStmt *stmt)
 			 */
 			Relation	conrel;
 
-			conrel = heap_openr(stmt->constrrel->relname, NoLock);
+			conrel = heap_openrv(stmt->constrrel, NoLock);
 			constrrelid = conrel->rd_id;
 			heap_close(conrel, NoLock);
 		}
@@ -285,8 +285,8 @@ CreateTrigger(CreateTrigStmt *stmt)
 	 * rebuild relcache entries.
 	 */
 	pgrel = heap_openr(RelationRelationName, RowExclusiveLock);
-	tuple = SearchSysCacheCopy(RELNAME,
-							   PointerGetDatum(stmt->relation->relname),
+	tuple = SearchSysCacheCopy(RELOID,
+							   ObjectIdGetDatum(RelationGetRelid(rel)),
 							   0, 0, 0);
 	if (!HeapTupleIsValid(tuple))
 		elog(ERROR, "CreateTrigger: relation %s not found in pg_class",
@@ -323,7 +323,7 @@ DropTrigger(DropTrigStmt *stmt)
 	int			found = 0;
 	int			tgfound = 0;
 
-	rel = heap_openr(stmt->relation->relname, AccessExclusiveLock);
+	rel = heap_openrv(stmt->relation, AccessExclusiveLock);
 
 	if (rel->rd_rel->relkind != RELKIND_RELATION)
 		elog(ERROR, "DropTrigger: relation \"%s\" is not a table",
@@ -380,8 +380,8 @@ DropTrigger(DropTrigStmt *stmt)
 	 * rebuild relcache entries.
 	 */
 	pgrel = heap_openr(RelationRelationName, RowExclusiveLock);
-	tuple = SearchSysCacheCopy(RELNAME,
-							   PointerGetDatum(stmt->relation->relname),
+	tuple = SearchSysCacheCopy(RELOID,
+							   ObjectIdGetDatum(RelationGetRelid(rel)),
 							   0, 0, 0);
 	if (!HeapTupleIsValid(tuple))
 		elog(ERROR, "DropTrigger: relation %s not found in pg_class",
@@ -452,7 +452,7 @@ RelationRemoveTriggers(Relation rel)
 
 		pgrel = heap_openr(RelationRelationName, RowExclusiveLock);
 		tup = SearchSysCacheCopy(RELOID,
-								 RelationGetRelid(rel),
+								 ObjectIdGetDatum(RelationGetRelid(rel)),
 								 0, 0, 0);
 		if (!HeapTupleIsValid(tup))
 			elog(ERROR, "RelationRemoveTriggers: relation %u not found in pg_class",
diff --git a/src/backend/commands/user.c b/src/backend/commands/user.c
index 3de55ad71c0..98ee4308975 100644
--- a/src/backend/commands/user.c
+++ b/src/backend/commands/user.c
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Header: /cvsroot/pgsql/src/backend/commands/user.c,v 1.93 2002/03/06 06:09:37 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/user.c,v 1.94 2002/03/26 19:15:48 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -919,12 +919,12 @@ DropUser(DropUserStmt *stmt)
  * check to see if there is an ACL on pg_shadow
  */
 static void
-CheckPgUserAclNotNull()
+CheckPgUserAclNotNull(void)
 {
 	HeapTuple	htup;
 
-	htup = SearchSysCache(RELNAME,
-						  PointerGetDatum(ShadowRelationName),
+	htup = SearchSysCache(RELOID,
+						  ObjectIdGetDatum(RelOid_pg_shadow),
 						  0, 0, 0);
 	if (!HeapTupleIsValid(htup))
 		elog(ERROR, "CheckPgUserAclNotNull: \"%s\" not found",
diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c
index 8532da15975..ab41dd50c3c 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.154 2002/03/21 23:27:23 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.155 2002/03/26 19:15:54 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -35,6 +35,7 @@
 
 #include "access/heapam.h"
 #include "catalog/heap.h"
+#include "catalog/namespace.h"
 #include "commands/command.h"
 #include "commands/trigger.h"
 #include "executor/execdebug.h"
@@ -696,10 +697,6 @@ InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate)
 
 	if (operation == CMD_SELECT)
 	{
-		char	   *intoName;
-		Oid			intoRelationId;
-		TupleDesc	tupdesc;
-
 		if (!parseTree->isPortal)
 		{
 			/*
@@ -707,10 +704,16 @@ InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate)
 			 */
 			if (parseTree->into != NULL)
 			{
+				char	   *intoName;
+				Oid			namespaceId;
+				Oid			intoRelationId;
+				TupleDesc	tupdesc;
+
 				/*
 				 * create the "into" relation
 				 */
 				intoName = parseTree->into->relname;
+				namespaceId = RangeVarGetCreationNamespace(parseTree->into);
 
 				/*
 				 * have to copy tupType to get rid of constraints
@@ -719,6 +722,7 @@ InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate)
 
 				intoRelationId =
 					heap_create_with_catalog(intoName,
+											 namespaceId,
 											 tupdesc,
 											 RELKIND_RELATION, true,
 											 parseTree->into->istemp,
@@ -738,7 +742,7 @@ InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate)
 				 * with CommandCounterIncrement(), so that the TOAST table
 				 * will be visible for insertion.
 				 */
-				AlterTableCreateToastTable(intoName, true);
+				AlterTableCreateToastTable(intoRelationId, true);
 
 				intoRelationDesc = heap_open(intoRelationId,
 											 AccessExclusiveLock);
diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c
index adefcd040cf..270637d451a 100644
--- a/src/backend/parser/analyze.c
+++ b/src/backend/parser/analyze.c
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- *	$Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.222 2002/03/22 02:56:33 tgl Exp $
+ *	$Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.223 2002/03/26 19:15:56 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -17,6 +17,7 @@
 #include "catalog/catname.h"
 #include "catalog/heap.h"
 #include "catalog/index.h"
+#include "catalog/namespace.h"
 #include "catalog/pg_index.h"
 #include "catalog/pg_type.h"
 #include "nodes/makefuncs.h"
@@ -118,7 +119,7 @@ static void transformConstraintAttrs(List *constraintList);
 static void transformColumnType(ParseState *pstate, ColumnDef *column);
 static void transformFkeyCheckAttrs(FkConstraint *fkconstraint, Oid *pktypoid);
 static void transformFkeyGetPrimaryKey(FkConstraint *fkconstraint, Oid *pktypoid);
-static bool relationHasPrimaryKey(char *relname);
+static bool relationHasPrimaryKey(Oid relationOid);
 static Oid	transformFkeyGetColType(CreateStmtContext *cxt, char *colname);
 static void release_pstate_resources(ParseState *pstate);
 static FromExpr *makeFromExpr(List *fromlist, Node *quals);
@@ -1048,7 +1049,7 @@ transformIndexConstraints(ParseState *pstate, CreateStmtContext *cxt)
 			/* In ALTER TABLE case, a primary index might already exist */
 			if (cxt->pkey != NULL ||
 				(OidIsValid(cxt->relOid) &&
-				 relationHasPrimaryKey((cxt->relation)->relname)))
+				 relationHasPrimaryKey(cxt->relOid)))
 				elog(ERROR, "%s / PRIMARY KEY multiple primary keys"
 					 " for table '%s' are not allowed",
 					 cxt->stmtType, (cxt->relation)->relname);
@@ -1115,10 +1116,10 @@ transformIndexConstraints(ParseState *pstate, CreateStmtContext *cxt)
 					int			count;
 
 					Assert(IsA(inh, RangeVar));
-					rel = heap_openr(inh->relname, AccessShareLock);
+					rel = heap_openrv(inh, AccessShareLock);
 					if (rel->rd_rel->relkind != RELKIND_RELATION)
 						elog(ERROR, "inherited table \"%s\" is not a relation",
-							 strVal(inh));
+							 inh->relname);
 					for (count = 0; count < rel->rd_att->natts; count++)
 					{
 						Form_pg_attribute inhattr = rel->rd_att->attrs[count];
@@ -1724,7 +1725,7 @@ transformRuleStmt(ParseState *pstate, RuleStmt *stmt,
 	 * beforehand.	We don't need to hold a refcount on the relcache
 	 * entry, however.
 	 */
-	heap_close(heap_openr(stmt->relation->relname, AccessExclusiveLock),
+	heap_close(heap_openrv(stmt->relation, AccessExclusiveLock),
 			   NoLock);
 
 	/*
@@ -2562,9 +2563,7 @@ transformAlterTableStmt(ParseState *pstate, AlterTableStmt *stmt,
 			cxt.relation = stmt->relation;
 			cxt.inhRelations = NIL;
 			cxt.relation->istemp = is_temp_rel_name(stmt->relation->relname);
-			cxt.relOid = GetSysCacheOid(RELNAME,
-										PointerGetDatum((stmt->relation)->relname),
-										0, 0, 0);
+			cxt.relOid = RangeVarGetRelid(stmt->relation, false);
 			cxt.hasoids = SearchSysCacheExists(ATTNUM,
 											ObjectIdGetDatum(cxt.relOid),
 								  Int16GetDatum(ObjectIdAttributeNumber),
@@ -2594,9 +2593,7 @@ transformAlterTableStmt(ParseState *pstate, AlterTableStmt *stmt,
 			cxt.relation = stmt->relation;
 			cxt.inhRelations = NIL;
 			cxt.relation->istemp = is_temp_rel_name(stmt->relation->relname);
-			cxt.relOid = GetSysCacheOid(RELNAME,
-										PointerGetDatum((stmt->relation)->relname),
-										0, 0, 0);
+			cxt.relOid = RangeVarGetRelid(stmt->relation, false);
 			cxt.hasoids = SearchSysCacheExists(ATTNUM,
 											ObjectIdGetDatum(cxt.relOid),
 								  Int16GetDatum(ObjectIdAttributeNumber),
@@ -2844,7 +2841,7 @@ transformFkeyCheckAttrs(FkConstraint *fkconstraint, Oid *pktypoid)
 	/*
 	 * Open the referenced table
 	 */
-	pkrel = heap_openr(fkconstraint->pktable->relname, AccessShareLock);
+	pkrel = heap_openrv(fkconstraint->pktable, AccessShareLock);
 
 	if (pkrel->rd_rel->relkind != RELKIND_RELATION)
 		elog(ERROR, "Referenced relation \"%s\" is not a table",
@@ -2937,7 +2934,7 @@ transformFkeyGetPrimaryKey(FkConstraint *fkconstraint, Oid *pktypoid)
 	/*
 	 * Open the referenced table
 	 */
-	pkrel = heap_openr(fkconstraint->pktable->relname, AccessShareLock);
+	pkrel = heap_openrv(fkconstraint->pktable, AccessShareLock);
 
 	if (pkrel->rd_rel->relkind != RELKIND_RELATION)
 		elog(ERROR, "Referenced relation \"%s\" is not a table",
@@ -3002,14 +2999,14 @@ transformFkeyGetPrimaryKey(FkConstraint *fkconstraint, Oid *pktypoid)
  *	See whether an existing relation has a primary key.
  */
 static bool
-relationHasPrimaryKey(char *relname)
+relationHasPrimaryKey(Oid relationOid)
 {
 	bool		result = false;
 	Relation	rel;
 	List	   *indexoidlist,
 			   *indexoidscan;
 
-	rel = heap_openr(relname, AccessShareLock);
+	rel = heap_open(relationOid, AccessShareLock);
 
 	/*
 	 * Get the list of index OIDs for the table from the relcache, and
@@ -3084,10 +3081,10 @@ transformFkeyGetColType(CreateStmtContext *cxt, char *colname)
 		int			count;
 
 		Assert(IsA(inh, RangeVar));
-		rel = heap_openr(inh->relname, AccessShareLock);
+		rel = heap_openrv(inh, AccessShareLock);
 		if (rel->rd_rel->relkind != RELKIND_RELATION)
 			elog(ERROR, "inherited table \"%s\" is not a relation",
-				 strVal(inh));
+				 inh->relname);
 		for (count = 0; count < rel->rd_att->natts; count++)
 		{
 			char	   *name = NameStr(rel->rd_att->attrs[count]->attname);
diff --git a/src/backend/parser/parse_clause.c b/src/backend/parser/parse_clause.c
index c2f578f4e6d..6213e9edefc 100644
--- a/src/backend/parser/parse_clause.c
+++ b/src/backend/parser/parse_clause.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.86 2002/03/22 02:56:33 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.87 2002/03/26 19:15:57 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -133,7 +133,7 @@ setTargetTable(ParseState *pstate, RangeVar *relation,
 	 * analyze.c will eventually do the corresponding heap_close(), but *not*
 	 * release the lock.
 	 */
-	pstate->p_target_relation = heap_openr(relation->relname, RowExclusiveLock);
+	pstate->p_target_relation = heap_openrv(relation, RowExclusiveLock);
 
 	/*
 	 * Now build an RTE.
diff --git a/src/backend/parser/parse_relation.c b/src/backend/parser/parse_relation.c
index 3701539af58..f6a2dc208f8 100644
--- a/src/backend/parser/parse_relation.c
+++ b/src/backend/parser/parse_relation.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/parser/parse_relation.c,v 1.65 2002/03/22 02:56:34 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/parser/parse_relation.c,v 1.66 2002/03/26 19:15:59 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -443,7 +443,7 @@ addRangeTableEntry(ParseState *pstate,
 	 * access level depending on whether we're doing SELECT FOR UPDATE.
 	 */
 	lockmode = isForUpdate(pstate, refname) ? RowShareLock : AccessShareLock;
-	rel = heap_openr(relation->relname, lockmode);
+	rel = heap_openrv(relation, lockmode);
 	rte->relid = RelationGetRelid(rel);
 
 	eref = alias ? (Alias *) copyObject(alias) : makeAlias(refname, NIL);
diff --git a/src/backend/rewrite/rewriteDefine.c b/src/backend/rewrite/rewriteDefine.c
index 7e9f0fcfbb3..f20c9a0d982 100644
--- a/src/backend/rewrite/rewriteDefine.c
+++ b/src/backend/rewrite/rewriteDefine.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteDefine.c,v 1.65 2002/03/21 23:27:23 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteDefine.c,v 1.66 2002/03/26 19:16:02 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -138,7 +138,7 @@ DefineQueryRewrite(RuleStmt *stmt)
 	 * actions.  But for now, let's just grab AccessExclusiveLock all the
 	 * time.
 	 */
-	event_relation = heap_openr(event_obj->relname, AccessExclusiveLock);
+	event_relation = heap_openrv(event_obj, AccessExclusiveLock);
 	ev_relid = RelationGetRelid(event_relation);
 
 	/*
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
index cfa00e4cb59..84f3325256a 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.139 2002/03/24 04:31:08 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.140 2002/03/26 19:16:03 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -18,6 +18,7 @@
 
 #include "access/heapam.h"
 #include "catalog/catalog.h"
+#include "catalog/namespace.h"
 #include "catalog/pg_shadow.h"
 #include "commands/async.h"
 #include "commands/cluster.h"
@@ -94,9 +95,10 @@ DropErrorMsg(char *relname, char wrongkind, char rightkind)
 }
 
 static void
-CheckDropPermissions(char *name, char rightkind)
+CheckDropPermissions(RangeVar *rel, char rightkind)
 {
 	struct kindstrings *rentry;
+	Oid			relOid;
 	HeapTuple	tuple;
 	Form_pg_class classform;
 
@@ -105,49 +107,54 @@ CheckDropPermissions(char *name, char rightkind)
 			break;
 	Assert(rentry->kind != '\0');
 
-	tuple = SearchSysCache(RELNAME,
-						   PointerGetDatum(name),
+	relOid = RangeVarGetRelid(rel, true);
+	if (!OidIsValid(relOid))
+		elog(ERROR, "%s \"%s\" does not exist", rentry->name, rel->relname);
+	tuple = SearchSysCache(RELOID,
+						   ObjectIdGetDatum(relOid),
 						   0, 0, 0);
 	if (!HeapTupleIsValid(tuple))
-		elog(ERROR, "%s \"%s\" does not exist", rentry->name, name);
+		elog(ERROR, "%s \"%s\" does not exist", rentry->name, rel->relname);
 
 	classform = (Form_pg_class) GETSTRUCT(tuple);
 
 	if (classform->relkind != rightkind)
-		DropErrorMsg(name, classform->relkind, rightkind);
+		DropErrorMsg(rel->relname, classform->relkind, rightkind);
 
-	if (!pg_class_ownercheck(tuple->t_data->t_oid, GetUserId()))
+	if (!pg_class_ownercheck(relOid, GetUserId()))
 		elog(ERROR, "you do not own %s \"%s\"",
-			 rentry->name, name);
+			 rentry->name, rel->relname);
 
-	if (!allowSystemTableMods && IsSystemRelationName(name) &&
-		!is_temp_relname(name))
+	if (!allowSystemTableMods && IsSystemRelationName(rel->relname) &&
+		!is_temp_relname(rel->relname))
 		elog(ERROR, "%s \"%s\" is a system %s",
-			 rentry->name, name, rentry->name);
+			 rentry->name, rel->relname, rentry->name);
 
 	ReleaseSysCache(tuple);
 }
 
 static void
-CheckOwnership(char *relname, bool noCatalogs)
+CheckOwnership(RangeVar *rel, bool noCatalogs)
 {
+	Oid			relOid;
 	HeapTuple	tuple;
 
-	tuple = SearchSysCache(RELNAME,
-						   PointerGetDatum(relname),
+	relOid = RangeVarGetRelid(rel, false);
+	tuple = SearchSysCache(RELOID,
+						   ObjectIdGetDatum(relOid),
 						   0, 0, 0);
 	if (!HeapTupleIsValid(tuple))
-		elog(ERROR, "Relation \"%s\" does not exist", relname);
+		elog(ERROR, "Relation \"%s\" does not exist", rel->relname);
 
-	if (!pg_class_ownercheck(tuple->t_data->t_oid, GetUserId()))
-		elog(ERROR, "%s: %s", relname,
+	if (!pg_class_ownercheck(relOid, GetUserId()))
+		elog(ERROR, "%s: %s", rel->relname,
 			 aclcheck_error_strings[ACLCHECK_NOT_OWNER]);
 
 	if (noCatalogs)
 	{
-		if (!allowSystemTableMods && IsSystemRelationName(relname))
+		if (!allowSystemTableMods && IsSystemRelationName(rel->relname))
 			elog(ERROR, "relation \"%s\" is a system catalog",
-				 relname);
+				 rel->relname);
 	}
 
 	ReleaseSysCache(tuple);
@@ -251,47 +258,52 @@ ProcessUtility(Node *parsetree,
 			break;
 
 		case T_CreateStmt:
-			DefineRelation((CreateStmt *) parsetree, RELKIND_RELATION);
+			{
+				Oid			relOid;
 
-			/*
-			 * Let AlterTableCreateToastTable decide if this one needs a
-			 * secondary relation too.
-			 */
-			CommandCounterIncrement();
-			AlterTableCreateToastTable(((CreateStmt *) parsetree)->relation->relname,
-									   true);
+				relOid = DefineRelation((CreateStmt *) parsetree,
+										RELKIND_RELATION);
+
+				/*
+				 * Let AlterTableCreateToastTable decide if this one needs a
+				 * secondary relation too.
+				 */
+				CommandCounterIncrement();
+				AlterTableCreateToastTable(relOid, true);
+			}
 			break;
 
 		case T_DropStmt:
 			{
 				DropStmt   *stmt = (DropStmt *) parsetree;
-				List	   *args = stmt->objects;
 				List	   *arg;
 
-				foreach(arg, args)
+				foreach(arg, stmt->objects)
 				{
-					relname = ((RangeVar *) lfirst(arg))->relname;
+					RangeVar   *rel = (RangeVar *) lfirst(arg);
+
+					relname = rel->relname;
 
 					switch (stmt->removeType)
 					{
 						case DROP_TABLE:
-							CheckDropPermissions(relname, RELKIND_RELATION);
+							CheckDropPermissions(rel, RELKIND_RELATION);
 							RemoveRelation(relname);
 							break;
 
 						case DROP_SEQUENCE:
-							CheckDropPermissions(relname, RELKIND_SEQUENCE);
+							CheckDropPermissions(rel, RELKIND_SEQUENCE);
 							RemoveRelation(relname);
 							break;
 
 						case DROP_VIEW:
-							CheckDropPermissions(relname, RELKIND_VIEW);
+							CheckDropPermissions(rel, RELKIND_VIEW);
 							RemoveView(relname);
 							break;
 
 						case DROP_INDEX:
-							CheckDropPermissions(relname, RELKIND_INDEX);
-							RemoveIndex(relname);
+							CheckDropPermissions(rel, RELKIND_INDEX);
+							RemoveIndex(rel);
 							break;
 
 						case DROP_RULE:
@@ -329,13 +341,12 @@ ProcessUtility(Node *parsetree,
 
 		case T_CommentStmt:
 			{
-				CommentStmt *statement;
+				CommentStmt *stmt;
 
-				statement = ((CommentStmt *) parsetree);
+				stmt = ((CommentStmt *) parsetree);
 
-				CommentObject(statement->objtype, statement->objname,
-							  statement->objproperty, statement->objlist,
-							  statement->comment);
+				CommentObject(stmt->objtype, stmt->objschema, stmt->objname,
+							  stmt->objproperty, stmt->objlist, stmt->comment);
 			}
 			break;
 
@@ -370,7 +381,7 @@ ProcessUtility(Node *parsetree,
 				RenameStmt *stmt = (RenameStmt *) parsetree;
 
 				relname = stmt->relation->relname;
-				CheckOwnership(relname, true);
+				CheckOwnership(stmt->relation, true);
 
 				/* ----------------
 				 *	XXX using len == 3 to tell the difference
@@ -389,7 +400,7 @@ ProcessUtility(Node *parsetree,
 					 * Note: we also rename the "type" tuple corresponding to
 					 * the relation.
 					 */
-					renamerel(relname,	/* old name */
+					renamerel(stmt->relation,	/* old relation */
 							  stmt->newname);	/* new name */
 				}
 				else
@@ -454,11 +465,11 @@ ProcessUtility(Node *parsetree,
 												 stmt->behavior);
 						break;
 					case 'E':	/* CREATE TOAST TABLE */
-						AlterTableCreateToastTable(stmt->relation->relname,
+						AlterTableCreateToastTable(RangeVarGetRelid(stmt->relation, false),
 												   false);
 						break;
 					case 'U':	/* ALTER OWNER */
-						AlterTableOwner(stmt->relation->relname,
+						AlterTableOwner(stmt->relation,
 										stmt->name);
 						break;
 					default:	/* oops */
@@ -519,10 +530,9 @@ ProcessUtility(Node *parsetree,
 			{
 				IndexStmt  *stmt = (IndexStmt *) parsetree;
 
-				relname = stmt->relation->relname;
-				CheckOwnership(relname, true);
+				CheckOwnership(stmt->relation, true);
 
-				DefineIndex(stmt->relation->relname,	/* relation */
+				DefineIndex(stmt->relation,				/* relation */
 							stmt->idxname,				/* index name */
 							stmt->accessMethod, 		/* am name */
 							stmt->indexParams,			/* parameters */
@@ -638,10 +648,9 @@ ProcessUtility(Node *parsetree,
 			{
 				ClusterStmt *stmt = (ClusterStmt *) parsetree;
 
-				relname = stmt->relation->relname;
-				CheckOwnership(relname, true);
+				CheckOwnership(stmt->relation, true);
 
-				cluster(relname, stmt->indexname);
+				cluster(stmt->relation, stmt->indexname);
 			}
 			break;
 
@@ -775,13 +784,12 @@ ProcessUtility(Node *parsetree,
 								elog(ERROR, "\"%s\" is a system index. call REINDEX under standalone postgres with -P -O options",
 									 relname);
 						}
-						CheckOwnership(relname, false);
-						ReindexIndex(relname, stmt->force);
+						CheckOwnership(stmt->relation, false);
+						ReindexIndex(stmt->relation, stmt->force);
 						break;
 					case TABLE:
-						relname = (char *) stmt->relation->relname;
-						CheckOwnership(relname, false);
-						ReindexTable(relname, stmt->force);
+						CheckOwnership(stmt->relation, false);
+						ReindexTable(stmt->relation, stmt->force);
 						break;
 					case DATABASE:
 						relname = (char *) stmt->name;
diff --git a/src/backend/utils/adt/acl.c b/src/backend/utils/adt/acl.c
index 0e73cb04b10..1db296f5e02 100644
--- a/src/backend/utils/adt/acl.c
+++ b/src/backend/utils/adt/acl.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/utils/adt/acl.c,v 1.69 2002/03/21 23:27:24 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/adt/acl.c,v 1.70 2002/03/26 19:16:05 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -18,6 +18,7 @@
 
 #include "access/heapam.h"
 #include "catalog/catalog.h"
+#include "catalog/namespace.h"
 #include "catalog/pg_shadow.h"
 #include "catalog/pg_type.h"
 #include "lib/stringinfo.h"
@@ -723,7 +724,7 @@ makeAclString(const char *privileges, const char *grantee, char grant_or_revoke)
 /*
  * has_table_privilege_name_name
  *		Check user privileges on a relation given
- *		name usename, name relname, and text priv name.
+ *		name username, name relname, and text priv name.
  *
  * RETURNS
  *		a boolean value
@@ -995,7 +996,8 @@ has_table_privilege_cname_id(char *username, Oid reloid,
 							 text *priv_type_text)
 {
 	int32		usesysid;
-	char	   *relname;
+	AclMode		mode;
+	int32		result;
 
 	/*
 	 * Lookup userid based on username
@@ -1003,18 +1005,19 @@ has_table_privilege_cname_id(char *username, Oid reloid,
 	usesysid = get_usesysid(username);
 
 	/*
-	 * Lookup relname based on rel oid
+	 * Convert priv_type_text to an AclMode
 	 */
-	relname = get_rel_name(reloid);
-	if (relname == NULL)
-		elog(ERROR, "has_table_privilege: invalid relation oid %u",
-			 reloid);
+	mode = convert_priv_string(priv_type_text);
 
 	/*
-	 * Make use of has_table_privilege_id_cname. It accepts the arguments
-	 * we now have.
+	 * Finally, check for the privilege
 	 */
-	return has_table_privilege_id_cname(usesysid, relname, priv_type_text);
+	result = pg_class_aclcheck(reloid, usesysid, mode);
+
+	if (result == ACLCHECK_OK)
+		return true;
+	else
+		return false;
 }
 
 
@@ -1039,9 +1042,7 @@ has_table_privilege_id_cname(int32 usesysid, char *relname,
 	/*
 	 * Convert relname to rel OID.
 	 */
-	reloid = GetSysCacheOid(RELNAME,
-							PointerGetDatum(relname),
-							0, 0, 0);
+	reloid = RelnameGetRelid(relname);
 	if (!OidIsValid(reloid))
 		elog(ERROR, "has_table_privilege: relation \"%s\" does not exist",
 			 relname);
diff --git a/src/backend/utils/cache/catcache.c b/src/backend/utils/cache/catcache.c
index 6cb7b65fe3f..202f447076e 100644
--- a/src/backend/utils/cache/catcache.c
+++ b/src/backend/utils/cache/catcache.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/utils/cache/catcache.c,v 1.92 2002/03/06 20:49:45 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/cache/catcache.c,v 1.93 2002/03/26 19:16:08 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -656,11 +656,11 @@ do { \
 
 CatCache *
 InitCatCache(int id,
-			 char *relname,
-			 char *indname,
+			 const char *relname,
+			 const char *indname,
 			 int reloidattr,
 			 int nkeys,
-			 int *key)
+			 const int *key)
 {
 	CatCache   *cp;
 	MemoryContext oldcxt;
diff --git a/src/backend/utils/cache/lsyscache.c b/src/backend/utils/cache/lsyscache.c
index 11577801118..82be75ac799 100644
--- a/src/backend/utils/cache/lsyscache.c
+++ b/src/backend/utils/cache/lsyscache.c
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.65 2002/03/22 02:56:35 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.66 2002/03/26 19:16:09 tgl Exp $
  *
  * NOTES
  *	  Eventually, the index information should go through here, too.
@@ -634,6 +634,21 @@ func_iscachable(Oid funcid)
 
 /*				---------- RELATION CACHE ----------					 */
 
+/*
+ * get_relname_relid
+ *		Given name and namespace of a relation, look up the OID.
+ *
+ * Returns InvalidOid if there is no such relation.
+ */
+Oid
+get_relname_relid(const char *relname, Oid relnamespace)
+{
+	return GetSysCacheOid(RELNAMENSP,
+						  PointerGetDatum(relname),
+						  ObjectIdGetDatum(relnamespace),
+						  0, 0);
+}
+
 #ifdef NOT_USED
 /*
  * get_relnatts
@@ -664,10 +679,12 @@ get_relnatts(Oid relid)
 
 /*
  * get_rel_name
- *
  *		Returns the name of a given relation.
  *
- * Note: returns a palloc'd copy of the string, or NULL if no such relation.
+ * Returns a palloc'd copy of the string, or NULL if no such relation.
+ *
+ * NOTE: since relation name is not unique, be wary of code that uses this
+ * for anything except preparing error messages.
  */
 char *
 get_rel_name(Oid relid)
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c
index d10569fd7ce..4894cd27795 100644
--- a/src/backend/utils/cache/relcache.c
+++ b/src/backend/utils/cache/relcache.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.157 2002/03/19 02:18:22 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.158 2002/03/26 19:16:10 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -16,10 +16,9 @@
  * INTERFACE ROUTINES
  *		RelationCacheInitialize			- initialize relcache
  *		RelationCacheInitializePhase2	- finish initializing relcache
- *		RelationIdCacheGetRelation		- get a reldesc from the cache (id)
- *		RelationNameCacheGetRelation	- get a reldesc from the cache (name)
  *		RelationIdGetRelation			- get a reldesc by relation id
- *		RelationNameGetRelation			- get a reldesc by relation name
+ *		RelationSysNameGetRelation		- get a reldesc by system rel name
+ *		RelationIdCacheGetRelation		- get a cached reldesc by relid
  *		RelationClose					- close an open relation
  *
  * NOTES
@@ -39,13 +38,13 @@
 #include "access/istrat.h"
 #include "catalog/catalog.h"
 #include "catalog/catname.h"
-#include "catalog/index.h"
 #include "catalog/indexing.h"
 #include "catalog/pg_amop.h"
 #include "catalog/pg_amproc.h"
 #include "catalog/pg_attrdef.h"
 #include "catalog/pg_attribute.h"
 #include "catalog/pg_index.h"
+#include "catalog/pg_namespace.h"
 #include "catalog/pg_opclass.h"
 #include "catalog/pg_proc.h"
 #include "catalog/pg_relcheck.h"
@@ -70,7 +69,7 @@
 #define RELCACHE_INIT_FILENAME	"pg_internal.init"
 
 /*
- *		hardcoded tuple descriptors.  see lib/backend/catalog/pg_attribute.h
+ *		hardcoded tuple descriptors.  see include/catalog/pg_attribute.h
  */
 static FormData_pg_attribute Desc_pg_class[Natts_pg_class] = {Schema_pg_class};
 static FormData_pg_attribute Desc_pg_attribute[Natts_pg_attribute] = {Schema_pg_attribute};
@@ -80,11 +79,14 @@ static FormData_pg_attribute Desc_pg_type[Natts_pg_type] = {Schema_pg_type};
 /*
  *		Hash tables that index the relation cache
  *
- *		Relations are looked up two ways, by name and by id,
+ *		Relations are looked up two ways, by OID and by name,
  *		thus there are two hash tables for referencing them.
+ *
+ *		The OID index covers all relcache entries.  The name index
+ *		covers *only* system relations (only those in PG_CATALOG_NAMESPACE).
  */
-static HTAB *RelationNameCache;
 static HTAB *RelationIdCache;
+static HTAB *RelationSysNameCache;
 
 /*
  * Bufmgr uses RelFileNode for lookup. Actually, I would like to do
@@ -128,7 +130,7 @@ static List *initFileRelationIds = NIL;
 
 /*
  *		RelationBuildDescInfo exists so code can be shared
- *		between RelationIdGetRelation() and RelationNameGetRelation()
+ *		between RelationIdGetRelation() and RelationSysNameGetRelation()
  */
 typedef struct RelationBuildDescInfo
 {
@@ -138,22 +140,22 @@ typedef struct RelationBuildDescInfo
 	union
 	{
 		Oid			info_id;	/* relation object id */
-		char	   *info_name;	/* relation name */
+		char	   *info_name;	/* system relation name */
 	}			i;
 } RelationBuildDescInfo;
 
-typedef struct relnamecacheent
-{
-	NameData	relname;
-	Relation	reldesc;
-} RelNameCacheEnt;
-
 typedef struct relidcacheent
 {
 	Oid			reloid;
 	Relation	reldesc;
 } RelIdCacheEnt;
 
+typedef struct relnamecacheent
+{
+	NameData	relname;
+	Relation	reldesc;
+} RelNameCacheEnt;
+
 typedef struct relnodecacheent
 {
 	RelFileNode relnode;
@@ -165,24 +167,14 @@ typedef struct relnodecacheent
  */
 #define RelationCacheInsert(RELATION)	\
 do { \
-	RelIdCacheEnt *idhentry; RelNameCacheEnt *namehentry; \
-	char *relname; RelNodeCacheEnt *nodentry; bool found; \
-	relname = RelationGetPhysicalRelationName(RELATION); \
-	namehentry = (RelNameCacheEnt*)hash_search(RelationNameCache, \
-											   relname, \
-											   HASH_ENTER, \
-											   &found); \
-	if (namehentry == NULL) \
-		elog(ERROR, "out of memory for relation descriptor cache"); \
-	/* used to give notice if found -- now just keep quiet */ ; \
-	namehentry->reldesc = RELATION; \
+	RelIdCacheEnt *idhentry; RelNodeCacheEnt *nodentry; bool found; \
 	idhentry = (RelIdCacheEnt*)hash_search(RelationIdCache, \
 										   (void *) &(RELATION->rd_id), \
 										   HASH_ENTER, \
 										   &found); \
 	if (idhentry == NULL) \
 		elog(ERROR, "out of memory for relation descriptor cache"); \
-	/* used to give notice if found -- now just keep quiet */ ; \
+	/* used to give notice if found -- now just keep quiet */ \
 	idhentry->reldesc = RELATION; \
 	nodentry = (RelNodeCacheEnt*)hash_search(RelationNodeCache, \
 										   (void *) &(RELATION->rd_node), \
@@ -190,26 +182,39 @@ do { \
 										   &found); \
 	if (nodentry == NULL) \
 		elog(ERROR, "out of memory for relation descriptor cache"); \
-	/* used to give notice if found -- now just keep quiet */ ; \
+	/* used to give notice if found -- now just keep quiet */ \
 	nodentry->reldesc = RELATION; \
+	if (RelationGetNamespace(RELATION) == PG_CATALOG_NAMESPACE) \
+	{ \
+		char *relname = RelationGetPhysicalRelationName(RELATION); \
+		RelNameCacheEnt *namehentry; \
+		namehentry = (RelNameCacheEnt*)hash_search(RelationSysNameCache, \
+												   relname, \
+												   HASH_ENTER, \
+												   &found); \
+		if (namehentry == NULL) \
+			elog(ERROR, "out of memory for relation descriptor cache"); \
+		/* used to give notice if found -- now just keep quiet */ \
+		namehentry->reldesc = RELATION; \
+	} \
 } while(0)
 
-#define RelationNameCacheLookup(NAME, RELATION) \
+#define RelationIdCacheLookup(ID, RELATION) \
 do { \
-	RelNameCacheEnt *hentry; \
-	hentry = (RelNameCacheEnt*)hash_search(RelationNameCache, \
-										   (void *) (NAME), HASH_FIND,NULL); \
+	RelIdCacheEnt *hentry; \
+	hentry = (RelIdCacheEnt*)hash_search(RelationIdCache, \
+										 (void *)&(ID), HASH_FIND,NULL); \
 	if (hentry) \
 		RELATION = hentry->reldesc; \
 	else \
 		RELATION = NULL; \
 } while(0)
 
-#define RelationIdCacheLookup(ID, RELATION) \
+#define RelationSysNameCacheLookup(NAME, RELATION) \
 do { \
-	RelIdCacheEnt *hentry; \
-	hentry = (RelIdCacheEnt*)hash_search(RelationIdCache, \
-										 (void *)&(ID), HASH_FIND,NULL); \
+	RelNameCacheEnt *hentry; \
+	hentry = (RelNameCacheEnt*)hash_search(RelationSysNameCache, \
+										   (void *) (NAME), HASH_FIND,NULL); \
 	if (hentry) \
 		RELATION = hentry->reldesc; \
 	else \
@@ -229,14 +234,7 @@ do { \
 
 #define RelationCacheDelete(RELATION) \
 do { \
-	RelNameCacheEnt *namehentry; RelIdCacheEnt *idhentry; \
-	char *relname; RelNodeCacheEnt *nodentry; \
-	relname = RelationGetPhysicalRelationName(RELATION); \
-	namehentry = (RelNameCacheEnt*)hash_search(RelationNameCache, \
-											   relname, \
-											   HASH_REMOVE, NULL); \
-	if (namehentry == NULL) \
-		elog(WARNING, "trying to delete a reldesc that does not exist."); \
+	RelIdCacheEnt *idhentry; RelNodeCacheEnt *nodentry; \
 	idhentry = (RelIdCacheEnt*)hash_search(RelationIdCache, \
 										   (void *)&(RELATION->rd_id), \
 										   HASH_REMOVE, NULL); \
@@ -247,6 +245,16 @@ do { \
 										   HASH_REMOVE, NULL); \
 	if (nodentry == NULL) \
 		elog(WARNING, "trying to delete a reldesc that does not exist."); \
+	if (RelationGetNamespace(RELATION) == PG_CATALOG_NAMESPACE) \
+	{ \
+		char *relname = RelationGetPhysicalRelationName(RELATION); \
+		RelNameCacheEnt *namehentry; \
+		namehentry = (RelNameCacheEnt*)hash_search(RelationSysNameCache, \
+												   relname, \
+												   HASH_REMOVE, NULL); \
+		if (namehentry == NULL) \
+			elog(WARNING, "trying to delete a reldesc that does not exist."); \
+	} \
 } while(0)
 
 
@@ -275,11 +283,11 @@ static void RelationClearRelation(Relation relation, bool rebuildIt);
 static void RelationReloadClassinfo(Relation relation);
 #endif   /* ENABLE_REINDEX_NAILED_RELATIONS */
 static void RelationFlushRelation(Relation relation);
-static Relation RelationNameCacheGetRelation(const char *relationName);
+static Relation RelationSysNameCacheGetRelation(const char *relationName);
 static bool load_relcache_init_file(void);
 static void write_relcache_init_file(void);
 
-static void formrdesc(char *relationName, int natts,
+static void formrdesc(const char *relationName, int natts,
 		  FormData_pg_attribute *att);
 
 static HeapTuple ScanPgRelation(RelationBuildDescInfo buildinfo);
@@ -303,12 +311,6 @@ static OpClassCacheEnt *LookupOpclassInfo(Oid operatorClassOid,
 										  StrategyNumber numSupport);
 
 
-/*
- *		RelationIdGetRelation() and RelationNameGetRelation()
- *						support functions
- */
-
-
 /*
  *		ScanPgRelation
  *
@@ -326,7 +328,8 @@ ScanPgRelation(RelationBuildDescInfo buildinfo)
 	Relation	pg_class_desc;
 	const char *indexRelname;
 	SysScanDesc pg_class_scan;
-	ScanKeyData key;
+	ScanKeyData key[2];
+	int			nkeys;
 
 	/*
 	 * form a scan key
@@ -334,19 +337,25 @@ ScanPgRelation(RelationBuildDescInfo buildinfo)
 	switch (buildinfo.infotype)
 	{
 		case INFO_RELID:
-			ScanKeyEntryInitialize(&key, 0,
+			ScanKeyEntryInitialize(&key[0], 0,
 								   ObjectIdAttributeNumber,
 								   F_OIDEQ,
 								   ObjectIdGetDatum(buildinfo.i.info_id));
+			nkeys = 1;
 			indexRelname = ClassOidIndex;
 			break;
 
 		case INFO_RELNAME:
-			ScanKeyEntryInitialize(&key, 0,
+			ScanKeyEntryInitialize(&key[0], 0,
 								   Anum_pg_class_relname,
 								   F_NAMEEQ,
 								   NameGetDatum(buildinfo.i.info_name));
-			indexRelname = ClassNameIndex;
+			ScanKeyEntryInitialize(&key[1], 0,
+								   Anum_pg_class_relnamespace,
+								   F_OIDEQ,
+								   ObjectIdGetDatum(PG_CATALOG_NAMESPACE));
+			nkeys = 2;
+			indexRelname = ClassNameNspIndex;
 			break;
 
 		default:
@@ -363,7 +372,7 @@ ScanPgRelation(RelationBuildDescInfo buildinfo)
 	pg_class_scan = systable_beginscan(pg_class_desc, indexRelname,
 									   criticalRelcachesBuilt,
 									   SnapshotNow,
-									   1, &key);
+									   nkeys, key);
 
 	pg_class_tuple = systable_getnext(pg_class_scan);
 
@@ -512,12 +521,8 @@ RelationBuildTupleDesc(RelationBuildDescInfo buildinfo,
 			   (char *) attp,
 			   ATTRIBUTE_TUPLE_SIZE);
 
-
-
-		/*
-		 * Update constraint/default info
-		 */
-       if (attp->attnotnull)
+		/* Update constraint/default info */
+		if (attp->attnotnull)
 			constr->has_not_null = true;
 
 		if (attp->atthasdef)
@@ -1333,7 +1338,7 @@ LookupOpclassInfo(Oid operatorClassOid,
  * NOTE: we assume we are already switched into CacheMemoryContext.
  */
 static void
-formrdesc(char *relationName,
+formrdesc(const char *relationName,
 		  int natts,
 		  FormData_pg_attribute *att)
 {
@@ -1374,7 +1379,8 @@ formrdesc(char *relationName,
 	relation->rd_rel = (Form_pg_class) palloc(CLASS_TUPLE_SIZE);
 	MemSet(relation->rd_rel, 0, CLASS_TUPLE_SIZE);
 
-	strcpy(RelationGetPhysicalRelationName(relation), relationName);
+	namestrcpy(&relation->rd_rel->relname, relationName);
+	relation->rd_rel->relnamespace = PG_CATALOG_NAMESPACE;
 
 	/*
 	 * It's important to distinguish between shared and non-shared
@@ -1488,12 +1494,12 @@ RelationIdCacheGetRelation(Oid relationId)
 }
 
 /*
- *		RelationNameCacheGetRelation
+ *		RelationSysNameCacheGetRelation
  *
- *		As above, but lookup by name.
+ *		As above, but lookup by name; only works for system catalogs.
  */
 static Relation
-RelationNameCacheGetRelation(const char *relationName)
+RelationSysNameCacheGetRelation(const char *relationName)
 {
 	Relation	rd;
 	NameData	name;
@@ -1503,7 +1509,7 @@ RelationNameCacheGetRelation(const char *relationName)
 	 * null-padded
 	 */
 	namestrcpy(&name, relationName);
-	RelationNameCacheLookup(NameStr(name), rd);
+	RelationSysNameCacheLookup(NameStr(name), rd);
 
 	if (RelationIsValid(rd))
 		RelationIncrementReferenceCount(rd);
@@ -1539,12 +1545,6 @@ RelationIdGetRelation(Oid relationId)
 	Relation	rd;
 	RelationBuildDescInfo buildinfo;
 
-	/*
-	 * increment access statistics
-	 */
-	IncrHeapAccessStat(local_RelationIdGetRelation);
-	IncrHeapAccessStat(global_RelationIdGetRelation);
-
 	/*
 	 * first try and get a reldesc from the cache
 	 */
@@ -1564,23 +1564,17 @@ RelationIdGetRelation(Oid relationId)
 }
 
 /*
- *		RelationNameGetRelation
+ *		RelationSysNameGetRelation
  *
- *		As above, but lookup by name.
+ *		As above, but lookup by name; only works for system catalogs.
  */
 Relation
-RelationNameGetRelation(const char *relationName)
+RelationSysNameGetRelation(const char *relationName)
 {
 	char	   *temprelname;
 	Relation	rd;
 	RelationBuildDescInfo buildinfo;
 
-	/*
-	 * increment access statistics
-	 */
-	IncrHeapAccessStat(local_RelationNameGetRelation);
-	IncrHeapAccessStat(global_RelationNameGetRelation);
-
 	/*
 	 * if caller is looking for a temp relation, substitute its real name;
 	 * we only index temp rels by their real names.
@@ -1592,7 +1586,7 @@ RelationNameGetRelation(const char *relationName)
 	/*
 	 * first try and get a reldesc from the cache
 	 */
-	rd = RelationNameCacheGetRelation(relationName);
+	rd = RelationSysNameCacheGetRelation(relationName);
 	if (RelationIsValid(rd))
 		return rd;
 
@@ -1951,17 +1945,17 @@ void
 RelationCacheInvalidate(void)
 {
 	HASH_SEQ_STATUS status;
-	RelNameCacheEnt *namehentry;
+	RelIdCacheEnt *idhentry;
 	Relation	relation;
 	List	   *rebuildList = NIL;
 	List	   *l;
 
 	/* Phase 1 */
-	hash_seq_init(&status, RelationNameCache);
+	hash_seq_init(&status, RelationIdCache);
 
-	while ((namehentry = (RelNameCacheEnt *) hash_seq_search(&status)) != NULL)
+	while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)
 	{
-		relation = namehentry->reldesc;
+		relation = idhentry->reldesc;
 
 		/* Ignore xact-local relations, since they are never SI targets */
 		if (relation->rd_myxactonly)
@@ -2007,13 +2001,13 @@ void
 RelationCacheAbort(void)
 {
 	HASH_SEQ_STATUS status;
-	RelNameCacheEnt *namehentry;
+	RelIdCacheEnt *idhentry;
 
-	hash_seq_init(&status, RelationNameCache);
+	hash_seq_init(&status, RelationIdCache);
 
-	while ((namehentry = (RelNameCacheEnt *) hash_seq_search(&status)) != NULL)
+	while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)
 	{
-		Relation	relation = namehentry->reldesc;
+		Relation	relation = idhentry->reldesc;
 
 		if (relation->rd_isnailed)
 			RelationSetReferenceCount(relation, 1);
@@ -2029,8 +2023,10 @@ RelationCacheAbort(void)
  */
 Relation
 RelationBuildLocalRelation(const char *relname,
+						   Oid relnamespace,
 						   TupleDesc tupDesc,
 						   Oid relid, Oid dbid,
+						   RelFileNode rnode,
 						   bool nailit)
 {
 	Relation	rel;
@@ -2086,7 +2082,8 @@ RelationBuildLocalRelation(const char *relname,
 	rel->rd_rel = (Form_pg_class) palloc(CLASS_TUPLE_SIZE);
 	MemSet((char *) rel->rd_rel, 0, CLASS_TUPLE_SIZE);
 
-	strcpy(RelationGetPhysicalRelationName(rel), relname);
+	namestrcpy(&rel->rd_rel->relname, relname);
+	rel->rd_rel->relnamespace = relnamespace;
 
 	rel->rd_rel->relkind = RELKIND_UNCATALOGED;
 	rel->rd_rel->relhasoids = true;
@@ -2094,10 +2091,8 @@ RelationBuildLocalRelation(const char *relname,
 	rel->rd_rel->reltype = InvalidOid;
 
 	/*
-	 * Insert relation OID and database/tablespace ID into the right
-	 * places. XXX currently we assume physical tblspace/relnode are same
-	 * as logical dbid/reloid.	Probably should pass an extra pair of
-	 * parameters.
+	 * Insert relation physical and logical identifiers (OIDs) into the
+	 * right places.
 	 */
 	rel->rd_rel->relisshared = (dbid == InvalidOid);
 
@@ -2106,11 +2101,10 @@ RelationBuildLocalRelation(const char *relname,
 	for (i = 0; i < natts; i++)
 		rel->rd_att->attrs[i]->attrelid = relid;
 
-	RelationInitLockInfo(rel);	/* see lmgr.c */
+	rel->rd_node = rnode;
+	rel->rd_rel->relfilenode = rnode.relNode;
 
-	rel->rd_node.tblNode = dbid;
-	rel->rd_node.relNode = relid;
-	rel->rd_rel->relfilenode = relid;
+	RelationInitLockInfo(rel);	/* see lmgr.c */
 
 	/*
 	 * Okay to insert into the relcache hash tables.
@@ -2201,8 +2195,8 @@ RelationCacheInitialize(void)
 	MemSet(&ctl, 0, sizeof(ctl));
 	ctl.keysize = sizeof(NameData);
 	ctl.entrysize = sizeof(RelNameCacheEnt);
-	RelationNameCache = hash_create("Relcache by name", INITRELCACHESIZE,
-									&ctl, HASH_ELEM);
+	RelationSysNameCache = hash_create("Relcache by name", INITRELCACHESIZE,
+									   &ctl, HASH_ELEM);
 
 	ctl.keysize = sizeof(Oid);
 	ctl.entrysize = sizeof(RelIdCacheEnt);
@@ -2252,7 +2246,7 @@ void
 RelationCacheInitializePhase2(void)
 {
 	HASH_SEQ_STATUS status;
-	RelNameCacheEnt *namehentry;
+	RelIdCacheEnt *idhentry;
 
 	if (IsBootstrapProcessingMode())
 		return;
@@ -2290,7 +2284,7 @@ RelationCacheInitializePhase2(void)
 			RelationSetReferenceCount(ird, 1); \
 		} while (0)
 
-		LOAD_CRIT_INDEX(ClassNameIndex);
+		LOAD_CRIT_INDEX(ClassNameNspIndex);
 		LOAD_CRIT_INDEX(ClassOidIndex);
 		LOAD_CRIT_INDEX(AttributeRelidNumIndex);
 		LOAD_CRIT_INDEX(IndexRelidIndex);
@@ -2311,11 +2305,11 @@ RelationCacheInitializePhase2(void)
 	 * Also, if any of the relcache entries have rules or triggers,
 	 * load that info the hard way since it isn't recorded in the cache file.
 	 */
-	hash_seq_init(&status, RelationNameCache);
+	hash_seq_init(&status, RelationIdCache);
 
-	while ((namehentry = (RelNameCacheEnt *) hash_seq_search(&status)) != NULL)
+	while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)
 	{
-		Relation	relation = namehentry->reldesc;
+		Relation	relation = idhentry->reldesc;
 
 		/*
 		 * If it's a faked-up entry, read the real pg_class tuple.
@@ -2399,8 +2393,8 @@ CreateDummyCaches(void)
 	MemSet(&ctl, 0, sizeof(ctl));
 	ctl.keysize = sizeof(NameData);
 	ctl.entrysize = sizeof(RelNameCacheEnt);
-	RelationNameCache = hash_create("Relcache by name", INITRELCACHESIZE,
-									&ctl, HASH_ELEM);
+	RelationSysNameCache = hash_create("Relcache by name", INITRELCACHESIZE,
+									   &ctl, HASH_ELEM);
 
 	ctl.keysize = sizeof(Oid);
 	ctl.entrysize = sizeof(RelIdCacheEnt);
@@ -2427,14 +2421,14 @@ DestroyDummyCaches(void)
 
 	oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
 
-	if (RelationNameCache)
-		hash_destroy(RelationNameCache);
 	if (RelationIdCache)
 		hash_destroy(RelationIdCache);
+	if (RelationSysNameCache)
+		hash_destroy(RelationSysNameCache);
 	if (RelationNodeCache)
 		hash_destroy(RelationNodeCache);
 
-	RelationNameCache = RelationIdCache = RelationNodeCache = NULL;
+	RelationIdCache = RelationSysNameCache = RelationNodeCache = NULL;
 
 	MemoryContextSwitchTo(oldcxt);
 }
@@ -3001,7 +2995,7 @@ write_relcache_init_file(void)
 	char		tempfilename[MAXPGPATH];
 	char		finalfilename[MAXPGPATH];
 	HASH_SEQ_STATUS status;
-	RelNameCacheEnt *namehentry;
+	RelIdCacheEnt *idhentry;
 	MemoryContext oldcxt;
 	int			i;
 
@@ -3031,13 +3025,13 @@ write_relcache_init_file(void)
 	/*
 	 * Write all the reldescs (in no particular order).
 	 */
-	hash_seq_init(&status, RelationNameCache);
+	hash_seq_init(&status, RelationIdCache);
 
 	initFileRelationIds = NIL;
 
-	while ((namehentry = (RelNameCacheEnt *) hash_seq_search(&status)) != NULL)
+	while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)
 	{
-		Relation	rel = namehentry->reldesc;
+		Relation	rel = idhentry->reldesc;
 		Form_pg_class relform = rel->rd_rel;
 		Size		len;
 
diff --git a/src/backend/utils/cache/syscache.c b/src/backend/utils/cache/syscache.c
index c30bbe3090c..57d4719b294 100644
--- a/src/backend/utils/cache/syscache.c
+++ b/src/backend/utils/cache/syscache.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/utils/cache/syscache.c,v 1.69 2002/03/22 21:34:44 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/cache/syscache.c,v 1.70 2002/03/26 19:16:14 tgl Exp $
  *
  * NOTES
  *	  These routines allow the parser/planner/executor to perform
@@ -86,14 +86,14 @@
  */
 struct cachedesc
 {
-	char	   *name;			/* name of the relation being cached */
-	char	   *indname;		/* name of index relation for this cache */
+	const char *name;			/* name of the relation being cached */
+	const char *indname;		/* name of index relation for this cache */
 	int			reloidattr;		/* attr number of rel OID reference, or 0 */
 	int			nkeys;			/* # of keys needed for cache lookup */
 	int			key[4];			/* attribute numbers of key attrs */
 };
 
-static struct cachedesc cacheinfo[] = {
+static const struct cachedesc cacheinfo[] = {
 	{AggregateRelationName,		/* AGGNAME */
 		AggregateNameTypeIndex,
 		0,
@@ -324,13 +324,13 @@ static struct cachedesc cacheinfo[] = {
 			0,
 			0
 	}},
-	{RelationRelationName,		/* RELNAME */
-		ClassNameIndex,
+	{RelationRelationName,		/* RELNAMENSP */
+		ClassNameNspIndex,
 		ObjectIdAttributeNumber,
-		1,
+		2,
 		{
 			Anum_pg_class_relname,
-			0,
+			Anum_pg_class_relnamespace,
 			0,
 			0
 	}},
@@ -515,7 +515,7 @@ SearchSysCache(int cacheId,
 	 * when sought.  This is a kluge ... temp table substitution should be
 	 * happening at a higher level ...
 	 */
-	if (cacheId == RELNAME || cacheId == TYPENAME)
+	if (cacheId == RELNAMENSP || cacheId == TYPENAME)
 	{
 		char	   *nontemp_relname;
 
diff --git a/src/include/access/genam.h b/src/include/access/genam.h
index c8cb4c10586..fe0ab0fba15 100644
--- a/src/include/access/genam.h
+++ b/src/include/access/genam.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: genam.h,v 1.32 2002/02/19 20:11:19 tgl Exp $
+ * $Id: genam.h,v 1.33 2002/03/26 19:16:17 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -17,6 +17,7 @@
 #include "access/itup.h"
 #include "access/relscan.h"
 #include "access/sdir.h"
+#include "nodes/primnodes.h"
 
 
 /* Struct for statistics returned by bulk-delete operation */
@@ -50,7 +51,8 @@ typedef SysScanDescData *SysScanDesc;
  * generalized index_ interface routines (in indexam.c)
  */
 extern Relation index_open(Oid relationId);
-extern Relation index_openr(const char *relationName);
+extern Relation index_openrv(const RangeVar *relation);
+extern Relation index_openr(const char *sysRelationName);
 extern void index_close(Relation relation);
 extern InsertIndexResult index_insert(Relation relation,
 			 Datum *datum, char *nulls,
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index 9798b5f76a8..c0909584f99 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.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: heapam.h,v 1.72 2001/11/05 17:46:31 momjian Exp $
+ * $Id: heapam.h,v 1.73 2002/03/26 19:16:17 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -18,6 +18,7 @@
 #include "access/relscan.h"
 #include "access/tupmacs.h"
 #include "access/xlogutils.h"
+#include "nodes/primnodes.h"
 #include "storage/block.h"
 #include "storage/lmgr.h"
 #include "utils/rel.h"
@@ -134,11 +135,13 @@ extern Datum heap_getsysattr(HeapTuple tup, int attnum, bool *isnull);
 /* heapam.c */
 
 extern Relation relation_open(Oid relationId, LOCKMODE lockmode);
-extern Relation relation_openr(const char *relationName, LOCKMODE lockmode);
+extern Relation relation_openrv(const RangeVar *relation, LOCKMODE lockmode);
+extern Relation relation_openr(const char *sysRelationName, LOCKMODE lockmode);
 extern void relation_close(Relation relation, LOCKMODE lockmode);
 
 extern Relation heap_open(Oid relationId, LOCKMODE lockmode);
-extern Relation heap_openr(const char *relationName, LOCKMODE lockmode);
+extern Relation heap_openrv(const RangeVar *relation, LOCKMODE lockmode);
+extern Relation heap_openr(const char *sysRelationName, LOCKMODE lockmode);
 
 #define heap_close(r,l)  relation_close(r,l)
 
diff --git a/src/include/bootstrap/bootstrap.h b/src/include/bootstrap/bootstrap.h
index b80641bd96e..a2e3a0df193 100644
--- a/src/include/bootstrap/bootstrap.h
+++ b/src/include/bootstrap/bootstrap.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: bootstrap.h,v 1.27 2002/03/02 21:39:34 momjian Exp $
+ * $Id: bootstrap.h,v 1.28 2002/03/26 19:16:20 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -36,7 +36,7 @@ extern Form_pg_attribute attrtypes[MAXATTR];
 extern int	numattr;
 extern int	BootstrapMain(int ac, char *av[]);
 
-extern void index_register(char *heap, char *ind, IndexInfo *indexInfo);
+extern void index_register(Oid heap, Oid ind, IndexInfo *indexInfo);
 
 extern void err_out(void);
 extern void InsertOneTuple(Oid objectid);
diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h
index 086df0b2f84..0d9c280fb0d 100644
--- a/src/include/catalog/catversion.h
+++ b/src/include/catalog/catversion.h
@@ -37,7 +37,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: catversion.h,v 1.110 2002/03/22 21:34:44 tgl Exp $
+ * $Id: catversion.h,v 1.111 2002/03/26 19:16:22 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -53,6 +53,6 @@
  */
 
 /*							yyyymmddN */
-#define CATALOG_VERSION_NO	200203221
+#define CATALOG_VERSION_NO	200203251
 
 #endif
diff --git a/src/include/catalog/heap.h b/src/include/catalog/heap.h
index b2bcfb71bdc..eb34ee1404f 100644
--- a/src/include/catalog/heap.h
+++ b/src/include/catalog/heap.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: heap.h,v 1.46 2002/03/20 19:44:52 tgl Exp $
+ * $Id: heap.h,v 1.47 2002/03/26 19:16:23 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -19,6 +19,7 @@
 #include "parser/parse_node.h"
 #include "utils/rel.h"
 
+
 typedef struct RawColumnDefault
 {
 	AttrNumber	attnum;			/* attribute to attach default to */
@@ -26,15 +27,15 @@ typedef struct RawColumnDefault
 								 * tree) */
 } RawColumnDefault;
 
-extern Oid	RelnameFindRelid(const char *relname);
-
-extern Relation heap_create(char *relname, TupleDesc tupDesc,
+extern Relation heap_create(char *relname, Oid relnamespace,
+			TupleDesc tupDesc,
 			bool istemp, bool storage_create,
 			bool allow_system_table_mods);
 
 extern void heap_storage_create(Relation rel);
 
-extern Oid heap_create_with_catalog(char *relname, TupleDesc tupdesc,
+extern Oid heap_create_with_catalog(char *relname, Oid relnamespace,
+						 TupleDesc tupdesc,
 						 char relkind, bool relhasoids, bool istemp,
 						 bool allow_system_table_mods);
 
diff --git a/src/include/catalog/index.h b/src/include/catalog/index.h
index c31900a7ccd..86f0824e84a 100644
--- a/src/include/catalog/index.h
+++ b/src/include/catalog/index.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: index.h,v 1.45 2002/03/10 06:02:24 momjian Exp $
+ * $Id: index.h,v 1.46 2002/03/26 19:16:25 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -29,11 +29,12 @@ typedef void (*IndexBuildCallback) (Relation index,
 												void *state);
 
 
-extern Oid index_create(char *heapRelationName,
+extern Oid index_create(Oid heapRelationId,
 			 char *indexRelationName,
 			 IndexInfo *indexInfo,
 			 Oid accessMethodObjectId,
 			 Oid *classObjectId,
+			 bool istemp,
 			 bool primary,
 			 bool allow_system_table_mods);
 
diff --git a/src/include/catalog/indexing.h b/src/include/catalog/indexing.h
index c6291f2a3a4..222e0da51e9 100644
--- a/src/include/catalog/indexing.h
+++ b/src/include/catalog/indexing.h
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: indexing.h,v 1.58 2002/03/22 21:34:44 tgl Exp $
+ * $Id: indexing.h,v 1.59 2002/03/26 19:16:26 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -58,7 +58,7 @@
 #define AttrDefaultIndex			"pg_attrdef_adrelid_adnum_index"
 #define AttributeRelidNameIndex		"pg_attribute_relid_attnam_index"
 #define AttributeRelidNumIndex		"pg_attribute_relid_attnum_index"
-#define ClassNameIndex				"pg_class_relname_index"
+#define ClassNameNspIndex			"pg_class_relname_nsp_index"
 #define ClassOidIndex				"pg_class_oid_index"
 #define DatabaseNameIndex			"pg_database_datname_index"
 #define DatabaseOidIndex			"pg_database_oid_index"
@@ -156,7 +156,7 @@ DECLARE_UNIQUE_INDEX(pg_attrdef_adrelid_adnum_index on pg_attrdef using btree(ad
 DECLARE_UNIQUE_INDEX(pg_attribute_relid_attnam_index on pg_attribute using btree(attrelid oid_ops, attname name_ops));
 DECLARE_UNIQUE_INDEX(pg_attribute_relid_attnum_index on pg_attribute using btree(attrelid oid_ops, attnum int2_ops));
 DECLARE_UNIQUE_INDEX(pg_class_oid_index on pg_class using btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_class_relname_index on pg_class using btree(relname name_ops));
+DECLARE_UNIQUE_INDEX(pg_class_relname_nsp_index on pg_class using btree(relname name_ops, relnamespace oid_ops));
 DECLARE_UNIQUE_INDEX(pg_database_datname_index on pg_database using btree(datname name_ops));
 DECLARE_UNIQUE_INDEX(pg_database_oid_index on pg_database using btree(oid oid_ops));
 DECLARE_UNIQUE_INDEX(pg_description_o_c_o_index on pg_description using btree(objoid oid_ops, classoid oid_ops, objsubid int4_ops));
diff --git a/src/include/catalog/namespace.h b/src/include/catalog/namespace.h
new file mode 100644
index 00000000000..cbe65a07f55
--- /dev/null
+++ b/src/include/catalog/namespace.h
@@ -0,0 +1,26 @@
+/*-------------------------------------------------------------------------
+ *
+ * namespace.h
+ *	  prototypes for functions in backend/catalog/namespace.c
+ *
+ *
+ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * $Id: namespace.h,v 1.1 2002/03/26 19:16:28 tgl Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef NAMESPACE_H
+#define NAMESPACE_H
+
+#include "nodes/primnodes.h"
+
+
+extern Oid	RangeVarGetRelid(const RangeVar *relation, bool failOK);
+
+extern Oid	RangeVarGetCreationNamespace(const RangeVar *newRelation);
+
+extern Oid	RelnameGetRelid(const char *relname);
+
+#endif   /* NAMESPACE_H */
diff --git a/src/include/catalog/pg_attribute.h b/src/include/catalog/pg_attribute.h
index df7cec83974..e8166960d28 100644
--- a/src/include/catalog/pg_attribute.h
+++ b/src/include/catalog/pg_attribute.h
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pg_attribute.h,v 1.85 2002/03/20 19:44:55 tgl Exp $
+ * $Id: pg_attribute.h,v 1.86 2002/03/26 19:16:29 tgl Exp $
  *
  * NOTES
  *	  the genbki.sh script reads this file and generates .bki
@@ -437,52 +437,54 @@ DATA(insert ( 1249 tableoid			26 0  4  -7 0 -1 -1 t p f i f f));
  */
 #define Schema_pg_class \
 { 1259, {"relname"},	   19, DEFAULT_ATTSTATTARGET, NAMEDATALEN,	1, 0, -1, -1, false, 'p', false, 'i', false, false }, \
-{ 1259, {"reltype"},	   26, 0,	4,	2, 0, -1, -1, true, 'p', false, 'i', false, false }, \
-{ 1259, {"relowner"},	   23, 0,	4,	3, 0, -1, -1, true, 'p', false, 'i', false, false }, \
-{ 1259, {"relam"},		   26, 0,	4,	4, 0, -1, -1, true, 'p', false, 'i', false, false }, \
-{ 1259, {"relfilenode"},   26, 0,	4,	5, 0, -1, -1, true, 'p', false, 'i', false, false }, \
-{ 1259, {"relpages"},	   23, 0,	4,	6, 0, -1, -1, true, 'p', false, 'i', false, false }, \
-{ 1259, {"reltuples"},	   700, 0,	4,	7, 0, -1, -1, false, 'p', false, 'i', false, false }, \
-{ 1259, {"reltoastrelid"}, 26, 0,	4,	8, 0, -1, -1, true, 'p', false, 'i', false, false }, \
-{ 1259, {"reltoastidxid"}, 26, 0,	4,	9, 0, -1, -1, true, 'p', false, 'i', false, false }, \
-{ 1259, {"relhasindex"},   16, 0,	1, 10, 0, -1, -1, true, 'p', false, 'c', false, false }, \
-{ 1259, {"relisshared"},   16, 0,	1, 11, 0, -1, -1, true, 'p', false, 'c', false, false }, \
-{ 1259, {"relkind"},	   18, 0,	1, 12, 0, -1, -1, true, 'p', false, 'c', false, false }, \
-{ 1259, {"relnatts"},	   21, 0,	2, 13, 0, -1, -1, true, 'p', false, 's', false, false }, \
-{ 1259, {"relchecks"},	   21, 0,	2, 14, 0, -1, -1, true, 'p', false, 's', false, false }, \
-{ 1259, {"reltriggers"},   21, 0,	2, 15, 0, -1, -1, true, 'p', false, 's', false, false }, \
-{ 1259, {"relukeys"},	   21, 0,	2, 16, 0, -1, -1, true, 'p', false, 's', false, false }, \
-{ 1259, {"relfkeys"},	   21, 0,	2, 17, 0, -1, -1, true, 'p', false, 's', false, false }, \
-{ 1259, {"relrefs"},	   21, 0,	2, 18, 0, -1, -1, true, 'p', false, 's', false, false }, \
-{ 1259, {"relhasoids"},    16, 0,	1, 19, 0, -1, -1, true, 'p', false, 'c', false, false }, \
-{ 1259, {"relhaspkey"},    16, 0,	1, 20, 0, -1, -1, true, 'p', false, 'c', false, false }, \
-{ 1259, {"relhasrules"},   16, 0,	1, 21, 0, -1, -1, true, 'p', false, 'c', false, false }, \
-{ 1259, {"relhassubclass"},16, 0,	1, 22, 0, -1, -1, true, 'p', false, 'c', false, false }, \
-{ 1259, {"relacl"},		 1034, 0,  -1, 23, 0, -1, -1, false, 'x', false, 'i', false, false }
+{ 1259, {"relnamespace"},  26, 0,	4,	2, 0, -1, -1, true, 'p', false, 'i', false, false }, \
+{ 1259, {"reltype"},	   26, 0,	4,	3, 0, -1, -1, true, 'p', false, 'i', false, false }, \
+{ 1259, {"relowner"},	   23, 0,	4,	4, 0, -1, -1, true, 'p', false, 'i', false, false }, \
+{ 1259, {"relam"},		   26, 0,	4,	5, 0, -1, -1, true, 'p', false, 'i', false, false }, \
+{ 1259, {"relfilenode"},   26, 0,	4,	6, 0, -1, -1, true, 'p', false, 'i', false, false }, \
+{ 1259, {"relpages"},	   23, 0,	4,	7, 0, -1, -1, true, 'p', false, 'i', false, false }, \
+{ 1259, {"reltuples"},	   700, 0,	4,	8, 0, -1, -1, false, 'p', false, 'i', false, false }, \
+{ 1259, {"reltoastrelid"}, 26, 0,	4,	9, 0, -1, -1, true, 'p', false, 'i', false, false }, \
+{ 1259, {"reltoastidxid"}, 26, 0,	4, 10, 0, -1, -1, true, 'p', false, 'i', false, false }, \
+{ 1259, {"relhasindex"},   16, 0,	1, 11, 0, -1, -1, true, 'p', false, 'c', false, false }, \
+{ 1259, {"relisshared"},   16, 0,	1, 12, 0, -1, -1, true, 'p', false, 'c', false, false }, \
+{ 1259, {"relkind"},	   18, 0,	1, 13, 0, -1, -1, true, 'p', false, 'c', false, false }, \
+{ 1259, {"relnatts"},	   21, 0,	2, 14, 0, -1, -1, true, 'p', false, 's', false, false }, \
+{ 1259, {"relchecks"},	   21, 0,	2, 15, 0, -1, -1, true, 'p', false, 's', false, false }, \
+{ 1259, {"reltriggers"},   21, 0,	2, 16, 0, -1, -1, true, 'p', false, 's', false, false }, \
+{ 1259, {"relukeys"},	   21, 0,	2, 17, 0, -1, -1, true, 'p', false, 's', false, false }, \
+{ 1259, {"relfkeys"},	   21, 0,	2, 18, 0, -1, -1, true, 'p', false, 's', false, false }, \
+{ 1259, {"relrefs"},	   21, 0,	2, 19, 0, -1, -1, true, 'p', false, 's', false, false }, \
+{ 1259, {"relhasoids"},    16, 0,	1, 20, 0, -1, -1, true, 'p', false, 'c', false, false }, \
+{ 1259, {"relhaspkey"},    16, 0,	1, 21, 0, -1, -1, true, 'p', false, 'c', false, false }, \
+{ 1259, {"relhasrules"},   16, 0,	1, 22, 0, -1, -1, true, 'p', false, 'c', false, false }, \
+{ 1259, {"relhassubclass"},16, 0,	1, 23, 0, -1, -1, true, 'p', false, 'c', false, false }, \
+{ 1259, {"relacl"},		 1034, 0,  -1, 24, 0, -1, -1, false, 'x', false, 'i', false, false }
 
 DATA(insert ( 1259 relname			19 DEFAULT_ATTSTATTARGET NAMEDATALEN   1 0 -1 -1 f p f i f f));
-DATA(insert ( 1259 reltype			26 0  4   2 0 -1 -1 t p f i f f));
-DATA(insert ( 1259 relowner			23 0  4   3 0 -1 -1 t p f i f f));
-DATA(insert ( 1259 relam			26 0  4   4 0 -1 -1 t p f i f f));
-DATA(insert ( 1259 relfilenode		26 0  4   5 0 -1 -1 t p f i f f));
-DATA(insert ( 1259 relpages			23 0  4   6 0 -1 -1 t p f i f f));
-DATA(insert ( 1259 reltuples	   700 0  4   7 0 -1 -1 f p f i f f));
-DATA(insert ( 1259 reltoastrelid	26 0  4   8 0 -1 -1 t p f i f f));
-DATA(insert ( 1259 reltoastidxid	26 0  4   9 0 -1 -1 t p f i f f));
-DATA(insert ( 1259 relhasindex		16 0  1  10 0 -1 -1 t p f c f f));
-DATA(insert ( 1259 relisshared		16 0  1  11 0 -1 -1 t p f c f f));
-DATA(insert ( 1259 relkind			18 0  1  12 0 -1 -1 t p f c f f));
-DATA(insert ( 1259 relnatts			21 0  2  13 0 -1 -1 t p f s f f));
-DATA(insert ( 1259 relchecks		21 0  2  14 0 -1 -1 t p f s f f));
-DATA(insert ( 1259 reltriggers		21 0  2  15 0 -1 -1 t p f s f f));
-DATA(insert ( 1259 relukeys			21 0  2  16 0 -1 -1 t p f s f f));
-DATA(insert ( 1259 relfkeys			21 0  2  17 0 -1 -1 t p f s f f));
-DATA(insert ( 1259 relrefs			21 0  2  18 0 -1 -1 t p f s f f));
-DATA(insert ( 1259 relhasoids		16 0  1  19 0 -1 -1 t p f c f f));
-DATA(insert ( 1259 relhaspkey		16 0  1  20 0 -1 -1 t p f c f f));
-DATA(insert ( 1259 relhasrules		16 0  1  21 0 -1 -1 t p f c f f));
-DATA(insert ( 1259 relhassubclass	16 0  1  22 0 -1 -1 t p f c f f));
-DATA(insert ( 1259 relacl		  1034 0 -1  23 0 -1 -1 f x f i f f));
+DATA(insert ( 1259 relnamespace		26 0  4   2 0 -1 -1 t p f i f f));
+DATA(insert ( 1259 reltype			26 0  4   3 0 -1 -1 t p f i f f));
+DATA(insert ( 1259 relowner			23 0  4   4 0 -1 -1 t p f i f f));
+DATA(insert ( 1259 relam			26 0  4   5 0 -1 -1 t p f i f f));
+DATA(insert ( 1259 relfilenode		26 0  4   6 0 -1 -1 t p f i f f));
+DATA(insert ( 1259 relpages			23 0  4   7 0 -1 -1 t p f i f f));
+DATA(insert ( 1259 reltuples	   700 0  4   8 0 -1 -1 f p f i f f));
+DATA(insert ( 1259 reltoastrelid	26 0  4   9 0 -1 -1 t p f i f f));
+DATA(insert ( 1259 reltoastidxid	26 0  4  10 0 -1 -1 t p f i f f));
+DATA(insert ( 1259 relhasindex		16 0  1  11 0 -1 -1 t p f c f f));
+DATA(insert ( 1259 relisshared		16 0  1  12 0 -1 -1 t p f c f f));
+DATA(insert ( 1259 relkind			18 0  1  13 0 -1 -1 t p f c f f));
+DATA(insert ( 1259 relnatts			21 0  2  14 0 -1 -1 t p f s f f));
+DATA(insert ( 1259 relchecks		21 0  2  15 0 -1 -1 t p f s f f));
+DATA(insert ( 1259 reltriggers		21 0  2  16 0 -1 -1 t p f s f f));
+DATA(insert ( 1259 relukeys			21 0  2  17 0 -1 -1 t p f s f f));
+DATA(insert ( 1259 relfkeys			21 0  2  18 0 -1 -1 t p f s f f));
+DATA(insert ( 1259 relrefs			21 0  2  19 0 -1 -1 t p f s f f));
+DATA(insert ( 1259 relhasoids		16 0  1  20 0 -1 -1 t p f c f f));
+DATA(insert ( 1259 relhaspkey		16 0  1  21 0 -1 -1 t p f c f f));
+DATA(insert ( 1259 relhasrules		16 0  1  22 0 -1 -1 t p f c f f));
+DATA(insert ( 1259 relhassubclass	16 0  1  23 0 -1 -1 t p f c f f));
+DATA(insert ( 1259 relacl		  1034 0 -1  24 0 -1 -1 f x f i f f));
 DATA(insert ( 1259 ctid				27 0  6  -1 0 -1 -1 f p f i f f));
 DATA(insert ( 1259 oid				26 0  4  -2 0 -1 -1 t p f i f f));
 DATA(insert ( 1259 xmin				28 0  4  -3 0 -1 -1 t p f i f f));
diff --git a/src/include/catalog/pg_class.h b/src/include/catalog/pg_class.h
index ccfc0ceef91..60f524b2a62 100644
--- a/src/include/catalog/pg_class.h
+++ b/src/include/catalog/pg_class.h
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pg_class.h,v 1.62 2002/03/19 02:18:22 momjian Exp $
+ * $Id: pg_class.h,v 1.63 2002/03/26 19:16:35 tgl Exp $
  *
  * NOTES
  *	  the genbki.sh script reads this file and generates .bki
@@ -43,6 +43,7 @@
 CATALOG(pg_class) BOOTSTRAP
 {
 	NameData	relname;		/* class name */
+	Oid			relnamespace;	/* OID of namespace containing this class */
 	Oid			reltype;		/* OID of associated entry in pg_type */
 	int4		relowner;		/* class owner */
 	Oid			relam;			/* index access method; 0 if not an index */
@@ -99,31 +100,32 @@ typedef FormData_pg_class *Form_pg_class;
  *		relacl field.  This is a kluge.
  * ----------------
  */
-#define Natts_pg_class_fixed			22
-#define Natts_pg_class					23
+#define Natts_pg_class_fixed			23
+#define Natts_pg_class					24
 #define Anum_pg_class_relname			1
-#define Anum_pg_class_reltype			2
-#define Anum_pg_class_relowner			3
-#define Anum_pg_class_relam				4
-#define Anum_pg_class_relfilenode		5
-#define Anum_pg_class_relpages			6
-#define Anum_pg_class_reltuples			7
-#define Anum_pg_class_reltoastrelid		8
-#define Anum_pg_class_reltoastidxid		9
-#define Anum_pg_class_relhasindex		10
-#define Anum_pg_class_relisshared		11
-#define Anum_pg_class_relkind			12
-#define Anum_pg_class_relnatts			13
-#define Anum_pg_class_relchecks			14
-#define Anum_pg_class_reltriggers		15
-#define Anum_pg_class_relukeys			16
-#define Anum_pg_class_relfkeys			17
-#define Anum_pg_class_relrefs			18
-#define Anum_pg_class_relhasoids		19
-#define Anum_pg_class_relhaspkey		20
-#define Anum_pg_class_relhasrules		21
-#define Anum_pg_class_relhassubclass	22
-#define Anum_pg_class_relacl			23
+#define Anum_pg_class_relnamespace		2
+#define Anum_pg_class_reltype			3
+#define Anum_pg_class_relowner			4
+#define Anum_pg_class_relam				5
+#define Anum_pg_class_relfilenode		6
+#define Anum_pg_class_relpages			7
+#define Anum_pg_class_reltuples			8
+#define Anum_pg_class_reltoastrelid		9
+#define Anum_pg_class_reltoastidxid		10
+#define Anum_pg_class_relhasindex		11
+#define Anum_pg_class_relisshared		12
+#define Anum_pg_class_relkind			13
+#define Anum_pg_class_relnatts			14
+#define Anum_pg_class_relchecks			15
+#define Anum_pg_class_reltriggers		16
+#define Anum_pg_class_relukeys			17
+#define Anum_pg_class_relfkeys			18
+#define Anum_pg_class_relrefs			19
+#define Anum_pg_class_relhasoids		20
+#define Anum_pg_class_relhaspkey		21
+#define Anum_pg_class_relhasrules		22
+#define Anum_pg_class_relhassubclass	23
+#define Anum_pg_class_relacl			24
 
 /* ----------------
  *		initial contents of pg_class
@@ -132,21 +134,21 @@ typedef FormData_pg_class *Form_pg_class;
  * ----------------
  */
 
-DATA(insert OID = 1247 (  pg_type		71	PGUID 0 1247 0 0 0 0 f f r 22 0 0 0 0 0 t f f f _null_ ));
+DATA(insert OID = 1247 (  pg_type		PGNSP 71 PGUID 0 1247 0 0 0 0 f f r 22 0 0 0 0 0 t f f f _null_ ));
 DESCR("");
-DATA(insert OID = 1249 (  pg_attribute	75	PGUID 0 1249 0 0 0 0 f f r 15 0 0 0 0 0 f f f f _null_ ));
+DATA(insert OID = 1249 (  pg_attribute	PGNSP 75 PGUID 0 1249 0 0 0 0 f f r 15 0 0 0 0 0 f f f f _null_ ));
 DESCR("");
-DATA(insert OID = 1255 (  pg_proc		81	PGUID 0 1255 0 0 0 0 f f r 18 0 0 0 0 0 t f f f _null_ ));
+DATA(insert OID = 1255 (  pg_proc		PGNSP 81 PGUID 0 1255 0 0 0 0 f f r 18 0 0 0 0 0 t f f f _null_ ));
 DESCR("");
-DATA(insert OID = 1259 (  pg_class		83	PGUID 0 1259 0 0 0 0 f f r 23 0 0 0 0 0 t f f f _null_ ));
+DATA(insert OID = 1259 (  pg_class		PGNSP 83 PGUID 0 1259 0 0 0 0 f f r 24 0 0 0 0 0 t f f f _null_ ));
 DESCR("");
-DATA(insert OID = 1260 (  pg_shadow		86	PGUID 0 1260 0 0 0 0 f t r 9  0 0 0 0 0 f f f f _null_ ));
+DATA(insert OID = 1260 (  pg_shadow		PGNSP 86 PGUID 0 1260 0 0 0 0 f t r 9  0 0 0 0 0 f f f f _null_ ));
 DESCR("");
-DATA(insert OID = 1261 (  pg_group		87	PGUID 0 1261 0 0 0 0 f t r 3  0 0 0 0 0 f f f f _null_ ));
+DATA(insert OID = 1261 (  pg_group		PGNSP 87 PGUID 0 1261 0 0 0 0 f t r 3  0 0 0 0 0 f f f f _null_ ));
 DESCR("");
-DATA(insert OID = 1262 (  pg_database	88	PGUID 0 1262 0 0 0 0 f t r 10  0 0 0 0 0 t f f f _null_ ));
+DATA(insert OID = 1262 (  pg_database	PGNSP 88 PGUID 0 1262 0 0 0 0 f t r 10  0 0 0 0 0 t f f f _null_ ));
 DESCR("");
-DATA(insert OID = 376  (  pg_xactlock	0	PGUID 0    0 0 0 0 0 f t s 1  0 0 0 0 0 f f f f _null_ ));
+DATA(insert OID = 376  (  pg_xactlock	PGNSP  0 PGUID 0    0 0 0 0 0 f t s 1  0 0 0 0 0 f f f f _null_ ));
 DESCR("");
 
 #define RelOid_pg_type			1247
diff --git a/src/include/commands/cluster.h b/src/include/commands/cluster.h
index d0760070841..c04cca24b42 100644
--- a/src/include/commands/cluster.h
+++ b/src/include/commands/cluster.h
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994-5, Regents of the University of California
  *
- * $Id: cluster.h,v 1.12 2001/11/05 17:46:33 momjian Exp $
+ * $Id: cluster.h,v 1.13 2002/03/26 19:16:40 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -23,6 +23,6 @@
 /*
  * functions
  */
-extern void cluster(char *oldrelname, char *oldindexname);
+extern void cluster(RangeVar *oldrelation, char *oldindexname);
 
 #endif   /* CLUSTER_H */
diff --git a/src/include/commands/command.h b/src/include/commands/command.h
index 36757b1f702..1601898b405 100644
--- a/src/include/commands/command.h
+++ b/src/include/commands/command.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: command.h,v 1.34 2002/03/21 16:01:41 tgl Exp $
+ * $Id: command.h,v 1.35 2002/03/26 19:16:40 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -62,10 +62,9 @@ extern void AlterTableDropConstraint(const char *relationName,
 						 bool inh, const char *constrName,
 						 int behavior);
 
-extern void AlterTableCreateToastTable(const char *relationName,
-						   bool silent);
+extern void AlterTableCreateToastTable(Oid relOid, bool silent);
 
-extern void AlterTableOwner(const char *relationName, const char *newOwnerName);
+extern void AlterTableOwner(const RangeVar *tgtrel, const char *newOwnerName);
 
 /*
  * LOCK
diff --git a/src/include/commands/comment.h b/src/include/commands/comment.h
index 4d83372bdd6..f1e9a760b0b 100644
--- a/src/include/commands/comment.h
+++ b/src/include/commands/comment.h
@@ -25,8 +25,8 @@
  *------------------------------------------------------------------
  */
 
-extern void CommentObject(int objtype, char *objname, char *objproperty,
-			  List *objlist, char *comment);
+extern void CommentObject(int objtype, char * schemaname, char *objname,
+							char *objproperty, List *objlist, char *comment);
 
 extern void DeleteComments(Oid oid, Oid classoid);
 
diff --git a/src/include/commands/defrem.h b/src/include/commands/defrem.h
index 78b34614d58..97924979c28 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.31 2002/03/19 02:18:23 momjian Exp $
+ * $Id: defrem.h,v 1.32 2002/03/26 19:16:47 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -19,7 +19,7 @@
 /*
  * prototypes in indexcmds.c
  */
-extern void DefineIndex(char *heapRelationName,
+extern void DefineIndex(RangeVar *heapRelation,
 			char *indexRelationName,
 			char *accessMethodName,
 			List *attributeList,
@@ -27,9 +27,9 @@ extern void DefineIndex(char *heapRelationName,
 			bool primary,
 			Expr *predicate,
 			List *rangetable);
-extern void RemoveIndex(char *name);
-extern void ReindexIndex(const char *indexRelationName, bool force);
-extern void ReindexTable(const char *relationName, bool force);
+extern void RemoveIndex(RangeVar *relation);
+extern void ReindexIndex(RangeVar *indexRelation, bool force);
+extern void ReindexTable(RangeVar *relation, bool force);
 extern void ReindexDatabase(const char *databaseName, bool force, bool all);
 
 /*
diff --git a/src/include/commands/rename.h b/src/include/commands/rename.h
index 76b5167a83b..7bfd0479167 100644
--- a/src/include/commands/rename.h
+++ b/src/include/commands/rename.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: rename.h,v 1.13 2001/11/05 17:46:33 momjian Exp $
+ * $Id: rename.h,v 1.14 2002/03/26 19:16:49 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -19,7 +19,7 @@ extern void renameatt(char *relname,
 		  char *newattname,
 		  int recurse);
 
-extern void renamerel(const char *oldrelname,
+extern void renamerel(const RangeVar *relation,
 		  const char *newrelname);
 
 #endif   /* RENAME_H */
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index 883130f90a0..e66e7b8b646 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.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: parsenodes.h,v 1.164 2002/03/22 02:56:36 tgl Exp $
+ * $Id: parsenodes.h,v 1.165 2002/03/26 19:16:53 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -17,14 +17,6 @@
 #include "nodes/primnodes.h"
 
 
-typedef enum InhOption
-{
-	INH_NO,						/* Do NOT scan child tables */
-	INH_YES,					/* DO scan child tables */
-	INH_DEFAULT					/* Use current SQL_inheritance option */
-} InhOption;
-
-
 /*****************************************************************************
  *	Query Tree
  *****************************************************************************/
@@ -49,7 +41,7 @@ typedef struct Query
 								 * statement */
 
 	int			resultRelation; /* target relation (index into rtable) */
-	struct RangeVar *into;		/* target relation or portal (cursor) 
+	RangeVar   *into;			/* target relation or portal (cursor) 
 								 * for portal just name is meaningful */
 	bool		isPortal;		/* is this a retrieve into portal? */
 	bool		isBinary;		/* binary portal? */
@@ -368,39 +360,6 @@ typedef struct SortGroupBy
 	Node	   *node;			/* Expression  */
 } SortGroupBy;
 
-/*
- * Alias -
- *	  specifies an alias for a range variable; the alias might also
- *	  specify renaming of columns within the table.
- */
-typedef struct Alias
-{
-	NodeTag		type;
-	char	   *aliasname;		/* aliased rel name (never qualified) */
-	List	   *colnames;		/* optional list of column aliases */
-	/* Note: colnames is a list of Value nodes (always strings) */
-} Alias;
-
-/*
- * RangeVar - range variable, used in FROM clauses
- *
- * Also used to represent table names in utility statements; there, the alias
- * field is not used, and inhOpt shows whether to apply the operation
- * recursively to child tables.  In some contexts it is also useful to carry
- * a TEMP table indication here.
- */
-typedef struct RangeVar
-{
-	NodeTag		type;
-	char	   *catalogname;	/* the catalog (database) name, or NULL */
-	char	   *schemaname;		/* the schema name, or NULL */
-	char	   *relname;		/* the relation/sequence name */
-	InhOption	inhOpt;			/* expand rel by inheritance? 
-								 * recursively act on children? */
-	bool		istemp;			/* is this a temp relation/sequence? */
-	Alias	   *alias;			/* table alias & optional column aliases */
-} RangeVar;
-
 /*
  * RangeSubselect - subquery appearing in a FROM clause
  */
diff --git a/src/include/nodes/primnodes.h b/src/include/nodes/primnodes.h
index f7323058251..dc01689e30e 100644
--- a/src/include/nodes/primnodes.h
+++ b/src/include/nodes/primnodes.h
@@ -10,7 +10,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: primnodes.h,v 1.59 2002/03/21 16:01:48 tgl Exp $
+ * $Id: primnodes.h,v 1.60 2002/03/26 19:16:53 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -93,6 +93,47 @@ typedef struct Fjoin
 } Fjoin;
 
 
+/*
+ * Alias -
+ *	  specifies an alias for a range variable; the alias might also
+ *	  specify renaming of columns within the table.
+ */
+typedef struct Alias
+{
+	NodeTag		type;
+	char	   *aliasname;		/* aliased rel name (never qualified) */
+	List	   *colnames;		/* optional list of column aliases */
+	/* Note: colnames is a list of Value nodes (always strings) */
+} Alias;
+
+typedef enum InhOption
+{
+	INH_NO,						/* Do NOT scan child tables */
+	INH_YES,					/* DO scan child tables */
+	INH_DEFAULT					/* Use current SQL_inheritance option */
+} InhOption;
+
+/*
+ * RangeVar - range variable, used in FROM clauses
+ *
+ * Also used to represent table names in utility statements; there, the alias
+ * field is not used, and inhOpt shows whether to apply the operation
+ * recursively to child tables.  In some contexts it is also useful to carry
+ * a TEMP table indication here.
+ */
+typedef struct RangeVar
+{
+	NodeTag		type;
+	char	   *catalogname;	/* the catalog (database) name, or NULL */
+	char	   *schemaname;		/* the schema name, or NULL */
+	char	   *relname;		/* the relation/sequence name */
+	InhOption	inhOpt;			/* expand rel by inheritance? 
+								 * recursively act on children? */
+	bool		istemp;			/* is this a temp relation/sequence? */
+	Alias	   *alias;			/* table alias & optional column aliases */
+} RangeVar;
+
+
 /* ----------------------------------------------------------------
  *					node types for executable expressions
  * ----------------------------------------------------------------
@@ -527,7 +568,7 @@ typedef struct JoinExpr
 	Node	   *rarg;			/* right subtree */
 	List	   *using;			/* USING clause, if any (list of String) */
 	Node	   *quals;			/* qualifiers on join, if any */
-	struct Alias *alias;		/* user-written alias clause, if any */
+	Alias	   *alias;			/* user-written alias clause, if any */
 	int			rtindex;		/* RT index assigned for join */
 } JoinExpr;
 
diff --git a/src/include/utils/catcache.h b/src/include/utils/catcache.h
index 034c061e7d4..8e98f41c019 100644
--- a/src/include/utils/catcache.h
+++ b/src/include/utils/catcache.h
@@ -13,7 +13,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: catcache.h,v 1.40 2002/03/06 20:49:46 momjian Exp $
+ * $Id: catcache.h,v 1.41 2002/03/26 19:16:56 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -33,8 +33,8 @@ typedef struct catcache
 {
 	int			id;				/* cache identifier --- see syscache.h */
 	struct catcache *cc_next;	/* link to next catcache */
-	char	   *cc_relname;		/* name of relation the tuples come from */
-	char	   *cc_indname;		/* name of index matching cache keys */
+	const char *cc_relname;		/* name of relation the tuples come from */
+	const char *cc_indname;		/* name of index matching cache keys */
 	Oid			cc_reloid;		/* OID of relation the tuples come from */
 	bool		cc_relisshared; /* is relation shared? */
 	TupleDesc	cc_tupdesc;		/* tuple descriptor (copied from reldesc) */
@@ -107,9 +107,9 @@ extern MemoryContext CacheMemoryContext;
 extern void CreateCacheMemoryContext(void);
 extern void AtEOXact_CatCache(bool isCommit);
 
-extern CatCache *InitCatCache(int id, char *relname, char *indname,
+extern CatCache *InitCatCache(int id, const char *relname, const char *indname,
 			 int reloidattr,
-			 int nkeys, int *key);
+			 int nkeys, const int *key);
 extern void InitCatCachePhase2(CatCache *cache);
 
 extern HeapTuple SearchCatCache(CatCache *cache,
diff --git a/src/include/utils/lsyscache.h b/src/include/utils/lsyscache.h
index 89dda37bf7c..a18ed521074 100644
--- a/src/include/utils/lsyscache.h
+++ b/src/include/utils/lsyscache.h
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: lsyscache.h,v 1.45 2002/03/22 02:56:37 tgl Exp $
+ * $Id: lsyscache.h,v 1.46 2002/03/26 19:16:57 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -39,6 +39,7 @@ extern RegProcedure get_oprrest(Oid opno);
 extern RegProcedure get_oprjoin(Oid opno);
 extern Oid	get_func_rettype(Oid funcid);
 extern bool func_iscachable(Oid funcid);
+extern Oid	get_relname_relid(const char *relname, Oid relnamespace);
 extern char *get_rel_name(Oid relid);
 extern Oid	get_rel_type_id(Oid relid);
 extern int16 get_typlen(Oid typid);
diff --git a/src/include/utils/rel.h b/src/include/utils/rel.h
index 49814386ca6..16398b4c08f 100644
--- a/src/include/utils/rel.h
+++ b/src/include/utils/rel.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: rel.h,v 1.56 2002/02/19 20:11:19 tgl Exp $
+ * $Id: rel.h,v 1.57 2002/03/26 19:16:58 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -282,6 +282,14 @@ typedef Relation *RelationPtr;
 		RelationGetPhysicalRelationName(relation) \
 )
 
+/*
+ * RelationGetNamespace
+ *
+ *	  Returns the rel's namespace OID.
+ */
+#define RelationGetNamespace(relation) \
+	((relation)->rd_rel->relnamespace)
+
 /* added to prevent circular dependency.  bjm 1999/11/15 */
 extern char *get_temp_rel_by_physicalname(const char *relname);
 
diff --git a/src/include/utils/relcache.h b/src/include/utils/relcache.h
index e5af1bee61b..6e6164b87c8 100644
--- a/src/include/utils/relcache.h
+++ b/src/include/utils/relcache.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: relcache.h,v 1.30 2002/02/19 20:11:20 tgl Exp $
+ * $Id: relcache.h,v 1.31 2002/03/26 19:16:59 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -20,11 +20,11 @@
  * relation lookup routines
  */
 extern Relation RelationIdGetRelation(Oid relationId);
-extern Relation RelationNameGetRelation(const char *relationName);
-extern Relation RelationNodeCacheGetRelation(RelFileNode rnode);
+extern Relation RelationSysNameGetRelation(const char *relationName);
 
 /* finds an existing cache entry, but won't make a new one */
 extern Relation RelationIdCacheGetRelation(Oid relationId);
+extern Relation RelationNodeCacheGetRelation(RelFileNode rnode);
 
 extern void RelationClose(Relation relation);
 
@@ -46,8 +46,10 @@ extern void RelationCacheInitializePhase3(void);
  * Routine to create a relcache entry for an about-to-be-created relation
  */
 extern Relation RelationBuildLocalRelation(const char *relname,
+						   Oid relnamespace,
 						   TupleDesc tupDesc,
 						   Oid relid, Oid dbid,
+						   RelFileNode rnode,
 						   bool nailit);
 
 /*
diff --git a/src/include/utils/syscache.h b/src/include/utils/syscache.h
index 45de795c9c8..49af9690758 100644
--- a/src/include/utils/syscache.h
+++ b/src/include/utils/syscache.h
@@ -9,7 +9,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: syscache.h,v 1.39 2002/03/22 21:34:44 tgl Exp $
+ * $Id: syscache.h,v 1.40 2002/03/26 19:16:59 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -51,7 +51,7 @@
 #define OPEROID			20
 #define PROCNAME		21
 #define PROCOID			22
-#define RELNAME			23
+#define RELNAMENSP		23
 #define RELOID			24
 #define RULENAME		25
 #define SHADOWNAME		26
diff --git a/src/pl/plpgsql/src/pl_comp.c b/src/pl/plpgsql/src/pl_comp.c
index 0e9ca176ac4..44c5146eb63 100644
--- a/src/pl/plpgsql/src/pl_comp.c
+++ b/src/pl/plpgsql/src/pl_comp.c
@@ -3,7 +3,7 @@
  *			  procedural language
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_comp.c,v 1.38 2002/03/06 06:10:45 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_comp.c,v 1.39 2002/03/26 19:17:02 tgl Exp $
  *
  *	  This software is copyrighted by Jan Wieck - Hamburg.
  *
@@ -46,6 +46,7 @@
 
 #include "access/heapam.h"
 #include "catalog/catname.h"
+#include "catalog/namespace.h"
 #include "catalog/pg_proc.h"
 #include "catalog/pg_type.h"
 #include "catalog/pg_class.h"
@@ -941,6 +942,7 @@ plpgsql_parse_dblwordtype(char *string)
 	char	   *word2;
 	PLpgSQL_nsitem *nse;
 	bool		old_nsstate;
+	Oid			classOid;
 	HeapTuple	classtup;
 	Form_pg_class classStruct;
 	HeapTuple	attrtup;
@@ -998,8 +1000,14 @@ plpgsql_parse_dblwordtype(char *string)
 	/*
 	 * First word could also be a table name
 	 */
-	classtup = SearchSysCache(RELNAME,
-							  PointerGetDatum(word1),
+	classOid = RelnameGetRelid(word1);
+	if (!OidIsValid(classOid))
+	{
+		pfree(word1);
+		return T_ERROR;
+	}
+	classtup = SearchSysCache(RELOID,
+							  ObjectIdGetDatum(classOid),
 							  0, 0, 0);
 	if (!HeapTupleIsValid(classtup))
 	{
@@ -1024,7 +1032,7 @@ plpgsql_parse_dblwordtype(char *string)
 	 * Fetch the named table field and it's type
 	 */
 	attrtup = SearchSysCache(ATTNAME,
-							 ObjectIdGetDatum(classtup->t_data->t_oid),
+							 ObjectIdGetDatum(classOid),
 							 PointerGetDatum(word2),
 							 0, 0);
 	if (!HeapTupleIsValid(attrtup))
@@ -1049,7 +1057,7 @@ plpgsql_parse_dblwordtype(char *string)
 	typ = (PLpgSQL_type *) malloc(sizeof(PLpgSQL_type));
 
 	typ->typname = strdup(NameStr(typeStruct->typname));
-	typ->typoid = typetup->t_data->t_oid;
+	typ->typoid = attrStruct->atttypid;
 	perm_fmgr_info(typeStruct->typinput, &(typ->typinput));
 	typ->typelem = typeStruct->typelem;
 	typ->typbyval = typeStruct->typbyval;
@@ -1074,6 +1082,7 @@ plpgsql_parse_dblwordtype(char *string)
 int
 plpgsql_parse_wordrowtype(char *string)
 {
+	Oid			classOid;
 	HeapTuple	classtup;
 	Form_pg_class classStruct;
 	HeapTuple	typetup;
@@ -1093,8 +1102,11 @@ plpgsql_parse_wordrowtype(char *string)
 	cp = strchr(word1, '%');
 	*cp = '\0';
 
-	classtup = SearchSysCache(RELNAME,
-							  PointerGetDatum(word1),
+	classOid = RelnameGetRelid(word1);
+	if (!OidIsValid(classOid))
+		elog(ERROR, "%s: no such class", word1);
+	classtup = SearchSysCache(RELOID,
+							  ObjectIdGetDatum(classOid),
 							  0, 0, 0);
 	if (!HeapTupleIsValid(classtup))
 		elog(ERROR, "%s: no such class", word1);
@@ -1105,15 +1117,6 @@ plpgsql_parse_wordrowtype(char *string)
 		classStruct->relkind != RELKIND_VIEW)
 		elog(ERROR, "%s isn't a table", word1);
 
-	/*
-	 * Fetch the table's pg_type tuple too
-	 */
-	typetup = SearchSysCache(TYPENAME,
-							 PointerGetDatum(word1),
-							 0, 0, 0);
-	if (!HeapTupleIsValid(typetup))
-		elog(ERROR, "cache lookup for %s in pg_type failed", word1);
-
 	/*
 	 * Create a row datum entry and all the required variables that it
 	 * will point to.
@@ -1123,19 +1126,17 @@ plpgsql_parse_wordrowtype(char *string)
 
 	row->dtype = PLPGSQL_DTYPE_ROW;
 	row->nfields = classStruct->relnatts;
-	row->rowtypeclass = typetup->t_data->t_oid;
+	row->rowtypeclass = classStruct->reltype;
 	row->fieldnames = malloc(sizeof(char *) * row->nfields);
 	row->varnos = malloc(sizeof(int) * row->nfields);
 
-	ReleaseSysCache(typetup);
-
 	for (i = 0; i < row->nfields; i++)
 	{
 		/*
 		 * Get the attribute and it's type
 		 */
 		attrtup = SearchSysCache(ATTNUM,
-							   ObjectIdGetDatum(classtup->t_data->t_oid),
+								 ObjectIdGetDatum(classOid),
 								 Int16GetDatum(i + 1),
 								 0, 0);
 		if (!HeapTupleIsValid(attrtup))
@@ -1172,7 +1173,7 @@ plpgsql_parse_wordrowtype(char *string)
 		strcat(var->refname, cp);
 		var->datatype = malloc(sizeof(PLpgSQL_type));
 		var->datatype->typname = strdup(NameStr(typeStruct->typname));
-		var->datatype->typoid = typetup->t_data->t_oid;
+		var->datatype->typoid = attrStruct->atttypid;
 		perm_fmgr_info(typeStruct->typinput, &(var->datatype->typinput));
 		var->datatype->typelem = typeStruct->typelem;
 		var->datatype->typbyval = typeStruct->typbyval;
-- 
GitLab