default, but OIDS are removed from many system catalogs that don't need them.
Some interesting side effects: TOAST pointers are 20 bytes not 32 now;
pg_description has a three-column key instead of one.
Bugs fixed in passing: BINARY cursors work again; pg_class.relhaspkey
has some usefulness; pg_dump dumps comments on indexes, rules, and
triggers in a valid order.
initdb forced.
 --  http://www.druid.net/darcy/
 -- 
---  $Header: /cvsroot/pgsql/contrib/chkpass/Attic/chkpass.sql,v 1.1 2001/05/03 12:32:13 darcy Exp $
+--  $Header: /cvsroot/pgsql/contrib/chkpass/Attic/chkpass.sql,v 1.2 2001/08/10 18:57:32 tgl Exp $
 --  best viewed with tabs set to 4
 --  %%PGDIR%% changed to your local directory where modules is
 --
    procedure = ne
 );
 
-INSERT INTO pg_description (objoid, description)
-   SELECT oid, 'password type with checks'
-       FROM pg_type WHERE typname = 'chkpass';
+COMMENT ON TYPE chkpass IS 'password type with checks';
 
 --
 -- eof
 
 Uses pgeasy library.
 
 Run on an empty database, it returns the system join relationships (shown
-below for 7.1).  Note that unexpected matches may indicate bogus entries
+below for 7.2).  Note that unexpected matches may indicate bogus entries
 in system tables --- don't accept a peculiar match without question.
 In particular, a field shown as joining to more than one target table is
-probably messed up.  In 7.1, the *only* field that should join to more
+probably messed up.  In 7.2, the *only* field that should join to more
 than one target is pg_description.objoid.  (Running make_oidjoins_check
 is an easy way to spot fields joining to more than one table, BTW.)
 
 (Ideally we'd just regenerate the script as part of the regression
 tests themselves, but that seems too slow...)
 
-NOTE: in 7.1, make_oidjoins_check produces two bogus join checks, one for
-pg_database.datlastsysoid => pg_description.oid and one for
-pg_class.relfilenode => pg_class.oid.  These are artifacts and should not
+NOTE: in 7.2, make_oidjoins_check produces one bogus join check, for
+pg_class.relfilenode => pg_class.oid.  This is an artifact and should not
 be added to the oidjoins regress test.
 
 ---------------------------------------------------------------------------
 Join pg_aggregate.aggfinaltype => pg_type.oid
 Join pg_am.amgettuple => pg_proc.oid
 Join pg_am.aminsert => pg_proc.oid
-Join pg_am.amdelete => pg_proc.oid
 Join pg_am.ambeginscan => pg_proc.oid
 Join pg_am.amrescan => pg_proc.oid
 Join pg_am.amendscan => pg_proc.oid
 Join pg_am.ammarkpos => pg_proc.oid
 Join pg_am.amrestrpos => pg_proc.oid
 Join pg_am.ambuild => pg_proc.oid
+Join pg_am.ambulkdelete => pg_proc.oid
 Join pg_am.amcostestimate => pg_proc.oid
 Join pg_amop.amopid => pg_am.oid
 Join pg_amop.amopclaid => pg_opclass.oid
 Join pg_class.relam => pg_am.oid
 Join pg_class.reltoastrelid => pg_class.oid
 Join pg_class.reltoastidxid => pg_class.oid
+Join pg_description.classoid => pg_class.oid
 Join pg_index.indexrelid => pg_class.oid
 Join pg_index.indrelid => pg_class.oid
 Join pg_opclass.opcdeftype => pg_type.oid
 Join pg_proc.prorettype => pg_type.oid
 Join pg_rewrite.ev_class => pg_class.oid
 Join pg_statistic.starelid => pg_class.oid
-Join pg_statistic.staop => pg_operator.oid
+Join pg_statistic.staop1 => pg_operator.oid
+Join pg_statistic.staop2 => pg_operator.oid
+Join pg_statistic.staop3 => pg_operator.oid
 Join pg_trigger.tgrelid => pg_class.oid
 Join pg_trigger.tgfoid => pg_proc.oid
 Join pg_type.typrelid => pg_class.oid
 
        FROM pg_class c, pg_attribute a, pg_type t \
        WHERE a.attnum > 0 AND \
              relkind = 'r' AND \
-             relhasrules = 'f' AND \
              (typname = 'oid' OR \
               typname = 'regproc') AND \
              a.attrelid = c.oid AND \
        DECLARE c_relations BINARY CURSOR FOR \
        SELECT relname \
        FROM pg_class c \
-       WHERE relkind = 'r' AND \
-             relhasrules = 'f' \
+       WHERE relkind = 'r' AND relhasoids \
        ORDER BY 1; \
        ");
    doquery("FETCH ALL IN c_relations");
                sprintf(query, "\
                    DECLARE c_matches BINARY CURSOR FOR \
                    SELECT  count(*) \
-                       FROM %s t1, %s t2 \
-                   WHERE t1.%s = t2.oid ", relname, relname2, attname);
+                       FROM \"%s\" t1, \"%s\" t2 \
+                   WHERE t1.\"%s\" = t2.oid ", relname, relname2, attname);
            else
                sprintf(query, "\
                    DECLARE c_matches BINARY CURSOR FOR \
                    SELECT  count(*) \
-                               FROM %s t1, %s t2 \
-                               WHERE RegprocToOid(t1.%s) = t2.oid ", relname, relname2, attname);
+                               FROM \"%s\" t1, \"%s\" t2 \
+                               WHERE RegprocToOid(t1.\"%s\") = t2.oid ", relname, relname2, attname);
 
            doquery(query);
            doquery("FETCH ALL IN c_matches");
 
 #! /bin/sh
 
 # You first run findoidjoins on the template1 database, and send that
-# output into this file to generate a list of SQL statements.
+# output into this script to generate a list of SQL statements.
 
 # NOTE: any field that findoidjoins thinks joins to more than one table
 # will NOT be checked by the output of this script.  You should be
    }
    {
        printf "\
-SELECT oid, %s.%s \n\
+SELECT ctid, %s.%s \n\
 FROM   %s \n\
 WHERE  %s.%s != 0 AND \n\
    NOT EXISTS(SELECT * FROM %s AS t1 WHERE t1.oid = %s.%s);\n",
 
 CREATE FUNCTION _int_contains(_int4, _int4) RETURNS bool
    AS 'MODULE_PATHNAME' LANGUAGE 'c' with (isstrict);
 
-INSERT INTO pg_description (objoid, description)
-   SELECT oid, 'contains'::text
-   FROM pg_proc
-   WHERE proname = '_int_contains'::name;
+COMMENT ON FUNCTION _int_contains(_int4, _int4) IS 'contains';
 
 CREATE FUNCTION _int_contained(_int4, _int4) RETURNS bool
    AS 'MODULE_PATHNAME' LANGUAGE 'c' with (isstrict);
 
-INSERT INTO pg_description (objoid, description)
-   SELECT oid, 'contained in'::text
-   FROM pg_proc
-   WHERE proname = '_int_contained'::name;
+COMMENT ON FUNCTION _int_contained(_int4, _int4) IS 'contained in';
 
 CREATE FUNCTION _int_overlap(_int4, _int4) RETURNS bool
    AS 'MODULE_PATHNAME' LANGUAGE 'c' with (isstrict);
 
-INSERT INTO pg_description (objoid, description)
-   SELECT oid, 'overlaps'::text
-   FROM pg_proc
-   WHERE proname = '_int_overlap'::name;
+COMMENT ON FUNCTION _int_overlap(_int4, _int4) IS 'overlaps';
 
 CREATE FUNCTION _int_same(_int4, _int4) RETURNS bool
    AS 'MODULE_PATHNAME' LANGUAGE 'c' with (isstrict);
 
-INSERT INTO pg_description (objoid, description)
-   SELECT oid, 'same as'::text
-   FROM pg_proc
-   WHERE proname = '_int_same'::name;
+COMMENT ON FUNCTION _int_same(_int4, _int4) IS 'same as';
 
 CREATE FUNCTION _int_different(_int4, _int4) RETURNS bool
    AS 'MODULE_PATHNAME' LANGUAGE 'c' with (isstrict);
 
-INSERT INTO pg_description (objoid, description)
-   SELECT oid, 'different'::text
-   FROM pg_proc
-   WHERE proname = '_int_different'::name;
+COMMENT ON FUNCTION _int_different(_int4, _int4) IS 'different';
 
 -- support routines for indexing
 
 
 <!--
  Documentation of the system catalogs, directed toward PostgreSQL developers
- $Header: /cvsroot/pgsql/doc/src/sgml/catalogs.sgml,v 2.19 2001/07/15 22:48:15 tgl Exp $
+ $Header: /cvsroot/pgsql/doc/src/sgml/catalogs.sgml,v 2.20 2001/08/10 18:57:32 tgl Exp $
  -->
 
 <chapter id="catalogs">
   <para>
    <structname>pg_class</structname> catalogues tables and mostly
    everything else that has columns or is otherwise similar to a
-   table.  This includes indexes (but see
+   table.  This includes indexes (but see also
    <structname>pg_index</structname>), sequences, views, and some
-   kinds of special relation kinds.  Below, when we mean all of these
+   kinds of special relation.  Below, when we mean all of these
    kinds of objects we speak of <quote>relations</quote>.  Not all
    fields are meaningful for all relation types.
   </para>
       <entry><type>oid</type></entry>
       <entry>pg_type.oid</entry>
       <entry>
-       The data type that corresponds to this table (not functional,
-       only set for system tables)
+       The OID of the data type that corresponds to this table, if any
+       (zero for indexes, which have no pg_type entry)
       </entry>
      </row>
 
       <entry>reltoastidxid</entry>
       <entry><type>oid</type></entry>
       <entry>pg_class.oid</entry>
-      <entry>Oid of the index on the TOAST table for this table, 0 if none</entry>
+      <entry>
+       For a TOAST table, the OID of its index.  0 if not a TOAST table.
+      </entry>
      </row>
 
      <row>
       <entry>relhasindex</entry>
       <entry><type>bool</type></entry>
       <entry></entry>
-      <entry>True if this is a table and it has at least one index</entry>
+      <entry>True if this is a table and it has (or recently had) any indexes.
+       This is set by CREATE INDEX, but not cleared immediately by DROP INDEX.
+       VACUUM clears relhasindex if it finds the table has no indexes.
+      </entry>
      </row>
 
      <row>
       <entry><type>int2</type></entry>
       <entry></entry>
       <entry>
-       Number of columns in the relation, besides system columns.
+       Number of user columns in the relation (system columns not counted).
        There must be this many corresponding entries in
        <structname>pg_attribute</structname>.  See also
        <structname>pg_attribute</structname>.<structfield>attnum</structfield>.
       <entry>relukeys</entry>
       <entry><type>int2</type></entry>
       <entry></entry>
-      <entry>unused  (<emphasis>Not</emphasis> the number of unique keys or something.)</entry>
+      <entry>unused  (<emphasis>Not</emphasis> the number of unique keys)</entry>
      </row>
 
      <row>
       <entry>relfkeys</entry>
       <entry><type>int2</type></entry>
       <entry></entry>
-      <entry>Number foreign keys on the table</entry>
+      <entry>unused  (<emphasis>Not</emphasis> the number of foreign keys on the table)</entry>
+     </row>
+
+     <row>
+      <entry>relrefs</entry>
+      <entry><type>int2</type></entry>
+      <entry></entry>
+      <entry>unused</entry>
+     </row>
+
+     <row>
+      <entry>relhasoids</entry>
+      <entry><type>bool</type></entry>
+      <entry></entry>
+      <entry>
+       True if we generate an OID for each row of the relation.
+      </entry>
      </row>
 
      <row>
       <entry><type>bool</type></entry>
       <entry></entry>
       <entry>
-       unused  (No, this does not say whether the table has a primary
-       key.  It's really unused.)
+       True if the table has (or once had) a primary key.
       </entry>
      </row>
 
       <entry>relhassubclass</entry>
       <entry><type>bool</type></entry>
       <entry></entry>
-      <entry>At least one table inherits this one</entry>
+      <entry>At least one table inherits from this one</entry>
      </row>
 
      <row>
       <entry>The oid of the object this description pertains to</entry>
      </row>
 
+     <row>
+      <entry>classoid</entry>
+      <entry><type>oid</type></entry>
+      <entry>pg_class.oid</entry>
+      <entry>The oid of the system catalog this object appears in</entry>
+     </row>
+
+     <row>
+      <entry>objsubid</entry>
+      <entry><type>int4</type></entry>
+      <entry></entry>
+      <entry>For a comment on a table attribute, this is the attribute's
+       column number (the objoid and classoid refer to the table itself).
+       For all other object types, this field is presently zero.
+      </entry>
+     </row>
+
      <row>
       <entry>description</entry>
       <entry><type>text</type></entry>
 
 <!--
-$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_table.sgml,v 1.42 2001/05/03 17:50:55 tgl Exp $
+$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_table.sgml,v 1.43 2001/08/10 18:57:32 tgl Exp $
 Postgres documentation
 -->
 
   <synopsis>
 CREATE [ TEMPORARY | TEMP ] TABLE <replaceable class="PARAMETER">table_name</replaceable> (
     { <replaceable class="PARAMETER">column_name</replaceable> <replaceable class="PARAMETER">type</replaceable> [ <replaceable class="PARAMETER">column_constraint</replaceable> [ ... ] ]
-      | <replaceable>table_constraint</replaceable> }  [, ... ]
-    ) [ INHERITS ( <replaceable>parent_table</replaceable> [, ... ] ) ]
+      | <replaceable>table_constraint</replaceable> }  [, ... ] )
+    [ INHERITS ( <replaceable>parent_table</replaceable> [, ... ] ) ]
+    [ WITH OIDS | WITHOUT OIDS ]
 
 where <replaceable class="PARAMETER">column_constraint</replaceable> can be:
 [ CONSTRAINT <replaceable class="PARAMETER">constraint_name</replaceable> ]
       </listitem>
      </varlistentry>
 
+     <varlistentry>
+      <term>WITH OIDS or WITHOUT OIDS</term>
+      <listitem>
+       <para>
+        This optional clause specifies whether rows of the new table should
+   have OIDs (object identifiers) assigned to them.  The default is
+   WITH OIDS.  (If the new table inherits from any tables that have OIDs,
+   then WITH OIDS is forced even if the command says WITHOUT OIDS.)
+       </para>
+      </listitem>
+     </varlistentry>
+
      <varlistentry>
       <term><replaceable class="PARAMETER">constraint_name</replaceable></term>
       <listitem>
   </para>
  </refsect1>
 
+ <refsect1 id="R1-SQL-OIDSCLAUSE-1">
+  <title id="R1-SQL-OIDSCLAUSE-1-TITLE">
+   OIDS Clause
+  </title>
+  <para>
+   <synopsis>
+    WITH OIDS | WITHOUT OIDS
+   </synopsis>
+  </para>
+
+  <para>
+   This clause controls whether an OID (object ID) is generated and assigned
+   to each row inserted into the table.  The default is WITH OIDS.
+   Specifying WITHOUT OIDS allows the user to suppress generation of
+   OIDs for rows of a table.  This may be worthwhile for large
+   tables, since it will reduce OID consumption and thereby postpone
+   wraparound of the 32-bit OID counter.  Once the counter wraps around,
+   uniqueness of OIDs can no longer be assumed, which considerably reduces
+   their usefulness.
+  </para>
+
+  <para>
+   Whenever an application makes use of OIDs to identify specific rows of
+   a table, it is recommended that you create a unique index on OID for
+   that table, to ensure that OIDs in the table will indeed uniquely
+   identify rows even after counter wraparound.  (An index on OID is needed
+   anyway for fast lookup of rows by OID.)  Avoid assuming that OIDs are
+   unique across tables --- if you need a database-wide unique identifier,
+   use the combination of tableoid and row OID for the purpose.  (It is
+   likely that future Postgres releases will use a separate OID counter
+   for each table, so that it will be <emphasis>necessary</> not optional
+   to include tableoid to have a unique identifier database-wide.)
+  </para>
+
+  <tip>
+   <para>
+    WITHOUT OIDS is not recommended for tables with no primary key, since
+    without either an OID or a unique data key, it is difficult to identify
+    specific rows.
+   </para>
+  </tip>
+ </refsect1>
+
  <refsect1 id="R1-SQL-DEFAULTCLAUSE-1">
   <title id="R1-SQL-DEFAULTCLAUSE-1-TITLE">
    DEFAULT Clause
      supported by <productname>Postgres</productname>.
     </para>
    </refsect3>
+
+   <refsect3 id="R3-SQL-INHERITANCE-1">
+    <title>
+     Object IDs
+    </title>
+    <para>
+     The <productname>Postgres</productname> concept of OIDs is not
+     standard.  SQL99 (but not SQL92) has a notion of object ID, but
+     the syntax and semantics are different --- SQL99 associates OIDs
+     with individual values, not with rows.
+    </para>
+   </refsect3>
   </refsect2>
  </refsect1>
 </refentry>
 
 <!--
-$Header: /cvsroot/pgsql/doc/src/sgml/syntax.sgml,v 1.43 2001/06/19 22:39:08 tgl Exp $
+$Header: /cvsroot/pgsql/doc/src/sgml/syntax.sgml,v 1.44 2001/08/10 18:57:32 tgl Exp $
 -->
 
 <chapter id="sql-syntax">
      <primary>OID</primary>
     </indexterm>
     The unique identifier (object ID) of a row.  This is a serial number
-    that is added by Postgres to all rows automatically. OIDs are not
-    reused and are 32-bit quantities.
+    that is automatically added by Postgres to all table rows (unless
+    the table was created WITHOUT OIDS, in which case this column is
+    not present).
    </para>
        </listitem>
       </varlistentry>
        <listitem>
    <para>
     The identity (transaction ID) of the deleting transaction,
-    or zero for an undeleted tuple.  In practice, this is never nonzero
-    for a visible tuple.
+    or zero for an undeleted tuple.  It is possible for this field
+    to be nonzero in a visible tuple: that indicates that the
+    deleting transaction hasn't committed yet, or that an attempted
+    deletion was rolled back.
    </para>
        </listitem>
       </varlistentry>
        <listitem>
    <para>
     The command identifier within the deleting transaction, or zero.
-    Again, this is never nonzero for a visible tuple.
    </para>
        </listitem>
       </varlistentry>
      </variablelist>
     </para>
 
+    <para>
+     OIDs are 32-bit quantities and are assigned from a single cluster-wide
+     counter.  In a large or long-lived database, it is possible for the
+     counter to wrap around.  Hence, it is bad practice to assume that OIDs
+     are unique, unless you take steps to ensure that they are unique.
+     Recommended practice when using OIDs for row identification is to create
+     a unique index on the OID column of each table for which the OID will be
+     used.  Never assume that OIDs are unique across tables; use the
+     combination of tableoid and row OID if you need a database-wide
+     identifier.  (Future releases of Postgres are likely to use a separate
+     OID counter for each table, so that tableoid <emphasis>must</> be
+     included to arrive at a globally unique identifier.)
+    </para>
+
+    <para>
+     Transaction and command identifiers are 32-bit quantities.
+    </para>
+
     <para>
      For further information on the system attributes consult
      <xref linkend="STON87a" endterm="STON87a">.
-     Transaction and command identifiers are 32-bit quantities.
     </para>
 
   </sect1>
 
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.123 2001/07/12 04:11:12 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.124 2001/08/10 18:57:32 tgl Exp $
  *
  *
  * INTERFACE ROUTINES
 }
 
 /* ----------------
- *     heap_insert     - insert tuple
+ *     heap_insert     - insert tuple into a heap
  *
  *     The assignment of t_min (and thus the others) should be
  *     removed eventually.
- *
- *     Currently places the tuple onto the last page.  If there is no room,
- *     it is placed on new pages.  (Heap relations)
- *     Note that concurrent inserts during a scan will probably have
- *     unexpected results, though this will be fixed eventually.
- *
- *     Fix to work with indexes.
  * ----------------
  */
 Oid
    IncrHeapAccessStat(local_insert);
    IncrHeapAccessStat(global_insert);
 
-   /*
-    * If the object id of this tuple has already been assigned, trust the
-    * caller.  There are a couple of ways this can happen.  At initial db
-    * creation, the backend program sets oids for tuples.  When we define
-    * an index, we set the oid.  Finally, in the future, we may allow
-    * users to set their own object ids in order to support a persistent
-    * object store (objects need to contain pointers to one another).
-    */
-   if (!OidIsValid(tup->t_data->t_oid))
-       tup->t_data->t_oid = newoid();
-   else
-       CheckMaxObjectId(tup->t_data->t_oid);
+   if (relation->rd_rel->relhasoids)
+   {
+       /*
+        * If the object id of this tuple has already been assigned, trust the
+        * caller.  There are a couple of ways this can happen.  At initial db
+        * creation, the backend program sets oids for tuples.  When we define
+        * an index, we set the oid.  Finally, in the future, we may allow
+        * users to set their own object ids in order to support a persistent
+        * object store (objects need to contain pointers to one another).
+        */
+       if (!OidIsValid(tup->t_data->t_oid))
+           tup->t_data->t_oid = newoid();
+       else
+           CheckMaxObjectId(tup->t_data->t_oid);
+   }
 
    TransactionIdStore(GetCurrentTransactionId(), &(tup->t_data->t_xmin));
    tup->t_data->t_cmin = GetCurrentCommandId();
 
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/access/heap/tuptoaster.c,v 1.23 2001/06/22 19:16:20 wieck Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/access/heap/tuptoaster.c,v 1.24 2001/08/10 18:57:33 tgl Exp $
  *
  *
  * INTERFACE ROUTINES
 static void toast_delete_datum(Relation rel, Datum value);
 static void toast_insert_or_update(Relation rel, HeapTuple newtup,
                       HeapTuple oldtup);
-static Datum toast_save_datum(Relation rel, Oid mainoid, int16 attno, Datum value);
+static Datum toast_save_datum(Relation rel, Datum value);
 static varattrib *toast_fetch_datum(varattrib *attr);
 
 
                VARATT_IS_EXTERNAL(old_value))
            {
                if (new_isnull || !VARATT_IS_EXTERNAL(new_value) ||
-                   old_value->va_content.va_external.va_rowid !=
-                   new_value->va_content.va_external.va_rowid ||
-                   old_value->va_content.va_external.va_attno !=
-                   new_value->va_content.va_external.va_attno)
+                   old_value->va_content.va_external.va_valueid !=
+                   new_value->va_content.va_external.va_valueid ||
+                   old_value->va_content.va_external.va_toastrelid !=
+                   new_value->va_content.va_external.va_toastrelid)
                {
 
                    /*
        i = biggest_attno;
        old_value = toast_values[i];
        toast_action[i] = 'p';
-       toast_values[i] = toast_save_datum(rel,
-                                          newtup->t_data->t_oid,
-                                          i + 1,
-                                          toast_values[i]);
+       toast_values[i] = toast_save_datum(rel, toast_values[i]);
        if (toast_free[i])
            pfree(DatumGetPointer(old_value));
 
        i = biggest_attno;
        old_value = toast_values[i];
        toast_action[i] = 'p';
-       toast_values[i] = toast_save_datum(rel,
-                                          newtup->t_data->t_oid,
-                                          i + 1,
-                                          toast_values[i]);
+       toast_values[i] = toast_save_datum(rel, toast_values[i]);
        if (toast_free[i])
            pfree(DatumGetPointer(old_value));
 
  * ----------
  */
 static Datum
-toast_save_datum(Relation rel, Oid mainoid, int16 attno, Datum value)
+toast_save_datum(Relation rel, Datum value)
 {
    Relation    toastrel;
    Relation    toastidx;
    result->va_content.va_external.va_valueid = newoid();
    result->va_content.va_external.va_toastrelid =
        rel->rd_rel->reltoastrelid;
-   result->va_content.va_external.va_toastidxid =
-       rel->rd_rel->reltoastidxid;
-   result->va_content.va_external.va_rowid = mainoid;
-   result->va_content.va_external.va_attno = attno;
 
    /*
     * Initialize constant parts of the tuple data
     */
    toastrel = heap_open(rel->rd_rel->reltoastrelid, RowExclusiveLock);
    toasttupDesc = toastrel->rd_att;
-   toastidx = index_open(rel->rd_rel->reltoastidxid);
+   toastidx = index_open(toastrel->rd_rel->reltoastidxid);
 
    /*
     * Split up the item into chunks
     */
    while (data_todo > 0)
    {
-
        /*
         * Calculate the size of this chunk
         */
        chunk_size = Min(TOAST_MAX_CHUNK_SIZE, data_todo);
 
        /*
-        * Build a tuple
+        * Build a tuple and store it
         */
        t_values[1] = Int32GetDatum(chunk_seq++);
        VARATT_SIZEP(&chunk_data) = chunk_size + VARHDRSZ;
        if (!HeapTupleIsValid(toasttup))
            elog(ERROR, "Failed to build TOAST tuple");
 
+       heap_insert(toastrel, toasttup);
+
        /*
-        * Store it and create the index entry
+        * Create the index entry.  We cheat a little here by not using
+        * FormIndexDatum: this relies on the knowledge that the index
+        * columns are the same as the initial columns of the table.
+        *
+        * Note also that there had better not be any user-created index
+        * on the TOAST table, since we don't bother to update anything else.
         */
-       heap_insert(toastrel, toasttup);
        idxres = index_insert(toastidx, t_values, t_nulls,
                              &(toasttup->t_self),
                              toastrel);
        /*
         * Free memory
         */
-       heap_freetuple(toasttup);
        pfree(idxres);
+       heap_freetuple(toasttup);
 
        /*
         * Move on to next chunk
     */
    toastrel = heap_open(attr->va_content.va_external.va_toastrelid,
                         RowExclusiveLock);
-   toastidx = index_open(attr->va_content.va_external.va_toastidxid);
+   toastidx = index_open(toastrel->rd_rel->reltoastidxid);
 
    /*
     * Setup a scan key to fetch from the index by va_valueid
+    * (we don't particularly care whether we see them in sequence or not)
     */
    ScanKeyEntryInitialize(&toastkey,
                           (bits16) 0,
              ObjectIdGetDatum(attr->va_content.va_external.va_valueid));
 
    /*
-    * Read the chunks by index
+    * Find the chunks by index
     */
    toastscan = index_beginscan(toastidx, false, 1, &toastkey);
    while ((indexRes = index_getnext(toastscan, ForwardScanDirection)) != NULL)
    toastrel = heap_open(attr->va_content.va_external.va_toastrelid,
                         AccessShareLock);
    toasttupDesc = toastrel->rd_att;
-   toastidx = index_open(attr->va_content.va_external.va_toastidxid);
+   toastidx = index_open(toastrel->rd_rel->reltoastidxid);
 
    /*
     * Setup a scan key to fetch from the index by va_valueid
         * Some checks on the data we've found
         */
        if (residx < 0 || residx >= numchunks)
-           elog(ERROR, "unexpected chunk number %d for toast value %d",
+           elog(ERROR, "unexpected chunk number %d for toast value %u",
                 residx,
                 attr->va_content.va_external.va_valueid);
        if (residx < numchunks - 1)
        {
            if (chunksize != TOAST_MAX_CHUNK_SIZE)
-               elog(ERROR, "unexpected chunk size %d in chunk %d for toast value %d",
+               elog(ERROR, "unexpected chunk size %d in chunk %d for toast value %u",
                     chunksize, residx,
                     attr->va_content.va_external.va_valueid);
        }
        else
        {
            if ((residx * TOAST_MAX_CHUNK_SIZE + chunksize) != ressize)
-               elog(ERROR, "unexpected chunk size %d in chunk %d for toast value %d",
+               elog(ERROR, "unexpected chunk size %d in chunk %d for toast value %u",
                     chunksize, residx,
                     attr->va_content.va_external.va_valueid);
        }
        if (chunks_found[residx]++ > 0)
-           elog(ERROR, "chunk %d for toast value %d appears multiple times",
+           elog(ERROR, "chunk %d for toast value %u appears multiple times",
                 residx,
                 attr->va_content.va_external.va_valueid);
 
     * Final checks that we successfully fetched the datum
     */
    if (memcmp(chunks_found, chunks_expected, numchunks) != 0)
-       elog(ERROR, "not all toast chunks found for value %d",
+       elog(ERROR, "not all toast chunks found for value %u",
             attr->va_content.va_external.va_valueid);
    pfree(chunks_expected);
    pfree(chunks_found);
 
  * Copyright (c) 2000, PostgreSQL Global Development Group
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/access/transam/varsup.c,v 1.42 2001/07/16 22:43:33 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/access/transam/varsup.c,v 1.43 2001/08/10 18:57:33 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 
 static Oid lastSeenOid = InvalidOid;
 
-void
-GetNewObjectId(Oid *oid_return)
+Oid
+GetNewObjectId(void)
 {
+   Oid     result;
+
    SpinAcquire(OidGenLockId);
 
+   /*
+    * Check for wraparound of the OID counter.  We *must* not return 0
+    * (InvalidOid); and as long as we have to check that, it seems a good
+    * idea to skip over everything below BootstrapObjectIdData too.  (This
+    * basically just reduces the odds of OID collision right after a wrap
+    * occurs.)  Note we are relying on unsigned comparison here.
+    */
+   if (ShmemVariableCache->nextOid < ((Oid) BootstrapObjectIdData))
+   {
+       ShmemVariableCache->nextOid = BootstrapObjectIdData;
+       ShmemVariableCache->oidCount = 0;
+   }
+
    /* If we run out of logged for use oids then we must log more */
    if (ShmemVariableCache->oidCount == 0)
    {
        ShmemVariableCache->oidCount = VAR_OID_PREFETCH;
    }
 
-   if (PointerIsValid(oid_return))
-       lastSeenOid = (*oid_return) = ShmemVariableCache->nextOid;
+   result = ShmemVariableCache->nextOid;
 
    (ShmemVariableCache->nextOid)++;
    (ShmemVariableCache->oidCount)--;
 
    SpinRelease(OidGenLockId);
+
+   lastSeenOid = result;
+
+   return result;
 }
 
 void
     */
 
    XLogPutNextOid(assigned_oid + VAR_OID_PREFETCH);
-   ShmemVariableCache->oidCount = VAR_OID_PREFETCH - 1;
    ShmemVariableCache->nextOid = assigned_oid + 1;
+   ShmemVariableCache->oidCount = VAR_OID_PREFETCH - 1;
 
    SpinRelease(OidGenLockId);
 }
 
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Header: /cvsroot/pgsql/src/backend/access/transam/xlog.c,v 1.72 2001/07/22 22:01:04 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/access/transam/xlog.c,v 1.73 2001/08/10 18:57:33 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
         checkPoint.nextXid, checkPoint.nextOid);
    if (checkPoint.nextXid < FirstTransactionId)
        elog(STOP, "invalid next transaction id");
-   if (checkPoint.nextOid < BootstrapObjectIdData)
-       elog(STOP, "invalid next oid");
 
    ShmemVariableCache->nextXid = checkPoint.nextXid;
    ShmemVariableCache->nextOid = checkPoint.nextOid;
 
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/bootstrap/bootparse.y,v 1.36 2001/05/12 01:48:49 petere Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/bootstrap/bootparse.y,v 1.37 2001/08/10 18:57:33 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 
 
 int num_columns_read = 0;
-static Oid objectid;
 
 %}
 
 %type <list>  boot_index_params
 %type <ielem> boot_index_param
 %type <ival> boot_const boot_ident
-%type <ival> optbootstrap boot_tuple boot_tuplelist
+%type <ival> optbootstrap optwithoutoids boot_tuple boot_tuplelist
 %type <oidval> optoideq
 
 %token <ival> CONST ID
 %token STRING XDEFINE
 %token XDECLARE INDEX ON USING XBUILD INDICES UNIQUE
 %token COMMA EQUALS LPAREN RPAREN
-%token OBJ_ID XBOOTSTRAP NULLVAL
+%token OBJ_ID XBOOTSTRAP XWITHOUT_OIDS NULLVAL
 %start TopLevel
 
 %nonassoc low
        ;
 
 Boot_CreateStmt:
-         XCREATE optbootstrap boot_ident LPAREN
+         XCREATE optbootstrap optwithoutoids boot_ident LPAREN
                {
                    do_start();
                    numattr = 0;
                    {
                        if ($2)
                            elog(DEBUG, "creating bootstrap relation %s...",
-                                LexIDStr($3));
+                                LexIDStr($4));
                        else
                            elog(DEBUG, "creating relation %s...",
-                                LexIDStr($3));
+                                LexIDStr($4));
                    }
                }
          boot_typelist
                            closerel(NULL);
                        }
 
-                       tupdesc = CreateTupleDesc(numattr,attrtypes);
-                       reldesc = heap_create(LexIDStr($3), tupdesc,
+                       tupdesc = CreateTupleDesc(numattr, attrtypes);
+                       reldesc = heap_create(LexIDStr($4), tupdesc,
                                              false, true, true);
+                       reldesc->rd_rel->relhasoids = ! ($3);
                        if (DebugMode)
                            elog(DEBUG, "bootstrap relation created");
                    }
                        TupleDesc tupdesc;
 
                        tupdesc = CreateTupleDesc(numattr,attrtypes);
-                       id = heap_create_with_catalog(LexIDStr($3),
+                       id = heap_create_with_catalog(LexIDStr($4),
                                                      tupdesc,
                                                      RELKIND_RELATION,
+                                                     ! ($3),
                                                      false,
                                                      true);
                        if (DebugMode)
                        elog(ERROR, "relation not open");
                        err_out();
                    }
-                   objectid = $2;
-                   InsertOneTuple(objectid);
+                   InsertOneTuple($2);
                    do_end();
                }
        ;
        |               { $$ = 0; }
        ;
 
+optwithoutoids:
+           XWITHOUT_OIDS   { $$ = 1; }
+       |                   { $$ = 0; }
+       ;
+
 boot_typelist:
          boot_type_thing
        | boot_typelist COMMA boot_type_thing
        ;
 
 optoideq:
-           OBJ_ID EQUALS boot_ident { $$ = atol(LexIDStr($3));             }
-       |                       { $$ = newoid();    }
+           OBJ_ID EQUALS boot_ident { $$ = atol(LexIDStr($3)); }
+       |                       { $$ = (Oid) 0; }
        ;
 
 boot_tuplelist:
        ;
 
 boot_tuple:
-         boot_ident {InsertOneValue(objectid, LexIDStr($1), num_columns_read++); }
-       | boot_const {InsertOneValue(objectid, LexIDStr($1), num_columns_read++); }
+         boot_ident
+           { InsertOneValue(LexIDStr($1), num_columns_read++); }
+       | boot_const
+           { InsertOneValue(LexIDStr($1), num_columns_read++); }
        | NULLVAL
            { InsertOneNull(num_columns_read++); }
        ;
 
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/bootstrap/bootscanner.l,v 1.20 2001/05/12 01:48:49 petere Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/bootstrap/bootscanner.l,v 1.21 2001/08/10 18:57:33 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 "index"            { return(INDEX); }
 "on"           { return(ON); }
 "using"            { return(USING); }
+"without_oids" { return(XWITHOUT_OIDS); }
+
 {arrayid}      {
                    yylval.ival = EnterString(MapArrayTypeName((char*)yytext));
                    return(ID);
 
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/bootstrap/bootstrap.c,v 1.113 2001/08/04 00:14:43 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/bootstrap/bootstrap.c,v 1.114 2001/08/10 18:57:33 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 
 /* ----------------
  *     InsertOneTuple
- *     assumes that 'oid' will not be zero.
+ *
+ * If objectid is not zero, it is a specific OID to assign to the tuple.
+ * Otherwise, an OID will be assigned (if necessary) by heap_insert.
  * ----------------
  */
 void
 {
    HeapTuple   tuple;
    TupleDesc   tupDesc;
-
    int         i;
 
    if (DebugMode)
  * ----------------
  */
 void
-InsertOneValue(Oid objectid, char *value, int i)
+InsertOneValue(char *value, int i)
 {
    int         typeindex;
    char       *prt;
 
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/catalog/catalog.c,v 1.42 2001/05/30 20:52:32 momjian Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/catalog/catalog.c,v 1.43 2001/08/10 18:57:33 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
  *     newoid          - returns a unique identifier across all catalogs.
  *
  *     Object Id allocation is now done by GetNewObjectID in
- *     access/transam/varsup.c.  oids are now allocated correctly.
+ *     access/transam/varsup.
  *
- * old comments:
- *     This needs to change soon, it fails if there are too many more
- *     than one call per second when postgres restarts after it dies.
- *
- *     The distribution of OID's should be done by the POSTMASTER.
- *     Also there needs to be a facility to preallocate OID's.  Ie.,
- *     for a block of OID's to be declared as invalid ones to allow
- *     user programs to use them for temporary object identifiers.
+ *     This code probably needs to change to generate OIDs separately
+ *     for each table.
  */
 Oid
 newoid(void)
 {
-   Oid         lastoid;
-
-   GetNewObjectId(&lastoid);
-   if (!OidIsValid(lastoid))
-       elog(ERROR, "newoid: GetNewObjectId returns invalid oid");
-   return lastoid;
+   return GetNewObjectId();
 }
 
 #
 #
 # IDENTIFICATION
-#    $Header: /cvsroot/pgsql/src/backend/catalog/Attic/genbki.sh,v 1.20 2001/05/07 00:43:16 tgl Exp $
+#    $Header: /cvsroot/pgsql/src/backend/catalog/Attic/genbki.sh,v 1.21 2001/08/10 18:57:33 tgl Exp $
 #
 # NOTES
 #    non-essential whitespace is removed from the generated file.
     fi
 done
 
+# Get FirstGenBKIObjectId from access/transam.h
+for dir in $INCLUDE_DIRS; do
+    if [ -f "$dir/access/transam.h" ]; then
+        BKIOBJECTID=`grep '#define[    ]*FirstGenBKIObjectId' $dir/access/transam.h | $AWK '{ print $3 }'`
+        break
+    fi
+done
+export BKIOBJECTID
+
 # NOTE: we assume here that FUNC_MAX_ARGS has the same value as INDEX_MAX_KEYS,
 # and don't read it separately from config.h.  This is OK because both of them
 # must be equal to the length of oidvector.
 #  nc is the number of catalogs
 #  inside is a variable set to 1 when we are scanning the
 #     contents of a catalog definition.
-#  inserting_data is a flag indicating when we are processing DATA lines.
-#      (i.e. have a relation open and need to close it)
+#  reln_open is a flag indicating when we are processing DATA lines.
+#     (i.e. have a relation open and need to close it)
+#  nextbkioid is the next OID available for automatic assignment.
+#  oid is the most recently seen or assigned oid.
 # ----------------
 BEGIN {
    inside = 0;
    raw = 0;
-   bootstrap = 0;
+   bootstrap = "";
+   without_oids = "";
    nc = 0;
    reln_open = 0;
-        comment_level = 0;
+   comment_level = 0;
+   nextbkioid = ENVIRON["BKIOBJECTID"];
+   oid = 0;
 }
 
 # ----------------
 raw == 1   { print; next; }
 
 # ----------------
-#  DATA() statements should get passed right through after
-#  stripping off the DATA( and the ) on the end.
+#  DATA() statements are basically passed right through after
+#  stripping off the DATA( and the ) on the end.  However,
+#  if we see "OID = 0" then we should assign an oid from nextbkioid.
+#  Remember any explicit or assigned OID for use by DESCR().
 # ----------------
 /^DATA\(/ {
    data = substr($0, 6, length($0) - 6);
-   print data;
-   nf = 1;
    oid = 0;
-   while (nf <= NF-3)
+   nf = split(data, datafields);
+   if (nf >= 4 && datafields[1] == "insert" && datafields[2] == "OID" && datafields[3] == "=")
    {
-       if ($nf == "OID" && $(nf+1) == "=")
+       oid = datafields[4];
+       if (oid == 0)
        {
-           oid = $(nf+2);
-           break;
+           oid = nextbkioid;
+           nextbkioid++;
+           sub("OID *= *0", "OID = " oid, data);
        }
-       nf++;
    }
+   print data;
    next;
 }
 
    {
        data = substr($0, 8, length($0) - 9);
        if (data != "")
-           printf "%d  %s\n", oid, data >>descriptionfile;
+           printf "%d\t%s\t0\t%s\n", oid, catalog, data >>descriptionfile;
    }
    next;
 }
    }
 
 # ----
-#  get the name of the new catalog
+#  get the name and properties of the new catalog
 # ----
    pos = index($1,")");
    catalog = substr($1,9,pos-9); 
 
    if ($0 ~ /BOOTSTRAP/) {
-       bootstrap = 1;
+       bootstrap = "bootstrap ";
+   }
+   if ($0 ~ /BKI_WITHOUT_OIDS/) {
+       without_oids = "without_oids ";
    }
 
         i = 1;
 #  if this is the last line, then output the bki catalog stuff.
 # ----
    if ($1 ~ /}/) {
-       if (bootstrap) {
-           print "create bootstrap " catalog;
-       } else {
-           print "create " catalog;
-       }
+       print "create " bootstrap without_oids catalog;
        print "\t(";
 
        for (j=1; j<i-1; j++) {
        print "\t " attname[ j ] " = " atttype[ j ] ;
        print "\t)";
 
-       if (! bootstrap) {
+       if (bootstrap == "") {
            print "open " catalog;
        }
 
        i = 1;
        reln_open = 1;
        inside = 0;
-       bootstrap = 0;
+       bootstrap = "";
+       without_oids = "";
        next;
    }
 
 
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.173 2001/08/10 15:49:39 petere Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.174 2001/08/10 18:57:33 tgl Exp $
  *
  *
  * INTERFACE ROUTINES
 
 
 static void AddNewRelationTuple(Relation pg_class_desc,
-               Relation new_rel_desc, Oid new_rel_oid, Oid new_type_oid,
-                   int natts, char relkind, char *temp_relname);
+                               Relation new_rel_desc,
+                               Oid new_rel_oid, Oid new_type_oid,
+                               char relkind, bool relhasoids,
+                               char *temp_relname);
 static void DeleteAttributeTuples(Relation rel);
 static void DeleteRelationTuple(Relation rel);
 static void DeleteTypeTuple(Relation rel);
  * This function returns a Form_pg_attribute pointer for a system attribute.
  */
 Form_pg_attribute
-SystemAttributeDefinition(AttrNumber attno)
+SystemAttributeDefinition(AttrNumber attno, bool relhasoids)
 {
    if (attno >= 0 || attno < - (int) lengthof(SysAtt))
        elog(ERROR, "SystemAttributeDefinition: invalid attribute number %d",
             attno);
+   if (attno == ObjectIdAttributeNumber && !relhasoids)
+       elog(ERROR, "SystemAttributeDefinition: invalid attribute number %d",
+            attno);
    return SysAtt[-attno - 1];
 }
 
 /* ----------------------------------------------------------------
  *     heap_create     - Create an uncataloged heap relation
  *
- *     Fields relpages, reltuples, reltuples, relkeys, relhistory,
- *     relisindexed, and relkind of rel->rd_rel are initialized
- *     to all zeros, as are rd_last and rd_hook.  Rd_refcnt is set to 1.
+ *     rel->rd_rel is initialized by RelationBuildLocalRelation,
+ *     and is mostly zeroes at return.
  *
  *     Remove the system relation specific code to elsewhere eventually.
  *
  * --------------------------------
  */
 static void
-CheckAttributeNames(TupleDesc tupdesc)
+CheckAttributeNames(TupleDesc tupdesc, bool relhasoids)
 {
    int         i;
    int         j;
    {
        for (j = 0; j < (int) lengthof(SysAtt); j++)
        {
-           if (strcmp(NameStr(SysAtt[j]->attname),
-                      NameStr(tupdesc->attrs[i]->attname)) == 0)
+           if (relhasoids || SysAtt[j]->attnum != ObjectIdAttributeNumber)
            {
-               elog(ERROR, "name of column \"%s\" conflicts with an existing system column",
-                    NameStr(SysAtt[j]->attname));
+               if (strcmp(NameStr(SysAtt[j]->attname),
+                          NameStr(tupdesc->attrs[i]->attname)) == 0)
+                   elog(ERROR, "name of column \"%s\" conflicts with an existing system column",
+                        NameStr(SysAtt[j]->attname));
            }
        }
        if (tupdesc->attrs[i]->atttypid == UNKNOWNOID)
-       {
            elog(NOTICE, "Attribute '%s' has an unknown type"
-                "\n\tRelation created; continue",
+                "\n\tProceeding with relation creation anyway",
                 NameStr(tupdesc->attrs[i]->attname));
-       }
    }
 
    /*
        {
            if (strcmp(NameStr(tupdesc->attrs[j]->attname),
                       NameStr(tupdesc->attrs[i]->attname)) == 0)
-           {
                elog(ERROR, "column name \"%s\" is duplicated",
                     NameStr(tupdesc->attrs[j]->attname));
-           }
        }
    }
 }
  */
 static void
 AddNewAttributeTuples(Oid new_rel_oid,
-                     TupleDesc tupdesc)
+                     TupleDesc tupdesc,
+                     bool relhasoids)
 {
    Form_pg_attribute *dpp;
    int         i;
    }
 
    /*
-    * next we add the system attributes..
+    * next we add the system attributes.  Skip OID if rel has no OIDs.
     */
    dpp = SysAtt;
    for (i = 0; i < -1 - FirstLowInvalidHeapAttributeNumber; i++)
    {
-       Form_pg_attribute attStruct;
+       if (relhasoids || (*dpp)->attnum != ObjectIdAttributeNumber)
+       {
+           Form_pg_attribute attStruct;
 
-       tup = heap_addheader(Natts_pg_attribute,
-                            ATTRIBUTE_TUPLE_SIZE,
-                            (void *) *dpp);
+           tup = heap_addheader(Natts_pg_attribute,
+                                ATTRIBUTE_TUPLE_SIZE,
+                                (void *) *dpp);
 
-       /* Fill in the correct relation OID in the copied tuple */
-       attStruct = (Form_pg_attribute) GETSTRUCT(tup);
-       attStruct->attrelid = new_rel_oid;
-       /* Unneeded since they should be OK in the constant data anyway */
-       /* attStruct->attstattarget = 0; */
-       /* attStruct->attcacheoff = -1; */
+           /* Fill in the correct relation OID in the copied tuple */
+           attStruct = (Form_pg_attribute) GETSTRUCT(tup);
+           attStruct->attrelid = new_rel_oid;
+           /* Unneeded since they should be OK in the constant data anyway */
+           /* attStruct->attstattarget = 0; */
+           /* attStruct->attcacheoff = -1; */
 
-       heap_insert(rel, tup);
+           heap_insert(rel, tup);
 
-       if (hasindex)
-           CatalogIndexInsert(idescs, Num_pg_attr_indices, rel, tup);
+           if (hasindex)
+               CatalogIndexInsert(idescs, Num_pg_attr_indices, rel, tup);
 
-       heap_freetuple(tup);
+           heap_freetuple(tup);
+       }
        dpp++;
    }
 
                    Relation new_rel_desc,
                    Oid new_rel_oid,
                    Oid new_type_oid,
-                   int natts,
                    char relkind,
+                   bool relhasoids,
                    char *temp_relname)
 {
    Form_pg_class new_rel_reltup;
    new_rel_reltup->relowner = GetUserId();
    new_rel_reltup->reltype = new_type_oid;
    new_rel_reltup->relkind = relkind;
-   new_rel_reltup->relnatts = natts;
+   new_rel_reltup->relhasoids = relhasoids;
 
    /* ----------------
     *  now form a tuple to add to pg_class
 heap_create_with_catalog(char *relname,
                         TupleDesc tupdesc,
                         char relkind,
+                        bool relhasoids,
                         bool istemp,
                         bool allow_system_table_mods)
 {
    Relation    new_rel_desc;
    Oid         new_rel_oid;
    Oid         new_type_oid;
-   int         natts = tupdesc->natts;
    char       *temp_relname = NULL;
 
    /*
     * sanity checks
     */
    Assert(IsNormalProcessingMode() || IsBootstrapProcessingMode());
-   if (natts <= 0 || natts > MaxHeapAttributeNumber)
+   if (tupdesc->natts <= 0 || tupdesc->natts > MaxHeapAttributeNumber)
        elog(ERROR, "Number of columns is out of range (1 to %d)",
             MaxHeapAttributeNumber);
 
-   CheckAttributeNames(tupdesc);
+   CheckAttributeNames(tupdesc, relhasoids);
 
    /* temp tables can mask non-temp tables */
    if ((!istemp && RelnameFindRelid(relname)) ||
                        new_rel_desc,
                        new_rel_oid,
                        new_type_oid,
-                       natts,
                        relkind,
+                       relhasoids,
                        temp_relname);
 
    /*
     * now add tuples to pg_attribute for the attributes in our new
     * relation.
     */
-   AddNewAttributeTuples(new_rel_oid, tupdesc);
+   AddNewAttributeTuples(new_rel_oid, tupdesc, relhasoids);
 
    StoreConstraints(new_rel_desc);
 
-   if (istemp)
-   {
-       pfree(relname);
-       pfree(temp_relname);
-   }
-
    /*
     * We create the disk file for this relation here
     */
    /*
     * ok, the relation has been cataloged, so close our relations and
     * return the oid of the newly created relation.
-    *
-    * SOMEDAY: fill the STATISTIC relation properly.
     */
    heap_close(new_rel_desc, NoLock);   /* do not unlock till end of xact */
    heap_close(pg_class_desc, RowExclusiveLock);
 
+   if (istemp)
+   {
+       pfree(relname);
+       pfree(temp_relname);
+   }
+
    return new_rel_oid;
 }
 
                                 0, 0);
        if (HeapTupleIsValid(tup))
        {
-           /*** Delete any comments associated with this attribute ***/
-           DeleteComments(tup->t_data->t_oid);
-
            simple_heap_delete(pg_attribute_desc, &tup->t_self);
            heap_freetuple(tup);
        }
  *     3)  remove indexes
  *     4)  remove pg_class tuple
  *     5)  remove pg_attribute tuples and related descriptions
- *             6)      remove pg_description tuples
+ *     6)  remove pg_description tuples
  *     7)  remove pg_type tuples
  *     8)  RemoveConstraints ()
  *     9)  unlink relation
    /*
     * delete comments, statistics, and constraints
     */
-   DeleteComments(RelationGetRelid(rel));
+   DeleteComments(rid, RelOid_pg_class);
 
    RemoveStatistics(rel);
 
 
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.158 2001/08/10 15:49:39 petere Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.159 2001/08/10 18:57:33 tgl Exp $
  *
  *
  * INTERFACE ROUTINES
            /*
             * here we are indexing on a system attribute (-1...-n)
             */
-           from = SystemAttributeDefinition(atnum);
+           from = SystemAttributeDefinition(atnum,
+                                            heapRelation->rd_rel->relhasoids);
        }
        else
        {
    indexRelation->rd_rel->relisshared = 
        IsSharedSystemRelationName(RelationGetPhysicalRelationName(indexRelation));
    indexRelation->rd_rel->relkind = RELKIND_INDEX;
+   indexRelation->rd_rel->relhasoids = false;
 }
 
 /* ----------------------------------------------------------------
 
 /* ----------------------------------------------------------------
  *     index_create
+ *
+ * Returns OID of the created index.
  * ----------------------------------------------------------------
  */
-void
+Oid
 index_create(char *heapRelationName,
             char *indexRelationName,
             IndexInfo *indexInfo,
    }
    else
        index_build(heapRelation, indexRelation, indexInfo);
+
+   return indexoid;
 }
 
 /* ----------------------------------------------------------------
    /*
     * fix DESCRIPTION relation
     */
-   DeleteComments(indexId);
+   DeleteComments(indexId, RelOid_pg_class);
 
    /*
     * fix RELATION relation
     * must send out a shared-cache-inval notice on the owning relation to
     * ensure other backends update their relcache lists of indexes.  So,
     * unconditionally do setRelhasindex(true).
+    *
+    * Possible future improvement: skip the physical tuple update and
+    * just send out an invalidation message.
     */
-   setRelhasindex(heapId, true);
+   setRelhasindex(heapId, true, false, InvalidOid);
 
    heap_close(relationRelation, RowExclusiveLock);
 
 /* ----------------
  *     set relhasindex of relation's pg_class entry
  *
+ * If isprimary is TRUE, we are defining a primary index, so also set
+ * relhaspkey to TRUE.  Otherwise, leave relhaspkey alone.
+ *
+ * If reltoastidxid is not InvalidOid, also set reltoastidxid to that value.
+ * This is only used for TOAST relations.
+ *
  * NOTE: an important side-effect of this operation is that an SI invalidation
  * message is sent out to all backends --- including me --- causing relcache
  * entries to be flushed or updated with the new hasindex data.
  * ----------------
  */
 void
-setRelhasindex(Oid relid, bool hasindex)
+setRelhasindex(Oid relid, bool hasindex, bool isprimary, Oid reltoastidxid)
 {
    Relation    pg_class;
    HeapTuple   tuple;
+   Form_pg_class classtuple;
    HeapScanDesc pg_class_scan = NULL;
 
    /*
     */
    pg_class = heap_openr(RelationRelationName, RowExclusiveLock);
 
-   if (!IsIgnoringSystemIndexes() && (!IsReindexProcessing() || pg_class->rd_rel->relhasindex))
+   if (!IsIgnoringSystemIndexes() &&
+       (!IsReindexProcessing() || pg_class->rd_rel->relhasindex))
    {
        tuple = SearchSysCacheCopy(RELOID,
                                   ObjectIdGetDatum(relid),
    }
 
    /*
-    * Update hasindex in pg_class.
+    * Update fields in the pg_class tuple.
     */
    if (pg_class_scan)
        LockBuffer(pg_class_scan->rs_cbuf, BUFFER_LOCK_EXCLUSIVE);
-   ((Form_pg_class) GETSTRUCT(tuple))->relhasindex = hasindex;
+
+   classtuple = (Form_pg_class) GETSTRUCT(tuple);
+   classtuple->relhasindex = hasindex;
+   if (isprimary)
+       classtuple->relhaspkey = true;
+   if (OidIsValid(reltoastidxid))
+   {
+       Assert(classtuple->relkind == RELKIND_TOASTVALUE);
+       classtuple->reltoastidxid = reltoastidxid;
+   }
+
    if (pg_class_scan)
        LockBuffer(pg_class_scan->rs_cbuf, BUFFER_LOCK_UNLOCK);
 
    if (IndexesAreActive(relid, true))
    {
        if (!activate)
-           setRelhasindex(relid, false);
+           setRelhasindex(relid, false, false, InvalidOid);
        else
            return false;
    }
                 * For pg_class, relhasindex should be set to true here in
                 * place.
                 */
-               setRelhasindex(relid, true);
+               setRelhasindex(relid, true, false, InvalidOid);
                CommandCounterIncrement();
 
                /*
                 * keep consistency with WAL.
                 */
            }
-           setRelhasindex(relid, true);
+           setRelhasindex(relid, true, false, InvalidOid);
        }
    }
    SetReindexProcessing(old);
 
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/catalog/indexing.c,v 1.80 2001/06/22 19:16:21 wieck Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/catalog/indexing.c,v 1.81 2001/08/10 18:57:34 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
  */
 
 char      *Name_pg_aggregate_indices[Num_pg_aggregate_indices] =
-{AggregateNameTypeIndex};
+{AggregateNameTypeIndex, AggregateOidIndex};
 char      *Name_pg_am_indices[Num_pg_am_indices] =
 {AmNameIndex, AmOidIndex};
 char      *Name_pg_amop_indices[Num_pg_amop_indices] =
 
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/commands/cluster.c,v 1.67 2001/07/12 20:35:54 momjian Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/commands/cluster.c,v 1.68 2001/08/10 18:57:34 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
    tupdesc = CreateTupleDescCopyConstr(OldHeapDesc);
 
    OIDNewHeap = heap_create_with_catalog(NewName, tupdesc,
-                                         RELKIND_RELATION, istemp,
+                                         OldHeap->rd_rel->relkind,
+                                         OldHeap->rd_rel->relhasoids,
+                                         istemp,
                                          allowSystemTableMods);
 
    /*
                 Old_pg_index_Form->indisprimary,
                 allowSystemTableMods);
 
-   setRelhasindex(OIDNewHeap, true);
+   setRelhasindex(OIDNewHeap, true,
+                  Old_pg_index_Form->indisprimary, InvalidOid);
 
    ReleaseSysCache(Old_pg_index_Tuple);
    ReleaseSysCache(Old_pg_index_relation_Tuple);
 
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.139 2001/08/10 14:30:14 momjian Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.140 2001/08/10 18:57:34 tgl Exp $
  *
  * NOTES
  *   The PerformAddAttribute() code, like most of the relation
    QueryDesc  *queryDesc;
    EState     *estate;
    MemoryContext oldcontext;
-   bool        faked_desc = false;
+   bool        temp_desc = false;
 
    /*
     * sanity checks
    oldcontext = MemoryContextSwitchTo(PortalGetHeapMemory(portal));
 
    /*
-    * tell the destination to prepare to receive some tuples.
+    * If the requested destination is not the same as the query's
+    * original destination, make a temporary QueryDesc with the proper
+    * destination.  This supports MOVE, for example, which will pass in
+    * dest = None.
     *
-    * If we've been asked for a MOVE, make a temporary QueryDesc with the
-    * appropriate dummy destination.
+    * EXCEPTION: if the query's original dest is RemoteInternal (ie, it's
+    * a binary cursor) and the request is Remote, we do NOT override the
+    * original dest.  This is necessary since a FETCH command will pass
+    * dest = Remote, not knowing whether the cursor is binary or not.
     */
    queryDesc = PortalGetQueryDesc(portal);
    estate = PortalGetState(portal);
 
-   if (dest != queryDesc->dest)            /* MOVE */
+   if (dest != queryDesc->dest &&
+       !(queryDesc->dest == RemoteInternal && dest == Remote))
    {
        QueryDesc  *qdesc = (QueryDesc *) palloc(sizeof(QueryDesc));
 
        memcpy(qdesc, queryDesc, sizeof(QueryDesc));
        qdesc->dest = dest;
        queryDesc = qdesc;
-       faked_desc = true;
+       temp_desc = true;
    }
 
+   /*
+    * tell the destination to prepare to receive some tuples.
+    */
    BeginCommand(name,
                 queryDesc->operation,
                 PortalGetTupleDesc(portal),
                 false,         /* this is a portal fetch, not a "retrieve
                                 * portal" */
                 tag,
-                dest);
+                queryDesc->dest);
 
    /*
     * Determine which direction to go in, and check to see if we're
    /*
     * Clean up and switch back to old context.
     */
-   if (faked_desc)         /* MOVE */
+   if (temp_desc)
        pfree(queryDesc);
 
    MemoryContextSwitchTo(oldcontext);
 #ifdef _DROP_COLUMN_HACK__
    Relation    rel,
                attrdesc;
-   Oid         myrelid,
-               attoid;
+   Oid         myrelid;
    HeapTuple   reltup;
    HeapTupleData classtuple;
    Buffer      buffer;
    if (attnum <= 0)
        elog(ERROR, "ALTER TABLE: column name \"%s\" was already dropped",
             colName);
-   attoid = tup->t_data->t_oid;
 
    /*
     * Check constraints/indices etc here
    heap_close(attrdesc, NoLock);
    heap_freetuple(tup);
 
-   /* delete comments */
-   DeleteComments(attoid);
+   /* delete comment for this attribute only */
+   CreateComments(RelationGetRelid(rel), RelOid_pg_class,
+                  (int32) attnum, NULL);
 
    /* delete attrdef */
    drop_default(myrelid, attnum);
    Oid         toast_idxid;
    char        toast_relname[NAMEDATALEN + 1];
    char        toast_idxname[NAMEDATALEN + 1];
-   Relation    toast_idxrel;
    IndexInfo  *indexInfo;
-   Oid         classObjectId[1];
+   Oid         classObjectId[2];
 
    /*
     * permissions checking.  XXX exactly what is appropriate here?
     * so there's no need to handle the toast rel as temp.
     */
    toast_relid = heap_create_with_catalog(toast_relname, tupdesc,
-                                          RELKIND_TOASTVALUE,
+                                          RELKIND_TOASTVALUE, false,
                                           false, true);
 
    /* make the toast relation visible, else index creation will fail */
    CommandCounterIncrement();
 
-   /* create index on chunk_id */
+   /*
+    * Create unique index on chunk_id, chunk_seq.
+    *
+    * NOTE: the tuple toaster could actually function with a single-column
+    * index on chunk_id only.  However, it couldn't be unique then.  We
+    * want it to be unique as a check against the possibility of duplicate
+    * TOAST chunk OIDs.  Too, the index might be a little more efficient this
+    * way, since btree isn't all that happy with large numbers of equal keys.
+    */
 
    indexInfo = makeNode(IndexInfo);
-   indexInfo->ii_NumIndexAttrs = 1;
-   indexInfo->ii_NumKeyAttrs = 1;
+   indexInfo->ii_NumIndexAttrs = 2;
+   indexInfo->ii_NumKeyAttrs = 2;
    indexInfo->ii_KeyAttrNumbers[0] = 1;
+   indexInfo->ii_KeyAttrNumbers[1] = 2;
    indexInfo->ii_Predicate = NIL;
    indexInfo->ii_FuncOid = InvalidOid;
-   indexInfo->ii_Unique = false;
+   indexInfo->ii_Unique = true;
 
    classObjectId[0] = OID_OPS_OID;
+   classObjectId[1] = INT4_OPS_OID;
 
-   index_create(toast_relname, toast_idxname, indexInfo,
-                BTREE_AM_OID, classObjectId,
-                false, false, true);
+   toast_idxid = index_create(toast_relname, toast_idxname, indexInfo,
+                              BTREE_AM_OID, classObjectId,
+                              false, true, true);
 
    /*
     * Update toast rel's pg_class entry to show that it has an index.
+    * The index OID is stored into the reltoastidxid field for
+    * easy access by the tuple toaster.
     */
-   setRelhasindex(toast_relid, true);
-
-   /*
-    * Make index visible
-    */
-   CommandCounterIncrement();
-
-   /*
-    * Get the OID of the newly created index
-    */
-   toast_idxrel = index_openr(toast_idxname);
-   toast_idxid = RelationGetRelid(toast_idxrel);
-   index_close(toast_idxrel);
+   setRelhasindex(toast_relid, true, true, toast_idxid);
 
    /*
-    * Store the toast table- and index-Oid's in the relation tuple
+    * Store the toast table's OID in the parent relation's tuple
     */
    ((Form_pg_class) GETSTRUCT(reltup))->reltoastrelid = toast_relid;
-   ((Form_pg_class) GETSTRUCT(reltup))->reltoastidxid = toast_idxid;
    simple_heap_update(class_rel, &reltup->t_self, reltup);
 
    /*
 
  * Copyright (c) 1999-2001, PostgreSQL Global Development Group
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/commands/comment.c,v 1.31 2001/06/25 21:11:43 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/commands/comment.c,v 1.32 2001/08/10 18:57:34 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 
 #include "postgres.h"
 
+#include "access/genam.h"
 #include "access/heapam.h"
 #include "catalog/catname.h"
 #include "catalog/indexing.h"
 #include "catalog/pg_operator.h"
 #include "catalog/pg_trigger.h"
 #include "catalog/pg_type.h"
-#include "catalog/pg_class.h"
 #include "commands/comment.h"
 #include "miscadmin.h"
 #include "parser/parse_expr.h"
 #include "utils/acl.h"
 #include "utils/builtins.h"
 #include "utils/fmgroids.h"
+#include "utils/lsyscache.h"
 #include "utils/syscache.h"
 
 
 static void CommentProc(char *function, List *arguments, char *comment);
 static void CommentOperator(char *opname, List *arguments, char *comment);
 static void CommentTrigger(char *trigger, char *relation, char *comments);
-static void CreateComments(Oid oid, char *comment);
+
 
 /*------------------------------------------------------------------
  * CommentObject --
  * to this routine. If the routine cannot determine an Oid to
  * associated with the parameters handed to this routine, an
  * error is thrown. Otherwise the comment is added to pg_description
- * by calling the CreateComments() routine. If the comments were
+ * by calling the CreateComments() routine. If the comment string is
  * empty, CreateComments() will drop any comments associated with
  * the object.
  *------------------------------------------------------------------
 CommentObject(int objtype, char *objname, char *objproperty,
              List *objlist, char *comment)
 {
-
    switch (objtype)
    {
-           case (INDEX):
-           case (SEQUENCE):
-           case (TABLE):
-           case (VIEW):
+       case INDEX:
+       case SEQUENCE:
+       case TABLE:
+       case VIEW:
            CommentRelation(objtype, objname, comment);
            break;
-       case (COLUMN):
+       case COLUMN:
            CommentAttribute(objname, objproperty, comment);
            break;
-       case (DATABASE):
+       case DATABASE:
            CommentDatabase(objname, comment);
            break;
-       case (RULE):
+       case RULE:
            CommentRewrite(objname, comment);
            break;
-       case (TYPE_P):
+       case TYPE_P:
            CommentType(objname, comment);
            break;
-       case (AGGREGATE):
+       case AGGREGATE:
            CommentAggregate(objname, objlist, comment);
            break;
-       case (FUNCTION):
+       case FUNCTION:
            CommentProc(objname, objlist, comment);
            break;
-       case (OPERATOR):
+       case OPERATOR:
            CommentOperator(objname, objlist, comment);
            break;
-       case (TRIGGER):
+       case TRIGGER:
            CommentTrigger(objname, objproperty, comment);
            break;
        default:
-           elog(ERROR, "An attempt was made to comment on a unknown type: %i",
+           elog(ERROR, "An attempt was made to comment on a unknown type: %d",
                 objtype);
    }
-
-
 }
 
 /*------------------------------------------------------------------
  * CreateComments --
  *
- * This routine is handed the oid and the command associated
- * with that id and will insert, update, or delete (if the
- * comment is an empty string or a NULL pointer) the associated
- * comment from the system cataloge, pg_description.
+ * Create a comment for the specified object descriptor.  Inserts a new
+ * pg_description tuple, or replaces an existing one with the same key.
  *
+ * If the comment given is null or an empty string, instead delete any
+ * existing comment for the specified key.
  *------------------------------------------------------------------
  */
 
-static void
-CreateComments(Oid oid, char *comment)
+void
+CreateComments(Oid oid, Oid classoid, int32 subid, char *comment)
 {
-
    Relation    description;
-   TupleDesc   tupDesc;
-   HeapScanDesc scan;
-   ScanKeyData entry;
-   HeapTuple   desctuple = NULL,
-               searchtuple;
+   Relation    descriptionindex;
+   ScanKeyData skey[3];
+   IndexScanDesc sd;
+   RetrieveIndexResult indexRes;
+   HeapTupleData oldtuple;
+   Buffer      buffer;
+   HeapTuple   newtuple = NULL;
    Datum       values[Natts_pg_description];
    char        nulls[Natts_pg_description];
    char        replaces[Natts_pg_description];
-   bool        modified = false;
    int         i;
 
-   /*** Open pg_description, form a new tuple, if necessary ***/
+   /* Reduce empty-string to NULL case */
+   if (comment != NULL && strlen(comment) == 0)
+       comment = NULL;
 
-   description = heap_openr(DescriptionRelationName, RowExclusiveLock);
-   tupDesc = description->rd_att;
-   if ((comment != NULL) && (strlen(comment) > 0))
+   /* Prepare to form or update a tuple, if necessary */
+   if (comment != NULL)
    {
        for (i = 0; i < Natts_pg_description; i++)
        {
            nulls[i] = ' ';
            replaces[i] = 'r';
-           values[i] = (Datum) NULL;
        }
        i = 0;
        values[i++] = ObjectIdGetDatum(oid);
+       values[i++] = ObjectIdGetDatum(classoid);
+       values[i++] = Int32GetDatum(subid);
        values[i++] = DirectFunctionCall1(textin, CStringGetDatum(comment));
    }
 
-   /*** Now, open pg_description and attempt to find the old tuple ***/
+   /* Open pg_description and its index */
 
-   ScanKeyEntryInitialize(&entry, 0x0, Anum_pg_description_objoid, F_OIDEQ,
+   description = heap_openr(DescriptionRelationName, RowExclusiveLock);
+   descriptionindex = index_openr(DescriptionObjIndex);
+
+   /* Use the index to search for a matching old tuple */
+
+   ScanKeyEntryInitialize(&skey[0],
+                          (bits16) 0x0,
+                          (AttrNumber) 1,
+                          (RegProcedure) F_OIDEQ,
                           ObjectIdGetDatum(oid));
-   scan = heap_beginscan(description, false, SnapshotNow, 1, &entry);
-   searchtuple = heap_getnext(scan, 0);
 
-   /*** If a previous tuple exists, either delete or prep replacement ***/
+   ScanKeyEntryInitialize(&skey[1],
+                          (bits16) 0x0,
+                          (AttrNumber) 2,
+                          (RegProcedure) F_OIDEQ,
+                          ObjectIdGetDatum(classoid));
+
+   ScanKeyEntryInitialize(&skey[2],
+                          (bits16) 0x0,
+                          (AttrNumber) 3,
+                          (RegProcedure) F_INT4EQ,
+                          Int32GetDatum(subid));
+
+   sd = index_beginscan(descriptionindex, false, 3, skey);
 
-   if (HeapTupleIsValid(searchtuple))
+   oldtuple.t_datamcxt = CurrentMemoryContext;
+   oldtuple.t_data = NULL;
+
+   while ((indexRes = index_getnext(sd, ForwardScanDirection)))
    {
+       oldtuple.t_self = indexRes->heap_iptr;
+       heap_fetch(description, SnapshotNow, &oldtuple, &buffer, sd);
+       pfree(indexRes);
+
+       if (oldtuple.t_data == NULL)
+           continue;           /* time qual failed */
 
-       /*** If the comment is blank, delete old entry, else update it ***/
+       /* Found the old tuple, so delete or update it */
 
-       if ((comment == NULL) || (strlen(comment) == 0))
-           simple_heap_delete(description, &searchtuple->t_self);
+       if (comment == NULL)
+           simple_heap_delete(description, &oldtuple.t_self);
        else
        {
-           desctuple = heap_modifytuple(searchtuple, description, values,
-                                        nulls, replaces);
-           simple_heap_update(description, &searchtuple->t_self, desctuple);
-           modified = TRUE;
+           newtuple = heap_modifytuple(&oldtuple, description, values,
+                                       nulls, replaces);
+           simple_heap_update(description, &oldtuple.t_self, newtuple);
        }
 
+       ReleaseBuffer(buffer);
+       break;                  /* Assume there can be only one match */
    }
-   else
-   {
 
-       /*** Only if comment is non-blank do we form a new tuple ***/
+   index_endscan(sd);
 
-       if ((comment != NULL) && (strlen(comment) > 0))
-       {
-           desctuple = heap_formtuple(tupDesc, values, nulls);
-           heap_insert(description, desctuple);
-           modified = TRUE;
-       }
+   /* If we didn't find an old tuple, insert a new one */
 
+   if (oldtuple.t_data == NULL && comment != NULL)
+   {
+       newtuple = heap_formtuple(RelationGetDescr(description),
+                                 values, nulls);
+       heap_insert(description, newtuple);
    }
 
-   /*** Complete the scan, update indices, if necessary ***/
+   /* Update indexes, if necessary */
 
-   heap_endscan(scan);
-
-   if (modified)
+   if (newtuple != NULL)
    {
        if (RelationGetForm(description)->relhasindex)
        {
            CatalogOpenIndices(Num_pg_description_indices,
                               Name_pg_description_indices, idescs);
            CatalogIndexInsert(idescs, Num_pg_description_indices, description,
-                              desctuple);
+                              newtuple);
            CatalogCloseIndices(Num_pg_description_indices, idescs);
        }
-       heap_freetuple(desctuple);
-
+       heap_freetuple(newtuple);
    }
 
-   heap_close(description, RowExclusiveLock);
+   /* Done */
 
+   index_close(descriptionindex);
+   heap_close(description, NoLock);
 }
 
 /*------------------------------------------------------------------
  * DeleteComments --
  *
- * This routine is used to purge any comments
- * associated with the Oid handed to this routine,
- * regardless of the actual object type. It is
- * called, for example, when a relation is destroyed.
+ * This routine is used to purge all comments associated with an object,
+ * regardless of their objsubid.  It is called, for example, when a relation
+ * is destroyed.
  *------------------------------------------------------------------
  */
 
 void
-DeleteComments(Oid oid)
+DeleteComments(Oid oid, Oid classoid)
 {
-
    Relation    description;
-   TupleDesc   tupDesc;
-   ScanKeyData entry;
-   HeapScanDesc scan;
-   HeapTuple   searchtuple;
+   Relation    descriptionindex;
+   ScanKeyData skey[2];
+   IndexScanDesc sd;
+   RetrieveIndexResult indexRes;
+   HeapTupleData oldtuple;
+   Buffer      buffer;
+
+   /* Open pg_description and its index */
 
    description = heap_openr(DescriptionRelationName, RowExclusiveLock);
-   tupDesc = description->rd_att;
+   descriptionindex = index_openr(DescriptionObjIndex);
 
-   /*** Now, open pg_description and attempt to find the old tuple ***/
+   /* Use the index to search for all matching old tuples */
 
-   ScanKeyEntryInitialize(&entry, 0x0, Anum_pg_description_objoid, F_OIDEQ,
+   ScanKeyEntryInitialize(&skey[0],
+                          (bits16) 0x0,
+                          (AttrNumber) 1,
+                          (RegProcedure) F_OIDEQ,
                           ObjectIdGetDatum(oid));
-   scan = heap_beginscan(description, false, SnapshotNow, 1, &entry);
-   searchtuple = heap_getnext(scan, 0);
 
-   /*** If a previous tuple exists, delete it ***/
+   ScanKeyEntryInitialize(&skey[1],
+                          (bits16) 0x0,
+                          (AttrNumber) 2,
+                          (RegProcedure) F_OIDEQ,
+                          ObjectIdGetDatum(classoid));
+
+   sd = index_beginscan(descriptionindex, false, 2, skey);
 
-   if (HeapTupleIsValid(searchtuple))
-       simple_heap_delete(description, &searchtuple->t_self);
+   while ((indexRes = index_getnext(sd, ForwardScanDirection)))
+   {
+       oldtuple.t_self = indexRes->heap_iptr;
+       heap_fetch(description, SnapshotNow, &oldtuple, &buffer, sd);
+       pfree(indexRes);
 
-   /*** Complete the scan, update indices, if necessary ***/
+       if (oldtuple.t_data == NULL)
+           continue;           /* time qual failed */
 
-   heap_endscan(scan);
-   heap_close(description, RowExclusiveLock);
+       simple_heap_delete(description, &oldtuple.t_self);
+
+       ReleaseBuffer(buffer);
+   }
+
+   /* Done */
 
+   index_endscan(sd);
+   index_close(descriptionindex);
+   heap_close(description, NoLock);
 }
 
 /*------------------------------------------------------------------
  * the appropriate tuple, and inserting a comment using that
  * tuple's oid. Its parameters are the relation name and comments.
  *------------------------------------------------------------------
-*/
+ */
 
 static void
 CommentRelation(int reltype, char *relname, char *comment)
 {
-   HeapTuple   reltuple;
-   Oid         oid;
-   char        relkind;
+   Relation    relation;
 
-   /*** First, check object security ***/
+   /* First, check object security */
 
    if (!pg_ownercheck(GetUserId(), relname, RELNAME))
        elog(ERROR, "you are not permitted to comment on class '%s'", relname);
 
-   /*** Now, attempt to find the oid in the cached version of pg_class ***/
-
-   reltuple = SearchSysCache(RELNAME,
-                             PointerGetDatum(relname),
-                             0, 0, 0);
-   if (!HeapTupleIsValid(reltuple))
-       elog(ERROR, "relation '%s' does not exist", relname);
-
-   oid = reltuple->t_data->t_oid;
-
-   relkind = ((Form_pg_class) GETSTRUCT(reltuple))->relkind;
-
-   ReleaseSysCache(reltuple);
+   /*
+    * Open the relation.  We do this mainly to acquire a lock that ensures
+    * no one else drops the relation before we commit.  (If they did, they'd
+    * fail to remove the entry we are about to make in pg_description.)
+    *
+    * heap_openr will complain if it's an index, so we must do this:
+    */
+   if (reltype != INDEX)
+       relation = heap_openr(relname, AccessShareLock);
+   else
+   {
+       relation = index_openr(relname);
+       LockRelation(relation, AccessShareLock);
+   }
 
-   /*** Next, verify that the relation type matches the intent ***/
+   /* Next, verify that the relation type matches the intent */
 
    switch (reltype)
    {
-       case (INDEX):
-           if (relkind != RELKIND_INDEX)
+       case INDEX:
+           if (relation->rd_rel->relkind != RELKIND_INDEX)
                elog(ERROR, "relation '%s' is not an index", relname);
            break;
-       case (TABLE):
-           if (relkind != RELKIND_RELATION)
+       case TABLE:
+           if (relation->rd_rel->relkind != RELKIND_RELATION)
                elog(ERROR, "relation '%s' is not a table", relname);
            break;
-       case (VIEW):
-           if (relkind != RELKIND_VIEW)
+       case VIEW:
+           if (relation->rd_rel->relkind != RELKIND_VIEW)
                elog(ERROR, "relation '%s' is not a view", relname);
            break;
-       case (SEQUENCE):
-           if (relkind != RELKIND_SEQUENCE)
+       case SEQUENCE:
+           if (relation->rd_rel->relkind != RELKIND_SEQUENCE)
                elog(ERROR, "relation '%s' is not a sequence", relname);
            break;
    }
 
-   /*** Create the comments using the tuple's oid ***/
+   /* Create the comment using the relation's oid */
+
+   CreateComments(RelationGetRelid(relation), RelOid_pg_class, 0, comment);
 
-   CreateComments(oid, comment);
+   /* Done, but hold lock until commit */
+
+   if (reltype != INDEX)
+       heap_close(relation, NoLock);
+   else
+       index_close(relation);
 }
 
 /*------------------------------------------------------------------
  *
  * This routine is used to add/drop a comment from an attribute
  * such as a table's column. The routine will check security
- * restrictions and then attempt to fetch the oid of the associated
+ * restrictions and then attempt to look up the specified
  * attribute. If successful, a comment is added/dropped, else an
  * elog() exception is thrown. The parameters are the relation
  * and attribute names, and the comments
 CommentAttribute(char *relname, char *attrname, char *comment)
 {
    Relation    relation;
-   Oid         oid;
+   AttrNumber  attnum;
 
-   /*** First, check object security ***/
+   /* First, check object security */
 
    if (!pg_ownercheck(GetUserId(), relname, RELNAME))
-       elog(ERROR, "you are not permitted to comment on class '%s\'", relname);
+       elog(ERROR, "you are not permitted to comment on class '%s'", relname);
 
    /* Open the containing relation to ensure it won't go away meanwhile */
 
    relation = heap_openr(relname, AccessShareLock);
 
-   /*** Now, fetch the attribute oid from the system cache ***/
+   /* Now, fetch the attribute number from the system cache */
 
-   oid = GetSysCacheOid(ATTNAME,
-                        ObjectIdGetDatum(relation->rd_id),
-                        PointerGetDatum(attrname),
-                        0, 0);
-   if (!OidIsValid(oid))
+   attnum = get_attnum(RelationGetRelid(relation), attrname);
+   if (attnum == InvalidAttrNumber)
        elog(ERROR, "'%s' is not an attribute of class '%s'",
             attrname, relname);
 
-   /*** Call CreateComments() to create/drop the comments ***/
+   /* Create the comment using the relation's oid */
 
-   CreateComments(oid, comment);
+   CreateComments(RelationGetRelid(relation), RelOid_pg_class,
+                  (int32) attnum, comment);
 
-   /*** Now, close the heap relation and return ***/
+   /* Done, but hold lock until commit */
 
    heap_close(relation, NoLock);
 }
    HeapTuple   dbtuple;
    Oid         oid;
 
-   /*** First find the tuple in pg_database for the database ***/
+   /* First find the tuple in pg_database for the database */
 
    pg_database = heap_openr(DatabaseRelationName, AccessShareLock);
    ScanKeyEntryInitialize(&entry, 0, Anum_pg_database_datname,
    scan = heap_beginscan(pg_database, 0, SnapshotNow, 1, &entry);
    dbtuple = heap_getnext(scan, 0);
 
-   /*** Validate database exists, and fetch the db oid ***/
+   /* Validate database exists, and fetch the db oid */
 
    if (!HeapTupleIsValid(dbtuple))
        elog(ERROR, "database '%s' does not exist", database);
    oid = dbtuple->t_data->t_oid;
 
-   /*** Allow if the user matches the database dba or is a superuser ***/
+   /* Allow if the user matches the database dba or is a superuser */
 
    if (!(superuser() || is_dbadmin(oid)))
        elog(ERROR, "you are not permitted to comment on database '%s'",
             database);
 
-   /*** Create the comments with the pg_database oid ***/
+   /* Create the comments with the pg_database oid */
 
-   CreateComments(oid, comment);
+   CreateComments(oid, RelOid_pg_database, 0, comment);
 
-   /*** Complete the scan and close any opened relations ***/
+   /* Complete the scan and close any opened relations */
 
    heap_endscan(scan);
    heap_close(pg_database, AccessShareLock);
 CommentRewrite(char *rule, char *comment)
 {
    Oid         oid;
+   Oid         classoid;
    char       *relation;
    int         aclcheck;
 
-   /*** First, validate user ***/
+   /* First, validate user */
 
-#ifndef NO_SECURITY
    relation = RewriteGetRuleEventRel(rule);
    aclcheck = pg_aclcheck(relation, GetUserId(), ACL_RULE);
    if (aclcheck != ACLCHECK_OK)
-   {
        elog(ERROR, "you are not permitted to comment on rule '%s'",
             rule);
-   }
-#endif
 
-   /*** Next, find the rule's oid ***/
+   /* Next, find the rule's oid */
 
    oid = GetSysCacheOid(RULENAME,
                         PointerGetDatum(rule),
    if (!OidIsValid(oid))
        elog(ERROR, "rule '%s' does not exist", rule);
 
-   /*** Call CreateComments() to create/drop the comments ***/
+   /* pg_rewrite doesn't have a hard-coded OID, so must look it up */
+
+   classoid = GetSysCacheOid(RELNAME,
+                             PointerGetDatum(RewriteRelationName),
+                             0, 0, 0);
+   Assert(OidIsValid(classoid));
 
-   CreateComments(oid, comment);
+   /* Call CreateComments() to create/drop the comments */
+
+   CreateComments(oid, classoid, 0, comment);
 }
 
 /*------------------------------------------------------------------
 {
    Oid         oid;
 
-   /*** First, validate user ***/
+   /* First, validate user */
 
    if (!pg_ownercheck(GetUserId(), type, TYPENAME))
        elog(ERROR, "you are not permitted to comment on type '%s'",
             type);
 
-   /*** Next, find the type's oid ***/
+   /* Next, find the type's oid */
 
    oid = GetSysCacheOid(TYPENAME,
                         PointerGetDatum(type),
    if (!OidIsValid(oid))
        elog(ERROR, "type '%s' does not exist", type);
 
-   /*** Call CreateComments() to create/drop the comments ***/
+   /* Call CreateComments() to create/drop the comments */
 
-   CreateComments(oid, comment);
+   CreateComments(oid, RelOid_pg_type, 0, comment);
 }
 
 /*------------------------------------------------------------------
    char       *aggtypename = NULL;
    Oid         baseoid,
                oid;
+   Oid         classoid;
    bool        defined;
 
-   /*** First, attempt to determine the base aggregate oid ***/
+   /* First, attempt to determine the base aggregate oid */
 
    if (aggtype)
    {
            elog(ERROR, "type '%s' does not exist", aggtypename);
    }
    else
-       baseoid = 0;
+       baseoid = InvalidOid;
 
-   /*** Next, validate the user's attempt to comment ***/
+   /* Next, validate the user's attempt to comment */
 
    if (!pg_aggr_ownercheck(GetUserId(), aggregate, baseoid))
    {
        if (aggtypename)
-           elog(ERROR, "you are not permitted to comment on aggregate '%s' %s '%s'",
-                aggregate, "with type", aggtypename);
+           elog(ERROR, "you are not permitted to comment on aggregate '%s' with type '%s'",
+                aggregate, aggtypename);
        else
            elog(ERROR, "you are not permitted to comment on aggregate '%s'",
                 aggregate);
    }
 
-   /*** Now, attempt to find the actual tuple in pg_aggregate ***/
+   /* Now, attempt to find the actual tuple in pg_aggregate */
 
    oid = GetSysCacheOid(AGGNAME,
                         PointerGetDatum(aggregate),
    if (!OidIsValid(oid))
    {
        if (aggtypename)
-       {
            elog(ERROR, "aggregate type '%s' does not exist for aggregate '%s'",
                 aggtypename, aggregate);
-       }
        else
            elog(ERROR, "aggregate '%s' does not exist", aggregate);
    }
 
-   /*** Call CreateComments() to create/drop the comments ***/
+   /* pg_aggregate doesn't have a hard-coded OID, so must look it up */
+
+   classoid = GetSysCacheOid(RELNAME,
+                             PointerGetDatum(AggregateRelationName),
+                             0, 0, 0);
+   Assert(OidIsValid(classoid));
 
-   CreateComments(oid, comment);
+   /* Call CreateComments() to create/drop the comments */
+
+   CreateComments(oid, classoid, 0, comment);
 }
 
 /*------------------------------------------------------------------
    int         i,
                argcount;
 
-   /*** First, initialize function's argument list with their type oids ***/
+   /* First, initialize function's argument list with their type oids */
 
    MemSet(argoids, 0, FUNC_MAX_ARGS * sizeof(Oid));
    argcount = length(arguments);
        }
    }
 
-   /*** Now, validate the user's ability to comment on this function ***/
+   /* Now, validate the user's ability to comment on this function */
 
    if (!pg_func_ownercheck(GetUserId(), function, argcount, argoids))
        elog(ERROR, "you are not permitted to comment on function '%s'",
             function);
 
-   /*** Now, find the corresponding oid for this procedure ***/
+   /* Now, find the corresponding oid for this procedure */
 
    oid = GetSysCacheOid(PROCNAME,
                         PointerGetDatum(function),
    if (!OidIsValid(oid))
        func_error("CommentProc", function, argcount, argoids, NULL);
 
-   /*** Call CreateComments() to create/drop the comments ***/
+   /* Call CreateComments() to create/drop the comments */
 
-   CreateComments(oid, comment);
+   CreateComments(oid, RelOid_pg_proc, 0, comment);
 }
 
 /*------------------------------------------------------------------
  * expected to be a couple of parse nodes pointed to be a List
  * object. If the comments string is empty, the associated comment
  * is dropped.
+ *
+ * NOTE: we actually attach the comment to the procedure that underlies
+ * the operator.  This is a feature, not a bug: we want the same comment
+ * to be visible for both operator and function.
  *------------------------------------------------------------------
 */
 
                rightoid = InvalidOid;
    bool        defined;
 
-   /*** Initialize our left and right argument types ***/
+   /* Initialize our left and right argument types */
 
    if (typenode1 != NULL)
        lefttype = TypeNameToInternalName(typenode1);
    if (typenode2 != NULL)
        righttype = TypeNameToInternalName(typenode2);
 
-   /*** Attempt to fetch the left oid, if specified ***/
+   /* Attempt to fetch the left oid, if specified */
 
    if (lefttype != NULL)
    {
            elog(ERROR, "left type '%s' does not exist", lefttype);
    }
 
-   /*** Attempt to fetch the right oid, if specified ***/
+   /* Attempt to fetch the right oid, if specified */
 
    if (righttype != NULL)
    {
            elog(ERROR, "right type '%s' does not exist", righttype);
    }
 
-   /*** Determine operator type ***/
+   /* Determine operator type */
 
    if (OidIsValid(leftoid) && (OidIsValid(rightoid)))
        oprtype = 'b';
    else
        elog(ERROR, "operator '%s' is of an illegal type'", opername);
 
-   /*** Attempt to fetch the operator oid ***/
+   /* Attempt to fetch the operator oid */
 
    optuple = SearchSysCache(OPERNAME,
                             PointerGetDatum(opername),
 
    oid = optuple->t_data->t_oid;
 
-   /*** Valid user's ability to comment on this operator ***/
+   /* Valid user's ability to comment on this operator */
 
    if (!pg_oper_ownercheck(GetUserId(), oid))
        elog(ERROR, "you are not permitted to comment on operator '%s'",
             opername);
 
-   /*** Get the procedure associated with the operator ***/
+   /* Get the procedure associated with the operator */
 
    data = (Form_pg_operator) GETSTRUCT(optuple);
    oid = data->oprcode;
 
    ReleaseSysCache(optuple);
 
-   /*** Call CreateComments() to create/drop the comments ***/
+   /* Call CreateComments() to create/drop the comments */
 
-   CreateComments(oid, comment);
+   CreateComments(oid, RelOid_pg_proc, 0, comment);
 }
 
 /*------------------------------------------------------------------
 static void
 CommentTrigger(char *trigger, char *relname, char *comment)
 {
-
-   Form_pg_trigger data;
    Relation    pg_trigger,
                relation;
    HeapTuple   triggertuple;
    HeapScanDesc scan;
-   ScanKeyData entry;
-   Oid         oid = InvalidOid;
+   ScanKeyData entry[2];
+   Oid         oid;
 
-   /*** First, validate the user's action ***/
+   /* First, validate the user's action */
 
    if (!pg_ownercheck(GetUserId(), relname, RELNAME))
        elog(ERROR, "you are not permitted to comment on trigger '%s' %s '%s'",
             trigger, "defined for relation", relname);
 
-   /*** Now, fetch the trigger oid from pg_trigger  ***/
+   /* Now, fetch the trigger oid from pg_trigger  */
 
    relation = heap_openr(relname, AccessShareLock);
    pg_trigger = heap_openr(TriggerRelationName, AccessShareLock);
-   ScanKeyEntryInitialize(&entry, 0, Anum_pg_trigger_tgrelid,
-                          F_OIDEQ, RelationGetRelid(relation));
-   scan = heap_beginscan(pg_trigger, 0, SnapshotNow, 1, &entry);
+   ScanKeyEntryInitialize(&entry[0], 0x0, Anum_pg_trigger_tgrelid,
+                          F_OIDEQ,
+                          ObjectIdGetDatum(RelationGetRelid(relation)));
+   ScanKeyEntryInitialize(&entry[1], 0x0, Anum_pg_trigger_tgname,
+                          F_NAMEEQ,
+                          NameGetDatum(trigger));
+   scan = heap_beginscan(pg_trigger, 0, SnapshotNow, 2, entry);
    triggertuple = heap_getnext(scan, 0);
-   while (HeapTupleIsValid(triggertuple))
-   {
-       data = (Form_pg_trigger) GETSTRUCT(triggertuple);
-       if (namestrcmp(&(data->tgname), trigger) == 0)
-       {
-           oid = triggertuple->t_data->t_oid;
-           break;
-       }
-       triggertuple = heap_getnext(scan, 0);
-   }
 
-   /*** If no trigger exists for the relation specified, notify user ***/
+   /* If no trigger exists for the relation specified, notify user */
 
-   if (oid == InvalidOid)
-   {
+   if (!HeapTupleIsValid(triggertuple))
        elog(ERROR, "trigger '%s' defined for relation '%s' does not exist",
             trigger, relname);
-   }
 
-   /*** Create the comments with the pg_trigger oid ***/
+   oid = triggertuple->t_data->t_oid;
 
-   CreateComments(oid, comment);
+   heap_endscan(scan);
 
-   /*** Complete the scan and close any opened relations ***/
+   /* Create the comments with the pg_trigger oid */
+
+   CreateComments(oid, RelationGetRelid(pg_trigger), 0, comment);
+
+   /* Done, but hold lock on relation */
 
-   heap_endscan(scan);
    heap_close(pg_trigger, AccessShareLock);
    heap_close(relation, NoLock);
 }
 
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.140 2001/07/11 21:53:59 momjian Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.141 2001/08/10 18:57:34 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 
 /*
  *  DoCopy executes the SQL COPY statement.
+ *
+ * Either unload or reload contents of table <relname>, depending on <from>.
+ * (<from> = TRUE means we are inserting into the table.)
+ *
+ * If <pipe> is false, transfer is between the table and the file named
+ * <filename>.  Otherwise, transfer is between the table and our regular
+ * input/output stream.    The latter could be either stdin/stdout or a
+ * socket, depending on whether we're running under Postmaster control.
+ *
+ * Iff <binary>, unload or reload in the binary format, as opposed to the
+ * more wasteful but more robust and portable text format.
+ *
+ * Iff <oids>, unload or reload the format that includes OID information.
+ * On input, we accept OIDs whether or not the table has an OID column,
+ * but silently drop them if it does not.  On output, we report an error
+ * if the user asks for OIDs in a table that has none (not providing an
+ * OID column might seem friendlier, but could seriously confuse programs).
+ *
+ * If in the text format, delimit columns with delimiter <delim> and print
+ * NULL values as <null_print>.
+ *
+ * When loading in the text format from an input stream (as opposed to
+ * a file), recognize a "." on a line by itself as EOF.    Also recognize
+ * a stream EOF.  When unloading in the text format to an output stream,
+ * write a "." on a line by itself at the end of the data.
+ *
+ * Do not allow a Postgres user without superuser privilege to read from
+ * or write to a file.
+ *
+ * Do not allow the copy if user doesn't have proper permission to access
+ * the table.
  */
-
 void
 DoCopy(char *relname, bool binary, bool oids, bool from, bool pipe,
       char *filename, char *delim, char *null_print)
 {
-/*----------------------------------------------------------------------------
-  Either unload or reload contents of class <relname>, depending on <from>.
-
-  If <pipe> is false, transfer is between the class and the file named
-  <filename>.  Otherwise, transfer is between the class and our regular
-  input/output stream. The latter could be either stdin/stdout or a
-  socket, depending on whether we're running under Postmaster control.
-
-  Iff <binary>, unload or reload in the binary format, as opposed to the
-  more wasteful but more robust and portable text format.
-
-  If in the text format, delimit columns with delimiter <delim> and print
-  NULL values as <null_print>.
-
-  When loading in the text format from an input stream (as opposed to
-  a file), recognize a "." on a line by itself as EOF. Also recognize
-  a stream EOF.  When unloading in the text format to an output stream,
-  write a "." on a line by itself at the end of the data.
-
-  Iff <oids>, unload or reload the format that includes OID information.
-
-  Do not allow a Postgres user without superuser privilege to read from
-  or write to a file.
-
-  Do not allow the copy if user doesn't have proper permission to access
-  the class.
-----------------------------------------------------------------------------*/
-
    FILE       *fp;
    Relation    rel;
-   const AclMode required_access = from ? ACL_INSERT : ACL_SELECT;
+   const AclMode required_access = (from ? ACL_INSERT : ACL_SELECT);
    int         result;
 
    /*
 
    if (from)
    {                           /* copy from file to database */
-       if (rel->rd_rel->relkind == RELKIND_SEQUENCE)
-           elog(ERROR, "You cannot change sequence relation %s", relname);
-       if (rel->rd_rel->relkind == RELKIND_VIEW)
-           elog(ERROR, "You cannot copy view %s", relname);
+       if (rel->rd_rel->relkind != RELKIND_RELATION)
+       {
+           if (rel->rd_rel->relkind == RELKIND_VIEW)
+               elog(ERROR, "You cannot copy view %s", relname);
+           else if (rel->rd_rel->relkind == RELKIND_SEQUENCE)
+               elog(ERROR, "You cannot change sequence relation %s", relname);
+           else
+               elog(ERROR, "You cannot copy object %s", relname);
+       }
        if (pipe)
        {
            if (IsUnderPostmaster)
    }
    else
    {                           /* copy from database to file */
-       if (rel->rd_rel->relkind == RELKIND_VIEW)
-           elog(ERROR, "You cannot copy view %s", relname);
+       if (rel->rd_rel->relkind != RELKIND_RELATION)
+       {
+           if (rel->rd_rel->relkind == RELKIND_VIEW)
+               elog(ERROR, "You cannot copy view %s", relname);
+           else if (rel->rd_rel->relkind == RELKIND_SEQUENCE)
+               elog(ERROR, "You cannot copy sequence %s", relname);
+           else
+               elog(ERROR, "You cannot copy object %s", relname);
+       }
        if (pipe)
        {
            if (IsUnderPostmaster)
    int16       fld_size;
    char       *string;
 
+   if (oids && !rel->rd_rel->relhasoids)
+       elog(ERROR, "COPY: table %s does not have OIDs",
+            RelationGetRelationName(rel));
+
    tupDesc = rel->rd_att;
    attr_count = rel->rd_att->natts;
    attr = rel->rd_att->attrs;
        elements = NULL;
    }
 
+   /* Silently drop incoming OIDs if table does not have OIDs */
+   if (!rel->rd_rel->relhasoids)
+       oids = false;
+
    values = (Datum *) palloc(attr_count * sizeof(Datum));
    nulls = (char *) palloc(attr_count * sizeof(char));
 
 
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/commands/Attic/creatinh.c,v 1.78 2001/06/22 21:37:14 momjian Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/commands/Attic/creatinh.c,v 1.79 2001/08/10 18:57:34 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
  */
 
 static List *MergeAttributes(List *schema, List *supers, bool istemp,
-               List **supOids, List **supconstr);
+               List **supOids, List **supconstr, bool *supHasOids);
 static bool change_varattnos_of_a_node(Node *node, const AttrNumber *newattno);
 static void StoreCatalogInheritance(Oid relationId, List *supers);
 static int findAttrByName(const char *attributeName, List *schema);
    TupleDesc   descriptor;
    List       *inheritOids;
    List       *old_constraints;
+   bool        parentHasOids;
    List       *rawDefaults;
    List       *listptr;
    int         i;
     * including inherited attributes.
     */
    schema = MergeAttributes(schema, stmt->inhRelnames, stmt->istemp,
-                            &inheritOids, &old_constraints);
+                            &inheritOids, &old_constraints, &parentHasOids);
 
    numberOfAttributes = length(schema);
    if (numberOfAttributes <= 0)
    }
 
    relationId = heap_create_with_catalog(relname, descriptor,
-                                         relkind, stmt->istemp,
+                                         relkind,
+                                         stmt->hasoids || parentHasOids,
+                                         stmt->istemp,
                                          allowSystemTableMods);
 
    StoreCatalogInheritance(relationId, inheritOids);
  * 'supOids' receives an integer list of the OIDs of the parent relations.
  * 'supconstr' receives a list of constraints belonging to the parents,
  *     updated as necessary to be valid for the child.
+ * 'supHasOids' is set TRUE if any parent has OIDs, else it is set FALSE.
  *
  * Return value:
  * Completed schema list.
  */
 static List *
 MergeAttributes(List *schema, List *supers, bool istemp,
-               List **supOids, List **supconstr)
+               List **supOids, List **supconstr, bool *supHasOids)
 {
    List       *entry;
    List       *inhSchema = NIL;
    List       *parentOids = NIL;
    List       *constraints = NIL;
+   bool        parentHasOids = false;
    bool        have_bogus_defaults = false;
    char       *bogus_marker = "Bogus!"; /* marks conflicting defaults */
    int         child_attno;
 
    /*
     * Scan the parents left-to-right, and merge their attributes to form
-    * a list of inherited attributes (inhSchema).
+    * a list of inherited attributes (inhSchema).  Also check to see if
+    * we need to inherit an OID column.
     */
    child_attno = 0;
    foreach(entry, supers)
        parentOids = lappendi(parentOids, relation->rd_id);
        setRelhassubclassInRelation(relation->rd_id, true);
 
+       parentHasOids |= relation->rd_rel->relhasoids;
+
        tupleDesc = RelationGetDescr(relation);
        constr = tupleDesc->constr;
 
 
    *supOids = parentOids;
    *supconstr = constraints;
+   *supHasOids = parentHasOids;
    return schema;
 }
 
 
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/commands/dbcommands.c,v 1.77 2001/08/04 00:14:43 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/commands/dbcommands.c,v 1.78 2001/08/10 18:57:34 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 
    heap_endscan(pgdbscan);
 
+   /* Delete any comments associated with the database */
+   DeleteComments(db_id, RelationGetRelid(pgdbrel));
+
    /*
     * Close pg_database, but keep exclusive lock till commit to ensure
     * that any new backend scanning pg_database will see the tuple dead.
     */
    heap_close(pgdbrel, NoLock);
 
-   /* Delete any comments associated with the database */
-   DeleteComments(db_id);
-
    /*
     * Drop pages for this database that are in the shared buffer cache.
     * This is important to ensure that no remaining backend tries to
 
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.55 2001/08/09 18:28:17 petere Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.56 2001/08/10 18:57:34 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
     * backends to flush their relcache entries and in particular their
     * cached lists of the indexes for this relation.
     */
-   setRelhasindex(relationId, true);
+   setRelhasindex(relationId, true, primary, InvalidOid);
 }
 
 
 
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/commands/Attic/remove.c,v 1.61 2001/06/05 19:34:56 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/commands/Attic/remove.c,v 1.62 2001/08/10 18:57:34 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
            elog(ERROR, "RemoveOperator: operator '%s': permission denied",
                 operatorName);
 
-       /*** Delete any comments associated with this operator ***/
-
-       DeleteComments(tup->t_data->t_oid);
+       /* Delete any comments associated with this operator */
+       DeleteComments(tup->t_data->t_oid, RelationGetRelid(relation));
 
        simple_heap_delete(relation, &tup->t_self);
 
        scan = heap_beginscan(rel, 0, SnapshotNow, 1, key);
        while (HeapTupleIsValid(tup = heap_getnext(scan, 0)))
        {
-
-           /*** This is apparently a routine not in use, but remove ***/
-           /*** any comments anyways ***/
-
-           DeleteComments(tup->t_data->t_oid);
+           /* Delete any comments associated with this operator */
+           DeleteComments(tup->t_data->t_oid, RelationGetRelid(rel));
 
            simple_heap_delete(rel, &tup->t_self);
        }
 {
    Relation    relation;
    HeapTuple   tup;
-   Oid         typeOid;
    char       *shadow_type;
 
    if (!pg_ownercheck(GetUserId(), typeName, TYPENAME))
    if (!HeapTupleIsValid(tup))
        elog(ERROR, "RemoveType: type '%s' does not exist", typeName);
 
-   typeOid = tup->t_data->t_oid;
-
-   /*** Delete any comments associated with this type ***/
-
-   DeleteComments(typeOid);
+   /* Delete any comments associated with this type */
+   DeleteComments(tup->t_data->t_oid, RelationGetRelid(relation));
 
    simple_heap_delete(relation, &tup->t_self);
 
        elog(NOTICE, "Removing built-in function \"%s\"", functionName);
    }
 
-   /*** Delete any comments associated with this function ***/
-
-   DeleteComments(tup->t_data->t_oid);
+   /* Delete any comments associated with this function */
+   DeleteComments(tup->t_data->t_oid, RelationGetRelid(relation));
 
    simple_heap_delete(relation, &tup->t_self);
 
        }
    }
 
-   /*** Remove any comments related to this aggregate ***/
-
-   DeleteComments(tup->t_data->t_oid);
+   /* Remove any comments related to this aggregate */
+   DeleteComments(tup->t_data->t_oid, RelationGetRelid(relation));
 
    simple_heap_delete(relation, &tup->t_self);
 
 
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/commands/sequence.c,v 1.61 2001/06/29 21:08:24 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/commands/sequence.c,v 1.62 2001/08/10 18:57:34 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
    }
 
    stmt->relname = seq->seqname;
-   stmt->istemp = seq->istemp;
    stmt->inhRelnames = NIL;
    stmt->constraints = NIL;
+   stmt->istemp = seq->istemp;
+   stmt->hasoids = false;
 
    DefineRelation(stmt, RELKIND_SEQUENCE);
 
 
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.94 2001/08/02 15:59:28 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.95 2001/08/10 18:57:34 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 
        if (namestrcmp(&(pg_trigger->tgname), stmt->trigname) == 0)
        {
-
-           /*** Delete any comments associated with this trigger ***/
-
-           DeleteComments(tuple->t_data->t_oid);
+           /* Delete any comments associated with this trigger */
+           DeleteComments(tuple->t_data->t_oid, RelationGetRelid(tgrel));
 
            simple_heap_delete(tgrel, &tuple->t_self);
            tgfound++;
 
    while (HeapTupleIsValid(tup = heap_getnext(tgscan, 0)))
    {
-
-       /*** Delete any comments associated with this trigger ***/
-
-       DeleteComments(tup->t_data->t_oid);
+       /* Delete any comments associated with this trigger */
+       DeleteComments(tup->t_data->t_oid, RelationGetRelid(tgrel));
 
        simple_heap_delete(tgrel, &tup->t_self);
 
 
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.206 2001/07/18 00:46:24 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.207 2001/08/10 18:57:35 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
    pgcform->relpages = (int32) num_pages;
    pgcform->reltuples = num_tuples;
    pgcform->relhasindex = hasindex;
+   /*
+    * If we have discovered that there are no indexes, then there's
+    * no primary key either.  This could be done more thoroughly...
+    */
+   if (!hasindex)
+       pgcform->relhaspkey = false;
 
    /* invalidate the tuple in the cache and write the buffer */
    RelationInvalidateHeapTuple(rd, &rtup);
            /*
             * Other checks...
             */
-           if (!OidIsValid(tuple.t_data->t_oid))
+           if (!OidIsValid(tuple.t_data->t_oid) &&
+               onerel->rd_rel->relhasoids)
                elog(NOTICE, "Rel %s: TID %u/%u: OID IS INVALID. TUPGONE %d.",
                     relname, blkno, offnum, (int) tupgone);
 
 
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/commands/vacuumlazy.c,v 1.3 2001/07/18 00:46:25 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/commands/vacuumlazy.c,v 1.4 2001/08/10 18:57:35 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
            /*
             * Other checks...
             */
-           if (!OidIsValid(tuple.t_data->t_oid))
+           if (!OidIsValid(tuple.t_data->t_oid) &&
+               onerel->rd_rel->relhasoids)
                elog(NOTICE, "Rel %s: TID %u/%u: OID IS INVALID. TUPGONE %d.",
                     relname, blkno, offnum, (int) tupgone);
 
 
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: view.c,v 1.54 2001/03/22 03:59:25 momjian Exp $
+ * $Id: view.c,v 1.55 2001/08/10 18:57:35 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
     * nil...
     */
    createStmt->relname = relname;
-   createStmt->istemp = false;
    createStmt->tableElts = attrList;
    createStmt->inhRelnames = NIL;
    createStmt->constraints = NIL;
+   createStmt->istemp = false;
+   createStmt->hasoids = false;
 
    /*
     * finally create the relation...
 
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.144 2001/06/22 19:16:22 wieck Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.145 2001/08/10 18:57:35 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
                intoRelationId =
                    heap_create_with_catalog(intoName,
                                             tupdesc,
-                                            RELKIND_RELATION,
+                                            RELKIND_RELATION, true,
                                             parseTree->isTemp,
                                             allowSystemTableMods);
 
 
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.151 2001/08/10 14:30:14 momjian Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.152 2001/08/10 18:57:36 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 {
    CreateStmt *newnode = makeNode(CreateStmt);
 
-   newnode->istemp = from->istemp;
    newnode->relname = pstrdup(from->relname);
    Node_Copy(from, newnode, tableElts);
    Node_Copy(from, newnode, inhRelnames);
    Node_Copy(from, newnode, constraints);
+   newnode->istemp = from->istemp;
+   newnode->hasoids = from->hasoids;
 
    return newnode;
 }
 
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.99 2001/08/10 14:30:14 momjian Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.100 2001/08/10 18:57:36 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 static bool
 _equalCreateStmt(CreateStmt *a, CreateStmt *b)
 {
-   if (a->istemp != b->istemp)
-       return false;
    if (!equalstr(a->relname, b->relname))
        return false;
    if (!equal(a->tableElts, b->tableElts))
        return false;
    if (!equal(a->constraints, b->constraints))
        return false;
+   if (a->istemp != b->istemp)
+       return false;
+   if (a->hasoids != b->hasoids)
+       return false;
 
    return true;
 }
 
  * 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.142 2001/06/19 22:39:11 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.143 2001/08/10 18:57:36 tgl Exp $
  *
  * NOTES
  *   Every (plan) node in POSTGRES has an associated "out" routine which
    appendStringInfo(str, " CREATE :relname ");
    _outToken(str, node->relname);
 
-   appendStringInfo(str, " :istemp %s ",
-                    booltostr(node->istemp));
-
    appendStringInfo(str, " :columns ");
    _outNode(str, node->tableElts);
 
 
    appendStringInfo(str, " :constraints ");
    _outNode(str, node->constraints);
+
+   appendStringInfo(str, " :istemp %s :hasoids %s ",
+                    booltostr(node->istemp),
+                    booltostr(node->hasoids));
 }
 
 static void
 
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.242 2001/08/10 14:30:14 momjian Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.243 2001/08/10 18:57:36 tgl Exp $
  *
  * HISTORY
  *   AUTHOR            DATE            MAJOR EVENT
 
 %type <typnam> func_arg, func_return, func_type, aggr_argtype
 
-%type <boolean>    opt_arg, TriggerForOpt, TriggerForType, OptTemp
+%type <boolean>    opt_arg, TriggerForOpt, TriggerForType, OptTemp, OptWithOids
 
 %type <list>   for_update_clause, opt_for_update_clause, update_list
 %type <boolean>    opt_all
  *
  *****************************************************************************/
 
-CreateStmt:  CREATE OptTemp TABLE relation_name '(' OptTableElementList ')' OptInherit
+CreateStmt:  CREATE OptTemp TABLE relation_name '(' OptTableElementList ')' OptInherit OptWithOids
                {
                    CreateStmt *n = makeNode(CreateStmt);
-                   n->istemp = $2;
                    n->relname = $4;
                    n->tableElts = $6;
                    n->inhRelnames = $8;
                    n->constraints = NIL;
+                   n->istemp = $2;
+                   n->hasoids = $9;
                    $$ = (Node *)n;
                }
        ;
        | /*EMPTY*/                                 { $$ = NIL; }
        ;
 
+OptWithOids:  WITH OIDS                        { $$ = TRUE; }
+           | WITHOUT OIDS                  { $$ = FALSE; }
+           | /*EMPTY*/                     { $$ = TRUE; }
+       ;
+
+
 /*
  * Note: CREATE TABLE ... AS SELECT ... is just another spelling for
  * SELECT ... INTO.
 
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/parser/parse_relation.c,v 1.55 2001/05/07 00:43:23 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/parser/parse_relation.c,v 1.56 2001/08/10 18:57:37 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 #include "rewrite/rewriteManip.h"
 #include "utils/builtins.h"
 #include "utils/lsyscache.h"
+#include "utils/syscache.h"
 
 
 static Node *scanNameSpaceForRefname(ParseState *pstate, Node *nsnode,
                  int sublevels_up);
 static bool isForUpdate(ParseState *pstate, char *relname);
 static List *expandNamesVars(ParseState *pstate, List *names, List *vars);
+static int specialAttNum(char *a);
 static void warnAutoRange(ParseState *pstate, char *refname);
 
 
     */
    if (rte->relid != InvalidOid)
    {
+       /* quick check to see if name could be a system column */
        attnum = specialAttNum(colname);
        if (attnum != InvalidAttrNumber)
        {
-           result = (Node *) make_var(pstate, rte, attnum);
-           rte->checkForRead = true;
+           /* now check to see if column actually is defined */
+           if (SearchSysCacheExists(ATTNUM,
+                                    ObjectIdGetDatum(rte->relid),
+                                    Int16GetDatum(attnum),
+                                    0, 0))
+           {
+               result = (Node *) make_var(pstate, rte, attnum);
+               rte->checkForRead = true;
+           }
        }
    }
 
            return i + 1;
 
    if ((i = specialAttNum(a)) != InvalidAttrNumber)
-       return i;
+   {
+       if (i != ObjectIdAttributeNumber || rd->rd_rel->relhasoids)
+           return i;
+   }
 
    /* on failure */
    elog(ERROR, "Relation '%s' does not have attribute '%s'",
 }
 
 /* specialAttNum()
+ *
  * Check attribute name to see if it is "special", e.g. "oid".
  * - thomas 2000-02-07
+ *
+ * Note: this only discovers whether the name could be a system attribute.
+ * Caller needs to verify that it really is an attribute of the rel,
+ * at least in the case of "oid", which is now optional.
  */
-int
+static int
 specialAttNum(char *a)
 {
    int         i;
 }
 
 
-#ifdef NOT_USED
-/*
- * Given range variable, return whether attribute of this name
- * is a set.
- * NOTE the ASSUMPTION here that no system attributes are, or ever
- * will be, sets.
- *
- * This should only be used if the relation is already
- * heap_open()'ed.  Use the cache version get_attisset()
- * for access to non-opened relations.
- */
-bool
-attnameIsSet(Relation rd, char *name)
-{
-   int         i;
-
-   /* First check if this is a system attribute */
-   for (i = 0; i < SPECIALS; i++)
-   {
-       if (strcmp(special_attr[i].attrname, name) == 0)
-           return false;       /* no sys attr is a set */
-   }
-   return get_attisset(RelationGetRelid(rd), name);
-}
-
-#endif
-
 /* given attribute id, return type of that attribute */
 /*
  * This should only be used if the relation is already
  * heap_open()'ed.  Use the cache version get_atttype()
  * for access to non-opened relations.
+ *
+ * Note: we don't bother to check rd->rd_rel->relhasoids; we assume that
+ * the caller will only ask about OID if that column has been found valid.
  */
 Oid
 attnumTypeId(Relation rd, int attid)
 
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteRemove.c,v 1.44 2001/03/22 03:59:44 momjian Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteRemove.c,v 1.45 2001/08/10 18:57:37 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
    /*
     * Delete any comments associated with this rule
     */
-   DeleteComments(ruleId);
+   DeleteComments(ruleId, RelationGetRelid(RewriteRelation));
 
    /*
     * Now delete the pg_rewrite tuple for the rule
 
    while (HeapTupleIsValid(tuple = heap_getnext(scanDesc, 0)))
    {
-
-       /*** Delete any comments associated with this relation ***/
-
-       DeleteComments(tuple->t_data->t_oid);
+       /* Delete any comments associated with this rule */
+       DeleteComments(tuple->t_data->t_oid, RelationGetRelid(RewriteRelation));
 
        simple_heap_delete(RewriteRelation, &tuple->t_self);
    }
 
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.141 2001/06/29 21:08:25 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.142 2001/08/10 18:57:37 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
    relation->rd_rel->relpages = 1;
    relation->rd_rel->reltuples = 1;
    relation->rd_rel->relkind = RELKIND_RELATION;
+   relation->rd_rel->relhasoids = true;
    relation->rd_rel->relnatts = (int16) natts;
 
    /*
    strcpy(RelationGetPhysicalRelationName(rel), relname);
 
    rel->rd_rel->relkind = RELKIND_UNCATALOGED;
+   rel->rd_rel->relhasoids = true;
    rel->rd_rel->relnatts = natts;
    rel->rd_rel->reltype = InvalidOid;
    if (tupDesc->constr)
 
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/utils/cache/syscache.c,v 1.63 2001/06/18 03:35:07 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/utils/cache/syscache.c,v 1.64 2001/08/10 18:57:37 tgl Exp $
  *
  * NOTES
  *   These routines allow the parser/planner/executor to perform
    return newtuple;
 }
 
+/*
+ * SearchSysCacheExists
+ *
+ * A convenience routine that just probes to see if a tuple can be found.
+ * No lock is retained on the syscache entry.
+ */
+bool
+SearchSysCacheExists(int cacheId,
+                    Datum key1,
+                    Datum key2,
+                    Datum key3,
+                    Datum key4)
+{
+   HeapTuple   tuple;
+
+   tuple = SearchSysCache(cacheId, key1, key2, key3, key4);
+   if (!HeapTupleIsValid(tuple))
+       return false;
+   ReleaseSysCache(tuple);
+   return true;
+}
+
 /*
  * GetSysCacheOid
  *
 
 # Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
 # Portions Copyright (c) 1994, Regents of the University of California
 #
-# $Header: /cvsroot/pgsql/src/bin/initdb/Attic/initdb.sh,v 1.131 2001/07/31 01:16:09 tgl Exp $
+# $Header: /cvsroot/pgsql/src/bin/initdb/Attic/initdb.sh,v 1.132 2001/08/10 18:57:38 tgl Exp $
 #
 #-------------------------------------------------------------------------
 
 # To break an SQL command across lines in this script, backslash-escape all
 # internal newlines in the command.
 
-echo "Initializing pg_shadow."
+if [ "$debug" = yes ]
+then
+    PGSQL_OPT="-O -F -D$PGDATA"
+else
+    PGSQL_OPT="-o /dev/null -O -F -D$PGDATA"
+fi
 
-PGSQL_OPT="-o /dev/null -O -F -D$PGDATA"
+echo "Initializing pg_shadow."
 
 "$PGPATH"/postgres $PGSQL_OPT template1 >/dev/null <<EOF
 -- Create a trigger so that direct updates to pg_shadow will be written
     FROM pg_class C FULL OUTER JOIN \
             pg_index I ON C.oid = I.indrelid FULL OUTER JOIN \
             pg_class T ON C.reltoastrelid = T.oid FULL OUTER JOIN \
-            pg_class X ON C.reltoastidxid = X.oid \
+            pg_class X ON T.reltoastidxid = X.oid \
     WHERE C.relkind = 'r' \
     GROUP BY C.oid, C.relname, T.oid, X.oid;
 
 
 echo "Loading pg_description."
 (
-  echo "COPY pg_description FROM STDIN;";
+  cat <<EOF
+    CREATE TEMP TABLE tmp_pg_description ( \
+   objoid oid, \
+   classname name, \
+   objsubid int4, \
+   description text) WITHOUT OIDS;
+    COPY tmp_pg_description FROM STDIN;
+EOF
   cat "$POSTGRES_DESCR"
+  cat <<EOF
+\.
+    INSERT INTO pg_description SELECT \
+   t.objoid, c.oid, t.objsubid, t.description \
+    FROM tmp_pg_description t, pg_class c WHERE c.relname = t.classname;
+EOF
 ) \
    | "$PGPATH"/postgres $PGSQL_OPT template1 > /dev/null || exit_nicely
 
-echo "Setting lastsysoid."
-
-"$PGPATH"/postgres $PGSQL_OPT template1 >/dev/null <<EOF
-UPDATE pg_database SET \
-   datistemplate = 't', \
-   datlastsysoid = (SELECT max(oid) FROM pg_description) \
-    WHERE datname = 'template1';
-EOF
-if [ "$?" -ne 0 ]; then
-    exit_nicely
-fi
-
 echo "Vacuuming database."
 
 "$PGPATH"/postgres $PGSQL_OPT template1 >/dev/null <<EOF
 
 "$PGPATH"/postgres $PGSQL_OPT template1 >/dev/null <<EOF
 CREATE DATABASE template0;
+
 UPDATE pg_database SET \
    datistemplate = 't', \
    datallowconn = 'f' \
     WHERE datname = 'template0';
+
+-- We use the OID of template0 to determine lastsysoid
+
+UPDATE pg_database SET datlastsysoid = \
+    (SELECT oid - 1 FROM pg_database WHERE datname = 'template0');
+
 VACUUM FULL pg_database;
 EOF
 if [ "$?" -ne 0 ]; then
 
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.218 2001/08/03 20:47:40 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.219 2001/08/10 18:57:38 tgl Exp $
  *
  *
    /* only checks for 'opts == CONV_ALL' anyway. */
 } formatLiteralOptions;
 
-static void dumpComment(Archive *outfile, const char *target, const char *oid,
+static void dumpComment(Archive *fout, const char *target, const char *oid,
+                       const char *classname, int subid,
                        const char *((*deps)[]));
 static void dumpSequence(Archive *fout, TableInfo tbinfo, const bool schemaOnly, const bool dataOnly);
 static void dumpACL(Archive *fout, TableInfo tbinfo);
 {
    const DumpContext *dctx = (DumpContext *) dctxv;
    const char *classname = dctx->tblinfo[dctx->tblidx].relname;
+   const bool  hasoids = dctx->tblinfo[dctx->tblidx].hasoids;
    const bool  oids = dctx->oids;
 
    PGresult   *res;
    if (g_verbose)
        write_msg(NULL, "dumping out the contents of table %s\n", classname);
 
-   if (oids == true)
+   if (oids && hasoids)
    {
 
        /*
 dumpClasses(const TableInfo *tblinfo, const int numTables, Archive *fout,
         const char *onlytable, const bool oids, const bool force_quotes)
 {
-
    int         i;
    DataDumperPtr dumpFn;
    DumpContext *dumpCtx;
-   char       *oidsPart;
    char        copyBuf[512];
    char       *copyStmt;
 
-   if (oids == true)
-       oidsPart = "WITH OIDS ";
-   else
-       oidsPart = "";
-
-
    if (g_verbose)
    {
        if (onlytable == NULL || (strlen(onlytable) == 0))
            dumpCtx->tblidx = i;
            dumpCtx->oids = oids;
 
-           if (!dumpData)      /* Dump/restore using COPY */
+           if (!dumpData)
            {
+               /* Dump/restore using COPY */
                dumpFn = dumpClasses_nodumpData;
-               /* dumpClasses_nodumpData(fout, classname, oids); */
-               sprintf(copyBuf, "COPY %s %sFROM stdin;\n", fmtId(tblinfo[i].relname, force_quotes),
-                       oidsPart);
+               sprintf(copyBuf, "COPY %s %sFROM stdin;\n",
+                       fmtId(tblinfo[i].relname, force_quotes),
+                       (oids && tblinfo[i].hasoids) ? "WITH OIDS " : "");
                copyStmt = copyBuf;
            }
            else
-/* Restore using INSERT */
            {
+               /* Restore using INSERT */
                dumpFn = dumpClasses_dumpData;
-               /* dumpClasses_dumpData(fout, classname); */
                copyStmt = NULL;
            }
 
            ArchiveEntry(fout, tblinfo[i].oid, tblinfo[i].relname,
-               "TABLE DATA", NULL, "", "", copyStmt, tblinfo[i].usename,
+                        "TABLE DATA", NULL, "", "",
+                        copyStmt, tblinfo[i].usename,
                         dumpFn, dumpCtx);
        }
    }
    MoveToEnd(g_fout, "TRIGGER");
    MoveToEnd(g_fout, "RULE");
    MoveToEnd(g_fout, "SEQUENCE SET");
+   /*
+    * Moving all comments to end is annoying, but must do it for comments
+    * on stuff we just moved, and we don't seem to have quite enough
+    * dependency structure to get it really right...
+    */
+   MoveToEnd(g_fout, "COMMENT");
 
    if (plainText)
    {
    int         loFd;
    char        buf[loBufSize];
    int         cnt;
-   int         blobOid;
+   Oid         blobOid;
 
    if (g_verbose)
        write_msg(NULL, "saving BLOBs\n");
        /* Process the tuples, if any */
        for (i = 0; i < PQntuples(res); i++)
        {
-           blobOid = atoi(PQgetvalue(res, i, 0));
+           blobOid = atooid(PQgetvalue(res, i, 0));
            /* Open the BLOB */
            loFd = lo_open(g_conn, blobOid, INV_READ);
            if (loFd == -1)
        /* Process Attributes */
        for (j = 0; j < tblinfo[i].numatts; j++)
        {
-           if (tblinfo[i].attoids[j])
-               free(tblinfo[i].attoids[j]);
            if (tblinfo[i].attnames[j])
                free(tblinfo[i].attnames[j]);
            if (tblinfo[i].typnames[j])
        finfo[i].prorettype = strdup(PQgetvalue(res, i, i_prorettype));
        finfo[i].retset = (strcmp(PQgetvalue(res, i, i_proretset), "t") == 0);
        finfo[i].nargs = atoi(PQgetvalue(res, i, i_pronargs));
-       finfo[i].lang = atoi(PQgetvalue(res, i, i_prolang));
+       finfo[i].lang = atooid(PQgetvalue(res, i, i_prolang));
        finfo[i].usename = strdup(PQgetvalue(res, i, i_usename));
        finfo[i].iscachable = (strcmp(PQgetvalue(res, i, i_iscachable), "t") == 0);
        finfo[i].isstrict = (strcmp(PQgetvalue(res, i, i_isstrict), "t") == 0);
    int         i_relchecks;
    int         i_reltriggers;
    int         i_relhasindex;
+   int         i_relhasoids;
 
    char        relkindview[2];
 
     * (sequence) or 'v' (view).
     */
 
-   if (g_fout->remoteVersion >= 70100)
+   if (g_fout->remoteVersion >= 70200)
    {
        appendPQExpBuffer(query,
                      "SELECT pg_class.oid, relname, relacl, relkind, "
                      "(select usename from pg_user where relowner = usesysid) as usename, "
-                     "relchecks, reltriggers, relhasindex "
+                     "relchecks, reltriggers, relhasindex, relhasoids "
+                     "from pg_class "
+                     "where relname !~ '^pg_' "
+                     "and relkind in ('%c', '%c', '%c') "
+                     "order by oid",
+                     RELKIND_RELATION, RELKIND_SEQUENCE, RELKIND_VIEW);
+   }
+   else if (g_fout->remoteVersion >= 70100)
+   {
+       /* all tables have oids in 7.1 */
+       appendPQExpBuffer(query,
+                     "SELECT pg_class.oid, relname, relacl, relkind, "
+                     "(select usename from pg_user where relowner = usesysid) as usename, "
+                     "relchecks, reltriggers, relhasindex, 't'::bool as relhasoids "
                      "from pg_class "
                      "where relname !~ '^pg_' "
                      "and relkind in ('%c', '%c', '%c') "
                      "THEN '%c'::\"char\" "
                      "ELSE relkind END AS relkind,"
                      "(select usename from pg_user where relowner = usesysid) as usename, "
-                     "relchecks, reltriggers, relhasindex "
+                     "relchecks, reltriggers, relhasindex, 't'::bool as relhasoids "
                      "from pg_class c "
                      "where relname !~ '^pg_' "
                      "and relkind in ('%c', '%c', '%c') "
    i_relchecks = PQfnumber(res, "relchecks");
    i_reltriggers = PQfnumber(res, "reltriggers");
    i_relhasindex = PQfnumber(res, "relhasindex");
+   i_relhasoids = PQfnumber(res, "relhasoids");
 
    for (i = 0; i < ntups; i++)
    {
                              "          )"
                              "      and c.rcsrc = pg_relcheck.rcsrc "
                              "      and c.rcrelid = i.inhparent) "
-                             " Order By oid ",
+                             " order by rcname ",
                              tblinfo[i].oid);
            res2 = PQexec(g_conn, query->data);
            if (!res2 ||
        else
            tblinfo[i].pkIndexOid = NULL;
 
+       /* Has it got OIDs? */
+       tblinfo[i].hasoids = (strcmp(PQgetvalue(res, i, i_relhasoids), "t") == 0);
+
        /* Get primary key name (if primary key exist) */
        if (tblinfo[i].pkIndexOid != NULL)
        {
    int         i_atttypmod;
    int         i_attnotnull;
    int         i_atthasdef;
-   int         i_attoid;
    int         i_atttypedefn;
    PGresult   *res;
    int         ntups;
        {
            /* Fake the LOJ below */
            appendPQExpBuffer(q,
-                       "  SELECT a.oid as attoid, a.attnum, a.attname, t.typname, a.atttypmod, "
+                       "  SELECT a.attnum, a.attname, t.typname, a.atttypmod, "
                        "        a.attnotnull, a.atthasdef, NULL as atttypedefn "
                        "    from pg_attribute a, pg_type t "
                        "    where a.attrelid = '%s'::oid "
                        "        and a.attnum > 0 "
                        "        and a.atttypid = t.oid "
-                       " UNION ALL SELECT a.oid as attoid, a.attnum, a.attname, NULL as typname, a.atttypmod, "
+                       " UNION ALL SELECT a.attnum, a.attname, NULL as typname, a.atttypmod, "
                        "        a.attnotnull, a.atthasdef, NULL as atttypedefn "
                        "    from pg_attribute a "
                        "    where a.attrelid = '%s'::oid "
                        tblinfo[i].oid, tblinfo[i].oid);
 
        } else {
-           appendPQExpBuffer(q, "SELECT a.oid as attoid, a.attnum, a.attname, t.typname, a.atttypmod, "
+           appendPQExpBuffer(q, "SELECT a.attnum, a.attname, t.typname, a.atttypmod, "
                                "a.attnotnull, a.atthasdef, format_type(a.atttypid, a.atttypmod) as atttypedefn "
                                "from pg_attribute a LEFT OUTER JOIN pg_type t ON a.atttypid = t.oid "
                                "where a.attrelid = '%s'::oid "
 
        ntups = PQntuples(res);
 
-       i_attoid = PQfnumber(res, "attoid");
        i_attname = PQfnumber(res, "attname");
        i_typname = PQfnumber(res, "typname");
        i_atttypmod = PQfnumber(res, "atttypmod");
        i_atttypedefn = PQfnumber(res, "atttypedefn");
 
        tblinfo[i].numatts = ntups;
-       tblinfo[i].attoids = (char **) malloc(ntups * sizeof(char *));
        tblinfo[i].attnames = (char **) malloc(ntups * sizeof(char *));
        tblinfo[i].atttypedefns = (char **) malloc(ntups * sizeof(char *));
        tblinfo[i].typnames = (char **) malloc(ntups * sizeof(char *));
                exit_nicely();
            }
 
-           tblinfo[i].attoids[j] = strdup(PQgetvalue(res, j, i_attoid));
            tblinfo[i].attnames[j] = strdup(PQgetvalue(res, j, i_attname));
            tblinfo[i].atttypedefns[j] = strdup(PQgetvalue(res, j, i_atttypedefn));
            tblinfo[i].typnames[j] = strdup(PQgetvalue(res, j, i_typname));
 }
 
 /*------------------------------------------------------------------
- * dumpComments --
+ * dumpComment --
  *
  * This routine is used to dump any comments associated with the
  * oid handed to this routine. The routine takes a constant character
- * string for the target part of the object and the oid of the object
- * whose comments are to be dumped. It is perfectly acceptable
- * to hand an oid to this routine which has not been commented.  Additional
- * dependencies can be passed for the comment, too --- this is needed for
- * VIEWs, whose comments are filed under the table OID but which are dumped
- * in order by their rule OID.
+ * string for the target part of the comment-creation command, plus
+ * OID, class name, and subid which are the primary key for pg_description.
+ * If a matching pg_description entry is found, it is dumped.
+ * Additional dependencies can be passed for the comment, too --- this is
+ * needed for VIEWs, whose comments are filed under the table OID but
+ * which are dumped in order by their rule OID.
  *------------------------------------------------------------------
 */
 
 static void
 dumpComment(Archive *fout, const char *target, const char *oid,
+           const char *classname, int subid,
            const char *((*deps)[]))
 {
    PGresult   *res;
    /*** Build query to find comment ***/
 
    query = createPQExpBuffer();
-   appendPQExpBuffer(query, "SELECT description FROM pg_description WHERE objoid = ");
-   appendPQExpBuffer(query, oid);
+
+   if (fout->remoteVersion >= 70200)
+   {
+       appendPQExpBuffer(query, "SELECT description FROM pg_description "
+                         "WHERE objoid = %s and classoid = "
+                         "(SELECT oid FROM pg_class where relname = '%s') "
+                         "and objsubid = %d",
+                         oid, classname, subid);
+   }
+   else
+   {
+       /* Note: this will fail to find attribute comments in pre-7.2... */
+       appendPQExpBuffer(query, "SELECT description FROM pg_description WHERE objoid = %s", oid);
+   }
 
    /*** Execute query ***/
 
 
    /*** If a comment exists, build COMMENT ON statement ***/
 
-   if (PQntuples(res) != 0)
+   if (PQntuples(res) == 1)
    {
        i_description = PQfnumber(res, "description");
        resetPQExpBuffer(query);
        appendPQExpBuffer(query, "COMMENT ON %s IS ", target);
-       formatStringLiteral(query, PQgetvalue(res, 0, i_description), PASS_LFTAB);
+       formatStringLiteral(query, PQgetvalue(res, 0, i_description),
+                           PASS_LFTAB);
        appendPQExpBuffer(query, ";\n");
 
        ArchiveEntry(fout, oid, target, "COMMENT", deps,
                     query->data, "" /* Del */ ,
                     "" /* Copy */ , "" /* Owner */ , NULL, NULL);
-
    }
 
    /*** Clear the statement buffer and return ***/
        i_oid = PQfnumber(res, "oid");
        resetPQExpBuffer(query);
        appendPQExpBuffer(query, "DATABASE %s", fmtId(PQdb(g_conn), force_quotes));
-       dumpComment(fout, query->data, PQgetvalue(res, 0, i_oid), NULL);
+       dumpComment(fout, query->data, PQgetvalue(res, 0, i_oid),
+                   "pg_database", 0, NULL);
    }
 
    /*** Clear the statement buffer and return ***/
            continue;
 
        /* skip relation types */
-       if (atoi(tinfo[i].typrelid) != 0)
+       if (atooid(tinfo[i].typrelid) != 0)
            continue;
 
        /* skip undefined placeholder types */
        resetPQExpBuffer(q);
 
        appendPQExpBuffer(q, "TYPE %s", fmtId(tinfo[i].typname, force_quotes));
-       dumpComment(fout, q->data, tinfo[i].oid, NULL);
+       dumpComment(fout, q->data, tinfo[i].oid, "pg_type", 0, NULL);
    }
 
    destroyPQExpBuffer(q);
    appendPQExpBuffer(q, "FUNCTION %s ",
                      fmtId(finfo[i].proname, force_quotes));
    appendPQExpBuffer(q, "( %s )", fnlist->data);
-   dumpComment(fout, q->data, finfo[i].oid, NULL);
+   dumpComment(fout, q->data, finfo[i].oid, "pg_proc", 0, NULL);
 
 done:
    destroyPQExpBuffer(q);
        resetPQExpBuffer(q);
        appendPQExpBuffer(q, "AGGREGATE %s %s", agginfo[i].aggname,
                          findTypeByOid(tinfo, numTypes, agginfo[i].aggbasetype, zeroAsOpaque + useBaseTypeName));
-       dumpComment(fout, q->data, agginfo[i].oid, NULL);
+       dumpComment(fout, q->data, agginfo[i].oid, "pg_aggregate", 0, NULL);
    }
 
    destroyPQExpBuffer(q);
                    appendPQExpBuffer(q, ")");
                }
 
+               if (!tblinfo[i].hasoids)
+                   appendPQExpBuffer(q, " WITHOUT OIDS");
+
                appendPQExpBuffer(q, ";\n");
            }
 
                appendPQExpBuffer(q, "COLUMN %s", fmtId(tblinfo[i].relname, force_quotes));
                appendPQExpBuffer(q, ".");
                appendPQExpBuffer(q, "%s", fmtId(tblinfo[i].attnames[j], force_quotes));
-               dumpComment(fout, q->data, tblinfo[i].attoids[j], NULL);
+               dumpComment(fout, q->data, tblinfo[i].oid,
+                           "pg_class", j+1, commentDeps);
            }
 
            /* Dump Table Comments */
 
            resetPQExpBuffer(q);
            appendPQExpBuffer(q, "%s %s", reltypename, fmtId(tblinfo[i].relname, force_quotes));
-           dumpComment(fout, q->data, tblinfo[i].oid, commentDeps);
+           dumpComment(fout, q->data, tblinfo[i].oid,
+                       "pg_class", 0, commentDeps);
 
        }
    }
    char       *classname[INDEX_MAX_KEYS];
    char       *funcname;       /* the name of the function to comput the
                                 * index key from */
-   int         indclass;
+   Oid         indclass;
    int         nclass;
    PGresult   *res;
 
        {
            int         numRows;
 
-           indclass = atoi(indinfo[i].indclass[nclass]);
+           indclass = atooid(indinfo[i].indclass[nclass]);
            if (indclass == 0)
                break;
            resetPQExpBuffer(q);
             * is not necessarily right but should answer 99% of the time.
             * Would have to add owner name to IndInfo to do it right.
             */
-           ArchiveEntry(fout, tblinfo[tableInd].oid, id1->data, "INDEX", NULL, q->data, delq->data,
+           ArchiveEntry(fout, indinfo[i].indexreloid, id1->data,
+                        "INDEX", NULL, q->data, delq->data,
                         "", tblinfo[tableInd].usename, NULL, NULL);
 
            /* Dump Index Comments */
            resetPQExpBuffer(q);
            appendPQExpBuffer(q, "INDEX %s", id1->data);
-           dumpComment(fout, q->data, indinfo[i].indexreloid, NULL);
+           dumpComment(fout, q->data, indinfo[i].indexreloid,
+                       "pg_class", 0, NULL);
 
        }
    }
        write_msg(NULL, "could not insert into pgdump_oid table: %s", PQerrorMessage(g_conn));
        exit_nicely();
    }
-   max_oid = atol(PQoidStatus(res));
+   max_oid = atooid(PQoidStatus(res));
    if (max_oid == 0)
    {
        write_msg(NULL, "inserted invalid oid\n");
    snprintf(sql, 1024,
             "CREATE TEMPORARY TABLE pgdump_oid (dummy int4);\n"
             "COPY pgdump_oid WITH OIDS FROM stdin;\n"
-            "%-d\t0\n"
+            "%u\t0\n"
             "\\.\n"
             "DROP TABLE pgdump_oid;\n",
             max_oid);
 
        resetPQExpBuffer(query);
        appendPQExpBuffer(query, "SEQUENCE %s", fmtId(tbinfo.relname, force_quotes));
-       dumpComment(fout, query->data, tbinfo.oid, NULL);
+       dumpComment(fout, query->data, tbinfo.oid,
+                   "pg_class", 0, NULL);
    }
 
    destroyPQExpBuffer(query);
            ArchiveEntry(fout, tblinfo[i].triggers[j].oid, tblinfo[i].triggers[j].tgname,
                   "TRIGGER", NULL, tblinfo[i].triggers[j].tgsrc, "", "",
                         tblinfo[i].usename, NULL, NULL);
-           dumpComment(fout, tblinfo[i].triggers[j].tgcomment, tblinfo[i].triggers[j].oid, NULL);
+           dumpComment(fout, tblinfo[i].triggers[j].tgcomment, tblinfo[i].triggers[j].oid,
+                       "pg_trigger", 0, NULL);
        }
    }
 }
 
            resetPQExpBuffer(query);
            appendPQExpBuffer(query, "RULE %s", fmtId(PQgetvalue(res, i, i_rulename), force_quotes));
-           dumpComment(fout, query->data, PQgetvalue(res, i, i_oid), NULL);
+           dumpComment(fout, query->data, PQgetvalue(res, i, i_oid),
+                       "pg_rewrite", 0, NULL);
 
        }
 
 
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pg_dump.h,v 1.68 2001/08/03 19:43:05 tgl Exp $
+ * $Id: pg_dump.h,v 1.69 2001/08/10 18:57:38 tgl Exp $
  *
  *
    char       *oid;
    char       *proname;
    char       *proowner;
-   int         lang;
+   Oid         lang;
    int         nargs;
    char       *argtypes[FUNC_MAX_ARGS];
    char       *prorettype;
                                 * created after the base table was created. 
                                 */
    bool        sequence;
+   bool        hasoids;        /* does it have OIDs? */
    int         numatts;        /* number of attributes */
    int        *inhAttrs;       /* an array of flags, one for each
                                 * attribute if the value is 1, then this
    int        *inhAttrDef;     /* Flags indicating if attrdef is inherited */
    int        *inhNotNull;     /* Flags indicating if NOT NULL in inherited */
    char      **attnames;       /* the attribute names */
-   char      **attoids;        /* oids of the various attributes */
    char      **atttypedefns;   /* formatted column type definitions */
    char      **typnames;       /* fill out attributes */
    bool       *notnull;        /* Not null constraints of an attribute */
 
  *
  * Copyright 2000 by PostgreSQL Global Development Group
  *
- * $Header: /cvsroot/pgsql/src/bin/psql/describe.c,v 1.37 2001/08/09 03:32:16 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/bin/psql/describe.c,v 1.38 2001/08/10 18:57:39 tgl Exp $
  */
 #include "postgres_fe.h"
 #include "describe.h"
             "    WHEN 0 THEN CAST('%s' AS text)\n"
             "    ELSE format_type(a.aggbasetype, NULL)\n"
             "  END AS \"%s\",\n"
-            "  obj_description(a.oid) as \"%s\"\n"
+            "  obj_description(a.oid, 'pg_aggregate') as \"%s\"\n"
             "FROM pg_aggregate a\n",
             _("Name"), _("(all types)"),
             _("Data type"), _("Description") );
                 ",\n  u.usename as \"%s\",\n"
                 "  l.lanname as \"%s\",\n"
                 "  p.prosrc as \"%s\",\n"
-                "  obj_description(p.oid) as \"%s\"",
+                "  obj_description(p.oid, 'pg_proc') as \"%s\"",
                 _("Owner"), _("Language"),
                 _("Source code"), _("Description") );
 
                 "  END AS \"%s\",\n",
                 _("Internal name"), _("Size") );
    snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),  
-            "  obj_description(t.oid) as \"%s\"\n",
+            "  obj_description(t.oid, 'pg_type') as \"%s\"\n",
             _("Description") );
 
    /*
             "  CASE WHEN o.oprkind='l' THEN NULL ELSE format_type(o.oprleft, NULL) END AS \"%s\",\n"
             "  CASE WHEN o.oprkind='r' THEN NULL ELSE format_type(o.oprright, NULL) END AS \"%s\",\n"
             "  format_type(p.prorettype, NULL) AS \"%s\",\n"
-            "  obj_description(p.oid) as \"%s\"\n"
+            "  obj_description(p.oid, 'pg_proc') as \"%s\"\n"
             "FROM pg_proc p, pg_operator o\n"
             "WHERE RegprocToOid(o.oprcode) = p.oid\n",
             _("Name"), _("Left arg type"), _("Right arg type"),
 #endif
    if (desc)
        snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
-                ",\n       obj_description(d.oid) as \"%s\"",
+                ",\n       obj_description(d.oid, 'pg_database') as \"%s\"",
                 _("Description"));
    strcat(buf,
           "\nFROM pg_database d LEFT JOIN pg_user u ON d.datdba = u.usesysid\n"
             "FROM (\n"
 
             /* Aggregate descriptions */
-            "  SELECT a.oid as oid, CAST(a.aggname AS text) as name, CAST('%s' AS text) as object\n"
+            "  SELECT a.oid as oid, a.tableoid as tableoid,\n"
+            "  CAST(a.aggname AS text) as name, CAST('%s' AS text) as object\n"
             "  FROM pg_aggregate a\n"
 
             /* Function descriptions (except in/outs for datatypes) */
             "UNION ALL\n"
-            "  SELECT p.oid as oid, CAST(p.proname AS text) as name, CAST('%s' AS text) as object\n"
+            "  SELECT p.oid as oid, p.tableoid as tableoid,\n"
+            "  CAST(p.proname AS text) as name, CAST('%s' AS text) as object\n"
             "  FROM pg_proc p\n"
             "  WHERE p.pronargs = 0 or oidvectortypes(p.proargtypes) <> ''\n"
 
             /* Operator descriptions (must get comment via associated function) */
             "UNION ALL\n"
-            "  SELECT RegprocToOid(o.oprcode) as oid, CAST(o.oprname AS text) as name, CAST('%s' AS text) as object\n"
+            "  SELECT RegprocToOid(o.oprcode) as oid,\n"
+            "  (SELECT oid FROM pg_class WHERE relname = 'pg_proc') as tableoid,\n"
+            "  CAST(o.oprname AS text) as name, CAST('%s' AS text) as object\n"
             "  FROM pg_operator o\n"
 
             /* Type description */
             "UNION ALL\n"
-            "  SELECT t.oid as oid, format_type(t.oid, NULL) as name, CAST('%s' AS text) as object\n"
+            "  SELECT t.oid as oid, t.tableoid as tableoid,\n"
+            "  format_type(t.oid, NULL) as name, CAST('%s' AS text) as object\n"
             "  FROM pg_type t\n"
 
             /* Relation (tables, views, indexes, sequences) descriptions */
             "UNION ALL\n"
-            "  SELECT c.oid as oid, CAST(c.relname AS text) as name,\n"
+            "  SELECT c.oid as oid, c.tableoid as tableoid,\n"
+            "  CAST(c.relname AS text) as name,\n"
             "  CAST(\n"
             "    CASE c.relkind WHEN 'r' THEN '%s' WHEN 'v' THEN '%s' WHEN 'i' THEN '%s' WHEN 'S' THEN '%s' END"
             "  AS text) as object\n"
 
             /* Rule description (ignore rules for views) */
             "UNION ALL\n"
-            "  SELECT r.oid as oid, CAST(r.rulename AS text) as name, CAST('%s' AS text) as object\n"
+            "  SELECT r.oid as oid, r.tableoid as tableoid,\n"
+            "  CAST(r.rulename AS text) as name, CAST('%s' AS text) as object\n"
             "  FROM pg_rewrite r\n"
             "  WHERE r.rulename !~ '^_RET'\n"
 
             /* Trigger description */
             "UNION ALL\n"
-            "  SELECT t.oid as oid, CAST(t.tgname AS text) as name, CAST('%s' AS text) as object\n"
+            "  SELECT t.oid as oid, t.tableoid as tableoid,\n"
+            "  CAST(t.tgname AS text) as name, CAST('%s' AS text) as object\n"
             "  FROM pg_trigger t\n"
 
             ") AS tt,\n"
             "pg_description d\n"
-            "WHERE tt.oid = d.objoid\n",
+            "WHERE tt.oid = d.objoid and tt.tableoid = d.classoid and d.objsubid = 0\n",
 
             _("Name"), _("Object"), _("Description"),
             _("aggregate"), _("function"), _("operator"),
    /* Get column info */
    strcpy(buf, "SELECT a.attname, format_type(a.atttypid, a.atttypmod), a.attnotnull, a.atthasdef, a.attnum");
    if (desc)
-       strcat(buf, ", obj_description(a.oid)");
+       strcat(buf, ", col_description(a.attrelid, a.attnum)");
    strcat(buf, "\nFROM pg_class c, pg_attribute a\n"
           "WHERE c.relname = '");
    strncat(buf, name, NAMEDATALEN);
 
    if (desc)
        snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
-                ",\n  obj_description(c.oid) as \"%s\"",
+                ",\n  obj_description(c.oid, 'pg_class') as \"%s\"",
                 _("Description"));
    strcat(buf,
           "\nFROM pg_class c LEFT JOIN pg_user u ON c.relowner = u.usesysid\n"
 
  *
  * Copyright 2000 by PostgreSQL Global Development Group
  *
- * $Header: /cvsroot/pgsql/src/bin/psql/large_obj.c,v 1.15 2001/06/02 18:25:18 petere Exp $
+ * $Header: /cvsroot/pgsql/src/bin/psql/large_obj.c,v 1.16 2001/08/10 18:57:39 tgl Exp $
  */
 #include "postgres_fe.h"
 #include "large_obj.h"
 {
    PGresult   *res;
    Oid         loid;
-   char        buf[1024];
+   char        oidbuf[32];
    unsigned int i;
    bool        own_transaction = true;
    const char *var = GetVariable(pset.vars, "LO_TRANSACTION");
    /* insert description if given */
    if (comment_arg)
    {
-       sprintf(buf, "INSERT INTO pg_description VALUES (%u, '", loid);
-       for (i = 0; i < strlen(comment_arg); i++)
-           if (comment_arg[i] == '\'')
-               strcat(buf, "\\'");
-           else
-               strncat(buf, &comment_arg[i], 1);
-       strcat(buf, "')");
-
-       if (!(res = PSQLexec(buf)))
+       char    *cmdbuf;
+       char    *bufptr;
+       int     slen = strlen(comment_arg);
+
+       cmdbuf = malloc(slen * 2 + 256);
+       if (!cmdbuf)
        {
            if (own_transaction)
            {
            }
            return false;
        }
+       sprintf(cmdbuf,
+               "INSERT INTO pg_description VALUES (%u, "
+               "(SELECT oid FROM pg_class WHERE relname = 'pg_largeobject'),"
+               " 0, '", loid);
+       bufptr = cmdbuf + strlen(cmdbuf);
+       for (i = 0; i < slen; i++)
+       {
+           if (comment_arg[i] == '\'' || comment_arg[i] == '\\')
+               *bufptr++ = '\\';
+           *bufptr++ = comment_arg[i];
+       }
+       strcpy(bufptr, "')");
+
+       if (!(res = PSQLexec(cmdbuf)))
+       {
+           if (own_transaction)
+           {
+               res = PQexec(pset.db, "ROLLBACK");
+               PQclear(res);
+           }
+           free(cmdbuf);
+           return false;
+       }
+
+       PQclear(res);
+       free(cmdbuf);
    }
 
    if (own_transaction)
    }
 
 
-   fprintf(pset.queryFout, "lo_import %d\n", loid);
-   sprintf(buf, "%u", (unsigned int) loid);
-   SetVariable(pset.vars, "LASTOID", buf);
+   fprintf(pset.queryFout, "lo_import %u\n", loid);
+   sprintf(oidbuf, "%u", loid);
+   SetVariable(pset.vars, "LASTOID", oidbuf);
 
    return true;
 }
    }
 
    /* remove the comment as well */
-   sprintf(buf, "DELETE FROM pg_description WHERE objoid = %u", loid);
+   sprintf(buf, "DELETE FROM pg_description WHERE objoid = %u "
+           "AND classoid = (SELECT oid FROM pg_class WHERE relname = 'pg_largeobject')",
+           loid);
    if (!(res = PSQLexec(buf)))
    {
        if (own_transaction)
    printQueryOpt myopt = pset.popt;
 
    snprintf(buf, sizeof(buf),
-            "SELECT loid as \"ID\", obj_description(loid) as \"%s\"\n"
+            "SELECT loid as \"ID\", obj_description(loid, 'pg_largeobject') as \"%s\"\n"
             "FROM (SELECT DISTINCT loid FROM pg_largeobject) x\n"
             "ORDER BY \"ID\"",
             gettext("Description"));
 
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: transam.h,v 1.36 2001/07/12 04:11:13 tgl Exp $
+ * $Id: transam.h,v 1.37 2001/08/10 18:57:39 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 typedef unsigned char XidStatus;   /* (2 bits) */
 
 /* ----------
- *     We reserve the first 16384 object ids for manual assignment.
- *     oid's less than this appear in the .bki files.  the choice of
- *     16384 is completely arbitrary.
+ *     Object ID (OID) zero is InvalidOid.
+ *
+ *     OIDs 1-9999 are reserved for manual assignment (see the files
+ *     in src/include/catalog/).
+ *
+ *     OIDS 10000-16383 are reserved for assignment by genbki.sh.
+ *
+ *     OIDs beginning at 16384 are assigned at runtime from the OID
+ *     generator.  (The first few of these will be assigned during initdb,
+ *     to objects created after the initial BKI script processing.)
+ *
+ * The choices of 10000 and 16384 are completely arbitrary, and can be moved
+ * if we run low on OIDs in either category.  Changing the macros below
+ * should be sufficient to do this.
+ *
+ * NOTE: if the OID generator wraps around, we should skip over OIDs 0-16383
+ * and resume with 16384.  This minimizes the odds of OID conflict, by not
+ * reassigning OIDs that might have been assigned during initdb.
  * ----------
  */
+#define FirstGenBKIObjectId   10000
 #define BootstrapObjectIdData 16384
 
 /*
 /* in transam/varsup.c */
 extern void GetNewTransactionId(TransactionId *xid);
 extern void ReadNewTransactionId(TransactionId *xid);
-extern void GetNewObjectId(Oid *oid_return);
+extern Oid GetNewObjectId(void);
 extern void CheckMaxObjectId(Oid assigned_oid);
 
 /* ----------------
 
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: bootstrap.h,v 1.22 2001/05/12 01:48:49 petere Exp $
+ * $Id: bootstrap.h,v 1.23 2001/08/10 18:57:39 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 extern char *LexIDStr(int ident_num);
 
 extern void DefineAttr(char *name, char *type, int attnum);
-extern void InsertOneValue(Oid objectid, char *value, int i);
+extern void InsertOneValue(char *value, int i);
 extern void InsertOneNull(int i);
 extern char *MapArrayTypeName(char *s);
 extern char *CleanUpStr(char *s);
 
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: catversion.h,v 1.86 2001/07/15 22:48:18 tgl Exp $
+ * $Id: catversion.h,v 1.87 2001/08/10 18:57:39 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
  */
 
 /*                         yyyymmddN */
-#define CATALOG_VERSION_NO 200107151
+#define CATALOG_VERSION_NO 200108101
 
 #endif
 
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: heap.h,v 1.36 2001/05/30 12:57:36 momjian Exp $
+ * $Id: heap.h,v 1.37 2001/08/10 18:57:39 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 extern void heap_storage_create(Relation rel);
 
 extern Oid heap_create_with_catalog(char *relname, TupleDesc tupdesc,
-                        char relkind, bool istemp,
+                        char relkind, bool relhasoids, bool istemp,
                         bool allow_system_table_mods);
 
 extern void heap_drop_with_catalog(const char *relname,
 extern int RemoveCheckConstraint(Relation rel, const char *constrName, bool inh);
 
 
-extern Form_pg_attribute SystemAttributeDefinition(AttrNumber attno);
+extern Form_pg_attribute SystemAttributeDefinition(AttrNumber attno,
+                                                  bool relhasoids);
 
 #endif  /* HEAP_H */
 
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: index.h,v 1.37 2001/07/16 05:06:59 tgl Exp $
+ * $Id: index.h,v 1.38 2001/08/10 18:57:39 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
                  Relation indexRelation,
                  Oid accessMethodObjectId);
 
-extern void index_create(char *heapRelationName,
+extern Oid index_create(char *heapRelationName,
             char *indexRelationName,
             IndexInfo *indexInfo,
             Oid accessMethodObjectId,
 
 extern void UpdateStats(Oid relid, double reltuples);
 extern bool IndexesAreActive(Oid relid, bool comfirmCommitted);
-extern void setRelhasindex(Oid relid, bool hasindex);
+extern void setRelhasindex(Oid relid, bool hasindex,
+                          bool isprimary, Oid reltoastidxid);
 
 extern void setNewRelfilenode(Relation relation);
 
 
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: indexing.h,v 1.51 2001/06/16 18:59:31 tgl Exp $
+ * $Id: indexing.h,v 1.52 2001/08/10 18:57:39 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 /*
  * Number of indices that exist for each system catalog
  */
-#define Num_pg_aggregate_indices   1
+#define Num_pg_aggregate_indices   2
 #define Num_pg_am_indices          2
 #define Num_pg_amop_indices            2
 #define Num_pg_amproc_indices      1
 #define AccessMethodStrategyIndex  "pg_amop_strategy_index"
 #define AccessProcedureIndex       "pg_amproc_am_opcl_procnum_index"
 #define AggregateNameTypeIndex     "pg_aggregate_name_type_index"
+#define AggregateOidIndex          "pg_aggregate_oid_index"
 #define AmNameIndex                    "pg_am_name_index"
 #define AmOidIndex                 "pg_am_oid_index"
 #define AttrDefaultIndex           "pg_attrdef_adrelid_adnum_index"
 #define ClassOidIndex              "pg_class_oid_index"
 #define DatabaseNameIndex          "pg_database_datname_index"
 #define DatabaseOidIndex           "pg_database_oid_index"
-#define DescriptionObjIndex            "pg_description_objoid_index"
+#define DescriptionObjIndex            "pg_description_o_c_o_index"
 #define GroupNameIndex             "pg_group_name_index"
 #define GroupSysidIndex                "pg_group_sysid_index"
 #define IndexIndrelidIndex         "pg_index_indrelid_index"
  */
 
 DECLARE_UNIQUE_INDEX(pg_aggregate_name_type_index on pg_aggregate using btree(aggname name_ops, aggbasetype oid_ops));
+DECLARE_UNIQUE_INDEX(pg_aggregate_oid_index on pg_aggregate using btree(oid oid_ops));
 DECLARE_UNIQUE_INDEX(pg_am_name_index on pg_am using btree(amname name_ops));
 DECLARE_UNIQUE_INDEX(pg_am_oid_index on pg_am using btree(oid oid_ops));
 DECLARE_UNIQUE_INDEX(pg_amop_opid_index on pg_amop using btree(amopclaid oid_ops, amopopr oid_ops, amopid oid_ops));
 DECLARE_UNIQUE_INDEX(pg_class_relname_index on pg_class using btree(relname name_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_objoid_index on pg_description using btree(objoid 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));
 DECLARE_UNIQUE_INDEX(pg_group_name_index on pg_group using btree(groname name_ops));
 DECLARE_UNIQUE_INDEX(pg_group_sysid_index on pg_group using btree(grosysid int4_ops));
 /* This following index is not used for a cache and is not unique */
 
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pg_amop.h,v 1.38 2001/03/22 04:00:37 momjian Exp $
+ * $Id: pg_amop.h,v 1.39 2001/08/10 18:57:39 tgl Exp $
  *
  * NOTES
  *  the genbki.sh script reads this file and generates .bki
  *     typedef struct FormData_pg_amop
  * ----------------
  */
-CATALOG(pg_amop)
+CATALOG(pg_amop) BKI_WITHOUT_OIDS
 {
    Oid         amopid;         /* an index access method */
    Oid         amopclaid;      /* an index opclass */
  * rtree box_ops
  */
 
-DATA(insert OID = 0 (  402 422 493 1 ));
-DATA(insert OID = 0 (  402 422 494 2 ));
-DATA(insert OID = 0 (  402 422 500 3 ));
-DATA(insert OID = 0 (  402 422 495 4 ));
-DATA(insert OID = 0 (  402 422 496 5 ));
-DATA(insert OID = 0 (  402 422 499 6 ));
-DATA(insert OID = 0 (  402 422 498 7 ));
-DATA(insert OID = 0 (  402 422 497 8 ));
+DATA(insert (  402 422 493 1 ));
+DATA(insert (  402 422 494 2 ));
+DATA(insert (  402 422 500 3 ));
+DATA(insert (  402 422 495 4 ));
+DATA(insert (  402 422 496 5 ));
+DATA(insert (  402 422 499 6 ));
+DATA(insert (  402 422 498 7 ));
+DATA(insert (  402 422 497 8 ));
 
 /*
  * rtree bigbox_ops
  */
 
-DATA(insert OID = 0 (  402 433 493 1 ));
-DATA(insert OID = 0 (  402 433 494 2 ));
-DATA(insert OID = 0 (  402 433 500 3 ));
-DATA(insert OID = 0 (  402 433 495 4 ));
-DATA(insert OID = 0 (  402 433 496 5 ));
-DATA(insert OID = 0 (  402 433 499 6 ));
-DATA(insert OID = 0 (  402 433 498 7 ));
-DATA(insert OID = 0 (  402 433 497 8 ));
+DATA(insert (  402 433 493 1 ));
+DATA(insert (  402 433 494 2 ));
+DATA(insert (  402 433 500 3 ));
+DATA(insert (  402 433 495 4 ));
+DATA(insert (  402 433 496 5 ));
+DATA(insert (  402 433 499 6 ));
+DATA(insert (  402 433 498 7 ));
+DATA(insert (  402 433 497 8 ));
 
 /*
  * rtree poly_ops (supports polygons)
  */
 
-DATA(insert OID = 0 (  402 434 485 1 ));
-DATA(insert OID = 0 (  402 434 486 2 ));
-DATA(insert OID = 0 (  402 434 492 3 ));
-DATA(insert OID = 0 (  402 434 487 4 ));
-DATA(insert OID = 0 (  402 434 488 5 ));
-DATA(insert OID = 0 (  402 434 491 6 ));
-DATA(insert OID = 0 (  402 434 490 7 ));
-DATA(insert OID = 0 (  402 434 489 8 ));
+DATA(insert (  402 434 485 1 ));
+DATA(insert (  402 434 486 2 ));
+DATA(insert (  402 434 492 3 ));
+DATA(insert (  402 434 487 4 ));
+DATA(insert (  402 434 488 5 ));
+DATA(insert (  402 434 491 6 ));
+DATA(insert (  402 434 490 7 ));
+DATA(insert (  402 434 489 8 ));
 
 /*
  * rtree circle_ops (supports circles)
  * writes such functions.
  */
 
-/* DATA(insert OID = 0 (  402 714 1506 1 )); */
-/* DATA(insert OID = 0 (  402 714 1507 2 )); */
-/* DATA(insert OID = 0 (  402 714 1513 3 )); */
-/* DATA(insert OID = 0 (  402 714 1508 4 )); */
-/* DATA(insert OID = 0 (  402 714 1509 5 )); */
-/* DATA(insert OID = 0 (  402 714 1512 6 )); */
-/* DATA(insert OID = 0 (  402 714 1511 7 )); */
-/* DATA(insert OID = 0 (  402 714 1510 8 )); */
+/* DATA(insert (  402 714 1506 1 )); */
+/* DATA(insert (  402 714 1507 2 )); */
+/* DATA(insert (  402 714 1513 3 )); */
+/* DATA(insert (  402 714 1508 4 )); */
+/* DATA(insert (  402 714 1509 5 )); */
+/* DATA(insert (  402 714 1512 6 )); */
+/* DATA(insert (  402 714 1511 7 )); */
+/* DATA(insert (  402 714 1510 8 )); */
 
 /*
  * nbtree int2_ops
  */
 
-DATA(insert OID = 0 (  403 421 95 1 ));
-DATA(insert OID = 0 (  403 421 522 2 ));
-DATA(insert OID = 0 (  403 421 94 3 ));
-DATA(insert OID = 0 (  403 421 524 4 ));
-DATA(insert OID = 0 (  403 421 520 5 ));
+DATA(insert (  403 421 95 1 ));
+DATA(insert (  403 421 522 2 ));
+DATA(insert (  403 421 94 3 ));
+DATA(insert (  403 421 524 4 ));
+DATA(insert (  403 421 520 5 ));
 
 /*
  * nbtree float8_ops
  */
 
-DATA(insert OID = 0 (  403 423 672 1 ));
-DATA(insert OID = 0 (  403 423 673 2 ));
-DATA(insert OID = 0 (  403 423 670 3 ));
-DATA(insert OID = 0 (  403 423 675 4 ));
-DATA(insert OID = 0 (  403 423 674 5 ));
+DATA(insert (  403 423 672 1 ));
+DATA(insert (  403 423 673 2 ));
+DATA(insert (  403 423 670 3 ));
+DATA(insert (  403 423 675 4 ));
+DATA(insert (  403 423 674 5 ));
 
 /*
  * nbtree int4_ops
  */
 
-DATA(insert OID = 0 (  403 426 97 1 ));
-DATA(insert OID = 0 (  403 426 523 2 ));
-DATA(insert OID = 0 (  403 426 96 3 ));
-DATA(insert OID = 0 (  403 426 525 4 ));
-DATA(insert OID = 0 (  403 426 521 5 ));
+DATA(insert (  403 426 97 1 ));
+DATA(insert (  403 426 523 2 ));
+DATA(insert (  403 426 96 3 ));
+DATA(insert (  403 426 525 4 ));
+DATA(insert (  403 426 521 5 ));
 
 /*
  * nbtree int8_ops
  */
 
-DATA(insert OID = 0 (  403 754 412 1 ));
-DATA(insert OID = 0 (  403 754 414 2 ));
-DATA(insert OID = 0 (  403 754 410 3 ));
-DATA(insert OID = 0 (  403 754 415 4 ));
-DATA(insert OID = 0 (  403 754 413 5 ));
+DATA(insert (  403 754 412 1 ));
+DATA(insert (  403 754 414 2 ));
+DATA(insert (  403 754 410 3 ));
+DATA(insert (  403 754 415 4 ));
+DATA(insert (  403 754 413 5 ));
 
 /*
  * nbtree oid_ops
  */
 
-DATA(insert OID = 0 (  403 427 609 1 ));
-DATA(insert OID = 0 (  403 427 611 2 ));
-DATA(insert OID = 0 (  403 427 607 3 ));
-DATA(insert OID = 0 (  403 427 612 4 ));
-DATA(insert OID = 0 (  403 427 610 5 ));
+DATA(insert (  403 427 609 1 ));
+DATA(insert (  403 427 611 2 ));
+DATA(insert (  403 427 607 3 ));
+DATA(insert (  403 427 612 4 ));
+DATA(insert (  403 427 610 5 ));
 
 /*
  * nbtree oidvector_ops
  */
 
-DATA(insert OID = 0 (  403 435 645 1 ));
-DATA(insert OID = 0 (  403 435 647 2 ));
-DATA(insert OID = 0 (  403 435 649 3 ));
-DATA(insert OID = 0 (  403 435 648 4 ));
-DATA(insert OID = 0 (  403 435 646 5 ));
+DATA(insert (  403 435 645 1 ));
+DATA(insert (  403 435 647 2 ));
+DATA(insert (  403 435 649 3 ));
+DATA(insert (  403 435 648 4 ));
+DATA(insert (  403 435 646 5 ));
 
 /*
  * nbtree float4_ops
  */
 
-DATA(insert OID = 0 (  403 428 622 1 ));
-DATA(insert OID = 0 (  403 428 624 2 ));
-DATA(insert OID = 0 (  403 428 620 3 ));
-DATA(insert OID = 0 (  403 428 625 4 ));
-DATA(insert OID = 0 (  403 428 623 5 ));
+DATA(insert (  403 428 622 1 ));
+DATA(insert (  403 428 624 2 ));
+DATA(insert (  403 428 620 3 ));
+DATA(insert (  403 428 625 4 ));
+DATA(insert (  403 428 623 5 ));
 
 /*
  * nbtree char_ops
  */
 
-DATA(insert OID = 0 (  403 429 631 1 ));
-DATA(insert OID = 0 (  403 429 632 2 ));
-DATA(insert OID = 0 (  403 429 92 3 ));
-DATA(insert OID = 0 (  403 429 634 4 ));
-DATA(insert OID = 0 (  403 429 633 5 ));
+DATA(insert (  403 429 631 1 ));
+DATA(insert (  403 429 632 2 ));
+DATA(insert (  403 429 92 3 ));
+DATA(insert (  403 429 634 4 ));
+DATA(insert (  403 429 633 5 ));
 
 /*
  * nbtree name_ops
  */
 
-DATA(insert OID = 0 (  403 1181 660 1 ));
-DATA(insert OID = 0 (  403 1181 661 2 ));
-DATA(insert OID = 0 (  403 1181 93 3 ));
-DATA(insert OID = 0 (  403 1181 663 4 ));
-DATA(insert OID = 0 (  403 1181 662 5 ));
+DATA(insert (  403 1181 660 1 ));
+DATA(insert (  403 1181 661 2 ));
+DATA(insert (  403 1181 93 3 ));
+DATA(insert (  403 1181 663 4 ));
+DATA(insert (  403 1181 662 5 ));
 
 /*
  * nbtree text_ops
  */
 
-DATA(insert OID = 0 (  403 431 664 1 ));
-DATA(insert OID = 0 (  403 431 665 2 ));
-DATA(insert OID = 0 (  403 431 98 3 ));
-DATA(insert OID = 0 (  403 431 667 4 ));
-DATA(insert OID = 0 (  403 431 666 5 ));
+DATA(insert (  403 431 664 1 ));
+DATA(insert (  403 431 665 2 ));
+DATA(insert (  403 431 98 3 ));
+DATA(insert (  403 431 667 4 ));
+DATA(insert (  403 431 666 5 ));
 
 /*
  * nbtree abstime_ops
  */
 
-DATA(insert OID = 0 (  403 432 562 1 ));
-DATA(insert OID = 0 (  403 432 564 2 ));
-DATA(insert OID = 0 (  403 432 560 3 ));
-DATA(insert OID = 0 (  403 432 565 4 ));
-DATA(insert OID = 0 (  403 432 563 5 ));
+DATA(insert (  403 432 562 1 ));
+DATA(insert (  403 432 564 2 ));
+DATA(insert (  403 432 560 3 ));
+DATA(insert (  403 432 565 4 ));
+DATA(insert (  403 432 563 5 ));
 
 /*
  * nbtree bpchar_ops
  */
 
-DATA(insert OID = 0 (  403 1076 1058 1 ));
-DATA(insert OID = 0 (  403 1076 1059 2 ));
-DATA(insert OID = 0 (  403 1076 1054 3 ));
-DATA(insert OID = 0 (  403 1076 1061 4 ));
-DATA(insert OID = 0 (  403 1076 1060 5 ));
+DATA(insert (  403 1076 1058 1 ));
+DATA(insert (  403 1076 1059 2 ));
+DATA(insert (  403 1076 1054 3 ));
+DATA(insert (  403 1076 1061 4 ));
+DATA(insert (  403 1076 1060 5 ));
 
 /*
  * nbtree varchar_ops
  */
 
-DATA(insert OID = 0 (  403 1077 1066 1 ));
-DATA(insert OID = 0 (  403 1077 1067 2 ));
-DATA(insert OID = 0 (  403 1077 1062 3 ));
-DATA(insert OID = 0 (  403 1077 1069 4 ));
-DATA(insert OID = 0 (  403 1077 1068 5 ));
+DATA(insert (  403 1077 1066 1 ));
+DATA(insert (  403 1077 1067 2 ));
+DATA(insert (  403 1077 1062 3 ));
+DATA(insert (  403 1077 1069 4 ));
+DATA(insert (  403 1077 1068 5 ));
 
 /*
  * nbtree date_ops
  */
 
-DATA(insert OID = 0 (  403 1114 1095 1 ));
-DATA(insert OID = 0 (  403 1114 1096 2 ));
-DATA(insert OID = 0 (  403 1114 1093 3 ));
-DATA(insert OID = 0 (  403 1114 1098 4 ));
-DATA(insert OID = 0 (  403 1114 1097 5 ));
+DATA(insert (  403 1114 1095 1 ));
+DATA(insert (  403 1114 1096 2 ));
+DATA(insert (  403 1114 1093 3 ));
+DATA(insert (  403 1114 1098 4 ));
+DATA(insert (  403 1114 1097 5 ));
 
 /*
  * nbtree time_ops
  */
 
-DATA(insert OID = 0 (  403 1115 1110 1 ));
-DATA(insert OID = 0 (  403 1115 1111 2 ));
-DATA(insert OID = 0 (  403 1115 1108 3 ));
-DATA(insert OID = 0 (  403 1115 1113 4 ));
-DATA(insert OID = 0 (  403 1115 1112 5 ));
+DATA(insert (  403 1115 1110 1 ));
+DATA(insert (  403 1115 1111 2 ));
+DATA(insert (  403 1115 1108 3 ));
+DATA(insert (  403 1115 1113 4 ));
+DATA(insert (  403 1115 1112 5 ));
 
 /*
  * nbtree timetz_ops
  */
 
-DATA(insert OID = 0 (  403 1399 1552 1 ));
-DATA(insert OID = 0 (  403 1399 1553 2 ));
-DATA(insert OID = 0 (  403 1399 1550 3 ));
-DATA(insert OID = 0 (  403 1399 1555 4 ));
-DATA(insert OID = 0 (  403 1399 1554 5 ));
+DATA(insert (  403 1399 1552 1 ));
+DATA(insert (  403 1399 1553 2 ));
+DATA(insert (  403 1399 1550 3 ));
+DATA(insert (  403 1399 1555 4 ));
+DATA(insert (  403 1399 1554 5 ));
 
 /*
  * nbtree timestamp_ops
  */
 
-DATA(insert OID = 0 (  403 1312 1322 1 ));
-DATA(insert OID = 0 (  403 1312 1323 2 ));
-DATA(insert OID = 0 (  403 1312 1320 3 ));
-DATA(insert OID = 0 (  403 1312 1325 4 ));
-DATA(insert OID = 0 (  403 1312 1324 5 ));
+DATA(insert (  403 1312 1322 1 ));
+DATA(insert (  403 1312 1323 2 ));
+DATA(insert (  403 1312 1320 3 ));
+DATA(insert (  403 1312 1325 4 ));
+DATA(insert (  403 1312 1324 5 ));
 
 /*
  * nbtree interval_ops
  */
 
-DATA(insert OID = 0 (  403 1313 1332 1 ));
-DATA(insert OID = 0 (  403 1313 1333 2 ));
-DATA(insert OID = 0 (  403 1313 1330 3 ));
-DATA(insert OID = 0 (  403 1313 1335 4 ));
-DATA(insert OID = 0 (  403 1313 1334 5 ));
+DATA(insert (  403 1313 1332 1 ));
+DATA(insert (  403 1313 1333 2 ));
+DATA(insert (  403 1313 1330 3 ));
+DATA(insert (  403 1313 1335 4 ));
+DATA(insert (  403 1313 1334 5 ));
 
 /*
  * nbtree macaddr
  */
 
-DATA(insert OID = 0 (  403 810 1222 1 ));
-DATA(insert OID = 0 (  403 810 1223 2 ));
-DATA(insert OID = 0 (  403 810 1220 3 ));
-DATA(insert OID = 0 (  403 810 1225 4 ));
-DATA(insert OID = 0 (  403 810 1224 5 ));
+DATA(insert (  403 810 1222 1 ));
+DATA(insert (  403 810 1223 2 ));
+DATA(insert (  403 810 1220 3 ));
+DATA(insert (  403 810 1225 4 ));
+DATA(insert (  403 810 1224 5 ));
 
 /*
  * nbtree inet
  */
 
-DATA(insert OID = 0 (  403 935 1203 1 ));
-DATA(insert OID = 0 (  403 935 1204 2 ));
-DATA(insert OID = 0 (  403 935 1201 3 ));
-DATA(insert OID = 0 (  403 935 1206 4 ));
-DATA(insert OID = 0 (  403 935 1205 5 ));
+DATA(insert (  403 935 1203 1 ));
+DATA(insert (  403 935 1204 2 ));
+DATA(insert (  403 935 1201 3 ));
+DATA(insert (  403 935 1206 4 ));
+DATA(insert (  403 935 1205 5 ));
 
 /*
  * nbtree cidr
  */
 
-DATA(insert OID = 0 (  403 652 822 1 ));
-DATA(insert OID = 0 (  403 652 823 2 ));
-DATA(insert OID = 0 (  403 652 820 3 ));
-DATA(insert OID = 0 (  403 652 825 4 ));
-DATA(insert OID = 0 (  403 652 824 5 ));
+DATA(insert (  403 652 822 1 ));
+DATA(insert (  403 652 823 2 ));
+DATA(insert (  403 652 820 3 ));
+DATA(insert (  403 652 825 4 ));
+DATA(insert (  403 652 824 5 ));
 
 /*
  * nbtree numeric
  */
 
-DATA(insert OID = 0 (  403 1768 1754 1 ));
-DATA(insert OID = 0 (  403 1768 1755 2 ));
-DATA(insert OID = 0 (  403 1768 1752 3 ));
-DATA(insert OID = 0 (  403 1768 1757 4 ));
-DATA(insert OID = 0 (  403 1768 1756 5 ));
+DATA(insert (  403 1768 1754 1 ));
+DATA(insert (  403 1768 1755 2 ));
+DATA(insert (  403 1768 1752 3 ));
+DATA(insert (  403 1768 1757 4 ));
+DATA(insert (  403 1768 1756 5 ));
 
 /*
  * nbtree bool
  */
 
-DATA(insert OID = 0 (  403 1690   58 1 ));
-DATA(insert OID = 0 (  403 1690 1694 2 ));
-DATA(insert OID = 0 (  403 1690   91 3 ));
-DATA(insert OID = 0 (  403 1690 1695 4 ));
-DATA(insert OID = 0 (  403 1690   59 5 ));
+DATA(insert (  403 1690   58 1 ));
+DATA(insert (  403 1690 1694 2 ));
+DATA(insert (  403 1690   91 3 ));
+DATA(insert (  403 1690 1695 4 ));
+DATA(insert (  403 1690   59 5 ));
 
 /*
  * nbtree bit
  */
 
-DATA(insert OID = 0 (  403 424 1786 1 ));
-DATA(insert OID = 0 (  403 424 1788 2 ));
-DATA(insert OID = 0 (  403 424 1784 3 ));
-DATA(insert OID = 0 (  403 424 1789 4 ));
-DATA(insert OID = 0 (  403 424 1787 5 ));
+DATA(insert (  403 424 1786 1 ));
+DATA(insert (  403 424 1788 2 ));
+DATA(insert (  403 424 1784 3 ));
+DATA(insert (  403 424 1789 4 ));
+DATA(insert (  403 424 1787 5 ));
 
 /*
  * nbtree varbit
  */
 
-DATA(insert OID = 0 (  403 425 1806 1 ));
-DATA(insert OID = 0 (  403 425 1808 2 ));
-DATA(insert OID = 0 (  403 425 1804 3 ));
-DATA(insert OID = 0 (  403 425 1809 4 ));
-DATA(insert OID = 0 (  403 425 1807 5 ));
+DATA(insert (  403 425 1806 1 ));
+DATA(insert (  403 425 1808 2 ));
+DATA(insert (  403 425 1804 3 ));
+DATA(insert (  403 425 1809 4 ));
+DATA(insert (  403 425 1807 5 ));
 
 
 /*
  */
 
 /* int2_ops */
-DATA(insert OID = 0 (  405 421   94 1 ));
+DATA(insert (  405 421   94 1 ));
 /* float8_ops */
-DATA(insert OID = 0 (  405 423  670 1 ));
+DATA(insert (  405 423  670 1 ));
 /* int4_ops */
-DATA(insert OID = 0 (  405 426   96 1 ));
+DATA(insert (  405 426   96 1 ));
 /* int8_ops */
-DATA(insert OID = 0 (  405 754  410 1 ));
+DATA(insert (  405 754  410 1 ));
 /* oid_ops */
-DATA(insert OID = 0 (  405 427  607 1 ));
+DATA(insert (  405 427  607 1 ));
 /* oidvector_ops */
-DATA(insert OID = 0 (  405 435  649 1 ));
+DATA(insert (  405 435  649 1 ));
 /* float4_ops */
-DATA(insert OID = 0 (  405 428  620 1 ));
+DATA(insert (  405 428  620 1 ));
 /* char_ops */
-DATA(insert OID = 0 (  405 429   92 1 ));
+DATA(insert (  405 429   92 1 ));
 /* name_ops */
-DATA(insert OID = 0 (  405 1181   93 1 ));
+DATA(insert (  405 1181   93 1 ));
 /* text_ops */
-DATA(insert OID = 0 (  405 431   98 1 ));
+DATA(insert (  405 431   98 1 ));
 /* bpchar_ops */
-DATA(insert OID = 0 (  405 1076 1054 1 ));
+DATA(insert (  405 1076 1054 1 ));
 /* varchar_ops */
-DATA(insert OID = 0 (  405 1077 1062 1 ));
+DATA(insert (  405 1077 1062 1 ));
 /* date_ops */
-DATA(insert OID = 0 (  405 1114 1093 1 ));
+DATA(insert (  405 1114 1093 1 ));
 /* time_ops */
-DATA(insert OID = 0 (  405 1115 1108 1 ));
+DATA(insert (  405 1115 1108 1 ));
 /* timetz_ops */
-DATA(insert OID = 0 (  405 1399 1550 1 ));
+DATA(insert (  405 1399 1550 1 ));
 /* timestamp_ops */
-DATA(insert OID = 0 (  405 1312 1320 1 ));
+DATA(insert (  405 1312 1320 1 ));
 /* interval_ops */
-DATA(insert OID = 0 (  405 1313 1330 1 ));
+DATA(insert (  405 1313 1330 1 ));
 /* macaddr_ops */
-DATA(insert OID = 0 (  405 810 1220 1 ));
+DATA(insert (  405 810 1220 1 ));
 /* inet_ops */
-DATA(insert OID = 0 (  405 935 1201 1 ));
+DATA(insert (  405 935 1201 1 ));
 /* cidr_ops */
-DATA(insert OID = 0 (  405 652 820 1 ));
+DATA(insert (  405 652 820 1 ));
 
 #endif  /* PG_AMOP_H */
 
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pg_amproc.h,v 1.27 2001/01/24 19:43:20 momjian Exp $
+ * $Id: pg_amproc.h,v 1.28 2001/08/10 18:57:39 tgl Exp $
  *
  * NOTES
  *   the genbki.sh script reads this file and generates .bki
  *     typedef struct FormData_pg_amproc
  * ----------------
  */
-CATALOG(pg_amproc)
+CATALOG(pg_amproc) BKI_WITHOUT_OIDS
 {
    Oid         amid;           /* the access method this proc is for */
    Oid         amopclaid;      /* the opclass this proc is for */
  */
 
 /* rtree */
-DATA(insert OID = 0 (402  422  193 1));
-DATA(insert OID = 0 (402  422  194 2));
-DATA(insert OID = 0 (402  422  195 3));
-DATA(insert OID = 0 (402  433  193 1));
-DATA(insert OID = 0 (402  433  194 2));
-DATA(insert OID = 0 (402  433  196 3));
-DATA(insert OID = 0 (402  434  197 1));
-DATA(insert OID = 0 (402  434  198 2));
-DATA(insert OID = 0 (402  434  199 3));
+DATA(insert (402  422  193 1));
+DATA(insert (402  422  194 2));
+DATA(insert (402  422  195 3));
+DATA(insert (402  433  193 1));
+DATA(insert (402  433  194 2));
+DATA(insert (402  433  196 3));
+DATA(insert (402  434  197 1));
+DATA(insert (402  434  198 2));
+DATA(insert (402  434  199 3));
 
 
 /* btree */
-DATA(insert OID = 0 (403  421  350 1));
-DATA(insert OID = 0 (403  423  355 1));
-DATA(insert OID = 0 (403  426  351 1));
-DATA(insert OID = 0 (403  427  356 1));
-DATA(insert OID = 0 (403  428  354 1));
-DATA(insert OID = 0 (403  429  358 1));
-DATA(insert OID = 0 (403  431  360 1));
-DATA(insert OID = 0 (403  432  357 1));
-DATA(insert OID = 0 (403  435  404 1));
-DATA(insert OID = 0 (403  754  842 1));
-DATA(insert OID = 0 (403 1076 1078 1));
-DATA(insert OID = 0 (403 1077 1079 1));
-DATA(insert OID = 0 (403 1114 1092 1));
-DATA(insert OID = 0 (403 1115 1107 1));
-DATA(insert OID = 0 (403 1181  359 1));
-DATA(insert OID = 0 (403 1312 1314 1));
-DATA(insert OID = 0 (403 1313 1315 1));
-DATA(insert OID = 0 (403  810  836 1));
-DATA(insert OID = 0 (403  935  926 1));
-DATA(insert OID = 0 (403  652  926 1));
-DATA(insert OID = 0 (403 1768 1769 1));
-DATA(insert OID = 0 (403 1690 1693 1));
-DATA(insert OID = 0 (403 1399 1358 1));
-DATA(insert OID = 0 (403  424 1596 1));
-DATA(insert OID = 0 (403  425 1672 1));
+DATA(insert (403  421  350 1));
+DATA(insert (403  423  355 1));
+DATA(insert (403  426  351 1));
+DATA(insert (403  427  356 1));
+DATA(insert (403  428  354 1));
+DATA(insert (403  429  358 1));
+DATA(insert (403  431  360 1));
+DATA(insert (403  432  357 1));
+DATA(insert (403  435  404 1));
+DATA(insert (403  754  842 1));
+DATA(insert (403 1076 1078 1));
+DATA(insert (403 1077 1079 1));
+DATA(insert (403 1114 1092 1));
+DATA(insert (403 1115 1107 1));
+DATA(insert (403 1181  359 1));
+DATA(insert (403 1312 1314 1));
+DATA(insert (403 1313 1315 1));
+DATA(insert (403  810  836 1));
+DATA(insert (403  935  926 1));
+DATA(insert (403  652  926 1));
+DATA(insert (403 1768 1769 1));
+DATA(insert (403 1690 1693 1));
+DATA(insert (403 1399 1358 1));
+DATA(insert (403  424 1596 1));
+DATA(insert (403  425 1672 1));
 
 
 /* hash */
-DATA(insert OID = 0 (405  421  449 1));
-DATA(insert OID = 0 (405  423  452 1));
-DATA(insert OID = 0 (405  426  450 1));
-DATA(insert OID = 0 (405  427  453 1));
-DATA(insert OID = 0 (405  428  451 1));
-DATA(insert OID = 0 (405  429  454 1));
-DATA(insert OID = 0 (405  431  456 1));
-DATA(insert OID = 0 (405  435  457 1));
-DATA(insert OID = 0 (405  652  456 1));
-DATA(insert OID = 0 (405  754  949 1));
-DATA(insert OID = 0 (405  810  399 1));
-DATA(insert OID = 0 (405  935  456 1));
-DATA(insert OID = 0 (405 1076 1080 1));
-DATA(insert OID = 0 (405 1077  456 1));
-DATA(insert OID = 0 (405 1114  450 1));
-DATA(insert OID = 0 (405 1115  452 1));
-DATA(insert OID = 0 (405 1181  455 1));
-DATA(insert OID = 0 (405 1312  452 1));
-DATA(insert OID = 0 (405 1313 1697 1));
-DATA(insert OID = 0 (405 1399 1696 1));
+DATA(insert (405  421  449 1));
+DATA(insert (405  423  452 1));
+DATA(insert (405  426  450 1));
+DATA(insert (405  427  453 1));
+DATA(insert (405  428  451 1));
+DATA(insert (405  429  454 1));
+DATA(insert (405  431  456 1));
+DATA(insert (405  435  457 1));
+DATA(insert (405  652  456 1));
+DATA(insert (405  754  949 1));
+DATA(insert (405  810  399 1));
+DATA(insert (405  935  456 1));
+DATA(insert (405 1076 1080 1));
+DATA(insert (405 1077  456 1));
+DATA(insert (405 1114  450 1));
+DATA(insert (405 1115  452 1));
+DATA(insert (405 1181  455 1));
+DATA(insert (405 1312  452 1));
+DATA(insert (405 1313 1697 1));
+DATA(insert (405 1399 1696 1));
 
 #endif  /* PG_AMPROC_H */
 
  *     typedef struct FormData_pg_attrdef
  * ----------------
  */
-CATALOG(pg_attrdef)
+CATALOG(pg_attrdef) BKI_WITHOUT_OIDS
 {
    Oid         adrelid;
    int2        adnum;
 
  * 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.73 2001/06/12 05:55:50 tgl Exp $
+ * $Id: pg_attribute.h,v 1.74 2001/08/10 18:57:40 tgl Exp $
  *
  * NOTES
  *   the genbki.sh script reads this file and generates .bki
  *   information from the DATA() statements.
  *
- *   utils/cache/relcache.c requires some hard-coded tuple descriptors
- *   for some of the system catalogs so if the schema for any of
+ *   utils/cache/relcache.c requires hard-coded tuple descriptors
+ *   for some of the system catalogs.  So if the schema for any of
  *   these changes, be sure and change the appropriate Schema_xxx
  *   macros!  -cim 2/5/91
  *
  *     system attributes in catalog/heap.c also.
  * ----------------
  */
-CATALOG(pg_attribute) BOOTSTRAP
+CATALOG(pg_attribute) BOOTSTRAP BKI_WITHOUT_OIDS
 {
    Oid         attrelid;       /* OID of relation containing this
                                 * attribute */
 { 1247, {"typstorage"},    18, 0,  1, 16, 0, -1, -1, true, 'p', false, 'c', false, false }, \
 { 1247, {"typdefault"},    25, 0,  -1, 17, 0, -1, -1, false    , 'x', false, 'i', false, false }
 
-DATA(insert OID = 0 ( 1247 typname         19 DEFAULT_ATTSTATTARGET NAMEDATALEN   1 0 -1 -1 f p f i f f));
-DATA(insert OID = 0 ( 1247 typowner            23 0  4   2 0 -1 -1 t p f i f f));
-DATA(insert OID = 0 ( 1247 typlen          21 0  2   3 0 -1 -1 t p f s f f));
-DATA(insert OID = 0 ( 1247 typprtlen       21 0  2   4 0 -1 -1 t p f s f f));
-DATA(insert OID = 0 ( 1247 typbyval            16 0  1   5 0 -1 -1 t p f c f f));
-DATA(insert OID = 0 ( 1247 typtype         18 0  1   6 0 -1 -1 t p f c f f));
-DATA(insert OID = 0 ( 1247 typisdefined        16 0  1   7 0 -1 -1 t p f c f f));
-DATA(insert OID = 0 ( 1247 typdelim            18 0  1   8 0 -1 -1 t p f c f f));
-DATA(insert OID = 0 ( 1247 typrelid            26 0  4   9 0 -1 -1 t p f i f f));
-DATA(insert OID = 0 ( 1247 typelem         26 0  4  10 0 -1 -1 t p f i f f));
-DATA(insert OID = 0 ( 1247 typinput            24 0  4  11 0 -1 -1 t p f i f f));
-DATA(insert OID = 0 ( 1247 typoutput       24 0  4  12 0 -1 -1 t p f i f f));
-DATA(insert OID = 0 ( 1247 typreceive      24 0  4  13 0 -1 -1 t p f i f f));
-DATA(insert OID = 0 ( 1247 typsend         24 0  4  14 0 -1 -1 t p f i f f));
-DATA(insert OID = 0 ( 1247 typalign            18 0  1  15 0 -1 -1 t p f c f f));
-DATA(insert OID = 0 ( 1247 typstorage      18 0  1  16 0 -1 -1 t p f c f f));
-DATA(insert OID = 0 ( 1247 typdefault      25 0 -1  17 0 -1 -1 f x f i f f));
-DATA(insert OID = 0 ( 1247 ctid                27 0  6  -1 0 -1 -1 f p f i f f));
-DATA(insert OID = 0 ( 1247 oid             26 0  4  -2 0 -1 -1 t p f i f f));
-DATA(insert OID = 0 ( 1247 xmin                28 0  4  -3 0 -1 -1 t p f i f f));
-DATA(insert OID = 0 ( 1247 cmin                29 0  4  -4 0 -1 -1 t p f i f f));
-DATA(insert OID = 0 ( 1247 xmax                28 0  4  -5 0 -1 -1 t p f i f f));
-DATA(insert OID = 0 ( 1247 cmax                29 0  4  -6 0 -1 -1 t p f i f f));
-DATA(insert OID = 0 ( 1247 tableoid            26 0  4  -7 0 -1 -1 t p f i f f));
+DATA(insert ( 1247 typname         19 DEFAULT_ATTSTATTARGET NAMEDATALEN   1 0 -1 -1 f p f i f f));
+DATA(insert ( 1247 typowner            23 0  4   2 0 -1 -1 t p f i f f));
+DATA(insert ( 1247 typlen          21 0  2   3 0 -1 -1 t p f s f f));
+DATA(insert ( 1247 typprtlen       21 0  2   4 0 -1 -1 t p f s f f));
+DATA(insert ( 1247 typbyval            16 0  1   5 0 -1 -1 t p f c f f));
+DATA(insert ( 1247 typtype         18 0  1   6 0 -1 -1 t p f c f f));
+DATA(insert ( 1247 typisdefined        16 0  1   7 0 -1 -1 t p f c f f));
+DATA(insert ( 1247 typdelim            18 0  1   8 0 -1 -1 t p f c f f));
+DATA(insert ( 1247 typrelid            26 0  4   9 0 -1 -1 t p f i f f));
+DATA(insert ( 1247 typelem         26 0  4  10 0 -1 -1 t p f i f f));
+DATA(insert ( 1247 typinput            24 0  4  11 0 -1 -1 t p f i f f));
+DATA(insert ( 1247 typoutput       24 0  4  12 0 -1 -1 t p f i f f));
+DATA(insert ( 1247 typreceive      24 0  4  13 0 -1 -1 t p f i f f));
+DATA(insert ( 1247 typsend         24 0  4  14 0 -1 -1 t p f i f f));
+DATA(insert ( 1247 typalign            18 0  1  15 0 -1 -1 t p f c f f));
+DATA(insert ( 1247 typstorage      18 0  1  16 0 -1 -1 t p f c f f));
+DATA(insert ( 1247 typdefault      25 0 -1  17 0 -1 -1 f x f i f f));
+DATA(insert ( 1247 ctid                27 0  6  -1 0 -1 -1 f p f i f f));
+DATA(insert ( 1247 oid             26 0  4  -2 0 -1 -1 t p f i f f));
+DATA(insert ( 1247 xmin                28 0  4  -3 0 -1 -1 t p f i f f));
+DATA(insert ( 1247 cmin                29 0  4  -4 0 -1 -1 t p f i f f));
+DATA(insert ( 1247 xmax                28 0  4  -5 0 -1 -1 t p f i f f));
+DATA(insert ( 1247 cmax                29 0  4  -6 0 -1 -1 t p f i f f));
+DATA(insert ( 1247 tableoid            26 0  4  -7 0 -1 -1 t p f i f f));
 
 /* ----------------
  *     pg_database
  * ----------------
  */
-DATA(insert OID = 0 ( 1262 datname         19 0 NAMEDATALEN   1 0 -1 -1 f p f i f f));
-DATA(insert OID = 0 ( 1262 datdba          23 0  4   2 0 -1 -1 t p f i f f));
-DATA(insert OID = 0 ( 1262 encoding            23 0  4   3 0 -1 -1 t p f i f f));
-DATA(insert OID = 0 ( 1262 datistemplate   16 0  1   4 0 -1 -1 t p f c f f));
-DATA(insert OID = 0 ( 1262 datallowconn        16 0  1   5 0 -1 -1 t p f c f f));
-DATA(insert OID = 0 ( 1262 datlastsysoid   26 0  4   6 0 -1 -1 t p f i f f));
+DATA(insert ( 1262 datname         19 0 NAMEDATALEN   1 0 -1 -1 f p f i f f));
+DATA(insert ( 1262 datdba          23 0  4   2 0 -1 -1 t p f i f f));
+DATA(insert ( 1262 encoding            23 0  4   3 0 -1 -1 t p f i f f));
+DATA(insert ( 1262 datistemplate   16 0  1   4 0 -1 -1 t p f c f f));
+DATA(insert ( 1262 datallowconn        16 0  1   5 0 -1 -1 t p f c f f));
+DATA(insert ( 1262 datlastsysoid   26 0  4   6 0 -1 -1 t p f i f f));
 /* do not mark datpath as toastable; GetRawDatabaseInfo won't cope */
-DATA(insert OID = 0 ( 1262 datpath         25 0 -1   7 0 -1 -1 f p f i f f));
-DATA(insert OID = 0 ( 1262 ctid                27 0  6  -1 0 -1 -1 f p f i f f));
-DATA(insert OID = 0 ( 1262 oid             26 0  4  -2 0 -1 -1 t p f i f f));
-DATA(insert OID = 0 ( 1262 xmin                28 0  4  -3 0 -1 -1 t p f i f f));
-DATA(insert OID = 0 ( 1262 cmin                29 0  4  -4 0 -1 -1 t p f i f f));
-DATA(insert OID = 0 ( 1262 xmax                28 0  4  -5 0 -1 -1 t p f i f f));
-DATA(insert OID = 0 ( 1262 cmax                29 0  4  -6 0 -1 -1 t p f i f f));
-DATA(insert OID = 0 ( 1262 tableoid            26 0  4  -7 0 -1 -1 t p f i f f));
+DATA(insert ( 1262 datpath         25 0 -1   7 0 -1 -1 f p f i f f));
+DATA(insert ( 1262 ctid                27 0  6  -1 0 -1 -1 f p f i f f));
+DATA(insert ( 1262 oid             26 0  4  -2 0 -1 -1 t p f i f f));
+DATA(insert ( 1262 xmin                28 0  4  -3 0 -1 -1 t p f i f f));
+DATA(insert ( 1262 cmin                29 0  4  -4 0 -1 -1 t p f i f f));
+DATA(insert ( 1262 xmax                28 0  4  -5 0 -1 -1 t p f i f f));
+DATA(insert ( 1262 cmax                29 0  4  -6 0 -1 -1 t p f i f f));
+DATA(insert ( 1262 tableoid            26 0  4  -7 0 -1 -1 t p f i f f));
 
 /* ----------------
  *     pg_proc
 { 1255, {"prosrc"},                25, 0, -1, 16, 0, -1, -1, false, 'x', false, 'i', false, false }, \
 { 1255, {"probin"},                17, 0, -1, 17, 0, -1, -1, false, 'x', false, 'i', false, false }
 
-DATA(insert OID = 0 ( 1255 proname         19 DEFAULT_ATTSTATTARGET NAMEDATALEN   1 0 -1 -1 f p f i f f));
-DATA(insert OID = 0 ( 1255 proowner            23 0  4   2 0 -1 -1 t p f i f f));
-DATA(insert OID = 0 ( 1255 prolang         26 0  4   3 0 -1 -1 t p f i f f));
-DATA(insert OID = 0 ( 1255 proisinh            16 0  1   4 0 -1 -1 t p f c f f));
-DATA(insert OID = 0 ( 1255 proistrusted        16 0  1   5 0 -1 -1 t p f c f f));
-DATA(insert OID = 0 ( 1255 proiscachable   16 0  1   6 0 -1 -1 t p f c f f));
-DATA(insert OID = 0 ( 1255 proisstrict     16 0  1   7 0 -1 -1 t p f c f f));
-DATA(insert OID = 0 ( 1255 pronargs            21 0  2   8 0 -1 -1 t p f s f f));
-DATA(insert OID = 0 ( 1255 proretset       16 0  1   9 0 -1 -1 t p f c f f));
-DATA(insert OID = 0 ( 1255 prorettype      26 0  4  10 0 -1 -1 t p f i f f));
-DATA(insert OID = 0 ( 1255 proargtypes     30 0 INDEX_MAX_KEYS*4 11 0 -1 -1 f p f i f f));
-DATA(insert OID = 0 ( 1255 probyte_pct     23 0  4  12 0 -1 -1 t p f i f f));
-DATA(insert OID = 0 ( 1255 properbyte_cpu  23 0  4  13 0 -1 -1 t p f i f f));
-DATA(insert OID = 0 ( 1255 propercall_cpu  23 0  4  14 0 -1 -1 t p f i f f));
-DATA(insert OID = 0 ( 1255 prooutin_ratio  23 0  4  15 0 -1 -1 t p f i f f));
-DATA(insert OID = 0 ( 1255 prosrc          25 0 -1  16 0 -1 -1 f x f i f f));
-DATA(insert OID = 0 ( 1255 probin          17 0 -1  17 0 -1 -1 f x f i f f));
-DATA(insert OID = 0 ( 1255 ctid                27 0  6  -1 0 -1 -1 f p f i f f));
-DATA(insert OID = 0 ( 1255 oid             26 0  4  -2 0 -1 -1 t p f i f f));
-DATA(insert OID = 0 ( 1255 xmin                28 0  4  -3 0 -1 -1 t p f i f f));
-DATA(insert OID = 0 ( 1255 cmin                29 0  4  -4 0 -1 -1 t p f i f f));
-DATA(insert OID = 0 ( 1255 xmax                28 0  4  -5 0 -1 -1 t p f i f f));
-DATA(insert OID = 0 ( 1255 cmax                29 0  4  -6 0 -1 -1 t p f i f f));
-DATA(insert OID = 0 ( 1255 tableoid            26 0  4  -7 0 -1 -1 t p f i f f));
+DATA(insert ( 1255 proname         19 DEFAULT_ATTSTATTARGET NAMEDATALEN   1 0 -1 -1 f p f i f f));
+DATA(insert ( 1255 proowner            23 0  4   2 0 -1 -1 t p f i f f));
+DATA(insert ( 1255 prolang         26 0  4   3 0 -1 -1 t p f i f f));
+DATA(insert ( 1255 proisinh            16 0  1   4 0 -1 -1 t p f c f f));
+DATA(insert ( 1255 proistrusted        16 0  1   5 0 -1 -1 t p f c f f));
+DATA(insert ( 1255 proiscachable   16 0  1   6 0 -1 -1 t p f c f f));
+DATA(insert ( 1255 proisstrict     16 0  1   7 0 -1 -1 t p f c f f));
+DATA(insert ( 1255 pronargs            21 0  2   8 0 -1 -1 t p f s f f));
+DATA(insert ( 1255 proretset       16 0  1   9 0 -1 -1 t p f c f f));
+DATA(insert ( 1255 prorettype      26 0  4  10 0 -1 -1 t p f i f f));
+DATA(insert ( 1255 proargtypes     30 0 INDEX_MAX_KEYS*4 11 0 -1 -1 f p f i f f));
+DATA(insert ( 1255 probyte_pct     23 0  4  12 0 -1 -1 t p f i f f));
+DATA(insert ( 1255 properbyte_cpu  23 0  4  13 0 -1 -1 t p f i f f));
+DATA(insert ( 1255 propercall_cpu  23 0  4  14 0 -1 -1 t p f i f f));
+DATA(insert ( 1255 prooutin_ratio  23 0  4  15 0 -1 -1 t p f i f f));
+DATA(insert ( 1255 prosrc          25 0 -1  16 0 -1 -1 f x f i f f));
+DATA(insert ( 1255 probin          17 0 -1  17 0 -1 -1 f x f i f f));
+DATA(insert ( 1255 ctid                27 0  6  -1 0 -1 -1 f p f i f f));
+DATA(insert ( 1255 oid             26 0  4  -2 0 -1 -1 t p f i f f));
+DATA(insert ( 1255 xmin                28 0  4  -3 0 -1 -1 t p f i f f));
+DATA(insert ( 1255 cmin                29 0  4  -4 0 -1 -1 t p f i f f));
+DATA(insert ( 1255 xmax                28 0  4  -5 0 -1 -1 t p f i f f));
+DATA(insert ( 1255 cmax                29 0  4  -6 0 -1 -1 t p f i f f));
+DATA(insert ( 1255 tableoid            26 0  4  -7 0 -1 -1 t p f i f f));
 
 /* ----------------
  *     pg_shadow
  * ----------------
  */
-DATA(insert OID = 0 ( 1260 usename         19  DEFAULT_ATTSTATTARGET NAMEDATALEN   1 0 -1 -1 f p f i f f));
-DATA(insert OID = 0 ( 1260 usesysid            23  DEFAULT_ATTSTATTARGET   4   2 0 -1 -1 t p f i f f));
-DATA(insert OID = 0 ( 1260 usecreatedb     16  0   1   3 0 -1 -1 t p f c f f));
-DATA(insert OID = 0 ( 1260 usetrace            16  0   1   4 0 -1 -1 t p f c f f));
-DATA(insert OID = 0 ( 1260 usesuper            16  0   1   5 0 -1 -1 t p f c f f));
-DATA(insert OID = 0 ( 1260 usecatupd       16  0   1   6 0 -1 -1 t p f c f f));
-DATA(insert OID = 0 ( 1260 passwd          25  0  -1   7 0 -1 -1 f x f i f f));
-DATA(insert OID = 0 ( 1260 valuntil            702 0   4   8 0 -1 -1 t p f i f f));
-DATA(insert OID = 0 ( 1260 ctid                27 0  6  -1 0 -1 -1 f p f i f f));
-DATA(insert OID = 0 ( 1260 oid             26 0  4  -2 0 -1 -1 t p f i f f));
-DATA(insert OID = 0 ( 1260 xmin                28 0  4  -3 0 -1 -1 t p f i f f));
-DATA(insert OID = 0 ( 1260 cmin                29 0  4  -4 0 -1 -1 t p f i f f));
-DATA(insert OID = 0 ( 1260 xmax                28 0  4  -5 0 -1 -1 t p f i f f));
-DATA(insert OID = 0 ( 1260 cmax                29 0  4  -6 0 -1 -1 t p f i f f));
-DATA(insert OID = 0 ( 1260 tableoid            26 0  4  -7 0 -1 -1 t p f i f f));
+DATA(insert ( 1260 usename         19  DEFAULT_ATTSTATTARGET NAMEDATALEN   1 0 -1 -1 f p f i f f));
+DATA(insert ( 1260 usesysid            23  DEFAULT_ATTSTATTARGET   4   2 0 -1 -1 t p f i f f));
+DATA(insert ( 1260 usecreatedb     16  0   1   3 0 -1 -1 t p f c f f));
+DATA(insert ( 1260 usetrace            16  0   1   4 0 -1 -1 t p f c f f));
+DATA(insert ( 1260 usesuper            16  0   1   5 0 -1 -1 t p f c f f));
+DATA(insert ( 1260 usecatupd       16  0   1   6 0 -1 -1 t p f c f f));
+DATA(insert ( 1260 passwd          25  0  -1   7 0 -1 -1 f x f i f f));
+DATA(insert ( 1260 valuntil            702 0   4   8 0 -1 -1 t p f i f f));
+DATA(insert ( 1260 ctid                27 0  6  -1 0 -1 -1 f p f i f f));
+/* no OIDs in pg_shadow */
+DATA(insert ( 1260 xmin                28 0  4  -3 0 -1 -1 t p f i f f));
+DATA(insert ( 1260 cmin                29 0  4  -4 0 -1 -1 t p f i f f));
+DATA(insert ( 1260 xmax                28 0  4  -5 0 -1 -1 t p f i f f));
+DATA(insert ( 1260 cmax                29 0  4  -6 0 -1 -1 t p f i f f));
+DATA(insert ( 1260 tableoid            26 0  4  -7 0 -1 -1 t p f i f f));
 
 /* ----------------
  *     pg_group
  * ----------------
  */
-DATA(insert OID = 0 ( 1261 groname         19 DEFAULT_ATTSTATTARGET NAMEDATALEN  1 0 -1 -1 f p f i f f));
-DATA(insert OID = 0 ( 1261 grosysid            23 DEFAULT_ATTSTATTARGET  4   2 0 -1 -1 t p f i f f));
-DATA(insert OID = 0 ( 1261 grolist       1007 0 -1   3 0 -1 -1 f x f i f f));
-DATA(insert OID = 0 ( 1261 ctid                27 0  6  -1 0 -1 -1 f p f i f f));
-DATA(insert OID = 0 ( 1261 oid             26 0  4  -2 0 -1 -1 t p f i f f));
-DATA(insert OID = 0 ( 1261 xmin                28 0  4  -3 0 -1 -1 t p f i f f));
-DATA(insert OID = 0 ( 1261 cmin                29 0  4  -4 0 -1 -1 t p f i f f));
-DATA(insert OID = 0 ( 1261 xmax                28 0  4  -5 0 -1 -1 t p f i f f));
-DATA(insert OID = 0 ( 1261 cmax                29 0  4  -6 0 -1 -1 t p f i f f));
-DATA(insert OID = 0 ( 1261 tableoid            26 0  4  -7 0 -1 -1 t p f i f f));
+DATA(insert ( 1261 groname         19 DEFAULT_ATTSTATTARGET NAMEDATALEN  1 0 -1 -1 f p f i f f));
+DATA(insert ( 1261 grosysid            23 DEFAULT_ATTSTATTARGET  4   2 0 -1 -1 t p f i f f));
+DATA(insert ( 1261 grolist       1007 0 -1   3 0 -1 -1 f x f i f f));
+DATA(insert ( 1261 ctid                27 0  6  -1 0 -1 -1 f p f i f f));
+/* no OIDs in pg_group */
+DATA(insert ( 1261 xmin                28 0  4  -3 0 -1 -1 t p f i f f));
+DATA(insert ( 1261 cmin                29 0  4  -4 0 -1 -1 t p f i f f));
+DATA(insert ( 1261 xmax                28 0  4  -5 0 -1 -1 t p f i f f));
+DATA(insert ( 1261 cmax                29 0  4  -6 0 -1 -1 t p f i f f));
+DATA(insert ( 1261 tableoid            26 0  4  -7 0 -1 -1 t p f i f f));
 
 /* ----------------
  *     pg_attribute
 { 1249, {"attnotnull"},  16, 0, 1, 14, 0, -1, -1, true, 'p', false, 'c', false, false }, \
 { 1249, {"atthasdef"},  16, 0, 1, 15, 0, -1, -1, true, 'p', false, 'c', false, false }
 
-DATA(insert OID = 0 ( 1249 attrelid            26 DEFAULT_ATTSTATTARGET  4   1 0 -1 -1 t p f i f f));
-DATA(insert OID = 0 ( 1249 attname         19 DEFAULT_ATTSTATTARGET NAMEDATALEN  2 0 -1 -1 f p f i f f));
-DATA(insert OID = 0 ( 1249 atttypid            26 0  4   3 0 -1 -1 t p f i f f));
-DATA(insert OID = 0 ( 1249 attstattarget   23 0  4   4 0 -1 -1 t p f i f f));
-DATA(insert OID = 0 ( 1249 attlen          21 0  2   5 0 -1 -1 t p f s f f));
-DATA(insert OID = 0 ( 1249 attnum          21 0  2   6 0 -1 -1 t p f s f f));
-DATA(insert OID = 0 ( 1249 attndims            23 0  4   7 0 -1 -1 t p f i f f));
-DATA(insert OID = 0 ( 1249 attcacheoff     23 0  4   8 0 -1 -1 t p f i f f));
-DATA(insert OID = 0 ( 1249 atttypmod       23 0  4   9 0 -1 -1 t p f i f f));
-DATA(insert OID = 0 ( 1249 attbyval            16 0  1  10 0 -1 -1 t p f c f f));
-DATA(insert OID = 0 ( 1249 attstorage      18 0  1  11 0 -1 -1 t p f c f f));
-DATA(insert OID = 0 ( 1249 attisset            16 0  1  12 0 -1 -1 t p f c f f));
-DATA(insert OID = 0 ( 1249 attalign            18 0  1  13 0 -1 -1 t p f c f f));
-DATA(insert OID = 0 ( 1249 attnotnull      16 0  1  14 0 -1 -1 t p f c f f));
-DATA(insert OID = 0 ( 1249 atthasdef       16 0  1  15 0 -1 -1 t p f c f f));
-DATA(insert OID = 0 ( 1249 ctid                27 0  6  -1 0 -1 -1 f p f i f f));
-DATA(insert OID = 0 ( 1249 oid             26 0  4  -2 0 -1 -1 t p f i f f));
-DATA(insert OID = 0 ( 1249 xmin                28 0  4  -3 0 -1 -1 t p f i f f));
-DATA(insert OID = 0 ( 1249 cmin                29 0  4  -4 0 -1 -1 t p f i f f));
-DATA(insert OID = 0 ( 1249 xmax                28 0  4  -5 0 -1 -1 t p f i f f));
-DATA(insert OID = 0 ( 1249 cmax                29 0  4  -6 0 -1 -1 t p f i f f));
-DATA(insert OID = 0 ( 1249 tableoid            26 0  4  -7 0 -1 -1 t p f i f f));
+DATA(insert ( 1249 attrelid            26 DEFAULT_ATTSTATTARGET  4   1 0 -1 -1 t p f i f f));
+DATA(insert ( 1249 attname         19 DEFAULT_ATTSTATTARGET NAMEDATALEN  2 0 -1 -1 f p f i f f));
+DATA(insert ( 1249 atttypid            26 0  4   3 0 -1 -1 t p f i f f));
+DATA(insert ( 1249 attstattarget   23 0  4   4 0 -1 -1 t p f i f f));
+DATA(insert ( 1249 attlen          21 0  2   5 0 -1 -1 t p f s f f));
+DATA(insert ( 1249 attnum          21 0  2   6 0 -1 -1 t p f s f f));
+DATA(insert ( 1249 attndims            23 0  4   7 0 -1 -1 t p f i f f));
+DATA(insert ( 1249 attcacheoff     23 0  4   8 0 -1 -1 t p f i f f));
+DATA(insert ( 1249 atttypmod       23 0  4   9 0 -1 -1 t p f i f f));
+DATA(insert ( 1249 attbyval            16 0  1  10 0 -1 -1 t p f c f f));
+DATA(insert ( 1249 attstorage      18 0  1  11 0 -1 -1 t p f c f f));
+DATA(insert ( 1249 attisset            16 0  1  12 0 -1 -1 t p f c f f));
+DATA(insert ( 1249 attalign            18 0  1  13 0 -1 -1 t p f c f f));
+DATA(insert ( 1249 attnotnull      16 0  1  14 0 -1 -1 t p f c f f));
+DATA(insert ( 1249 atthasdef       16 0  1  15 0 -1 -1 t p f c f f));
+DATA(insert ( 1249 ctid                27 0  6  -1 0 -1 -1 f p f i f f));
+/* no OIDs in pg_attribute */
+DATA(insert ( 1249 xmin                28 0  4  -3 0 -1 -1 t p f i f f));
+DATA(insert ( 1249 cmin                29 0  4  -4 0 -1 -1 t p f i f f));
+DATA(insert ( 1249 xmax                28 0  4  -5 0 -1 -1 t p f i f f));
+DATA(insert ( 1249 cmax                29 0  4  -6 0 -1 -1 t p f i f f));
+DATA(insert ( 1249 tableoid            26 0  4  -7 0 -1 -1 t p f i f f));
 
 /* ----------------
  *     pg_class
 { 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, {"relhaspkey"},    16, 0,  1, 19, 0, -1, -1, true, 'p', false, 'c', false, false }, \
-{ 1259, {"relhasrules"},   16, 0,  1, 20, 0, -1, -1, true, 'p', false, 'c', false, false }, \
-{ 1259, {"relhassubclass"},16, 0,  1, 21, 0, -1, -1, true, 'p', false, 'c', false, false }, \
-{ 1259, {"relacl"},         1034, 0,  -1, 22, 0, -1, -1,   false, 'x', false, 'i', false, false }
-
-DATA(insert OID = 0 ( 1259 relname         19 DEFAULT_ATTSTATTARGET NAMEDATALEN   1 0 -1 -1 f p f i f f));
-DATA(insert OID = 0 ( 1259 reltype         26 0  4   2 0 -1 -1 t p f i f f));
-DATA(insert OID = 0 ( 1259 relowner            23 0  4   3 0 -1 -1 t p f i f f));
-DATA(insert OID = 0 ( 1259 relam           26 0  4   4 0 -1 -1 t p f i f f));
-DATA(insert OID = 0 ( 1259 relfilenode     26 0  4   5 0 -1 -1 t p f i f f));
-DATA(insert OID = 0 ( 1259 relpages            23 0  4   6 0 -1 -1 t p f i f f));
-DATA(insert OID = 0 ( 1259 reltuples      700 0  4   7 0 -1 -1 f p f i f f));
-DATA(insert OID = 0 ( 1259 reltoastrelid   26 0  4   8 0 -1 -1 t p f i f f));
-DATA(insert OID = 0 ( 1259 reltoastidxid   26 0  4   9 0 -1 -1 t p f i f f));
-DATA(insert OID = 0 ( 1259 relhasindex     16 0  1  10 0 -1 -1 t p f c f f));
-DATA(insert OID = 0 ( 1259 relisshared     16 0  1  11 0 -1 -1 t p f c f f));
-DATA(insert OID = 0 ( 1259 relkind         18 0  1  12 0 -1 -1 t p f c f f));
-DATA(insert OID = 0 ( 1259 relnatts            21 0  2  13 0 -1 -1 t p f s f f));
-DATA(insert OID = 0 ( 1259 relchecks       21 0  2  14 0 -1 -1 t p f s f f));
-DATA(insert OID = 0 ( 1259 reltriggers     21 0  2  15 0 -1 -1 t p f s f f));
-DATA(insert OID = 0 ( 1259 relukeys            21 0  2  16 0 -1 -1 t p f s f f));
-DATA(insert OID = 0 ( 1259 relfkeys            21 0  2  17 0 -1 -1 t p f s f f));
-DATA(insert OID = 0 ( 1259 relrefs         21 0  2  18 0 -1 -1 t p f s f f));
-DATA(insert OID = 0 ( 1259 relhaspkey      16 0  1  19 0 -1 -1 t p f c f f));
-DATA(insert OID = 0 ( 1259 relhasrules     16 0  1  20 0 -1 -1 t p f c f f));
-DATA(insert OID = 0 ( 1259 relhassubclass  16 0  1  21 0 -1 -1 t p f c f f));
-DATA(insert OID = 0 ( 1259 relacl        1034 0 -1  22 0 -1 -1 f x f i f f));
-DATA(insert OID = 0 ( 1259 ctid                27 0  6  -1 0 -1 -1 f p f i f f));
-DATA(insert OID = 0 ( 1259 oid             26 0  4  -2 0 -1 -1 t p f i f f));
-DATA(insert OID = 0 ( 1259 xmin                28 0  4  -3 0 -1 -1 t p f i f f));
-DATA(insert OID = 0 ( 1259 cmin                29 0  4  -4 0 -1 -1 t p f i f f));
-DATA(insert OID = 0 ( 1259 xmax                28 0  4  -5 0 -1 -1 t p f i f f));
-DATA(insert OID = 0 ( 1259 cmax                29 0  4  -6 0 -1 -1 t p f i f f));
-DATA(insert OID = 0 ( 1259 tableoid            26 0  4  -7 0 -1 -1 t p f i f f));
+{ 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 }
+
+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 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));
+DATA(insert ( 1259 cmin                29 0  4  -4 0 -1 -1 t p f i f f));
+DATA(insert ( 1259 xmax                28 0  4  -5 0 -1 -1 t p f i f f));
+DATA(insert ( 1259 cmax                29 0  4  -6 0 -1 -1 t p f i f f));
+DATA(insert ( 1259 tableoid            26 0  4  -7 0 -1 -1 t p f i f f));
 
 /* ----------------
  *     pg_log - this relation is modified by special purpose access
 #define Schema_pg_log \
 { 1269, {"logfoo"},  26, 0, 4, 1, 0, -1, -1, true, 'p', false, 'i', false, false }
 
-DATA(insert OID = 0 ( 1269 logfoo          26 0  4   1 0 -1 -1 t p f i f f));
+DATA(insert ( 1269 logfoo          26 0  4   1 0 -1 -1 t p f i f f));
 
 /* ----------------
  *     pg_xactlock - this relation is modified by special purpose access
 #define Schema_pg_xactlock \
 { 376, {"xactlockfoo"},  26, 0, 4, 1, 0, -1, -1, true, 'p', false, 'i', false, false }
 
-DATA(insert OID = 0 ( 376 xactlockfoo      26 0  4   1 0 -1 -1 t p f i f f));
+DATA(insert ( 376 xactlockfoo      26 0  4   1 0 -1 -1 t p f i f f));
 
 #endif  /* PG_ATTRIBUTE_H */
 
  * 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.51 2001/06/12 05:55:50 tgl Exp $
+ * $Id: pg_class.h,v 1.52 2001/08/10 18:57:40 tgl Exp $
  *
  * NOTES
  *   the genbki.sh script reads this file and generates .bki
  */
 CATALOG(pg_class) BOOTSTRAP
 {
-   NameData    relname;
-   Oid         reltype;
-   int4        relowner;
-   Oid         relam;
-   Oid         relfilenode;
-   int4        relpages;
-   float4      reltuples;
-   Oid         reltoastrelid;
-   Oid         reltoastidxid;
-   bool        relhasindex;
-   bool        relisshared;
-   char        relkind;
-   int2        relnatts;
+   NameData    relname;        /* class name */
+   Oid         reltype;        /* OID of associated entry in pg_type */
+   int4        relowner;       /* class owner */
+   Oid         relam;          /* index access method; 0 if not an index */
+   Oid         relfilenode;    /* identifier of physical storage file */
+   int4        relpages;       /* # of blocks (not always up-to-date) */
+   float4      reltuples;      /* # of tuples (not always up-to-date) */
+   Oid         reltoastrelid;  /* OID of toast table; 0 if none */
+   Oid         reltoastidxid;  /* if toast table, OID of chunk_id index */
+   bool        relhasindex;    /* T if has (or has had) any indexes */
+   bool        relisshared;    /* T if shared across databases */
+   char        relkind;        /* see RELKIND_xxx constants below */
+   int2        relnatts;       /* number of user attributes */
    /*
-    * relnatts is the number of user attributes this class has.  There
-    * must be exactly this many instances in Class pg_attribute for this
-    * class that have attnum > 0 (= user attribute).
+    * Class pg_attribute must contain exactly "relnatts" user attributes
+    * (with attnums ranging from 1 to relnatts) for this class.  It may
+    * also contain entries with negative attnums for system attributes.
     */
    int2        relchecks;      /* # of CHECK constraints for class */
    int2        reltriggers;    /* # of TRIGGERs */
    int2        relukeys;       /* # of Unique keys (not used) */
    int2        relfkeys;       /* # of FOREIGN KEYs (not used) */
    int2        relrefs;        /* # of references to this rel (not used) */
-   bool        relhaspkey;     /* has PRIMARY KEY (not used) */
+   bool        relhasoids;     /* T if we generate OIDs for rows of rel */
+   bool        relhaspkey;     /* has PRIMARY KEY index */
    bool        relhasrules;    /* has associated rules */
    bool        relhassubclass; /* has derived classes */
    /*
 /* ----------------
  *     Natts_pg_class_fixed is used to tell routines that insert new
  *     pg_class tuples (as opposed to replacing old ones) that there's no
- *     relacl field.
+ *     relacl field.  This is a kluge.
  * ----------------
  */
-#define Natts_pg_class_fixed           21
-#define Natts_pg_class                 22
+#define Natts_pg_class_fixed           22
+#define Natts_pg_class                 23
 #define Anum_pg_class_relname          1
 #define Anum_pg_class_reltype          2
 #define Anum_pg_class_relowner         3
 #define Anum_pg_class_relukeys         16
 #define Anum_pg_class_relfkeys         17
 #define Anum_pg_class_relrefs          18
-#define Anum_pg_class_relhaspkey       19
-#define Anum_pg_class_relhasrules      20
-#define Anum_pg_class_relhassubclass   21
-#define Anum_pg_class_relacl           22
+#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
 
 /* ----------------
  *     initial contents of pg_class
  * ----------------
  */
 
-DATA(insert OID = 1247 (  pg_type 71         PGUID 0 1247 0 0 0 0 f f r 17 0 0 0 0 0 f f f _null_ ));
+DATA(insert OID = 1247 (  pg_type      71  PGUID 0 1247 0 0 0 0 f f r 17 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 _null_ ));
+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_ ));
 DESCR("");
-DATA(insert OID = 1255 (  pg_proc 81         PGUID 0 1255 0 0 0 0 f f r 17 0 0 0 0 0 f f f _null_ ));
+DATA(insert OID = 1255 (  pg_proc      81  PGUID 0 1255 0 0 0 0 f f r 17 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 22 0 0 0 0 0 f f f _null_ ));
+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_ ));
 DESCR("");
-DATA(insert OID = 1260 (  pg_shadow 86       PGUID 0 1260 0 0 0 0 f t r 8  0 0 0 0 0 f f f _null_ ));
+DATA(insert OID = 1260 (  pg_shadow        86  PGUID 0 1260 0 0 0 0 f t r 8  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 _null_ ));
+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_ ));
 DESCR("");
-DATA(insert OID = 1262 (  pg_database 88     PGUID 0 1262 0 0 0 0 f t r 7  0 0 0 0 0 f f f _null_ ));
+DATA(insert OID = 1262 (  pg_database  88  PGUID 0 1262 0 0 0 0 f t r 7  0 0 0 0 0 t f f f _null_ ));
 DESCR("");
-DATA(insert OID = 1269 (  pg_log  99         PGUID 0 1269 0 0 0 0 f t s 1  0 0 0 0 0 f f f _null_ ));
+DATA(insert OID = 1269 (  pg_log       99  PGUID 0 1269 0 0 0 0 f t s 1  0 0 0 0 0 f 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 _null_ ));
+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_ ));
 DESCR("");
 
 #define RelOid_pg_type         1247
 
  * pg_description.h
  *   definition of the system "description" relation (pg_description)
  *
+ * NOTE: an object is identified by the OID of the row that primarily
+ * defines the object, plus the OID of the table that that row appears in.
+ * For example, a function is identified by the OID of its pg_proc row
+ * plus the pg_class OID of table pg_proc.  This allows unique identification
+ * of objects without assuming that OIDs are unique across tables.
+ *
+ * Since attributes don't have OIDs of their own, we identify an attribute
+ * comment by the objoid+classoid of its parent table, plus an "objsubid"
+ * giving the attribute column number.  "objsubid" must be zero in a comment
+ * for a table itself, so that it is distinct from any column comment.
+ * Currently, objsubid is unused and zero for all other kinds of objects,
+ * but perhaps it might be useful someday to associate comments with
+ * constituent elements of other kinds of objects (arguments of a function,
+ * for example).
+ *
  *
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pg_description.h,v 1.12 2001/01/24 19:43:21 momjian Exp $
+ * $Id: pg_description.h,v 1.13 2001/08/10 18:57:40 tgl Exp $
  *
  * NOTES
  *     the genbki.sh script reads this file and generates .bki
  *     typedef struct FormData_pg_description
  * ----------------
  */
-CATALOG(pg_description)
+CATALOG(pg_description) BKI_WITHOUT_OIDS
 {
-   Oid         objoid;
-   text        description;
+   Oid         objoid;         /* OID of object itself */
+   Oid         classoid;       /* OID of table containing object */
+   int4        objsubid;       /* column number, or 0 if not used */
+   text        description;    /* description of object */
 } FormData_pg_description;
 
 /* ----------------
  *     compiler constants for pg_descrpition
  * ----------------
  */
-#define Natts_pg_description           2
+#define Natts_pg_description           4
 #define Anum_pg_description_objoid     1
-#define Anum_pg_description_description 2
+#define Anum_pg_description_classoid   2
+#define Anum_pg_description_objsubid   3
+#define Anum_pg_description_description 4
 
 /* ----------------
  *     initial contents of pg_description
 
 /*
  * Because the contents of this table are taken from the other *.h files,
- * there is no initialization. It is loaded from initdb using a COPY
- * statement.
+ * there is no initialization here.  The initial contents are extracted
+ * by genbki.sh and loaded during initdb.
  */
 
 #endif  /* PG_DESCRIPTION_H */
 
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pg_group.h,v 1.9 2001/01/24 19:43:21 momjian Exp $
+ * $Id: pg_group.h,v 1.10 2001/08/10 18:57:40 tgl Exp $
  *
  * NOTES
  *   the genbki.sh script reads this file and generates .bki
  * ----------------
  */
 
-CATALOG(pg_group) BOOTSTRAP
+CATALOG(pg_group) BOOTSTRAP BKI_WITHOUT_OIDS
 {
    NameData    groname;
    int4        grosysid;
 
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pg_index.h,v 1.22 2001/07/15 22:48:18 tgl Exp $
+ * $Id: pg_index.h,v 1.23 2001/08/10 18:57:40 tgl Exp $
  *
  * NOTES
  *   the genbki.sh script reads this file and generates .bki
  * first variable length field.  so I moved indislossy, indhaskeytype,
  * and indisunique before indpred. --djm 8/20/96
  */
-CATALOG(pg_index)
+CATALOG(pg_index) BKI_WITHOUT_OIDS
 {
-   Oid         indexrelid;
-   Oid         indrelid;
-   Oid         indproc;        /* registered procedure for functional
-                                * index */
-   int2vector  indkey;
-   oidvector   indclass;
+   Oid         indexrelid;     /* OID of the index */
+   Oid         indrelid;       /* OID of the relation it indexes */
+   Oid         indproc;        /* OID of function for functional index */
+   int2vector  indkey;         /* column numbers of indexed attributes */
+   oidvector   indclass;       /* opclass identifiers */
    bool        indisclustered; /* unused */
    bool        indislossy;     /* index hit must be reevaluated against heap
                                 * value to make sure it really is match;
 
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pg_inherits.h,v 1.10 2001/01/24 19:43:21 momjian Exp $
+ * $Id: pg_inherits.h,v 1.11 2001/08/10 18:57:40 tgl Exp $
  *
  * NOTES
  *   the genbki.sh script reads this file and generates .bki
  *     typedef struct FormData_pg_inherits
  * ----------------
  */
-CATALOG(pg_inherits)
+CATALOG(pg_inherits) BKI_WITHOUT_OIDS
 {
    Oid         inhrelid;
    Oid         inhparent;
 
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pg_largeobject.h,v 1.7 2001/03/22 04:00:39 momjian Exp $
+ * $Id: pg_largeobject.h,v 1.8 2001/08/10 18:57:40 tgl Exp $
  *
  * NOTES
  *   the genbki.sh script reads this file and generates .bki
 
 /* ----------------
  *     pg_largeobject definition.  cpp turns this into
- *     typedef struct FormData_pg_largeobject. Large object id
- *     is stored in loid;
+ *     typedef struct FormData_pg_largeobject
  * ----------------
  */
 
-CATALOG(pg_largeobject)
+CATALOG(pg_largeobject) BKI_WITHOUT_OIDS
 {
    Oid         loid;           /* Identifier of large object */
    int4        pageno;         /* Page number (starting from 0) */
 
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pg_listener.h,v 1.9 2001/06/12 05:55:50 tgl Exp $
+ * $Id: pg_listener.h,v 1.10 2001/08/10 18:57:40 tgl Exp $
  *
  * NOTES
  *   the genbki.sh script reads this file and generates .bki
  * ----------------------------------------------------------------
  */
 
-CATALOG(pg_listener)
+CATALOG(pg_listener) BKI_WITHOUT_OIDS
 {
    NameData    relname;
    int4        listenerpid;
 
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pg_log.h,v 1.8 2001/01/24 19:43:21 momjian Exp $
+ * $Id: pg_log.h,v 1.9 2001/08/10 18:57:40 tgl Exp $
  *
  * NOTES
  *   The structures and macros used by the transam/ code
  * ----------------
  */
 
-CATALOG(pg_log) BOOTSTRAP
+CATALOG(pg_log) BOOTSTRAP BKI_WITHOUT_OIDS
 {
    Oid         logfoo;
 } FormData_pg_log;
 
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pg_proc.h,v 1.200 2001/08/06 01:25:32 tgl Exp $
+ * $Id: pg_proc.h,v 1.201 2001/08/10 18:57:40 tgl Exp $
  *
  * NOTES
  *   The script catalog/genbki.sh reads this file and generates .bki
 DATA(insert OID = 1200 (  reltime         PGUID 12 f t t t 1 f  703 "23" 100 0 0 100  int4reltime - ));
 DESCR("convert int4 to reltime");
 
+DATA(insert OID = 1215 (  obj_description  PGUID 14 f t f t 2 f    25 "26 19" 100 0 0 100  "select description from pg_description where objoid = $1 and classoid = (select oid from pg_class where relname = $2) and objsubid = 0" - ));
+DESCR("get description for object id and catalog name");
+DATA(insert OID = 1216 (  col_description  PGUID 14 f t f t 2 f    25 "26 23" 100 0 0 100  "select description from pg_description where objoid = $1 and classoid = (select oid from pg_class where relname = 'pg_class') and objsubid = $2" - ));
+DESCR("get description for table column");
+
 DATA(insert OID = 1217 (  date_trunc      PGUID 12 f t f t 2 f 1184 "25 1184" 100 0 0 100  timestamp_trunc - ));
 DESCR("truncate timestamp to specified units");
 DATA(insert OID = 1218 (  date_trunc      PGUID 12 f t f t 2 f 1186 "25 1186" 100 0 0 100  interval_trunc - ));
 DATA(insert OID = 1347 (  exp               PGUID 12 f t t t 1 f 701 "701" 100 0 0 100  dexp - ));
 DESCR("exponential");
 
-DATA(insert OID = 1348 (  obj_description   PGUID 14 f t f t 1 f   25 "26" 100 0 0 100  "select description from pg_description where objoid = $1" - ));
-DESCR("get description for object id");
+/*
+ * This form of obj_description is now deprecated, since it will fail if
+ * OIDs are not unique across system catalogs.  Use the other forms instead.
+ */
+DATA(insert OID = 1348 (  obj_description   PGUID 14 f t f t 1 f   25 "26" 100 0 0 100  "select description from pg_description where objoid = $1 and objsubid = 0" - ));
+DESCR("get description for object id (deprecated)");
 DATA(insert OID = 1349 (  oidvectortypes    PGUID 12 f t f t 1 f   25 "30" 100 0 0 100  oidvectortypes - ));
 DESCR("print type names of oidvector field");
 
 
  *     typedef struct FormData_pg_relcheck
  * ----------------
  */
-CATALOG(pg_relcheck)
+CATALOG(pg_relcheck) BKI_WITHOUT_OIDS
 {
    Oid         rcrelid;
    NameData    rcname;
 
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pg_shadow.h,v 1.12 2001/06/13 21:44:41 tgl Exp $
+ * $Id: pg_shadow.h,v 1.13 2001/08/10 18:57:41 tgl Exp $
  *
  * NOTES
  *   the genbki.sh script reads this file and generates .bki
  *     typedef struct FormData_pg_shadow
  * ----------------
  */
-CATALOG(pg_shadow) BOOTSTRAP
+CATALOG(pg_shadow) BOOTSTRAP BKI_WITHOUT_OIDS
 {
    NameData    usename;
    int4        usesysid;
  * user choices.
  * ----------------
  */
-DATA(insert OID = 0 ( "POSTGRES" PGUID t t t t _null_ _null_ ));
+DATA(insert ( "POSTGRES" PGUID t t t t _null_ _null_ ));
 
 #endif  /* PG_SHADOW_H */
 
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pg_statistic.h,v 1.11 2001/05/07 00:43:25 tgl Exp $
+ * $Id: pg_statistic.h,v 1.12 2001/08/10 18:57:41 tgl Exp $
  *
  * NOTES
  *   the genbki.sh script reads this file and generates .bki
  *     typedef struct FormData_pg_statistic
  * ----------------
  */
-CATALOG(pg_statistic)
+CATALOG(pg_statistic) BKI_WITHOUT_OIDS
 {
    /* These fields form the unique key for the entry: */
    Oid         starelid;       /* relation containing attribute */
 
 #!/bin/sh
 # unused_oids
 #
-# $Header: /cvsroot/pgsql/src/include/catalog/unused_oids,v 1.3 2000/01/17 00:53:11 tgl Exp $
+# $Header: /cvsroot/pgsql/src/include/catalog/unused_oids,v 1.4 2001/08/10 18:57:41 tgl Exp $
 #
 #  finds blocks of oids that have not already been claimed by 
 #  post_hackers for internal purposes.  primarily useful for
 #
 #  run this script in src/include/catalog.
 #
+
+
+AWK="awk"
+
+# Get FirstGenBKIObjectId from access/transam.h
+BKIOBJECTID=`grep '#define[    ]*FirstGenBKIObjectId' ../access/transam.h | $AWK '{ print $3 }'`
+export BKIOBJECTID
+
 egrep '^DATA' pg_*.h | \
    sed -e 's/^.*OID[^=]*=[^0-9]*//' -e 's/[^0-9].*$//' | \
    sort -n | \
    uniq | \
-   awk '
+   $AWK '
 BEGIN {
    last = 0;
 }
    last = $1;
 }
 END {
-# 2^14-1 = current BootstrapObjectIdData value
-   print last + 1, "-", 2^14-1;
+   print last + 1, "-", ENVIRON["BKIOBJECTID"]-1;
 }'
 
  * Function Prototypes --
  *
  * The following protoypes define the public functions of the comment
- * related routines. CreateComments() is used to create/drop a comment
- * for any object with a valid oid. DeleteComments() deletes, if any,
- * the comments associated with the object. CommentObject() is used to
- * create comments to be identified by the specific type.
+ * related routines.  CommentObject() implements the SQL "COMMENT ON"
+ * command.  DeleteComments() deletes all comments for an object.
+ * CreateComments creates (or deletes, if comment is NULL) a comment
+ * for a specific key.
  *------------------------------------------------------------------
  */
 
-extern void DeleteComments(Oid oid);
 extern void CommentObject(int objtype, char *objname, char *objproperty,
              List *objlist, char *comment);
 
+extern void DeleteComments(Oid oid, Oid classoid);
+
+extern void CreateComments(Oid oid, Oid classoid, int32 subid, char *comment);
+
 #endif  /* COMMENT_H */
 
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: parsenodes.h,v 1.139 2001/08/10 14:30:15 momjian Exp $
+ * $Id: parsenodes.h,v 1.140 2001/08/10 18:57:41 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 typedef struct CreateStmt
 {
    NodeTag     type;
-   bool        istemp;         /* is this a temp table? */
    char       *relname;        /* name of relation to create */
    List       *tableElts;      /* column definitions (list of ColumnDef) */
    List       *inhRelnames;    /* relations to inherit from (list of
                                 * T_String Values) */
    List       *constraints;    /* constraints (list of Constraint and
                                 * FkConstraint nodes) */
+   bool        istemp;         /* is this a temp table? */
+   bool        hasoids;        /* should it have OIDs? */
 } CreateStmt;
 
 /* ----------
 
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: parse_relation.h,v 1.23 2001/03/22 04:00:58 momjian Exp $
+ * $Id: parse_relation.h,v 1.24 2001/08/10 18:57:41 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 extern List *expandJoinAttrs(ParseState *pstate, JoinExpr *join,
                int sublevels_up);
 extern int attnameAttNum(Relation rd, char *a);
-extern int specialAttNum(char *a);
 extern Oid attnumTypeId(Relation rd, int attid);
 
 #endif  /* PARSE_RELATION_H */
 
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1995, Regents of the University of California
  *
- * $Id: postgres.h,v 1.49 2001/06/12 05:55:50 tgl Exp $
+ * $Id: postgres.h,v 1.50 2001/08/10 18:57:41 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
  */
 
 /* ----------------
- *     struct varattrib is the header of a varlena object that may have been TOASTed.
+ * struct varattrib is the header of a varlena object that may have been TOASTed.
  * ----------------
  */
 #define TUPLE_TOASTER_ACTIVE
            int32       va_extsize;     /* External saved size */
            Oid         va_valueid;     /* Unique identifier of value */
            Oid         va_toastrelid;  /* RelID where to find chunks */
-           Oid         va_toastidxid;  /* Main tables row Oid */
-           Oid         va_rowid;       /* Referencing row Oid */
-           int16       va_attno;       /* Main tables attno */
        }           va_external;/* External stored attribute */
 
        char        va_data[1]; /* Plain stored attribute */
 
 #define BOOTSTRAP
 
+#define BKI_WITHOUT_OIDS
+
 /* these need to expand into some harmless, repeatable declaration */
 #define DATA(x)   extern int errno
 #define DESCR(x)  extern int errno
 
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: syscache.h,v 1.31 2001/06/12 05:55:50 tgl Exp $
+ * $Id: syscache.h,v 1.32 2001/08/10 18:57:41 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 /* convenience routines */
 extern HeapTuple SearchSysCacheCopy(int cacheId,
                   Datum key1, Datum key2, Datum key3, Datum key4);
+extern bool SearchSysCacheExists(int cacheId,
+              Datum key1, Datum key2, Datum key3, Datum key4);
 extern Oid GetSysCacheOid(int cacheId,
               Datum key1, Datum key2, Datum key3, Datum key4);
 
-/* macro for just probing for existence of a tuple via the syscache */
-#define SearchSysCacheExists(c,k1,k2,k3,k4)  \
-   OidIsValid(GetSysCacheOid(c,k1,k2,k3,k4))
-
 extern Datum SysCacheGetAttr(int cacheId, HeapTuple tup,
                AttrNumber attributeNumber, bool *isNull);
 
 
 %type  <str>    copy_delimiter ListenStmt CopyStmt copy_file_name opt_binary
 %type  <str>    opt_with_copy FetchStmt direction fetch_how_many from_in
 %type  <str>    ClosePortalStmt DropStmt VacuumStmt AnalyzeStmt opt_verbose
-%type  <str>    opt_full func_arg
+%type  <str>    opt_full func_arg OptWithOids
 %type  <str>    analyze_keyword opt_name_list ExplainStmt index_params
 %type  <str>    index_list func_index index_elem opt_class access_method_clause
 %type  <str>    index_opt_unique IndexStmt func_return ConstInterval
  *****************************************************************************/
 
 CreateStmt:  CREATE OptTemp TABLE relation_name '(' OptTableElementList ')'
-               OptInherit
+               OptInherit OptWithOids
                {
-                   $$ = cat_str(8, make_str("create"), $2, make_str("table"), $4, make_str("("), $6, make_str(")"), $8);
+                   $$ = cat_str(9, make_str("create"), $2, make_str("table"), $4, make_str("("), $6, make_str(")"), $8, $9);
                }
        ;
 
 
 OptInherit:  INHERITS '(' relation_name_list ')'                { $$ = cat_str(3, make_str("inherits ("), $3, make_str(")")); }
                 | /*EMPTY*/                    { $$ = EMPTY; }
-                ;      
+                ;
+
+OptWithOids:  WITH OIDS                        { $$ = make_str("with oids"); }
+           | WITHOUT OIDS                  { $$ = make_str("without oids"); }
+           | /*EMPTY*/                     { $$ = EMPTY; }
+       ;
+
 
 /*
  * Note: CREATE TABLE ... AS SELECT ... is just another spelling for
 
 --
 -- This is created by pgsql/contrib/findoidjoins/make_oidjoin_check
 --
-SELECT oid, pg_aggregate.aggtransfn 
+SELECT ctid, pg_aggregate.aggtransfn 
 FROM   pg_aggregate 
 WHERE  pg_aggregate.aggtransfn != 0 AND 
    NOT EXISTS(SELECT * FROM pg_proc AS t1 WHERE t1.oid = pg_aggregate.aggtransfn);
- oid | aggtransfn 
------+------------
+ ctid | aggtransfn 
+------+------------
 (0 rows)
 
-SELECT oid, pg_aggregate.aggfinalfn 
+SELECT ctid, pg_aggregate.aggfinalfn 
 FROM   pg_aggregate 
 WHERE  pg_aggregate.aggfinalfn != 0 AND 
    NOT EXISTS(SELECT * FROM pg_proc AS t1 WHERE t1.oid = pg_aggregate.aggfinalfn);
- oid | aggfinalfn 
------+------------
+ ctid | aggfinalfn 
+------+------------
 (0 rows)
 
-SELECT oid, pg_aggregate.aggbasetype 
+SELECT ctid, pg_aggregate.aggbasetype 
 FROM   pg_aggregate 
 WHERE  pg_aggregate.aggbasetype != 0 AND 
    NOT EXISTS(SELECT * FROM pg_type AS t1 WHERE t1.oid = pg_aggregate.aggbasetype);
- oid | aggbasetype 
------+-------------
+ ctid | aggbasetype 
+------+-------------
 (0 rows)
 
-SELECT oid, pg_aggregate.aggtranstype 
+SELECT ctid, pg_aggregate.aggtranstype 
 FROM   pg_aggregate 
 WHERE  pg_aggregate.aggtranstype != 0 AND 
    NOT EXISTS(SELECT * FROM pg_type AS t1 WHERE t1.oid = pg_aggregate.aggtranstype);
- oid | aggtranstype 
------+--------------
+ ctid | aggtranstype 
+------+--------------
 (0 rows)
 
-SELECT oid, pg_aggregate.aggfinaltype 
+SELECT ctid, pg_aggregate.aggfinaltype 
 FROM   pg_aggregate 
 WHERE  pg_aggregate.aggfinaltype != 0 AND 
    NOT EXISTS(SELECT * FROM pg_type AS t1 WHERE t1.oid = pg_aggregate.aggfinaltype);
- oid | aggfinaltype 
------+--------------
+ ctid | aggfinaltype 
+------+--------------
 (0 rows)
 
-SELECT oid, pg_am.amgettuple 
+SELECT ctid, pg_am.amgettuple 
 FROM   pg_am 
 WHERE  pg_am.amgettuple != 0 AND 
    NOT EXISTS(SELECT * FROM pg_proc AS t1 WHERE t1.oid = pg_am.amgettuple);
- oid | amgettuple 
------+------------
+ ctid | amgettuple 
+------+------------
 (0 rows)
 
-SELECT oid, pg_am.aminsert 
+SELECT ctid, pg_am.aminsert 
 FROM   pg_am 
 WHERE  pg_am.aminsert != 0 AND 
    NOT EXISTS(SELECT * FROM pg_proc AS t1 WHERE t1.oid = pg_am.aminsert);
- oid | aminsert 
------+----------
+ ctid | aminsert 
+------+----------
 (0 rows)
 
-SELECT oid, pg_am.ambeginscan 
+SELECT ctid, pg_am.ambeginscan 
 FROM   pg_am 
 WHERE  pg_am.ambeginscan != 0 AND 
    NOT EXISTS(SELECT * FROM pg_proc AS t1 WHERE t1.oid = pg_am.ambeginscan);
- oid | ambeginscan 
------+-------------
+ ctid | ambeginscan 
+------+-------------
 (0 rows)
 
-SELECT oid, pg_am.amrescan 
+SELECT ctid, pg_am.amrescan 
 FROM   pg_am 
 WHERE  pg_am.amrescan != 0 AND 
    NOT EXISTS(SELECT * FROM pg_proc AS t1 WHERE t1.oid = pg_am.amrescan);
- oid | amrescan 
------+----------
+ ctid | amrescan 
+------+----------
 (0 rows)
 
-SELECT oid, pg_am.amendscan 
+SELECT ctid, pg_am.amendscan 
 FROM   pg_am 
 WHERE  pg_am.amendscan != 0 AND 
    NOT EXISTS(SELECT * FROM pg_proc AS t1 WHERE t1.oid = pg_am.amendscan);
- oid | amendscan 
------+-----------
+ ctid | amendscan 
+------+-----------
 (0 rows)
 
-SELECT oid, pg_am.ammarkpos 
+SELECT ctid, pg_am.ammarkpos 
 FROM   pg_am 
 WHERE  pg_am.ammarkpos != 0 AND 
    NOT EXISTS(SELECT * FROM pg_proc AS t1 WHERE t1.oid = pg_am.ammarkpos);
- oid | ammarkpos 
------+-----------
+ ctid | ammarkpos 
+------+-----------
 (0 rows)
 
-SELECT oid, pg_am.amrestrpos 
+SELECT ctid, pg_am.amrestrpos 
 FROM   pg_am 
 WHERE  pg_am.amrestrpos != 0 AND 
    NOT EXISTS(SELECT * FROM pg_proc AS t1 WHERE t1.oid = pg_am.amrestrpos);
- oid | amrestrpos 
------+------------
+ ctid | amrestrpos 
+------+------------
 (0 rows)
 
-SELECT oid, pg_am.ambuild 
+SELECT ctid, pg_am.ambuild 
 FROM   pg_am 
 WHERE  pg_am.ambuild != 0 AND 
    NOT EXISTS(SELECT * FROM pg_proc AS t1 WHERE t1.oid = pg_am.ambuild);
- oid | ambuild 
------+---------
+ ctid | ambuild 
+------+---------
 (0 rows)
 
-SELECT oid, pg_am.ambulkdelete 
+SELECT ctid, pg_am.ambulkdelete 
 FROM   pg_am 
 WHERE  pg_am.ambulkdelete != 0 AND 
    NOT EXISTS(SELECT * FROM pg_proc AS t1 WHERE t1.oid = pg_am.ambulkdelete);
- oid | ambulkdelete 
------+--------------
+ ctid | ambulkdelete 
+------+--------------
 (0 rows)
 
-SELECT oid, pg_am.amcostestimate 
+SELECT ctid, pg_am.amcostestimate 
 FROM   pg_am 
 WHERE  pg_am.amcostestimate != 0 AND 
    NOT EXISTS(SELECT * FROM pg_proc AS t1 WHERE t1.oid = pg_am.amcostestimate);
- oid | amcostestimate 
------+----------------
+ ctid | amcostestimate 
+------+----------------
 (0 rows)
 
-SELECT oid, pg_amop.amopid 
+SELECT ctid, pg_amop.amopid 
 FROM   pg_amop 
 WHERE  pg_amop.amopid != 0 AND 
    NOT EXISTS(SELECT * FROM pg_am AS t1 WHERE t1.oid = pg_amop.amopid);
- oid | amopid 
------+--------
+ ctid | amopid 
+------+--------
 (0 rows)
 
-SELECT oid, pg_amop.amopclaid 
+SELECT ctid, pg_amop.amopclaid 
 FROM   pg_amop 
 WHERE  pg_amop.amopclaid != 0 AND 
    NOT EXISTS(SELECT * FROM pg_opclass AS t1 WHERE t1.oid = pg_amop.amopclaid);
- oid | amopclaid 
------+-----------
+ ctid | amopclaid 
+------+-----------
 (0 rows)
 
-SELECT oid, pg_amop.amopopr 
+SELECT ctid, pg_amop.amopopr 
 FROM   pg_amop 
 WHERE  pg_amop.amopopr != 0 AND 
    NOT EXISTS(SELECT * FROM pg_operator AS t1 WHERE t1.oid = pg_amop.amopopr);
- oid | amopopr 
------+---------
+ ctid | amopopr 
+------+---------
 (0 rows)
 
-SELECT oid, pg_amproc.amid 
+SELECT ctid, pg_amproc.amid 
 FROM   pg_amproc 
 WHERE  pg_amproc.amid != 0 AND 
    NOT EXISTS(SELECT * FROM pg_am AS t1 WHERE t1.oid = pg_amproc.amid);
- oid | amid 
------+------
+ ctid | amid 
+------+------
 (0 rows)
 
-SELECT oid, pg_amproc.amopclaid 
+SELECT ctid, pg_amproc.amopclaid 
 FROM   pg_amproc 
 WHERE  pg_amproc.amopclaid != 0 AND 
    NOT EXISTS(SELECT * FROM pg_opclass AS t1 WHERE t1.oid = pg_amproc.amopclaid);
- oid | amopclaid 
------+-----------
+ ctid | amopclaid 
+------+-----------
 (0 rows)
 
-SELECT oid, pg_amproc.amproc 
+SELECT ctid, pg_amproc.amproc 
 FROM   pg_amproc 
 WHERE  pg_amproc.amproc != 0 AND 
    NOT EXISTS(SELECT * FROM pg_proc AS t1 WHERE t1.oid = pg_amproc.amproc);
- oid | amproc 
------+--------
+ ctid | amproc 
+------+--------
 (0 rows)
 
-SELECT oid, pg_attribute.attrelid 
+SELECT ctid, pg_attribute.attrelid 
 FROM   pg_attribute 
 WHERE  pg_attribute.attrelid != 0 AND 
    NOT EXISTS(SELECT * FROM pg_class AS t1 WHERE t1.oid = pg_attribute.attrelid);
- oid | attrelid 
------+----------
+ ctid | attrelid 
+------+----------
 (0 rows)
 
-SELECT oid, pg_attribute.atttypid 
+SELECT ctid, pg_attribute.atttypid 
 FROM   pg_attribute 
 WHERE  pg_attribute.atttypid != 0 AND 
    NOT EXISTS(SELECT * FROM pg_type AS t1 WHERE t1.oid = pg_attribute.atttypid);
- oid | atttypid 
------+----------
+ ctid | atttypid 
+------+----------
 (0 rows)
 
-SELECT oid, pg_class.reltype 
+SELECT ctid, pg_class.reltype 
 FROM   pg_class 
 WHERE  pg_class.reltype != 0 AND 
    NOT EXISTS(SELECT * FROM pg_type AS t1 WHERE t1.oid = pg_class.reltype);
- oid | reltype 
------+---------
+ ctid | reltype 
+------+---------
 (0 rows)
 
-SELECT oid, pg_class.relam 
+SELECT ctid, pg_class.relam 
 FROM   pg_class 
 WHERE  pg_class.relam != 0 AND 
    NOT EXISTS(SELECT * FROM pg_am AS t1 WHERE t1.oid = pg_class.relam);
- oid | relam 
------+-------
+ ctid | relam 
+------+-------
 (0 rows)
 
-SELECT oid, pg_class.reltoastrelid 
+SELECT ctid, pg_class.reltoastrelid 
 FROM   pg_class 
 WHERE  pg_class.reltoastrelid != 0 AND 
    NOT EXISTS(SELECT * FROM pg_class AS t1 WHERE t1.oid = pg_class.reltoastrelid);
- oid | reltoastrelid 
------+---------------
+ ctid | reltoastrelid 
+------+---------------
 (0 rows)
 
-SELECT oid, pg_class.reltoastidxid 
+SELECT ctid, pg_class.reltoastidxid 
 FROM   pg_class 
 WHERE  pg_class.reltoastidxid != 0 AND 
    NOT EXISTS(SELECT * FROM pg_class AS t1 WHERE t1.oid = pg_class.reltoastidxid);
- oid | reltoastidxid 
------+---------------
+ ctid | reltoastidxid 
+------+---------------
 (0 rows)
 
-SELECT oid, pg_index.indexrelid 
+SELECT ctid, pg_description.classoid 
+FROM   pg_description 
+WHERE  pg_description.classoid != 0 AND 
+   NOT EXISTS(SELECT * FROM pg_class AS t1 WHERE t1.oid = pg_description.classoid);
+ ctid | classoid 
+------+----------
+(0 rows)
+
+SELECT ctid, pg_index.indexrelid 
 FROM   pg_index 
 WHERE  pg_index.indexrelid != 0 AND 
    NOT EXISTS(SELECT * FROM pg_class AS t1 WHERE t1.oid = pg_index.indexrelid);
- oid | indexrelid 
------+------------
+ ctid | indexrelid 
+------+------------
 (0 rows)
 
-SELECT oid, pg_index.indrelid 
+SELECT ctid, pg_index.indrelid 
 FROM   pg_index 
 WHERE  pg_index.indrelid != 0 AND 
    NOT EXISTS(SELECT * FROM pg_class AS t1 WHERE t1.oid = pg_index.indrelid);
- oid | indrelid 
------+----------
+ ctid | indrelid 
+------+----------
 (0 rows)
 
-SELECT oid, pg_opclass.opcdeftype 
+SELECT ctid, pg_opclass.opcdeftype 
 FROM   pg_opclass 
 WHERE  pg_opclass.opcdeftype != 0 AND 
    NOT EXISTS(SELECT * FROM pg_type AS t1 WHERE t1.oid = pg_opclass.opcdeftype);
- oid | opcdeftype 
------+------------
+ ctid | opcdeftype 
+------+------------
 (0 rows)
 
-SELECT oid, pg_operator.oprleft 
+SELECT ctid, pg_operator.oprleft 
 FROM   pg_operator 
 WHERE  pg_operator.oprleft != 0 AND 
    NOT EXISTS(SELECT * FROM pg_type AS t1 WHERE t1.oid = pg_operator.oprleft);
- oid | oprleft 
------+---------
+ ctid | oprleft 
+------+---------
 (0 rows)
 
-SELECT oid, pg_operator.oprright 
+SELECT ctid, pg_operator.oprright 
 FROM   pg_operator 
 WHERE  pg_operator.oprright != 0 AND 
    NOT EXISTS(SELECT * FROM pg_type AS t1 WHERE t1.oid = pg_operator.oprright);
- oid | oprright 
------+----------
+ ctid | oprright 
+------+----------
 (0 rows)
 
-SELECT oid, pg_operator.oprresult 
+SELECT ctid, pg_operator.oprresult 
 FROM   pg_operator 
 WHERE  pg_operator.oprresult != 0 AND 
    NOT EXISTS(SELECT * FROM pg_type AS t1 WHERE t1.oid = pg_operator.oprresult);
- oid | oprresult 
------+-----------
+ ctid | oprresult 
+------+-----------
 (0 rows)
 
-SELECT oid, pg_operator.oprcom 
+SELECT ctid, pg_operator.oprcom 
 FROM   pg_operator 
 WHERE  pg_operator.oprcom != 0 AND 
    NOT EXISTS(SELECT * FROM pg_operator AS t1 WHERE t1.oid = pg_operator.oprcom);
- oid | oprcom 
------+--------
+ ctid | oprcom 
+------+--------
 (0 rows)
 
-SELECT oid, pg_operator.oprnegate 
+SELECT ctid, pg_operator.oprnegate 
 FROM   pg_operator 
 WHERE  pg_operator.oprnegate != 0 AND 
    NOT EXISTS(SELECT * FROM pg_operator AS t1 WHERE t1.oid = pg_operator.oprnegate);
- oid | oprnegate 
------+-----------
+ ctid | oprnegate 
+------+-----------
 (0 rows)
 
-SELECT oid, pg_operator.oprlsortop 
+SELECT ctid, pg_operator.oprlsortop 
 FROM   pg_operator 
 WHERE  pg_operator.oprlsortop != 0 AND 
    NOT EXISTS(SELECT * FROM pg_operator AS t1 WHERE t1.oid = pg_operator.oprlsortop);
- oid | oprlsortop 
------+------------
+ ctid | oprlsortop 
+------+------------
 (0 rows)
 
-SELECT oid, pg_operator.oprrsortop 
+SELECT ctid, pg_operator.oprrsortop 
 FROM   pg_operator 
 WHERE  pg_operator.oprrsortop != 0 AND 
    NOT EXISTS(SELECT * FROM pg_operator AS t1 WHERE t1.oid = pg_operator.oprrsortop);
- oid | oprrsortop 
------+------------
+ ctid | oprrsortop 
+------+------------
 (0 rows)
 
-SELECT oid, pg_operator.oprcode 
+SELECT ctid, pg_operator.oprcode 
 FROM   pg_operator 
 WHERE  pg_operator.oprcode != 0 AND 
    NOT EXISTS(SELECT * FROM pg_proc AS t1 WHERE t1.oid = pg_operator.oprcode);
- oid | oprcode 
------+---------
+ ctid | oprcode 
+------+---------
 (0 rows)
 
-SELECT oid, pg_operator.oprrest 
+SELECT ctid, pg_operator.oprrest 
 FROM   pg_operator 
 WHERE  pg_operator.oprrest != 0 AND 
    NOT EXISTS(SELECT * FROM pg_proc AS t1 WHERE t1.oid = pg_operator.oprrest);
- oid | oprrest 
------+---------
+ ctid | oprrest 
+------+---------
 (0 rows)
 
-SELECT oid, pg_operator.oprjoin 
+SELECT ctid, pg_operator.oprjoin 
 FROM   pg_operator 
 WHERE  pg_operator.oprjoin != 0 AND 
    NOT EXISTS(SELECT * FROM pg_proc AS t1 WHERE t1.oid = pg_operator.oprjoin);
- oid | oprjoin 
------+---------
+ ctid | oprjoin 
+------+---------
 (0 rows)
 
-SELECT oid, pg_proc.prolang 
+SELECT ctid, pg_proc.prolang 
 FROM   pg_proc 
 WHERE  pg_proc.prolang != 0 AND 
    NOT EXISTS(SELECT * FROM pg_language AS t1 WHERE t1.oid = pg_proc.prolang);
- oid | prolang 
------+---------
+ ctid | prolang 
+------+---------
 (0 rows)
 
-SELECT oid, pg_proc.prorettype 
+SELECT ctid, pg_proc.prorettype 
 FROM   pg_proc 
 WHERE  pg_proc.prorettype != 0 AND 
    NOT EXISTS(SELECT * FROM pg_type AS t1 WHERE t1.oid = pg_proc.prorettype);
- oid | prorettype 
------+------------
+ ctid | prorettype 
+------+------------
 (0 rows)
 
-SELECT oid, pg_rewrite.ev_class 
+SELECT ctid, pg_rewrite.ev_class 
 FROM   pg_rewrite 
 WHERE  pg_rewrite.ev_class != 0 AND 
    NOT EXISTS(SELECT * FROM pg_class AS t1 WHERE t1.oid = pg_rewrite.ev_class);
- oid | ev_class 
------+----------
+ ctid | ev_class 
+------+----------
 (0 rows)
 
-SELECT oid, pg_statistic.starelid 
+SELECT ctid, pg_statistic.starelid 
 FROM   pg_statistic 
 WHERE  pg_statistic.starelid != 0 AND 
    NOT EXISTS(SELECT * FROM pg_class AS t1 WHERE t1.oid = pg_statistic.starelid);
- oid | starelid 
------+----------
+ ctid | starelid 
+------+----------
 (0 rows)
 
-SELECT oid, pg_statistic.staop1 
+SELECT ctid, pg_statistic.staop1 
 FROM   pg_statistic 
 WHERE  pg_statistic.staop1 != 0 AND 
    NOT EXISTS(SELECT * FROM pg_operator AS t1 WHERE t1.oid = pg_statistic.staop1);
- oid | staop1 
------+--------
+ ctid | staop1 
+------+--------
 (0 rows)
 
-SELECT oid, pg_statistic.staop2 
+SELECT ctid, pg_statistic.staop2 
 FROM   pg_statistic 
 WHERE  pg_statistic.staop2 != 0 AND 
    NOT EXISTS(SELECT * FROM pg_operator AS t1 WHERE t1.oid = pg_statistic.staop2);
- oid | staop2 
------+--------
+ ctid | staop2 
+------+--------
 (0 rows)
 
-SELECT oid, pg_statistic.staop3 
+SELECT ctid, pg_statistic.staop3 
 FROM   pg_statistic 
 WHERE  pg_statistic.staop3 != 0 AND 
    NOT EXISTS(SELECT * FROM pg_operator AS t1 WHERE t1.oid = pg_statistic.staop3);
- oid | staop3 
------+--------
+ ctid | staop3 
+------+--------
 (0 rows)
 
-SELECT oid, pg_trigger.tgrelid 
+SELECT ctid, pg_trigger.tgrelid 
 FROM   pg_trigger 
 WHERE  pg_trigger.tgrelid != 0 AND 
    NOT EXISTS(SELECT * FROM pg_class AS t1 WHERE t1.oid = pg_trigger.tgrelid);
- oid | tgrelid 
------+---------
+ ctid | tgrelid 
+------+---------
 (0 rows)
 
-SELECT oid, pg_trigger.tgfoid 
+SELECT ctid, pg_trigger.tgfoid 
 FROM   pg_trigger 
 WHERE  pg_trigger.tgfoid != 0 AND 
    NOT EXISTS(SELECT * FROM pg_proc AS t1 WHERE t1.oid = pg_trigger.tgfoid);
- oid | tgfoid 
------+--------
+ ctid | tgfoid 
+------+--------
 (0 rows)
 
-SELECT oid, pg_type.typrelid 
+SELECT ctid, pg_type.typrelid 
 FROM   pg_type 
 WHERE  pg_type.typrelid != 0 AND 
    NOT EXISTS(SELECT * FROM pg_class AS t1 WHERE t1.oid = pg_type.typrelid);
- oid | typrelid 
------+----------
+ ctid | typrelid 
+------+----------
 (0 rows)
 
-SELECT oid, pg_type.typelem 
+SELECT ctid, pg_type.typelem 
 FROM   pg_type 
 WHERE  pg_type.typelem != 0 AND 
    NOT EXISTS(SELECT * FROM pg_type AS t1 WHERE t1.oid = pg_type.typelem);
- oid | typelem 
------+---------
+ ctid | typelem 
+------+---------
 (0 rows)
 
-SELECT oid, pg_type.typinput 
+SELECT ctid, pg_type.typinput 
 FROM   pg_type 
 WHERE  pg_type.typinput != 0 AND 
    NOT EXISTS(SELECT * FROM pg_proc AS t1 WHERE t1.oid = pg_type.typinput);
- oid | typinput 
------+----------
+ ctid | typinput 
+------+----------
 (0 rows)
 
-SELECT oid, pg_type.typoutput 
+SELECT ctid, pg_type.typoutput 
 FROM   pg_type 
 WHERE  pg_type.typoutput != 0 AND 
    NOT EXISTS(SELECT * FROM pg_proc AS t1 WHERE t1.oid = pg_type.typoutput);
- oid | typoutput 
------+-----------
+ ctid | typoutput 
+------+-----------
 (0 rows)
 
-SELECT oid, pg_type.typreceive 
+SELECT ctid, pg_type.typreceive 
 FROM   pg_type 
 WHERE  pg_type.typreceive != 0 AND 
    NOT EXISTS(SELECT * FROM pg_proc AS t1 WHERE t1.oid = pg_type.typreceive);
- oid | typreceive 
------+------------
+ ctid | typreceive 
+------+------------
 (0 rows)
 
-SELECT oid, pg_type.typsend 
+SELECT ctid, pg_type.typsend 
 FROM   pg_type 
 WHERE  pg_type.typsend != 0 AND 
    NOT EXISTS(SELECT * FROM pg_proc AS t1 WHERE t1.oid = pg_type.typsend);
- oid | typsend 
------+---------
+ ctid | typsend 
+------+---------
 (0 rows)
 
 
           (p2.pronargs = 1 AND p1.aggbasetype = 0)));
   oid  | aggname | oid |   proname   
 -------+---------+-----+-------------
- 16959 | max     | 768 | int4larger
- 16973 | min     | 769 | int4smaller
+ 10020 | max     | 768 | int4larger
+ 10034 | min     | 769 | int4smaller
 (2 rows)
 
 -- Cross-check finalfn (if present) against its entry in pg_proc.
 
 -- **************** pg_amop ****************
 -- Look for illegal values in pg_amop fields
-SELECT p1.oid
+SELECT p1.amopclaid, p1.amopopr, p1.amopid
 FROM pg_amop as p1
 WHERE p1.amopid = 0 OR p1.amopclaid = 0 OR p1.amopopr = 0 OR
     p1.amopstrategy <= 0;
- oid 
------
-(0 rows)
-
--- Look for duplicate pg_amop entries
-SELECT p1.oid, p2.oid
-FROM pg_amop AS p1, pg_amop AS p2
-WHERE p1.oid != p2.oid AND
-    p1.amopid = p2.amopid AND
-    p1.amopclaid = p2.amopclaid AND
-    p1.amopstrategy = p2.amopstrategy;
- oid | oid 
------+-----
+ amopclaid | amopopr | amopid 
+-----------+---------+--------
 (0 rows)
 
 -- Cross-check amopstrategy index against parent AM
-SELECT p1.oid, p2.oid, p2.amname
+SELECT p1.amopclaid, p1.amopopr, p1.amopid, p2.oid, p2.amname
 FROM pg_amop AS p1, pg_am AS p2
 WHERE p1.amopid = p2.oid AND p1.amopstrategy > p2.amstrategies;
- oid | oid | amname 
------+-----+--------
+ amopclaid | amopopr | amopid | oid | amname 
+-----------+---------+--------+-----+--------
 (0 rows)
 
 -- Detect missing pg_amop entries: should have as many strategy functions
 -- operator yielding boolean.
 -- NOTE: for 7.1, add restriction that operator inputs are of same type.
 -- We used to have opclasses like "int24_ops" but these were broken.
-SELECT p1.oid, p2.oid, p2.oprname
+SELECT p1.amopclaid, p1.amopopr, p1.amopid, p2.oid, p2.oprname
 FROM pg_amop AS p1, pg_operator AS p2
 WHERE p1.amopopr = p2.oid AND
     (p2.oprkind != 'b' OR p2.oprresult != 16 OR p2.oprleft != p2.oprright);
- oid | oid | oprname 
------+-----+---------
+ amopclaid | amopopr | amopid | oid | oprname 
+-----------+---------+--------+-----+---------
 (0 rows)
 
 -- If opclass is for a specific type, operator inputs should be of that type
-SELECT p1.oid, p2.oid, p2.oprname, p3.oid, p3.opcname
+SELECT p1.amopclaid, p1.amopopr, p1.amopid, p2.oid, p2.oprname, p3.oid, p3.opcname
 FROM pg_amop AS p1, pg_operator AS p2, pg_opclass AS p3
 WHERE p1.amopopr = p2.oid AND p1.amopclaid = p3.oid AND
     p3.opcdeftype != 0 AND
     (p3.opcdeftype != p2.oprleft OR p3.opcdeftype != p2.oprright);
- oid | oid | oprname | oid | opcname 
------+-----+---------+-----+---------
+ amopclaid | amopopr | amopid | oid | oprname | oid | opcname 
+-----------+---------+--------+-----+---------+-----+---------
 (0 rows)
 
 -- **************** pg_amproc ****************
 -- Look for illegal values in pg_amproc fields
-SELECT p1.oid
+SELECT p1.amid, p1.amopclaid, p1.amprocnum
 FROM pg_amproc as p1
 WHERE p1.amid = 0 OR p1.amopclaid = 0 OR p1.amproc = 0 OR
     p1.amprocnum <= 0;
- oid 
------
-(0 rows)
-
--- Look for duplicate pg_amproc entries
-SELECT p1.oid, p2.oid
-FROM pg_amproc AS p1, pg_amproc AS p2
-WHERE p1.oid != p2.oid AND
-    p1.amid = p2.amid AND
-    p1.amopclaid = p2.amopclaid AND
-    p1.amprocnum = p2.amprocnum;
- oid | oid 
------+-----
+ amid | amopclaid | amprocnum 
+------+-----------+-----------
 (0 rows)
 
 -- Cross-check amprocnum index against parent AM
-SELECT p1.oid, p2.oid, p2.amname
+SELECT p1.amid, p1.amopclaid, p1.amprocnum, p2.oid, p2.amname
 FROM pg_amproc AS p1, pg_am AS p2
 WHERE p1.amid = p2.oid AND p1.amprocnum > p2.amsupport;
- oid | oid | amname 
------+-----+--------
+ amid | amopclaid | amprocnum | oid | amname 
+------+-----------+-----------+-----+--------
 (0 rows)
 
 -- Detect missing pg_amproc entries: should have as many support functions
 -- or different base data types.
 -- We can check that all the referenced instances of the same support
 -- routine number take the same number of parameters, but that's about it...
-SELECT p1.oid, p2.oid, p2.proname, p3.oid, p4.oid, p4.proname
+SELECT p1.amid, p1.amopclaid, p1.amprocnum,
+   p2.oid, p2.proname,
+   p3.amid, p3.amopclaid, p3.amprocnum,
+   p4.oid, p4.proname
 FROM pg_amproc AS p1, pg_proc AS p2, pg_amproc AS p3, pg_proc AS p4
-WHERE p1.oid != p3.oid AND
-    p1.amid = p3.amid AND p1.amprocnum = p3.amprocnum AND
+WHERE p1.amid = p3.amid AND p1.amprocnum = p3.amprocnum AND
     p1.amproc = p2.oid AND p3.amproc = p4.oid AND
     (p2.proretset OR p4.proretset OR p2.pronargs != p4.pronargs);
- oid | oid | proname | oid | oid | proname 
------+-----+---------+-----+-----+---------
+ amid | amopclaid | amprocnum | oid | proname | amid | amopclaid | amprocnum | oid | proname 
+------+-----------+-----------+-----+---------+------+-----------+-----------+-----+---------
 (0 rows)
 
 -- Cross-check that each opclass that has any entries for a given AM
 
  pg_stat_user_tables      | SELECT pg_stat_all_tables.relid, pg_stat_all_tables.relname, pg_stat_all_tables.seq_scan, pg_stat_all_tables.seq_tup_read, pg_stat_all_tables.idx_scan, pg_stat_all_tables.idx_tup_fetch, pg_stat_all_tables.n_tup_ins, pg_stat_all_tables.n_tup_upd, pg_stat_all_tables.n_tup_del FROM pg_stat_all_tables WHERE (pg_stat_all_tables.relname !~ '^pg_'::text);
  pg_statio_all_indexes    | SELECT c.oid AS relid, i.oid AS indexrelid, c.relname, i.relname AS indexrelname, (pg_stat_get_blocks_fetched(i.oid) - pg_stat_get_blocks_hit(i.oid)) AS idx_blks_read, pg_stat_get_blocks_hit(i.oid) AS idx_blks_hit FROM pg_class c, pg_class i, pg_index x WHERE (((c.relkind = 'r'::"char") AND (x.indrelid = c.oid)) AND (x.indexrelid = i.oid));
  pg_statio_all_sequences  | SELECT c.oid AS relid, c.relname, (pg_stat_get_blocks_fetched(c.oid) - pg_stat_get_blocks_hit(c.oid)) AS blks_read, pg_stat_get_blocks_hit(c.oid) AS blks_hit FROM pg_class c WHERE (c.relkind = 'S'::"char");
- pg_statio_all_tables     | SELECT c.oid AS relid, c.relname, (pg_stat_get_blocks_fetched(c.oid) - pg_stat_get_blocks_hit(c.oid)) AS heap_blks_read, pg_stat_get_blocks_hit(c.oid) AS heap_blks_hit, sum((pg_stat_get_blocks_fetched(i.indexrelid) - pg_stat_get_blocks_hit(i.indexrelid))) AS idx_blks_read, sum(pg_stat_get_blocks_hit(i.indexrelid)) AS idx_blks_hit, (pg_stat_get_blocks_fetched(t.oid) - pg_stat_get_blocks_hit(t.oid)) AS toast_blks_read, pg_stat_get_blocks_hit(t.oid) AS toast_blks_hit, (pg_stat_get_blocks_fetched(x.oid) - pg_stat_get_blocks_hit(x.oid)) AS tidx_blks_read, pg_stat_get_blocks_hit(x.oid) AS tidx_blks_hit FROM (((pg_class c FULL JOIN pg_index i ON ((c.oid = i.indrelid))) FULL JOIN pg_class t ON ((c.reltoastrelid = t.oid))) FULL JOIN pg_class x ON ((c.reltoastidxid = x.oid))) WHERE (c.relkind = 'r'::"char") GROUP BY c.oid, c.relname, t.oid, x.oid;
+ pg_statio_all_tables     | SELECT c.oid AS relid, c.relname, (pg_stat_get_blocks_fetched(c.oid) - pg_stat_get_blocks_hit(c.oid)) AS heap_blks_read, pg_stat_get_blocks_hit(c.oid) AS heap_blks_hit, sum((pg_stat_get_blocks_fetched(i.indexrelid) - pg_stat_get_blocks_hit(i.indexrelid))) AS idx_blks_read, sum(pg_stat_get_blocks_hit(i.indexrelid)) AS idx_blks_hit, (pg_stat_get_blocks_fetched(t.oid) - pg_stat_get_blocks_hit(t.oid)) AS toast_blks_read, pg_stat_get_blocks_hit(t.oid) AS toast_blks_hit, (pg_stat_get_blocks_fetched(x.oid) - pg_stat_get_blocks_hit(x.oid)) AS tidx_blks_read, pg_stat_get_blocks_hit(x.oid) AS tidx_blks_hit FROM (((pg_class c FULL JOIN pg_index i ON ((c.oid = i.indrelid))) FULL JOIN pg_class t ON ((c.reltoastrelid = t.oid))) FULL JOIN pg_class x ON ((t.reltoastidxid = x.oid))) WHERE (c.relkind = 'r'::"char") GROUP BY c.oid, c.relname, t.oid, x.oid;
  pg_statio_sys_indexes    | SELECT pg_statio_all_indexes.relid, pg_statio_all_indexes.indexrelid, pg_statio_all_indexes.relname, pg_statio_all_indexes.indexrelname, pg_statio_all_indexes.idx_blks_read, pg_statio_all_indexes.idx_blks_hit FROM pg_statio_all_indexes WHERE (pg_statio_all_indexes.relname ~ '^pg_'::text);
  pg_statio_sys_sequences  | SELECT pg_statio_all_sequences.relid, pg_statio_all_sequences.relname, pg_statio_all_sequences.blks_read, pg_statio_all_sequences.blks_hit FROM pg_statio_all_sequences WHERE (pg_statio_all_sequences.relname ~ '^pg_'::text);
  pg_statio_sys_tables     | SELECT pg_statio_all_tables.relid, pg_statio_all_tables.relname, pg_statio_all_tables.heap_blks_read, pg_statio_all_tables.heap_blks_hit, pg_statio_all_tables.idx_blks_read, pg_statio_all_tables.idx_blks_hit, pg_statio_all_tables.toast_blks_read, pg_statio_all_tables.toast_blks_hit, pg_statio_all_tables.tidx_blks_read, pg_statio_all_tables.tidx_blks_hit FROM pg_statio_all_tables WHERE (pg_statio_all_tables.relname ~ '^pg_'::text);
 
 
 -- **************** pg_attribute ****************
 -- Look for illegal values in pg_attribute fields
-SELECT p1.oid, p1.attrelid, p1.attname
+SELECT p1.attrelid, p1.attname
 FROM pg_attribute as p1
 WHERE p1.attrelid = 0 OR p1.atttypid = 0 OR p1.attnum = 0 OR
     p1.attcacheoff != -1;
- oid | attrelid | attname 
------+----------+---------
-(0 rows)
-
--- Look for duplicate pg_attribute entries
--- (This would not be necessary if the indexes on pg_attribute were UNIQUE?)
-SELECT p1.oid, p1.attname, p2.oid, p2.attname
-FROM pg_attribute AS p1, pg_attribute AS p2
-WHERE p1.oid != p2.oid AND
-    p1.attrelid = p2.attrelid AND
-    (p1.attname = p2.attname OR p1.attnum = p2.attnum);
- oid | attname | oid | attname 
------+---------+-----+---------
+ attrelid | attname 
+----------+---------
 (0 rows)
 
 -- Cross-check attnum against parent relation
-SELECT p1.oid, p1.attname, p2.oid, p2.relname
+SELECT p1.attrelid, p1.attname, p2.oid, p2.relname
 FROM pg_attribute AS p1, pg_class AS p2
 WHERE p1.attrelid = p2.oid AND p1.attnum > p2.relnatts;
- oid | attname | oid | relname 
------+---------+-----+---------
+ attrelid | attname | oid | relname 
+----------+---------+-----+---------
 (0 rows)
 
 -- Detect missing pg_attribute entries: should have as many non-system
 (0 rows)
 
 -- Cross-check against pg_type entry
-SELECT p1.oid, p1.attname, p2.oid, p2.typname
+SELECT p1.attrelid, p1.attname, p2.oid, p2.typname
 FROM pg_attribute AS p1, pg_type AS p2
 WHERE p1.atttypid = p2.oid AND
     (p1.attlen != p2.typlen OR
      p1.attalign != p2.typalign OR
      p1.attbyval != p2.typbyval);
- oid | attname | oid | typname 
------+---------+-----+---------
+ attrelid | attname | oid | typname 
+----------+---------+-----+---------
 (0 rows)
 
 
 --
 -- This is created by pgsql/contrib/findoidjoins/make_oidjoin_check
 --
-SELECT oid, pg_aggregate.aggtransfn 
+SELECT ctid, pg_aggregate.aggtransfn 
 FROM   pg_aggregate 
 WHERE  pg_aggregate.aggtransfn != 0 AND 
    NOT EXISTS(SELECT * FROM pg_proc AS t1 WHERE t1.oid = pg_aggregate.aggtransfn);
-SELECT oid, pg_aggregate.aggfinalfn 
+SELECT ctid, pg_aggregate.aggfinalfn 
 FROM   pg_aggregate 
 WHERE  pg_aggregate.aggfinalfn != 0 AND 
    NOT EXISTS(SELECT * FROM pg_proc AS t1 WHERE t1.oid = pg_aggregate.aggfinalfn);
-SELECT oid, pg_aggregate.aggbasetype 
+SELECT ctid, pg_aggregate.aggbasetype 
 FROM   pg_aggregate 
 WHERE  pg_aggregate.aggbasetype != 0 AND 
    NOT EXISTS(SELECT * FROM pg_type AS t1 WHERE t1.oid = pg_aggregate.aggbasetype);
-SELECT oid, pg_aggregate.aggtranstype 
+SELECT ctid, pg_aggregate.aggtranstype 
 FROM   pg_aggregate 
 WHERE  pg_aggregate.aggtranstype != 0 AND 
    NOT EXISTS(SELECT * FROM pg_type AS t1 WHERE t1.oid = pg_aggregate.aggtranstype);
-SELECT oid, pg_aggregate.aggfinaltype 
+SELECT ctid, pg_aggregate.aggfinaltype 
 FROM   pg_aggregate 
 WHERE  pg_aggregate.aggfinaltype != 0 AND 
    NOT EXISTS(SELECT * FROM pg_type AS t1 WHERE t1.oid = pg_aggregate.aggfinaltype);
-SELECT oid, pg_am.amgettuple 
+SELECT ctid, pg_am.amgettuple 
 FROM   pg_am 
 WHERE  pg_am.amgettuple != 0 AND 
    NOT EXISTS(SELECT * FROM pg_proc AS t1 WHERE t1.oid = pg_am.amgettuple);
-SELECT oid, pg_am.aminsert 
+SELECT ctid, pg_am.aminsert 
 FROM   pg_am 
 WHERE  pg_am.aminsert != 0 AND 
    NOT EXISTS(SELECT * FROM pg_proc AS t1 WHERE t1.oid = pg_am.aminsert);
-SELECT oid, pg_am.ambeginscan 
+SELECT ctid, pg_am.ambeginscan 
 FROM   pg_am 
 WHERE  pg_am.ambeginscan != 0 AND 
    NOT EXISTS(SELECT * FROM pg_proc AS t1 WHERE t1.oid = pg_am.ambeginscan);
-SELECT oid, pg_am.amrescan 
+SELECT ctid, pg_am.amrescan 
 FROM   pg_am 
 WHERE  pg_am.amrescan != 0 AND 
    NOT EXISTS(SELECT * FROM pg_proc AS t1 WHERE t1.oid = pg_am.amrescan);
-SELECT oid, pg_am.amendscan 
+SELECT ctid, pg_am.amendscan 
 FROM   pg_am 
 WHERE  pg_am.amendscan != 0 AND 
    NOT EXISTS(SELECT * FROM pg_proc AS t1 WHERE t1.oid = pg_am.amendscan);
-SELECT oid, pg_am.ammarkpos 
+SELECT ctid, pg_am.ammarkpos 
 FROM   pg_am 
 WHERE  pg_am.ammarkpos != 0 AND 
    NOT EXISTS(SELECT * FROM pg_proc AS t1 WHERE t1.oid = pg_am.ammarkpos);
-SELECT oid, pg_am.amrestrpos 
+SELECT ctid, pg_am.amrestrpos 
 FROM   pg_am 
 WHERE  pg_am.amrestrpos != 0 AND 
    NOT EXISTS(SELECT * FROM pg_proc AS t1 WHERE t1.oid = pg_am.amrestrpos);
-SELECT oid, pg_am.ambuild 
+SELECT ctid, pg_am.ambuild 
 FROM   pg_am 
 WHERE  pg_am.ambuild != 0 AND 
    NOT EXISTS(SELECT * FROM pg_proc AS t1 WHERE t1.oid = pg_am.ambuild);
-SELECT oid, pg_am.ambulkdelete 
+SELECT ctid, pg_am.ambulkdelete 
 FROM   pg_am 
 WHERE  pg_am.ambulkdelete != 0 AND 
    NOT EXISTS(SELECT * FROM pg_proc AS t1 WHERE t1.oid = pg_am.ambulkdelete);
-SELECT oid, pg_am.amcostestimate 
+SELECT ctid, pg_am.amcostestimate 
 FROM   pg_am 
 WHERE  pg_am.amcostestimate != 0 AND 
    NOT EXISTS(SELECT * FROM pg_proc AS t1 WHERE t1.oid = pg_am.amcostestimate);
-SELECT oid, pg_amop.amopid 
+SELECT ctid, pg_amop.amopid 
 FROM   pg_amop 
 WHERE  pg_amop.amopid != 0 AND 
    NOT EXISTS(SELECT * FROM pg_am AS t1 WHERE t1.oid = pg_amop.amopid);
-SELECT oid, pg_amop.amopclaid 
+SELECT ctid, pg_amop.amopclaid 
 FROM   pg_amop 
 WHERE  pg_amop.amopclaid != 0 AND 
    NOT EXISTS(SELECT * FROM pg_opclass AS t1 WHERE t1.oid = pg_amop.amopclaid);
-SELECT oid, pg_amop.amopopr 
+SELECT ctid, pg_amop.amopopr 
 FROM   pg_amop 
 WHERE  pg_amop.amopopr != 0 AND 
    NOT EXISTS(SELECT * FROM pg_operator AS t1 WHERE t1.oid = pg_amop.amopopr);
-SELECT oid, pg_amproc.amid 
+SELECT ctid, pg_amproc.amid 
 FROM   pg_amproc 
 WHERE  pg_amproc.amid != 0 AND 
    NOT EXISTS(SELECT * FROM pg_am AS t1 WHERE t1.oid = pg_amproc.amid);
-SELECT oid, pg_amproc.amopclaid 
+SELECT ctid, pg_amproc.amopclaid 
 FROM   pg_amproc 
 WHERE  pg_amproc.amopclaid != 0 AND 
    NOT EXISTS(SELECT * FROM pg_opclass AS t1 WHERE t1.oid = pg_amproc.amopclaid);
-SELECT oid, pg_amproc.amproc 
+SELECT ctid, pg_amproc.amproc 
 FROM   pg_amproc 
 WHERE  pg_amproc.amproc != 0 AND 
    NOT EXISTS(SELECT * FROM pg_proc AS t1 WHERE t1.oid = pg_amproc.amproc);
-SELECT oid, pg_attribute.attrelid 
+SELECT ctid, pg_attribute.attrelid 
 FROM   pg_attribute 
 WHERE  pg_attribute.attrelid != 0 AND 
    NOT EXISTS(SELECT * FROM pg_class AS t1 WHERE t1.oid = pg_attribute.attrelid);
-SELECT oid, pg_attribute.atttypid 
+SELECT ctid, pg_attribute.atttypid 
 FROM   pg_attribute 
 WHERE  pg_attribute.atttypid != 0 AND 
    NOT EXISTS(SELECT * FROM pg_type AS t1 WHERE t1.oid = pg_attribute.atttypid);
-SELECT oid, pg_class.reltype 
+SELECT ctid, pg_class.reltype 
 FROM   pg_class 
 WHERE  pg_class.reltype != 0 AND 
    NOT EXISTS(SELECT * FROM pg_type AS t1 WHERE t1.oid = pg_class.reltype);
-SELECT oid, pg_class.relam 
+SELECT ctid, pg_class.relam 
 FROM   pg_class 
 WHERE  pg_class.relam != 0 AND 
    NOT EXISTS(SELECT * FROM pg_am AS t1 WHERE t1.oid = pg_class.relam);
-SELECT oid, pg_class.reltoastrelid 
+SELECT ctid, pg_class.reltoastrelid 
 FROM   pg_class 
 WHERE  pg_class.reltoastrelid != 0 AND 
    NOT EXISTS(SELECT * FROM pg_class AS t1 WHERE t1.oid = pg_class.reltoastrelid);
-SELECT oid, pg_class.reltoastidxid 
+SELECT ctid, pg_class.reltoastidxid 
 FROM   pg_class 
 WHERE  pg_class.reltoastidxid != 0 AND 
    NOT EXISTS(SELECT * FROM pg_class AS t1 WHERE t1.oid = pg_class.reltoastidxid);
-SELECT oid, pg_index.indexrelid 
+SELECT ctid, pg_description.classoid 
+FROM   pg_description 
+WHERE  pg_description.classoid != 0 AND 
+   NOT EXISTS(SELECT * FROM pg_class AS t1 WHERE t1.oid = pg_description.classoid);
+SELECT ctid, pg_index.indexrelid 
 FROM   pg_index 
 WHERE  pg_index.indexrelid != 0 AND 
    NOT EXISTS(SELECT * FROM pg_class AS t1 WHERE t1.oid = pg_index.indexrelid);
-SELECT oid, pg_index.indrelid 
+SELECT ctid, pg_index.indrelid 
 FROM   pg_index 
 WHERE  pg_index.indrelid != 0 AND 
    NOT EXISTS(SELECT * FROM pg_class AS t1 WHERE t1.oid = pg_index.indrelid);
-SELECT oid, pg_opclass.opcdeftype 
+SELECT ctid, pg_opclass.opcdeftype 
 FROM   pg_opclass 
 WHERE  pg_opclass.opcdeftype != 0 AND 
    NOT EXISTS(SELECT * FROM pg_type AS t1 WHERE t1.oid = pg_opclass.opcdeftype);
-SELECT oid, pg_operator.oprleft 
+SELECT ctid, pg_operator.oprleft 
 FROM   pg_operator 
 WHERE  pg_operator.oprleft != 0 AND 
    NOT EXISTS(SELECT * FROM pg_type AS t1 WHERE t1.oid = pg_operator.oprleft);
-SELECT oid, pg_operator.oprright 
+SELECT ctid, pg_operator.oprright 
 FROM   pg_operator 
 WHERE  pg_operator.oprright != 0 AND 
    NOT EXISTS(SELECT * FROM pg_type AS t1 WHERE t1.oid = pg_operator.oprright);
-SELECT oid, pg_operator.oprresult 
+SELECT ctid, pg_operator.oprresult 
 FROM   pg_operator 
 WHERE  pg_operator.oprresult != 0 AND 
    NOT EXISTS(SELECT * FROM pg_type AS t1 WHERE t1.oid = pg_operator.oprresult);
-SELECT oid, pg_operator.oprcom 
+SELECT ctid, pg_operator.oprcom 
 FROM   pg_operator 
 WHERE  pg_operator.oprcom != 0 AND 
    NOT EXISTS(SELECT * FROM pg_operator AS t1 WHERE t1.oid = pg_operator.oprcom);
-SELECT oid, pg_operator.oprnegate 
+SELECT ctid, pg_operator.oprnegate 
 FROM   pg_operator 
 WHERE  pg_operator.oprnegate != 0 AND 
    NOT EXISTS(SELECT * FROM pg_operator AS t1 WHERE t1.oid = pg_operator.oprnegate);
-SELECT oid, pg_operator.oprlsortop 
+SELECT ctid, pg_operator.oprlsortop 
 FROM   pg_operator 
 WHERE  pg_operator.oprlsortop != 0 AND 
    NOT EXISTS(SELECT * FROM pg_operator AS t1 WHERE t1.oid = pg_operator.oprlsortop);
-SELECT oid, pg_operator.oprrsortop 
+SELECT ctid, pg_operator.oprrsortop 
 FROM   pg_operator 
 WHERE  pg_operator.oprrsortop != 0 AND 
    NOT EXISTS(SELECT * FROM pg_operator AS t1 WHERE t1.oid = pg_operator.oprrsortop);
-SELECT oid, pg_operator.oprcode 
+SELECT ctid, pg_operator.oprcode 
 FROM   pg_operator 
 WHERE  pg_operator.oprcode != 0 AND 
    NOT EXISTS(SELECT * FROM pg_proc AS t1 WHERE t1.oid = pg_operator.oprcode);
-SELECT oid, pg_operator.oprrest 
+SELECT ctid, pg_operator.oprrest 
 FROM   pg_operator 
 WHERE  pg_operator.oprrest != 0 AND 
    NOT EXISTS(SELECT * FROM pg_proc AS t1 WHERE t1.oid = pg_operator.oprrest);
-SELECT oid, pg_operator.oprjoin 
+SELECT ctid, pg_operator.oprjoin 
 FROM   pg_operator 
 WHERE  pg_operator.oprjoin != 0 AND 
    NOT EXISTS(SELECT * FROM pg_proc AS t1 WHERE t1.oid = pg_operator.oprjoin);
-SELECT oid, pg_proc.prolang 
+SELECT ctid, pg_proc.prolang 
 FROM   pg_proc 
 WHERE  pg_proc.prolang != 0 AND 
    NOT EXISTS(SELECT * FROM pg_language AS t1 WHERE t1.oid = pg_proc.prolang);
-SELECT oid, pg_proc.prorettype 
+SELECT ctid, pg_proc.prorettype 
 FROM   pg_proc 
 WHERE  pg_proc.prorettype != 0 AND 
    NOT EXISTS(SELECT * FROM pg_type AS t1 WHERE t1.oid = pg_proc.prorettype);
-SELECT oid, pg_rewrite.ev_class 
+SELECT ctid, pg_rewrite.ev_class 
 FROM   pg_rewrite 
 WHERE  pg_rewrite.ev_class != 0 AND 
    NOT EXISTS(SELECT * FROM pg_class AS t1 WHERE t1.oid = pg_rewrite.ev_class);
-SELECT oid, pg_statistic.starelid 
+SELECT ctid, pg_statistic.starelid 
 FROM   pg_statistic 
 WHERE  pg_statistic.starelid != 0 AND 
    NOT EXISTS(SELECT * FROM pg_class AS t1 WHERE t1.oid = pg_statistic.starelid);
-SELECT oid, pg_statistic.staop1 
+SELECT ctid, pg_statistic.staop1 
 FROM   pg_statistic 
 WHERE  pg_statistic.staop1 != 0 AND 
    NOT EXISTS(SELECT * FROM pg_operator AS t1 WHERE t1.oid = pg_statistic.staop1);
-SELECT oid, pg_statistic.staop2 
+SELECT ctid, pg_statistic.staop2 
 FROM   pg_statistic 
 WHERE  pg_statistic.staop2 != 0 AND 
    NOT EXISTS(SELECT * FROM pg_operator AS t1 WHERE t1.oid = pg_statistic.staop2);
-SELECT oid, pg_statistic.staop3 
+SELECT ctid, pg_statistic.staop3 
 FROM   pg_statistic 
 WHERE  pg_statistic.staop3 != 0 AND 
    NOT EXISTS(SELECT * FROM pg_operator AS t1 WHERE t1.oid = pg_statistic.staop3);
-SELECT oid, pg_trigger.tgrelid 
+SELECT ctid, pg_trigger.tgrelid 
 FROM   pg_trigger 
 WHERE  pg_trigger.tgrelid != 0 AND 
    NOT EXISTS(SELECT * FROM pg_class AS t1 WHERE t1.oid = pg_trigger.tgrelid);
-SELECT oid, pg_trigger.tgfoid 
+SELECT ctid, pg_trigger.tgfoid 
 FROM   pg_trigger 
 WHERE  pg_trigger.tgfoid != 0 AND 
    NOT EXISTS(SELECT * FROM pg_proc AS t1 WHERE t1.oid = pg_trigger.tgfoid);
-SELECT oid, pg_type.typrelid 
+SELECT ctid, pg_type.typrelid 
 FROM   pg_type 
 WHERE  pg_type.typrelid != 0 AND 
    NOT EXISTS(SELECT * FROM pg_class AS t1 WHERE t1.oid = pg_type.typrelid);
-SELECT oid, pg_type.typelem 
+SELECT ctid, pg_type.typelem 
 FROM   pg_type 
 WHERE  pg_type.typelem != 0 AND 
    NOT EXISTS(SELECT * FROM pg_type AS t1 WHERE t1.oid = pg_type.typelem);
-SELECT oid, pg_type.typinput 
+SELECT ctid, pg_type.typinput 
 FROM   pg_type 
 WHERE  pg_type.typinput != 0 AND 
    NOT EXISTS(SELECT * FROM pg_proc AS t1 WHERE t1.oid = pg_type.typinput);
-SELECT oid, pg_type.typoutput 
+SELECT ctid, pg_type.typoutput 
 FROM   pg_type 
 WHERE  pg_type.typoutput != 0 AND 
    NOT EXISTS(SELECT * FROM pg_proc AS t1 WHERE t1.oid = pg_type.typoutput);
-SELECT oid, pg_type.typreceive 
+SELECT ctid, pg_type.typreceive 
 FROM   pg_type 
 WHERE  pg_type.typreceive != 0 AND 
    NOT EXISTS(SELECT * FROM pg_proc AS t1 WHERE t1.oid = pg_type.typreceive);
-SELECT oid, pg_type.typsend 
+SELECT ctid, pg_type.typsend 
 FROM   pg_type 
 WHERE  pg_type.typsend != 0 AND 
    NOT EXISTS(SELECT * FROM pg_proc AS t1 WHERE t1.oid = pg_type.typsend);
 
 
 -- Look for illegal values in pg_amop fields
 
-SELECT p1.oid
+SELECT p1.amopclaid, p1.amopopr, p1.amopid
 FROM pg_amop as p1
 WHERE p1.amopid = 0 OR p1.amopclaid = 0 OR p1.amopopr = 0 OR
     p1.amopstrategy <= 0;
 
--- Look for duplicate pg_amop entries
-
-SELECT p1.oid, p2.oid
-FROM pg_amop AS p1, pg_amop AS p2
-WHERE p1.oid != p2.oid AND
-    p1.amopid = p2.amopid AND
-    p1.amopclaid = p2.amopclaid AND
-    p1.amopstrategy = p2.amopstrategy;
-
 -- Cross-check amopstrategy index against parent AM
 
-SELECT p1.oid, p2.oid, p2.amname
+SELECT p1.amopclaid, p1.amopopr, p1.amopid, p2.oid, p2.amname
 FROM pg_amop AS p1, pg_am AS p2
 WHERE p1.amopid = p2.oid AND p1.amopstrategy > p2.amstrategies;
 
 -- NOTE: for 7.1, add restriction that operator inputs are of same type.
 -- We used to have opclasses like "int24_ops" but these were broken.
 
-SELECT p1.oid, p2.oid, p2.oprname
+SELECT p1.amopclaid, p1.amopopr, p1.amopid, p2.oid, p2.oprname
 FROM pg_amop AS p1, pg_operator AS p2
 WHERE p1.amopopr = p2.oid AND
     (p2.oprkind != 'b' OR p2.oprresult != 16 OR p2.oprleft != p2.oprright);
 
 -- If opclass is for a specific type, operator inputs should be of that type
 
-SELECT p1.oid, p2.oid, p2.oprname, p3.oid, p3.opcname
+SELECT p1.amopclaid, p1.amopopr, p1.amopid, p2.oid, p2.oprname, p3.oid, p3.opcname
 FROM pg_amop AS p1, pg_operator AS p2, pg_opclass AS p3
 WHERE p1.amopopr = p2.oid AND p1.amopclaid = p3.oid AND
     p3.opcdeftype != 0 AND
 
 -- Look for illegal values in pg_amproc fields
 
-SELECT p1.oid
+SELECT p1.amid, p1.amopclaid, p1.amprocnum
 FROM pg_amproc as p1
 WHERE p1.amid = 0 OR p1.amopclaid = 0 OR p1.amproc = 0 OR
     p1.amprocnum <= 0;
 
--- Look for duplicate pg_amproc entries
-
-SELECT p1.oid, p2.oid
-FROM pg_amproc AS p1, pg_amproc AS p2
-WHERE p1.oid != p2.oid AND
-    p1.amid = p2.amid AND
-    p1.amopclaid = p2.amopclaid AND
-    p1.amprocnum = p2.amprocnum;
-
 -- Cross-check amprocnum index against parent AM
 
-SELECT p1.oid, p2.oid, p2.amname
+SELECT p1.amid, p1.amopclaid, p1.amprocnum, p2.oid, p2.amname
 FROM pg_amproc AS p1, pg_am AS p2
 WHERE p1.amid = p2.oid AND p1.amprocnum > p2.amsupport;
 
 -- We can check that all the referenced instances of the same support
 -- routine number take the same number of parameters, but that's about it...
 
-SELECT p1.oid, p2.oid, p2.proname, p3.oid, p4.oid, p4.proname
+SELECT p1.amid, p1.amopclaid, p1.amprocnum,
+   p2.oid, p2.proname,
+   p3.amid, p3.amopclaid, p3.amprocnum,
+   p4.oid, p4.proname
 FROM pg_amproc AS p1, pg_proc AS p2, pg_amproc AS p3, pg_proc AS p4
-WHERE p1.oid != p3.oid AND
-    p1.amid = p3.amid AND p1.amprocnum = p3.amprocnum AND
+WHERE p1.amid = p3.amid AND p1.amprocnum = p3.amprocnum AND
     p1.amproc = p2.oid AND p3.amproc = p4.oid AND
     (p2.proretset OR p4.proretset OR p2.pronargs != p4.pronargs);
 
 
 
 -- Look for illegal values in pg_attribute fields
 
-SELECT p1.oid, p1.attrelid, p1.attname
+SELECT p1.attrelid, p1.attname
 FROM pg_attribute as p1
 WHERE p1.attrelid = 0 OR p1.atttypid = 0 OR p1.attnum = 0 OR
     p1.attcacheoff != -1;
 
--- Look for duplicate pg_attribute entries
--- (This would not be necessary if the indexes on pg_attribute were UNIQUE?)
-
-SELECT p1.oid, p1.attname, p2.oid, p2.attname
-FROM pg_attribute AS p1, pg_attribute AS p2
-WHERE p1.oid != p2.oid AND
-    p1.attrelid = p2.attrelid AND
-    (p1.attname = p2.attname OR p1.attnum = p2.attnum);
-
 -- Cross-check attnum against parent relation
 
-SELECT p1.oid, p1.attname, p2.oid, p2.relname
+SELECT p1.attrelid, p1.attname, p2.oid, p2.relname
 FROM pg_attribute AS p1, pg_class AS p2
 WHERE p1.attrelid = p2.oid AND p1.attnum > p2.relnatts;
 
 
 -- Cross-check against pg_type entry
 
-SELECT p1.oid, p1.attname, p2.oid, p2.typname
+SELECT p1.attrelid, p1.attname, p2.oid, p2.typname
 FROM pg_attribute AS p1, pg_type AS p2
 WHERE p1.atttypid = p2.oid AND
     (p1.attlen != p2.typlen OR