diff --git a/contrib/btree_gist/btree_gist.sql.in b/contrib/btree_gist/btree_gist.sql.in
index 7089f1d3b56c5a43bbfce719cd9f0015de850d7d..98b868afc7283db8c33ed694a9bb387a6bb7caa6 100644
--- a/contrib/btree_gist/btree_gist.sql.in
+++ b/contrib/btree_gist/btree_gist.sql.in
@@ -41,12 +41,15 @@ create function gint4_union(bytea, opaque) returns int4 as 'MODULE_PATHNAME' lan
 create function gint4_same(opaque, opaque, opaque) returns opaque as 'MODULE_PATHNAME' language 'C';
 
 -- add a new opclass
-INSERT INTO pg_opclass (opcamid, opcname, opcintype, opckeytype, opcdefault)
-   SELECT pg_am.oid, 'gist_int4_ops', pg_type.oid, pg_key.oid, true 
-   FROM pg_type, pg_am, pg_type pg_key
-   WHERE pg_type.typname = 'int4' and
-   pg_key.typname = 'int4key' and
-   pg_am.amname='gist';
+INSERT INTO pg_opclass (opcamid, opcname, opcnamespace, opcowner, opcintype, opcdefault, opckeytype)
+    VALUES (
+        (SELECT oid FROM pg_am WHERE amname = 'gist'),
+        'gist_int4_ops',
+        (SELECT oid FROM pg_namespace WHERE nspname = 'pg_catalog'),
+        1,	-- UID of superuser is hardwired to 1 as of PG 7.3
+        (SELECT oid FROM pg_type WHERE typname = 'int4'),
+        true,
+        (SELECT oid FROM pg_type WHERE typname = 'int4key'));
 
 
 SELECT o.oid AS opoid, o.oprname
@@ -170,12 +173,16 @@ create function gts_union(bytea, opaque) returns int4 as 'MODULE_PATHNAME' langu
 
 create function gts_same(opaque, opaque, opaque) returns opaque as 'MODULE_PATHNAME' language 'C';
 
-INSERT INTO pg_opclass (opcamid, opcname, opcintype, opckeytype, opcdefault)
-   SELECT pg_am.oid, 'gist_timestamp_ops', pg_type.oid, pg_key.oid, true
-   FROM pg_type, pg_am, pg_type pg_key
-   WHERE pg_type.typname = 'timestamp' and
-   pg_key.typname = 'tskey' and
-   pg_am.amname='gist';
+-- add a new opclass
+INSERT INTO pg_opclass (opcamid, opcname, opcnamespace, opcowner, opcintype, opcdefault, opckeytype)
+    VALUES (
+        (SELECT oid FROM pg_am WHERE amname = 'gist'),
+        'gist_timestamp_ops',
+        (SELECT oid FROM pg_namespace WHERE nspname = 'pg_catalog'),
+        1,	-- UID of superuser is hardwired to 1 as of PG 7.3
+        (SELECT oid FROM pg_type WHERE typname = 'timestamp'),
+        true,
+        (SELECT oid FROM pg_type WHERE typname = 'tskey'));
 
 SELECT o.oid AS opoid, o.oprname
 INTO TABLE timestamp_ops_tmp
diff --git a/contrib/cube/cube.sql.in b/contrib/cube/cube.sql.in
index 00994d39a007c4b4c028719553777fb83f59fe20..a1a78ca9f58676ab678326e85498a4988d368333 100644
--- a/contrib/cube/cube.sql.in
+++ b/contrib/cube/cube.sql.in
@@ -212,10 +212,12 @@ CREATE FUNCTION g_cube_same(cube, cube, opaque) RETURNS opaque
 
 
 -- register the default opclass for indexing
-INSERT INTO pg_opclass (opcamid, opcname, opcintype, opcdefault, opckeytype)
+INSERT INTO pg_opclass (opcamid, opcname, opcnamespace, opcowner, opcintype, opcdefault, opckeytype)
     VALUES (
         (SELECT oid FROM pg_am WHERE amname = 'gist'),
         'gist_cube_ops',
+        (SELECT oid FROM pg_namespace WHERE nspname = 'pg_catalog'),
+        1,	-- UID of superuser is hardwired to 1 as of PG 7.3
         (SELECT oid FROM pg_type WHERE typname = 'cube'),
         true,
         0);
diff --git a/contrib/intarray/_int.sql.in b/contrib/intarray/_int.sql.in
index 61f2cbd3f6f32b0a05dd84367e9ae515cab0b546..60a4972984b813aadae0f9a485eb759285c33d61 100644
--- a/contrib/intarray/_int.sql.in
+++ b/contrib/intarray/_int.sql.in
@@ -144,10 +144,12 @@ CREATE FUNCTION g_int_same(_int4, _int4, opaque) RETURNS opaque
 
 
 -- register the default opclass for indexing
-INSERT INTO pg_opclass (opcamid, opcname, opcintype, opcdefault, opckeytype)
+INSERT INTO pg_opclass (opcamid, opcname, opcnamespace, opcowner, opcintype, opcdefault, opckeytype)
     VALUES (
         (SELECT oid FROM pg_am WHERE amname = 'gist'),
         'gist__int_ops',
+        (SELECT oid FROM pg_namespace WHERE nspname = 'pg_catalog'),
+        1,	-- UID of superuser is hardwired to 1 as of PG 7.3
         (SELECT oid FROM pg_type WHERE typname = '_int4'),
         true,
         0);
@@ -300,10 +302,12 @@ CREATE FUNCTION g_intbig_same(_int4, _int4, opaque) RETURNS opaque
 	AS 'MODULE_PATHNAME' LANGUAGE 'c';
 
 -- register the opclass for indexing (not as default)
-INSERT INTO pg_opclass (opcamid, opcname, opcintype, opcdefault, opckeytype)
+INSERT INTO pg_opclass (opcamid, opcname, opcnamespace, opcowner, opcintype, opcdefault, opckeytype)
     VALUES (
         (SELECT oid FROM pg_am WHERE amname = 'gist'),
         'gist__intbig_ops',
+        (SELECT oid FROM pg_namespace WHERE nspname = 'pg_catalog'),
+        1,	-- UID of superuser is hardwired to 1 as of PG 7.3
         (SELECT oid FROM pg_type WHERE typname = '_int4'),
         false,
         0);
diff --git a/contrib/rtree_gist/rtree_gist.sql.in b/contrib/rtree_gist/rtree_gist.sql.in
index df9bb823f09cce239bb7c55d1aae470f5d87916a..0d1770381f4e374f465fd5f6a3165a7b3a7421b8 100644
--- a/contrib/rtree_gist/rtree_gist.sql.in
+++ b/contrib/rtree_gist/rtree_gist.sql.in
@@ -21,11 +21,13 @@ create function gbox_union(bytea, opaque) returns box as 'MODULE_PATHNAME' langu
 
 create function gbox_same(box, box, opaque) returns opaque as 'MODULE_PATHNAME' language 'C';
 
--- add a new opclass (non-default)
-INSERT INTO pg_opclass (opcamid, opcname, opcintype, opcdefault, opckeytype)
+-- add a new opclass
+INSERT INTO pg_opclass (opcamid, opcname, opcnamespace, opcowner, opcintype, opcdefault, opckeytype)
     VALUES (
         (SELECT oid FROM pg_am WHERE amname = 'gist'),
         'gist_box_ops',
+        (SELECT oid FROM pg_namespace WHERE nspname = 'pg_catalog'),
+        1,	-- UID of superuser is hardwired to 1 as of PG 7.3
         (SELECT oid FROM pg_type WHERE typname = 'box'),
         true,
         0);
@@ -183,11 +185,13 @@ create function gpoly_consistent(opaque,polygon,int4) returns bool as 'MODULE_PA
 
 create function gpoly_compress(opaque) returns opaque as 'MODULE_PATHNAME' language 'C';
 
--- add a new opclass (non-default)
-INSERT INTO pg_opclass (opcamid, opcname, opcintype, opcdefault, opckeytype)
+-- add a new opclass
+INSERT INTO pg_opclass (opcamid, opcname, opcnamespace, opcowner, opcintype, opcdefault, opckeytype)
     VALUES (
         (SELECT oid FROM pg_am WHERE amname = 'gist'),
         'gist_poly_ops',
+        (SELECT oid FROM pg_namespace WHERE nspname = 'pg_catalog'),
+        1,	-- UID of superuser is hardwired to 1 as of PG 7.3
         (SELECT oid FROM pg_type WHERE typname = 'polygon'),
         true,
         (SELECT oid FROM pg_type WHERE typname = 'box'));
diff --git a/contrib/seg/seg.sql.in b/contrib/seg/seg.sql.in
index 74739dfc5cfcc809d75531a39860f0ad8fbc1ec4..f8acddeb3520b2d7e8e2f1b9ec757703faca1169 100644
--- a/contrib/seg/seg.sql.in
+++ b/contrib/seg/seg.sql.in
@@ -236,10 +236,12 @@ CREATE FUNCTION gseg_same(seg, seg, opaque) RETURNS opaque
 
 
 -- register the default opclass for indexing
-INSERT INTO pg_opclass (opcamid, opcname, opcintype, opcdefault, opckeytype)
+INSERT INTO pg_opclass (opcamid, opcname, opcnamespace, opcowner, opcintype, opcdefault, opckeytype)
     VALUES (
         (SELECT oid FROM pg_am WHERE amname = 'gist'),
         'gist_seg_ops',
+        (SELECT oid FROM pg_namespace WHERE nspname = 'pg_catalog'),
+        1,	-- UID of superuser is hardwired to 1 as of PG 7.3
         (SELECT oid FROM pg_type WHERE typname = 'seg'),
         true,
         0);
diff --git a/contrib/tsearch/tsearch.sql.in b/contrib/tsearch/tsearch.sql.in
index 48a5ae27e62183027b6db5447141bafc22f8996c..e53793cf718610039f7e04247cae6ccd53da8c14 100644
--- a/contrib/tsearch/tsearch.sql.in
+++ b/contrib/tsearch/tsearch.sql.in
@@ -155,10 +155,12 @@ CREATE FUNCTION gtxtidx_union(bytea, opaque) RETURNS _int4
 CREATE FUNCTION gtxtidx_same(gtxtidx, gtxtidx, opaque) RETURNS opaque
         AS 'MODULE_PATHNAME' LANGUAGE 'c';
 
-INSERT INTO pg_opclass (opcamid, opcname, opcintype, opcdefault, opckeytype)
+INSERT INTO pg_opclass (opcamid, opcname, opcnamespace, opcowner, opcintype, opcdefault, opckeytype)
     VALUES (
         (SELECT oid FROM pg_am WHERE amname = 'gist'),
         'gist_txtidx_ops',
+        (SELECT oid FROM pg_namespace WHERE nspname = 'pg_catalog'),
+        1,	-- UID of superuser is hardwired to 1 as of PG 7.3
         (SELECT oid FROM pg_type WHERE typname = 'txtidx'),
         true,
         (SELECT oid FROM pg_type WHERE typname = 'gtxtidx'));
diff --git a/doc/src/sgml/xindex.sgml b/doc/src/sgml/xindex.sgml
index 6a9062914113c06037ae7bc3b622049cf09ea9a5..dcb5f9b65170e8f0cd8d7f3e1ca61691fbdf17e6 100644
--- a/doc/src/sgml/xindex.sgml
+++ b/doc/src/sgml/xindex.sgml
@@ -1,5 +1,5 @@
 <!--
-$Header: /cvsroot/pgsql/doc/src/sgml/xindex.sgml,v 1.23 2002/03/27 19:19:23 petere Exp $
+$Header: /cvsroot/pgsql/doc/src/sgml/xindex.sgml,v 1.24 2002/04/17 20:57:56 tgl Exp $
 PostgreSQL documentation
 -->
 
@@ -280,10 +280,12 @@ SELECT oid FROM pg_am WHERE amname = 'btree';
    <classname>pg_opclass</classname>:
 
 <programlisting>
-INSERT INTO pg_opclass (opcamid, opcname, opcintype, opcdefault, opckeytype)
+INSERT INTO pg_opclass (opcamid, opcname, opcnamespace, opcowner, opcintype, opcdefault, opckeytype)
     VALUES (
         (SELECT oid FROM pg_am WHERE amname = 'btree'),
         'complex_abs_ops',
+        (SELECT oid FROM pg_namespace WHERE nspname = 'pg_catalog'),
+        1,	-- UID of superuser is hardwired to 1 as of PG 7.3
         (SELECT oid FROM pg_type WHERE typname = 'complex'),
         true,
         0);
@@ -292,9 +294,9 @@ SELECT oid, *
     FROM pg_opclass
     WHERE opcname = 'complex_abs_ops';
 
-  oid   | opcamid |     opcname     | opcintype | opcdefault | opckeytype
---------+---------+-----------------+-----------+------------+------------
- 277975 |     403 | complex_abs_ops |    277946 | t          |          0
+  oid   | opcamid |     opcname     | opcnamespace | opcowner | opcintype | opcdefault | opckeytype
+--------+---------+-----------------+--------------+----------+-----------+------------+------------
+ 277975 |     403 | complex_abs_ops |           11 |        1 |    277946 | t          |          0
 (1 row)
 </programlisting>
 
diff --git a/src/backend/access/index/indexam.c b/src/backend/access/index/indexam.c
index ea043afb341c2925d72b8969fbba55a47b8a6541..ce2c8e62f45cd7b3134f299c5915decd515101f2 100644
--- a/src/backend/access/index/indexam.c
+++ b/src/backend/access/index/indexam.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/access/index/indexam.c,v 1.56 2002/03/26 19:15:14 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/access/index/indexam.c,v 1.57 2002/04/17 20:57:56 tgl Exp $
  *
  * INTERFACE ROUTINES
  *		index_open		- open an index relation by relation OID
@@ -498,10 +498,23 @@ index_getprocinfo(Relation irel,
 	if (locinfo->fn_oid == InvalidOid)
 	{
 		RegProcedure *loc = irel->rd_support;
+		RegProcedure procId;
 
 		Assert(loc != NULL);
 
-		fmgr_info_cxt(loc[procindex], locinfo, irel->rd_indexcxt);
+		procId = loc[procindex];
+
+		/*
+		 * Complain if function was not found during IndexSupportInitialize.
+		 * This should not happen unless the system tables contain bogus
+		 * entries for the index opclass.  (If an AM wants to allow a
+		 * support function to be optional, it can use index_getprocid.)
+		 */
+		if (!RegProcedureIsValid(procId))
+			elog(ERROR, "Missing support function %d for attribute %d of index %s",
+				 procnum, attnum, RelationGetRelationName(irel));
+
+		fmgr_info_cxt(procId, locinfo, irel->rd_indexcxt);
 	}
 
 	return locinfo;
diff --git a/src/backend/bootstrap/bootparse.y b/src/backend/bootstrap/bootparse.y
index b5d039f9355ef63831e56edcf35786f811afee7c..e98eae3a423fffeeb28d539ec2e378f05a862d09 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.44 2002/04/09 20:35:46 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/bootstrap/bootparse.y,v 1.45 2002/04/17 20:57:56 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -273,7 +273,7 @@ boot_index_param:
 					IndexElem *n = makeNode(IndexElem);
 					n->name = LexIDStr($1);
 					n->funcname = n->args = NIL; /* no func indexes */
-					n->class = LexIDStr($2);
+					n->opclass = makeList1(makeString(LexIDStr($2)));
 					$$ = n;
 				}
 		;
diff --git a/src/backend/catalog/indexing.c b/src/backend/catalog/indexing.c
index 7bfede27b5ce77a407bf2f9686680a80ec76f5d1..203df67f628edf35dae10d0fa8157dd983a83a83 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.89 2002/04/16 23:08:10 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/catalog/indexing.c,v 1.90 2002/04/17 20:57:56 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -60,7 +60,7 @@ char	   *Name_pg_largeobject_indices[Num_pg_largeobject_indices] =
 char	   *Name_pg_namespace_indices[Num_pg_namespace_indices] =
 {NamespaceNameIndex, NamespaceOidIndex};
 char	   *Name_pg_opclass_indices[Num_pg_opclass_indices] =
-{OpclassAmNameIndex, OpclassOidIndex};
+{OpclassAmNameNspIndex, OpclassOidIndex};
 char	   *Name_pg_operator_indices[Num_pg_operator_indices] =
 {OperatorOidIndex, OperatorNameNspIndex};
 char	   *Name_pg_proc_indices[Num_pg_proc_indices] =
diff --git a/src/backend/catalog/namespace.c b/src/backend/catalog/namespace.c
index 15fdb01ed31cec5296a05492cf87b304464e6ed9..0a3aefeaf0fa0b483b92fa8ccf803245fdcace86 100644
--- a/src/backend/catalog/namespace.c
+++ b/src/backend/catalog/namespace.c
@@ -13,7 +13,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/catalog/namespace.c,v 1.10 2002/04/16 23:08:10 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/catalog/namespace.c,v 1.11 2002/04/17 20:57:56 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -27,6 +27,7 @@
 #include "catalog/namespace.h"
 #include "catalog/pg_inherits.h"
 #include "catalog/pg_namespace.h"
+#include "catalog/pg_opclass.h"
 #include "catalog/pg_operator.h"
 #include "catalog/pg_proc.h"
 #include "catalog/pg_shadow.h"
@@ -311,6 +312,54 @@ TypenameGetTypid(const char *typname)
 	return InvalidOid;
 }
 
+/*
+ * OpclassnameGetOpcid
+ *		Try to resolve an unqualified index opclass name.
+ *		Returns OID if opclass found in search path, else InvalidOid.
+ *
+ * This is essentially the same as TypenameGetTypid, but we have to have
+ * an extra argument for the index AM OID.
+ */
+Oid
+OpclassnameGetOpcid(Oid amid, const char *opcname)
+{
+	Oid			opcid;
+	List	   *lptr;
+
+	/*
+	 * If system namespace is not in path, implicitly search it before path
+	 */
+	if (!pathContainsSystemNamespace)
+	{
+		opcid = GetSysCacheOid(CLAAMNAMENSP,
+							   ObjectIdGetDatum(amid),
+							   PointerGetDatum(opcname),
+							   ObjectIdGetDatum(PG_CATALOG_NAMESPACE),
+							   0);
+		if (OidIsValid(opcid))
+			return opcid;
+	}
+
+	/*
+	 * Else search the path
+	 */
+	foreach(lptr, namespaceSearchPath)
+	{
+		Oid			namespaceId = (Oid) lfirsti(lptr);
+
+		opcid = GetSysCacheOid(CLAAMNAMENSP,
+							   ObjectIdGetDatum(amid),
+							   PointerGetDatum(opcname),
+							   ObjectIdGetDatum(namespaceId),
+							   0);
+		if (OidIsValid(opcid))
+			return opcid;
+	}
+
+	/* Not found in path */
+	return InvalidOid;
+}
+
 /*
  * FuncnameGetCandidates
  *		Given a possibly-qualified function name and argument count,
@@ -652,6 +701,123 @@ OpernameGetCandidates(List *names, char oprkind)
 	return resultList;
 }
 
+/*
+ * OpclassGetCandidates
+ *		Given an index access method OID, retrieve a list of all the
+ *		opclasses for that AM that are visible in the search path.
+ *
+ * NOTE: the opcname_tmp field in the returned structs should not be used
+ * by callers, because it points at syscache entries that we release at
+ * the end of this routine.  If any callers needed the name information,
+ * we could pstrdup() the names ... but at present it'd be wasteful.
+ */
+OpclassCandidateList
+OpclassGetCandidates(Oid amid)
+{
+	OpclassCandidateList resultList = NULL;
+	CatCList   *catlist;
+	int			i;
+
+	/* Search syscache by AM OID only */
+	catlist = SearchSysCacheList(CLAAMNAMENSP, 1,
+								 ObjectIdGetDatum(amid),
+								 0, 0, 0);
+
+	for (i = 0; i < catlist->n_members; i++)
+	{
+		HeapTuple	opctup = &catlist->members[i]->tuple;
+		Form_pg_opclass opcform = (Form_pg_opclass) GETSTRUCT(opctup);
+		int			pathpos = 0;
+		OpclassCandidateList newResult;
+
+		/* Consider only opclasses that are in the search path */
+		if (pathContainsSystemNamespace ||
+			!IsSystemNamespace(opcform->opcnamespace))
+		{
+			List	   *nsp;
+
+			foreach(nsp, namespaceSearchPath)
+			{
+				pathpos++;
+				if (opcform->opcnamespace == (Oid) lfirsti(nsp))
+					break;
+			}
+			if (nsp == NIL)
+				continue;		/* opclass is not in search path */
+		}
+
+		/*
+		 * Okay, it's in the search path, but does it have the same name
+		 * as something we already accepted?  If so, keep
+		 * only the one that appears earlier in the search path.
+		 *
+		 * If we have an ordered list from SearchSysCacheList (the
+		 * normal case), then any conflicting opclass must immediately
+		 * adjoin this one in the list, so we only need to look at
+		 * the newest result item.  If we have an unordered list,
+		 * we have to scan the whole result list.
+		 */
+		if (resultList)
+		{
+			OpclassCandidateList	prevResult;
+
+			if (catlist->ordered)
+			{
+				if (strcmp(NameStr(opcform->opcname),
+						   resultList->opcname_tmp) == 0)
+					prevResult = resultList;
+				else
+					prevResult = NULL;
+			}
+			else
+			{
+				for (prevResult = resultList;
+					 prevResult;
+					 prevResult = prevResult->next)
+				{
+					if (strcmp(NameStr(opcform->opcname),
+							   prevResult->opcname_tmp) == 0)
+						break;
+				}
+			}
+			if (prevResult)
+			{
+				/* We have a match with a previous result */
+				Assert(pathpos != prevResult->pathpos);
+				if (pathpos > prevResult->pathpos)
+					continue; /* keep previous result */
+				/* replace previous result */
+				prevResult->opcname_tmp = NameStr(opcform->opcname);
+				prevResult->pathpos = pathpos;
+				prevResult->oid = opctup->t_data->t_oid;
+				prevResult->opcintype = opcform->opcintype;
+				prevResult->opcdefault = opcform->opcdefault;
+				prevResult->opckeytype = opcform->opckeytype;
+				continue;
+			}
+		}
+
+		/*
+		 * Okay to add it to result list
+		 */
+		newResult = (OpclassCandidateList)
+			palloc(sizeof(struct _OpclassCandidateList));
+		newResult->opcname_tmp = NameStr(opcform->opcname);
+		newResult->pathpos = pathpos;
+		newResult->oid = opctup->t_data->t_oid;
+		newResult->opcintype = opcform->opcintype;
+		newResult->opcdefault = opcform->opcdefault;
+		newResult->opckeytype = opcform->opckeytype;
+		newResult->next = resultList;
+		resultList = newResult;
+	}
+
+	ReleaseSysCacheList(catlist);
+
+	return resultList;
+}
+
+
 /*
  * QualifiedNameGetCreationNamespace
  *		Given a possibly-qualified name for an object (in List-of-Values
diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index 297d5e726633576c1ad5d30ba724986b0536162e..14889a4f0c30b1ea5cebeb7aa512dcea682d594e 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.70 2002/04/12 20:38:22 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.71 2002/04/17 20:57:56 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -31,7 +31,6 @@
 #include "parser/parse_coerce.h"
 #include "parser/parse_func.h"
 #include "utils/builtins.h"
-#include "utils/fmgroids.h"
 #include "utils/lsyscache.h"
 #include "utils/syscache.h"
 
@@ -390,11 +389,14 @@ static Oid
 GetAttrOpClass(IndexElem *attribute, Oid attrType,
 			   char *accessMethodName, Oid accessMethodId)
 {
+	char	   *catalogname;
+	char	   *schemaname = NULL;
+	char	   *opcname = NULL;
 	HeapTuple	tuple;
 	Oid			opClassId,
 				opInputType;
 
-	if (attribute->class == NULL)
+	if (attribute->opclass == NIL)
 	{
 		/* no operator class specified, so find the default */
 		opClassId = GetDefaultOpClass(attrType, accessMethodId);
@@ -407,23 +409,79 @@ GetAttrOpClass(IndexElem *attribute, Oid attrType,
 	}
 
 	/*
-	 * Find the index operator class and verify that it accepts this
-	 * datatype.  Note we will accept binary compatibility.
+	 * Specific opclass name given, so look up the opclass.
 	 */
-	tuple = SearchSysCache(CLAAMNAME,
-						   ObjectIdGetDatum(accessMethodId),
-						   PointerGetDatum(attribute->class),
-						   0, 0);
+
+	/* deconstruct the name list */
+	switch (length(attribute->opclass))
+	{
+		case 1:
+			opcname = strVal(lfirst(attribute->opclass));
+			break;
+		case 2:
+			schemaname = strVal(lfirst(attribute->opclass));
+			opcname = strVal(lsecond(attribute->opclass));
+			break;
+		case 3:
+			catalogname = strVal(lfirst(attribute->opclass));
+			schemaname = strVal(lsecond(attribute->opclass));
+			opcname = strVal(lfirst(lnext(lnext(attribute->opclass))));
+			/*
+			 * We check the catalog name and then ignore it.
+			 */
+			if (strcmp(catalogname, DatabaseName) != 0)
+				elog(ERROR, "Cross-database references are not implemented");
+			break;
+		default:
+			elog(ERROR, "Improper opclass name (too many dotted names)");
+			break;
+	}
+
+	if (schemaname)
+	{
+		/* Look in specific schema only */
+		Oid		namespaceId;
+
+		namespaceId = GetSysCacheOid(NAMESPACENAME,
+									 CStringGetDatum(schemaname),
+									 0, 0, 0);
+		if (!OidIsValid(namespaceId))
+			elog(ERROR, "Namespace \"%s\" does not exist",
+				 schemaname);
+		tuple = SearchSysCache(CLAAMNAMENSP,
+							   ObjectIdGetDatum(accessMethodId),
+							   PointerGetDatum(opcname),
+							   ObjectIdGetDatum(namespaceId),
+							   0);
+	}
+	else
+	{
+		/* Unqualified opclass name, so search the search path */
+		opClassId = OpclassnameGetOpcid(accessMethodId, opcname);
+		if (!OidIsValid(opClassId))
+			elog(ERROR, "DefineIndex: operator class \"%s\" not supported by access method \"%s\"",
+				 opcname, accessMethodName);
+		tuple = SearchSysCache(CLAOID,
+							   ObjectIdGetDatum(opClassId),
+							   0, 0, 0);
+	}
+
 	if (!HeapTupleIsValid(tuple))
 		elog(ERROR, "DefineIndex: operator class \"%s\" not supported by access method \"%s\"",
-			 attribute->class, accessMethodName);
+			 NameListToString(attribute->opclass), accessMethodName);
+
+	/*
+	 * Verify that the index operator class accepts this
+	 * datatype.  Note we will accept binary compatibility.
+	 */
 	opClassId = tuple->t_data->t_oid;
 	opInputType = ((Form_pg_opclass) GETSTRUCT(tuple))->opcintype;
-	ReleaseSysCache(tuple);
 
 	if (!IsBinaryCompatible(attrType, opInputType))
 		elog(ERROR, "operator class \"%s\" does not accept data type %s",
-			 attribute->class, format_type_be(attrType));
+			 NameListToString(attribute->opclass), format_type_be(attrType));
+
+	ReleaseSysCache(tuple);
 
 	return opClassId;
 }
@@ -431,10 +489,7 @@ GetAttrOpClass(IndexElem *attribute, Oid attrType,
 static Oid
 GetDefaultOpClass(Oid attrType, Oid accessMethodId)
 {
-	Relation	relation;
-	ScanKeyData entry[1];
-	HeapScanDesc scan;
-	HeapTuple	tuple;
+	OpclassCandidateList opclass;
 	int			nexact = 0;
 	int			ncompatible = 0;
 	Oid			exactOid = InvalidOid;
@@ -449,44 +504,32 @@ GetDefaultOpClass(Oid attrType, Oid accessMethodId)
 	 * require the user to specify which one he wants.	If we find more
 	 * than one exact match, then someone put bogus entries in pg_opclass.
 	 *
-	 * We could use an indexscan here, but since pg_opclass is small and a
-	 * scan on opcamid won't be very selective, the indexscan would
-	 * probably actually be slower than heapscan.
+	 * The initial search is done by namespace.c so that we only consider
+	 * opclasses visible in the current namespace search path.
 	 */
-	ScanKeyEntryInitialize(&entry[0], 0x0,
-						   Anum_pg_opclass_opcamid,
-						   F_OIDEQ,
-						   ObjectIdGetDatum(accessMethodId));
-
-	relation = heap_openr(OperatorClassRelationName, AccessShareLock);
-	scan = heap_beginscan(relation, false, SnapshotNow, 1, entry);
-
-	while (HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
+	for (opclass = OpclassGetCandidates(accessMethodId);
+		 opclass != NULL;
+		 opclass = opclass->next)
 	{
-		Form_pg_opclass opclass = (Form_pg_opclass) GETSTRUCT(tuple);
-
 		if (opclass->opcdefault)
 		{
 			if (opclass->opcintype == attrType)
 			{
 				nexact++;
-				exactOid = tuple->t_data->t_oid;
+				exactOid = opclass->oid;
 			}
 			else if (IsBinaryCompatible(opclass->opcintype, attrType))
 			{
 				ncompatible++;
-				compatibleOid = tuple->t_data->t_oid;
+				compatibleOid = opclass->oid;
 			}
 		}
 	}
 
-	heap_endscan(scan);
-	heap_close(relation, AccessShareLock);
-
 	if (nexact == 1)
 		return exactOid;
 	if (nexact != 0)
-		elog(ERROR, "pg_opclass contains multiple default opclasses for data tyype %s",
+		elog(ERROR, "pg_opclass contains multiple default opclasses for data type %s",
 			 format_type_be(attrType));
 	if (ncompatible == 1)
 		return compatibleOid;
diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c
index 40e1dea79e3be7e735e1ddadb8971d448be6246f..8417f7a716c59afc3429e5839336e299fd53f138 100644
--- a/src/backend/nodes/copyfuncs.c
+++ b/src/backend/nodes/copyfuncs.c
@@ -15,7 +15,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.178 2002/04/16 23:08:10 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.179 2002/04/17 20:57:56 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1714,8 +1714,7 @@ _copyIndexElem(IndexElem *from)
 		newnode->name = pstrdup(from->name);
 	Node_Copy(from, newnode, funcname);
 	Node_Copy(from, newnode, args);
-	if (from->class)
-		newnode->class = pstrdup(from->class);
+	Node_Copy(from, newnode, opclass);
 
 	return newnode;
 }
diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c
index 245d72fc01445cfff63098d6ed7685ad8b608823..58f6b5a5d6353aa7c2cd6297053cbd5d352747f0 100644
--- a/src/backend/nodes/equalfuncs.c
+++ b/src/backend/nodes/equalfuncs.c
@@ -20,7 +20,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.126 2002/04/16 23:08:10 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.127 2002/04/17 20:57:56 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1599,7 +1599,7 @@ _equalIndexElem(IndexElem *a, IndexElem *b)
 		return false;
 	if (!equal(a->args, b->args))
 		return false;
-	if (!equalstr(a->class, b->class))
+	if (!equal(a->opclass, b->opclass))
 		return false;
 
 	return true;
diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c
index 65a501c429a832ab1559151811eb1c290b07c698..24238565d55c2bd2fba2ba90edbe57d407537475 100644
--- a/src/backend/nodes/outfuncs.c
+++ b/src/backend/nodes/outfuncs.c
@@ -5,7 +5,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/nodes/outfuncs.c,v 1.155 2002/04/16 23:08:10 tgl Exp $
+ *	$Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.156 2002/04/17 20:57:56 tgl Exp $
  *
  * NOTES
  *	  Every (plan) node in POSTGRES has an associated "out" routine which
@@ -217,8 +217,8 @@ _outIndexElem(StringInfo str, IndexElem *node)
 	_outNode(str, node->funcname);
 	appendStringInfo(str, " :args ");
 	_outNode(str, node->args);
-	appendStringInfo(str, " :class ");
-	_outToken(str, node->class);
+	appendStringInfo(str, " :opclass ");
+	_outNode(str, node->opclass);
 }
 
 static void
diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c
index 6a68adfff375d45e6fa5d8b27bd542638da09e59..b3b8859d12623a3731d9771859e0ed8c8d699944 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.230 2002/04/16 23:08:11 tgl Exp $
+ *	$Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.231 2002/04/17 20:57:56 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1209,7 +1209,7 @@ transformIndexConstraints(ParseState *pstate, CreateStmtContext *cxt)
 			iparam->name = pstrdup(key->name);
 			iparam->funcname = NIL;
 			iparam->args = NIL;
-			iparam->class = NULL;
+			iparam->opclass = NIL;
 			index->indexParams = lappend(index->indexParams, iparam);
 		}
 
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 26b1be11d821795c5200f41cedea8d65e7d55036..774f9fa743cbcbed648c72541d9da042805883c8 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -11,7 +11,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.302 2002/04/16 23:08:11 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.303 2002/04/17 20:57:56 tgl Exp $
  *
  * HISTORY
  *	  AUTHOR			DATE			MAJOR EVENT
@@ -174,15 +174,15 @@ static bool set_name_needs_quotes(const char *name);
 
 %type <str>		relation_name, copy_file_name, copy_delimiter, copy_null,
 		database_name, access_method_clause, access_method, attr_name,
-		class, index_name, name, function_name, file_name
+		index_name, name, function_name, file_name
 
-%type <list>	func_name, handler_name, qual_Op, qual_all_Op, OptUseOp
+%type <list>	func_name, handler_name, qual_Op, qual_all_Op, OptUseOp,
+		opt_class
 
 %type <range>	qualified_name, OptConstrFromTable
 
 %type <str>		opt_id,
-		all_Op, MathOp, opt_name,
-		opt_class, SpecialRuleRelation
+		all_Op, MathOp, opt_name, SpecialRuleRelation
 
 %type <str>		opt_level, opt_encoding
 %type <node>	grantee
@@ -2614,7 +2614,7 @@ func_index:  func_name '(' name_list ')' opt_class
 					$$->name = NULL;
 					$$->funcname = $1;
 					$$->args = $3;
-					$$->class = $5;
+					$$->opclass = $5;
 				}
 		  ;
 
@@ -2624,11 +2624,11 @@ index_elem:  attr_name opt_class
 					$$->name = $1;
 					$$->funcname = NIL;
 					$$->args = NIL;
-					$$->class = $2;
+					$$->opclass = $2;
 				}
 		;
 
-opt_class:  class
+opt_class:  any_name
 				{
 					/*
 					 * Release 7.0 removed network_ops, timespan_ops, and
@@ -2643,17 +2643,24 @@ opt_class:  class
 					 * so suppress that too for awhile.  I'm starting to
 					 * think we need a better approach.  tgl 2000/10/01
 					 */
-					if (strcmp($1, "network_ops") != 0 &&
-						strcmp($1, "timespan_ops") != 0 &&
-						strcmp($1, "datetime_ops") != 0 &&
-						strcmp($1, "lztext_ops") != 0 &&
-						strcmp($1, "timestamp_ops") != 0)
-						$$ = $1;
+					if (length($1) == 1)
+					{
+						char   *claname = strVal(lfirst($1));
+
+						if (strcmp(claname, "network_ops") != 0 &&
+							strcmp(claname, "timespan_ops") != 0 &&
+							strcmp(claname, "datetime_ops") != 0 &&
+							strcmp(claname, "lztext_ops") != 0 &&
+							strcmp(claname, "timestamp_ops") != 0)
+							$$ = $1;
+						else
+							$$ = NIL;
+					}
 					else
-						$$ = NULL;
+						$$ = $1;
 				}
-		| USING class							{ $$ = $2; }
-		| /*EMPTY*/								{ $$ = NULL; }
+		| USING any_name						{ $$ = $2; }
+		| /*EMPTY*/								{ $$ = NIL; }
 		;
 
 /*****************************************************************************
@@ -5782,7 +5789,6 @@ name:					ColId			{ $$ = $1; };
 database_name:			ColId			{ $$ = $1; };
 access_method:			ColId			{ $$ = $1; };
 attr_name:				ColId			{ $$ = $1; };
-class:					ColId			{ $$ = $1; };
 index_name:				ColId			{ $$ = $1; };
 file_name:				Sconst			{ $$ = $1; };
 
diff --git a/src/backend/utils/cache/syscache.c b/src/backend/utils/cache/syscache.c
index 720d19225c6b597cb4d303be009fc9cfed250c1c..5deea860897597358751efdb40cb07b3be8f2e62 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.77 2002/04/16 23:08:11 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/cache/syscache.c,v 1.78 2002/04/17 20:57:56 tgl Exp $
  *
  * NOTES
  *	  These routines allow the parser/planner/executor to perform
@@ -173,14 +173,14 @@ static const struct cachedesc cacheinfo[] = {
 			0,
 			0
 	}},
-	{OperatorClassRelationName, /* CLAAMNAME */
-		OpclassAmNameIndex,
+	{OperatorClassRelationName, /* CLAAMNAMENSP */
+		OpclassAmNameNspIndex,
 		0,
-		2,
+		3,
 		{
 			Anum_pg_opclass_opcamid,
 			Anum_pg_opclass_opcname,
-			0,
+			Anum_pg_opclass_opcnamespace,
 			0
 	}},
 	{OperatorClassRelationName, /* CLAOID */
diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h
index 4b0d011b3d6b49c751fe810669f4541a74e23cda..492c3e9b3fe1a0a2255b377f9bc38c651335c59f 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.116 2002/04/16 23:08:11 tgl Exp $
+ * $Id: catversion.h,v 1.117 2002/04/17 20:57:56 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -53,6 +53,6 @@
  */
 
 /*							yyyymmddN */
-#define CATALOG_VERSION_NO	200204161
+#define CATALOG_VERSION_NO	200204171
 
 #endif
diff --git a/src/include/catalog/indexing.h b/src/include/catalog/indexing.h
index 4ca83c5427385bdf33cafb40cac816de1196e1f8..b2b3f1f39c718ab335e58a309abb0f8cdeb6e6cb 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.63 2002/04/16 23:08:11 tgl Exp $
+ * $Id: indexing.h,v 1.64 2002/04/17 20:57:56 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -72,7 +72,7 @@
 #define LargeObjectLOidPNIndex		"pg_largeobject_loid_pn_index"
 #define NamespaceNameIndex			"pg_namespace_nspname_index"
 #define NamespaceOidIndex			"pg_namespace_oid_index"
-#define OpclassAmNameIndex			"pg_opclass_am_name_index"
+#define OpclassAmNameNspIndex		"pg_opclass_am_name_nsp_index"
 #define OpclassOidIndex				"pg_opclass_oid_index"
 #define OperatorNameNspIndex		"pg_operator_oprname_l_r_n_index"
 #define OperatorOidIndex			"pg_operator_oid_index"
@@ -169,7 +169,7 @@ DECLARE_UNIQUE_INDEX(pg_language_oid_index on pg_language using btree(oid oid_op
 DECLARE_UNIQUE_INDEX(pg_largeobject_loid_pn_index on pg_largeobject using btree(loid oid_ops, pageno int4_ops));
 DECLARE_UNIQUE_INDEX(pg_namespace_nspname_index on pg_namespace using btree(nspname name_ops));
 DECLARE_UNIQUE_INDEX(pg_namespace_oid_index on pg_namespace using btree(oid oid_ops));
-DECLARE_UNIQUE_INDEX(pg_opclass_am_name_index on pg_opclass using btree(opcamid oid_ops, opcname name_ops));
+DECLARE_UNIQUE_INDEX(pg_opclass_am_name_nsp_index on pg_opclass using btree(opcamid oid_ops, opcname name_ops, opcnamespace oid_ops));
 DECLARE_UNIQUE_INDEX(pg_opclass_oid_index on pg_opclass using btree(oid oid_ops));
 DECLARE_UNIQUE_INDEX(pg_operator_oid_index on pg_operator using btree(oid oid_ops));
 DECLARE_UNIQUE_INDEX(pg_operator_oprname_l_r_n_index on pg_operator using btree(oprname name_ops, oprleft oid_ops, oprright oid_ops, oprnamespace oid_ops));
diff --git a/src/include/catalog/namespace.h b/src/include/catalog/namespace.h
index d69e1da58b7678873b1bdbc1b85c27edcc4931c2..148fc210a889ed7d31df486432884703ae26efd7 100644
--- a/src/include/catalog/namespace.h
+++ b/src/include/catalog/namespace.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: namespace.h,v 1.8 2002/04/16 23:08:11 tgl Exp $
+ * $Id: namespace.h,v 1.9 2002/04/17 20:57:56 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -32,6 +32,21 @@ typedef struct _FuncCandidateList
 	Oid			args[1];		/* arg types --- VARIABLE LENGTH ARRAY */
 } *FuncCandidateList;			/* VARIABLE LENGTH STRUCT */
 
+/*
+ *	This structure holds a list of opclass candidates found by namespace
+ *	lookup.
+ */
+typedef struct _OpclassCandidateList
+{
+	struct _OpclassCandidateList *next;
+	char	   *opcname_tmp;	/* for internal use of namespace lookup */
+	int			pathpos;		/* for internal use of namespace lookup */
+	Oid			oid;			/* the opclass's OID */
+	Oid			opcintype;		/* type of input data for opclass */
+	bool		opcdefault;		/* T if opclass is default for opcintype */
+	Oid			opckeytype;		/* type of index data, or InvalidOid */
+} *OpclassCandidateList;
+
 
 extern Oid	RangeVarGetRelid(const RangeVar *relation, bool failOK);
 
@@ -41,10 +56,14 @@ extern Oid	RelnameGetRelid(const char *relname);
 
 extern Oid	TypenameGetTypid(const char *typname);
 
+extern Oid	OpclassnameGetOpcid(Oid amid, const char *opcname);
+
 extern FuncCandidateList FuncnameGetCandidates(List *names, int nargs);
 
 extern FuncCandidateList OpernameGetCandidates(List *names, char oprkind);
 
+extern OpclassCandidateList OpclassGetCandidates(Oid amid);
+
 extern Oid	QualifiedNameGetCreationNamespace(List *names, char **objname_p);
 
 extern RangeVar *makeRangeVarFromNameList(List *names);
diff --git a/src/include/catalog/pg_opclass.h b/src/include/catalog/pg_opclass.h
index 2e25e366c64a421dcea784b02b9d302c27d1f7d3..edb29267d6266ef018a0f883ece38c6f89cd1f34 100644
--- a/src/include/catalog/pg_opclass.h
+++ b/src/include/catalog/pg_opclass.h
@@ -26,7 +26,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pg_opclass.h,v 1.43 2001/11/05 17:46:32 momjian Exp $
+ * $Id: pg_opclass.h,v 1.44 2002/04/17 20:57:56 tgl Exp $
  *
  * NOTES
  *	  the genbki.sh script reads this file and generates .bki
@@ -54,6 +54,8 @@ CATALOG(pg_opclass)
 {
 	Oid			opcamid;		/* index access method opclass is for */
 	NameData	opcname;		/* name of this opclass */
+	Oid			opcnamespace;	/* namespace of this opclass */
+	int4		opcowner;		/* opclass owner */
 	Oid			opcintype;		/* type of input data for opclass */
 	bool		opcdefault;		/* T if opclass is default for opcintype */
 	Oid			opckeytype;		/* type of index data, or InvalidOid */
@@ -70,71 +72,73 @@ typedef FormData_pg_opclass *Form_pg_opclass;
  *		compiler constants for pg_opclass
  * ----------------
  */
-#define Natts_pg_opclass				5
+#define Natts_pg_opclass				7
 #define Anum_pg_opclass_opcamid			1
 #define Anum_pg_opclass_opcname			2
-#define Anum_pg_opclass_opcintype		3
-#define Anum_pg_opclass_opcdefault		4
-#define Anum_pg_opclass_opckeytype		5
+#define Anum_pg_opclass_opcnamespace	3
+#define Anum_pg_opclass_opcowner		4
+#define Anum_pg_opclass_opcintype		5
+#define Anum_pg_opclass_opcdefault		6
+#define Anum_pg_opclass_opckeytype		7
 
 /* ----------------
  *		initial contents of pg_opclass
  * ----------------
  */
 
-DATA(insert OID =  421 (	403		abstime_ops		 702	t	0 ));
-DATA(insert OID =  422 (	402		bigbox_ops		 603	f	0 ));
-DATA(insert OID =  423 (	403		bit_ops			1560	t	0 ));
-DATA(insert OID =  424 (	403		bool_ops		  16	t	0 ));
-DATA(insert OID =  425 (	402		box_ops			 603	t	0 ));
-DATA(insert OID =  426 (	403		bpchar_ops		1042	t	0 ));
-DATA(insert OID =  427 (	405		bpchar_ops		1042	t	0 ));
-DATA(insert OID =  428 (	403		bytea_ops		  17	t	0 ));
-DATA(insert OID =  429 (	403		char_ops		  18	t	0 ));
-DATA(insert OID =  431 (	405		char_ops		  18	t	0 ));
-DATA(insert OID =  432 (	403		cidr_ops		 650	t	0 ));
-DATA(insert OID =  433 (	405		cidr_ops		 650	t	0 ));
-DATA(insert OID =  434 (	403		date_ops		1082	t	0 ));
-DATA(insert OID =  435 (	405		date_ops		1082	t	0 ));
-DATA(insert OID = 1970 (	403		float4_ops		 700	t	0 ));
-DATA(insert OID = 1971 (	405		float4_ops		 700	t	0 ));
-DATA(insert OID = 1972 (	403		float8_ops		 701	t	0 ));
-DATA(insert OID = 1973 (	405		float8_ops		 701	t	0 ));
-DATA(insert OID = 1974 (	403		inet_ops		 869	t	0 ));
-DATA(insert OID = 1975 (	405		inet_ops		 869	t	0 ));
-DATA(insert OID = 1976 (	403		int2_ops		  21	t	0 ));
+DATA(insert OID =  421 (	403		abstime_ops		PGNSP PGUID  702 t 0 ));
+DATA(insert OID =  422 (	402		bigbox_ops		PGNSP PGUID  603 f 0 ));
+DATA(insert OID =  423 (	403		bit_ops			PGNSP PGUID 1560 t 0 ));
+DATA(insert OID =  424 (	403		bool_ops		PGNSP PGUID   16 t 0 ));
+DATA(insert OID =  425 (	402		box_ops			PGNSP PGUID  603 t 0 ));
+DATA(insert OID =  426 (	403		bpchar_ops		PGNSP PGUID 1042 t 0 ));
+DATA(insert OID =  427 (	405		bpchar_ops		PGNSP PGUID 1042 t 0 ));
+DATA(insert OID =  428 (	403		bytea_ops		PGNSP PGUID   17 t 0 ));
+DATA(insert OID =  429 (	403		char_ops		PGNSP PGUID   18 t 0 ));
+DATA(insert OID =  431 (	405		char_ops		PGNSP PGUID   18 t 0 ));
+DATA(insert OID =  432 (	403		cidr_ops		PGNSP PGUID  650 t 0 ));
+DATA(insert OID =  433 (	405		cidr_ops		PGNSP PGUID  650 t 0 ));
+DATA(insert OID =  434 (	403		date_ops		PGNSP PGUID 1082 t 0 ));
+DATA(insert OID =  435 (	405		date_ops		PGNSP PGUID 1082 t 0 ));
+DATA(insert OID = 1970 (	403		float4_ops		PGNSP PGUID  700 t 0 ));
+DATA(insert OID = 1971 (	405		float4_ops		PGNSP PGUID  700 t 0 ));
+DATA(insert OID = 1972 (	403		float8_ops		PGNSP PGUID  701 t 0 ));
+DATA(insert OID = 1973 (	405		float8_ops		PGNSP PGUID  701 t 0 ));
+DATA(insert OID = 1974 (	403		inet_ops		PGNSP PGUID  869 t 0 ));
+DATA(insert OID = 1975 (	405		inet_ops		PGNSP PGUID  869 t 0 ));
+DATA(insert OID = 1976 (	403		int2_ops		PGNSP PGUID   21 t 0 ));
 #define INT2_BTREE_OPS_OID 1976
-DATA(insert OID = 1977 (	405		int2_ops		  21	t	0 ));
-DATA(insert OID = 1978 (	403		int4_ops		  23	t	0 ));
+DATA(insert OID = 1977 (	405		int2_ops		PGNSP PGUID   21 t 0 ));
+DATA(insert OID = 1978 (	403		int4_ops		PGNSP PGUID   23 t 0 ));
 #define INT4_BTREE_OPS_OID 1978
-DATA(insert OID = 1979 (	405		int4_ops		  23	t	0 ));
-DATA(insert OID = 1980 (	403		int8_ops		  20	t	0 ));
-DATA(insert OID = 1981 (	405		int8_ops		  20	t	0 ));
-DATA(insert OID = 1982 (	403		interval_ops	1186	t	0 ));
-DATA(insert OID = 1983 (	405		interval_ops	1186	t	0 ));
-DATA(insert OID = 1984 (	403		macaddr_ops		 829	t	0 ));
-DATA(insert OID = 1985 (	405		macaddr_ops		 829	t	0 ));
-DATA(insert OID = 1986 (	403		name_ops		  19	t	0 ));
-DATA(insert OID = 1987 (	405		name_ops		  19	t	0 ));
-DATA(insert OID = 1988 (	403		numeric_ops		1700	t	0 ));
-DATA(insert OID = 1989 (	403		oid_ops			  26	t	0 ));
+DATA(insert OID = 1979 (	405		int4_ops		PGNSP PGUID   23 t 0 ));
+DATA(insert OID = 1980 (	403		int8_ops		PGNSP PGUID   20 t 0 ));
+DATA(insert OID = 1981 (	405		int8_ops		PGNSP PGUID   20 t 0 ));
+DATA(insert OID = 1982 (	403		interval_ops	PGNSP PGUID 1186 t 0 ));
+DATA(insert OID = 1983 (	405		interval_ops	PGNSP PGUID 1186 t 0 ));
+DATA(insert OID = 1984 (	403		macaddr_ops		PGNSP PGUID  829 t 0 ));
+DATA(insert OID = 1985 (	405		macaddr_ops		PGNSP PGUID  829 t 0 ));
+DATA(insert OID = 1986 (	403		name_ops		PGNSP PGUID   19 t 0 ));
+DATA(insert OID = 1987 (	405		name_ops		PGNSP PGUID   19 t 0 ));
+DATA(insert OID = 1988 (	403		numeric_ops		PGNSP PGUID 1700 t 0 ));
+DATA(insert OID = 1989 (	403		oid_ops			PGNSP PGUID   26 t 0 ));
 #define OID_BTREE_OPS_OID 1989
-DATA(insert OID = 1990 (	405		oid_ops			  26	t	0 ));
-DATA(insert OID = 1991 (	403		oidvector_ops	  30	t	0 ));
-DATA(insert OID = 1992 (	405		oidvector_ops	  30	t	0 ));
-DATA(insert OID = 1993 (	402		poly_ops		 604	t	0 ));
-DATA(insert OID = 1994 (	403		text_ops		  25	t	0 ));
-DATA(insert OID = 1995 (	405		text_ops		  25	t	0 ));
-DATA(insert OID = 1996 (	403		time_ops		1083	t	0 ));
-DATA(insert OID = 1997 (	405		time_ops		1083	t	0 ));
-DATA(insert OID = 1998 (	403		timestamptz_ops 1184	t	0 ));
-DATA(insert OID = 1999 (	405		timestamptz_ops 1184	t	0 ));
-DATA(insert OID = 2000 (	403		timetz_ops		1266	t	0 ));
-DATA(insert OID = 2001 (	405		timetz_ops		1266	t	0 ));
-DATA(insert OID = 2002 (	403		varbit_ops		1562	t	0 ));
-DATA(insert OID = 2003 (	403		varchar_ops		1043	t	0 ));
-DATA(insert OID = 2004 (	405		varchar_ops		1043	t	0 ));
-DATA(insert OID = 2039 (	403		timestamp_ops	1114	t	0 ));
-DATA(insert OID = 2040 (	405		timestamp_ops	1114	t	0 ));
+DATA(insert OID = 1990 (	405		oid_ops			PGNSP PGUID   26 t 0 ));
+DATA(insert OID = 1991 (	403		oidvector_ops	PGNSP PGUID   30 t 0 ));
+DATA(insert OID = 1992 (	405		oidvector_ops	PGNSP PGUID   30 t 0 ));
+DATA(insert OID = 1993 (	402		poly_ops		PGNSP PGUID  604 t 0 ));
+DATA(insert OID = 1994 (	403		text_ops		PGNSP PGUID   25 t 0 ));
+DATA(insert OID = 1995 (	405		text_ops		PGNSP PGUID   25 t 0 ));
+DATA(insert OID = 1996 (	403		time_ops		PGNSP PGUID 1083 t 0 ));
+DATA(insert OID = 1997 (	405		time_ops		PGNSP PGUID 1083 t 0 ));
+DATA(insert OID = 1998 (	403		timestamptz_ops	PGNSP PGUID 1184 t 0 ));
+DATA(insert OID = 1999 (	405		timestamptz_ops	PGNSP PGUID 1184 t 0 ));
+DATA(insert OID = 2000 (	403		timetz_ops		PGNSP PGUID 1266 t 0 ));
+DATA(insert OID = 2001 (	405		timetz_ops		PGNSP PGUID 1266 t 0 ));
+DATA(insert OID = 2002 (	403		varbit_ops		PGNSP PGUID 1562 t 0 ));
+DATA(insert OID = 2003 (	403		varchar_ops		PGNSP PGUID 1043 t 0 ));
+DATA(insert OID = 2004 (	405		varchar_ops		PGNSP PGUID 1043 t 0 ));
+DATA(insert OID = 2039 (	403		timestamp_ops	PGNSP PGUID 1114 t 0 ));
+DATA(insert OID = 2040 (	405		timestamp_ops	PGNSP PGUID 1114 t 0 ));
 
 #endif   /* PG_OPCLASS_H */
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index 7fe606825e40c4545a836f4c55af68c9c9273387..ba9ed9aa8de14e18343f5319ce4261a9519ff90a 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.170 2002/04/16 23:08:12 tgl Exp $
+ * $Id: parsenodes.h,v 1.171 2002/04/17 20:57:57 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -401,7 +401,7 @@ typedef struct IndexElem
 	char	   *name;			/* name of attribute to index, or NULL */
 	List	   *funcname;		/* qualified name of function */
 	List	   *args;			/* list of names of function arguments */
-	char	   *class;			/* name of desired opclass; NULL = default */
+	List	   *opclass;		/* name of desired opclass; NIL = default */
 } IndexElem;
 
 /*
diff --git a/src/include/utils/syscache.h b/src/include/utils/syscache.h
index e567a8b22b67bf99ab4f0f7cd5b41fcc96b10853..dbe50b37be63045b5b9edf1fa8f676fdacce0333 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.45 2002/04/16 23:08:12 tgl Exp $
+ * $Id: syscache.h,v 1.46 2002/04/17 20:57:57 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -36,7 +36,7 @@
 #define AMPROCNUM		5
 #define ATTNAME			6
 #define ATTNUM			7
-#define CLAAMNAME		8
+#define CLAAMNAMENSP	8
 #define CLAOID			9
 #define GRONAME			10
 #define GROSYSID		11
diff --git a/src/tutorial/complex.source b/src/tutorial/complex.source
index c30e048f3cb22777ebc18108f4ce183c643c5f94..6fbaaf89dbd98590f109539e3f849b746ab33374 100644
--- a/src/tutorial/complex.source
+++ b/src/tutorial/complex.source
@@ -7,7 +7,7 @@
 --
 -- Copyright (c) 1994, Regents of the University of California
 --
--- $Id: complex.source,v 1.11 2001/10/26 20:45:33 tgl Exp $
+-- $Id: complex.source,v 1.12 2002/04/17 20:57:57 tgl Exp $
 --
 ---------------------------------------------------------------------------
 
@@ -170,10 +170,12 @@ CREATE OPERATOR > (
    restrict = scalargtsel, join = scalargtjoinsel
 );
 
-INSERT INTO pg_opclass (opcamid, opcname, opcintype, opcdefault, opckeytype)
+INSERT INTO pg_opclass (opcamid, opcname, opcnamespace, opcowner, opcintype, opcdefault, opckeytype)
     VALUES (
         (SELECT oid FROM pg_am WHERE amname = 'btree'),
         'complex_abs_ops',
+        (SELECT oid FROM pg_namespace WHERE nspname = 'pg_catalog'),
+        1,	-- UID of superuser is hardwired to 1 as of PG 7.3
         (SELECT oid FROM pg_type WHERE typname = 'complex'),
         true,
         0);