Thread: updated WIP: arrays of composites

updated WIP: arrays of composites

From
Andrew Dunstan
Date:
Attached is my rework of David Fetter's array of composites patch. It
has all the agreed modifications and checks, except altering the name
mangling.

If people prefer I can apply this as it stands and then get working on
the name mangling piece. Or I can hold off.

I'm still wondering if we can get away without a catalog change on that
- e.g. could we look up an array type by looking for a pg_type entry
containing the base type's oid in the typelem field? Or would that be
too slow?

cheers

andrew
Index: doc/src/sgml/array.sgml
===================================================================
RCS file: /cvsroot/pgsql/doc/src/sgml/array.sgml,v
retrieving revision 1.60
diff -c -r1.60 array.sgml
*** doc/src/sgml/array.sgml    6 Apr 2007 19:22:38 -0000    1.60
--- doc/src/sgml/array.sgml    7 May 2007 17:17:29 -0000
***************
*** 11,17 ****
    <productname>PostgreSQL</productname> allows columns of a table to be
    defined as variable-length multidimensional arrays. Arrays of any
    built-in or user-defined base type or enum type can be created.
!   (Arrays of composite types or domains are not yet supported, however.)
   </para>

   <sect2>
--- 11,18 ----
    <productname>PostgreSQL</productname> allows columns of a table to be
    defined as variable-length multidimensional arrays. Arrays of any
    built-in or user-defined base type or enum type can be created.
!   Arrays of composite types are now supported.  Arrays of domains are
!   not yet supported.
   </para>

   <sect2>
Index: src/backend/catalog/heap.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/catalog/heap.c,v
retrieving revision 1.318
diff -c -r1.318 heap.c
*** src/backend/catalog/heap.c    2 Apr 2007 03:49:37 -0000    1.318
--- src/backend/catalog/heap.c    7 May 2007 17:17:31 -0000
***************
*** 45,50 ****
--- 45,51 ----
  #include "catalog/pg_statistic.h"
  #include "catalog/pg_type.h"
  #include "commands/tablecmds.h"
+ #include "commands/typecmds.h"
  #include "miscadmin.h"
  #include "optimizer/clauses.h"
  #include "optimizer/var.h"
***************
*** 402,417 ****
      char        att_typtype = get_typtype(atttypid);

      /*
!      * Warn user, but don't fail, if column to be created has UNKNOWN type
!      * (usually as a result of a 'retrieve into' - jolly)
       *
!      * Refuse any attempt to create a pseudo-type column.
       */
!     if (atttypid == UNKNOWNOID)
          ereport(WARNING,
                  (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
                   errmsg("column \"%s\" has type \"unknown\"", attname),
                   errdetail("Proceeding with relation creation anyway.")));
      else if (att_typtype == TYPTYPE_PSEUDO)
      {
          /* Special hack for pg_statistic: allow ANYARRAY during initdb */
--- 403,442 ----
      char        att_typtype = get_typtype(atttypid);

      /*
!      * For a composite type, recurse into its attributes. Otherwise,
       *
!      * a) warn user, but don't fail, if column to be created has UNKNOWN type
!      *    (usually as a result of a 'retrieve into' - jolly)
!      *
!      * b) Refuse any attempt to create a pseudo-type column, except for
!      *    pg_statistic hack.
       */
!     if (att_typtype == TYPTYPE_COMPOSITE)
!     {
!         Relation relation;
!         TupleDesc tupdesc;
!         int i;
!
!         relation = RelationIdGetRelation(get_typ_typrelid(atttypid));
!
!         tupdesc = RelationGetDescr(relation);
!
!         for (i = 0; i < tupdesc->natts; i++)
!         {
!             if (tupdesc->attrs[i]->attisdropped)
!                 continue;
!             CheckAttributeType(attname, tupdesc->attrs[i]->atttypid);
!         }
!
!         RelationClose(relation);
!     }
!     else if (atttypid == UNKNOWNOID)
!     {
          ereport(WARNING,
                  (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
                   errmsg("column \"%s\" has type \"unknown\"", attname),
                   errdetail("Proceeding with relation creation anyway.")));
+     }
      else if (att_typtype == TYPTYPE_PSEUDO)
      {
          /* Special hack for pg_statistic: allow ANYARRAY during initdb */
***************
*** 763,768 ****
--- 788,794 ----
      Relation    pg_class_desc;
      Relation    new_rel_desc;
      Oid            new_type_oid;
+     char       *relarrayname;

      pg_class_desc = heap_open(RelationRelationId, RowExclusiveLock);

***************
*** 815,820 ****
--- 841,880 ----
                                        relnamespace,
                                        relid,
                                        relkind);
+     /*
+      * Add in the corresponding array types if appropriate.
+      */
+     if (IsUnderPostmaster && (relkind == RELKIND_RELATION ||
+                               relkind == RELKIND_VIEW ||
+                               relkind == RELKIND_COMPOSITE_TYPE))
+     {
+         relarrayname = makeArrayTypeName(relname);
+         TypeCreate(relarrayname,        /* Array type name */
+                    relnamespace,        /* Same namespace as parent */
+                    InvalidOid,            /* Not composite, so no relationOid  */
+                    0,                    /* relkind, also N/A here */
+                    -1,                    /* Internal size, unlimited */
+                    TYPTYPE_BASE,        /* Not a complex type - typelem is */
+                    DEFAULT_TYPDELIM,    /* Use the default */
+                    F_ARRAY_IN,            /* Macro for array input procedure */
+                    F_ARRAY_OUT,            /* Macro for array output procedure */
+                    F_ARRAY_RECV,        /* Macro for array receive (binary input) procedure */
+                    F_ARRAY_SEND,        /* Macro for array send (binary output) procedure */
+                    InvalidOid,            /* No input typmod */
+                    InvalidOid,            /* No output typmod */
+                    InvalidOid,            /* Default ANALYZE procedure */
+                    new_type_oid,        /* The OID just created */
+                    InvalidOid,            /* No base type--this isn't a DOMAIN */
+                    NULL,                /* No default type value */
+                    NULL,                /* Don't send binary */
+                    false,                /* Never passed by value */
+                    'd',                    /* Type align. Largest for safety */
+                    'x',                    /* Always TOASTable */
+                    -1,                    /* No typMod for non-domain types. */
+                    0,                    /* Array diminsions of typbasetype */
+                    false);                /* Type NOT NULL */
+         pfree(relarrayname);    /* Seems like the right thing to do here. */
+     }

      /*
       * now create an entry in pg_class for the relation.
Index: src/backend/commands/tablecmds.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v
retrieving revision 1.219
diff -c -r1.219 tablecmds.c
*** src/backend/commands/tablecmds.c    8 Apr 2007 01:26:32 -0000    1.219
--- src/backend/commands/tablecmds.c    7 May 2007 17:17:36 -0000
***************
*** 287,298 ****
      Datum        reloptions;
      ListCell   *listptr;
      AttrNumber    attnum;

      /*
!      * Truncate relname to appropriate length (probably a waste of time, as
!      * parser should have done this already).
       */
!     StrNCpy(relname, stmt->relation->relname, NAMEDATALEN);

      /*
       * Check consistency of arguments
--- 287,309 ----
      Datum        reloptions;
      ListCell   *listptr;
      AttrNumber    attnum;
+     char       *relarrayname;

      /*
!      * Truncate relname to appropriate length (probably a waste of time, as *
!      * parser should have done this already).  Because tables and views now get
!      * an array type, this depends on the relkind.
       */
!     if (relkind == RELKIND_RELATION ||
!         relkind == RELKIND_VIEW ||
!         relkind == RELKIND_COMPOSITE_TYPE)
!     {
!         StrNCpy(relname, stmt->relation->relname, NAMEDATALEN-2);
!     }
!     else
!     {
!         StrNCpy(relname, stmt->relation->relname, NAMEDATALEN);
!     }

      /*
       * Check consistency of arguments
***************
*** 6461,6468 ****

      AlterRelationNamespaceInternal(classRel, relid, oldNspOid, nspOid, true);

!     /* Fix the table's rowtype too */
      AlterTypeNamespaceInternal(rel->rd_rel->reltype, nspOid, false);

      /* Fix other dependent stuff */
      if (rel->rd_rel->relkind == RELKIND_RELATION)
--- 6472,6480 ----

      AlterRelationNamespaceInternal(classRel, relid, oldNspOid, nspOid, true);

!     /* Fix the table's types too */
      AlterTypeNamespaceInternal(rel->rd_rel->reltype, nspOid, false);
+     AlterTypeNamespaceInternal(get_array_type(rel->rd_rel->reltype), nspOid, false);

      /* Fix other dependent stuff */
      if (rel->rd_rel->relkind == RELKIND_RELATION)
Index: src/backend/commands/typecmds.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/commands/typecmds.c,v
retrieving revision 1.101
diff -c -r1.101 typecmds.c
*** src/backend/commands/typecmds.c    2 Apr 2007 03:49:38 -0000    1.101
--- src/backend/commands/typecmds.c    7 May 2007 17:17:37 -0000
***************
*** 474,479 ****
--- 474,480 ----
      Oid            typeoid;
      HeapTuple    tup;
      ObjectAddress object;
+     Form_pg_type typ;

      /* Make a TypeName so we can use standard type lookup machinery */
      typename = makeTypeNameFromNameList(names);
***************
*** 505,513 ****
      if (!HeapTupleIsValid(tup))
          elog(ERROR, "cache lookup failed for type %u", typeoid);

      /* Permission check: must own type or its namespace */
      if (!pg_type_ownercheck(typeoid, GetUserId()) &&
!       !pg_namespace_ownercheck(((Form_pg_type) GETSTRUCT(tup))->typnamespace,
                                 GetUserId()))
          aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TYPE,
                         TypeNameToString(typename));
--- 506,524 ----
      if (!HeapTupleIsValid(tup))
          elog(ERROR, "cache lookup failed for type %u", typeoid);

+     typ = (Form_pg_type) GETSTRUCT(tup);
+
+     /* don't alow direct deletion of array types */
+     if (typ->typelem != 0 && typ->typlen == -1)
+             ereport(ERROR,
+                     (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
+                      errmsg("cannot delete array type \"%s\" ",
+                             TypeNameToString(typename))));
+
+
      /* Permission check: must own type or its namespace */
      if (!pg_type_ownercheck(typeoid, GetUserId()) &&
!       !pg_namespace_ownercheck(typ->typnamespace,
                                 GetUserId()))
          aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TYPE,
                         TypeNameToString(typename));
***************
*** 2249,2254 ****
--- 2260,2273 ----
          elog(ERROR, "cache lookup failed for type %u", typeOid);
      typTup = (Form_pg_type) GETSTRUCT(tup);

+     /* don't allow direct alteration of array types */
+     if (typTup->typelem != 0 && typTup->typlen == -1)
+             ereport(ERROR,
+                     (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
+                      errmsg("cannot alter array type \"%s\" ",
+                             TypeNameToString(typename))));
+
+
      /*
       * If it's a composite type, we need to check that it really is a
       * free-standing composite type, and not a table's underlying type. We
***************
*** 2352,2357 ****
--- 2371,2379 ----
      TypeName   *typename;
      Oid            typeOid;
      Oid            nspOid;
+     Relation    rel;
+     HeapTuple    tup;
+     Form_pg_type typ;

      /* Make a TypeName so we can use standard type lookup machinery */
      typename = makeTypeNameFromNameList(names);
***************
*** 2365,2372 ****
--- 2387,2420 ----
      /* get schema OID and check its permissions */
      nspOid = LookupCreationNamespace(newschema);

+     /* don't allow direct alteration of array types */
+
+     rel = heap_open(TypeRelationId, RowExclusiveLock);
+
+     tup = SearchSysCacheCopy(TYPEOID,
+                              ObjectIdGetDatum(typeOid),
+                              0, 0, 0);
+     if (!HeapTupleIsValid(tup))
+         elog(ERROR, "cache lookup failed for type %u", typeOid);
+
+     typ = (Form_pg_type) GETSTRUCT(tup);
+
+     if (typ->typelem != 0 && typ->typlen == -1)
+             ereport(ERROR,
+                     (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
+                      errmsg("cannot alter array type \"%s\" ",
+                             TypeNameToString(typename))));
+
+
+     heap_freetuple(tup);
+
+     heap_close(rel, RowExclusiveLock);
+
      /* and do the work */
      AlterTypeNamespaceInternal(typeOid, nspOid, true);
+     typeOid = get_array_type(typeOid);
+     if (typeOid != InvalidOid)
+         AlterTypeNamespaceInternal(typeOid, nspOid, true);
  }

  /*
***************
*** 2431,2442 ****

      /* Detect whether type is a composite type (but not a table rowtype) */
      isCompositeType =
!         (typform->typtype == TYPTYPE_COMPOSITE &&
           get_rel_relkind(typform->typrelid) == RELKIND_COMPOSITE_TYPE);

      /* Enforce not-table-type if requested */
      if (typform->typtype == TYPTYPE_COMPOSITE && !isCompositeType &&
!         errorOnTableType)
          ereport(ERROR,
                  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
                   errmsg("%s is a table's row type",
--- 2479,2490 ----

      /* Detect whether type is a composite type (but not a table rowtype) */
      isCompositeType =
!         (typform->typtype == TYPTYPE_COMPOSITE && typform->typrelid != InvalidOid &&
           get_rel_relkind(typform->typrelid) == RELKIND_COMPOSITE_TYPE);

      /* Enforce not-table-type if requested */
      if (typform->typtype == TYPTYPE_COMPOSITE && !isCompositeType &&
!         typform->typrelid != InvalidOid && errorOnTableType)
          ereport(ERROR,
                  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
                   errmsg("%s is a table's row type",
***************
*** 2457,2463 ****
       * We need to modify the pg_class tuple as well to reflect the change of
       * schema.
       */
!     if (isCompositeType)
      {
          Relation    classRel;

--- 2505,2511 ----
       * We need to modify the pg_class tuple as well to reflect the change of
       * schema.
       */
!     if (isCompositeType && typform->typrelid != InvalidOid)
      {
          Relation    classRel;

***************
*** 2490,2496 ****
           * Update dependency on schema, if any --- a table rowtype has not got
           * one.
           */
!         if (typform->typtype != TYPTYPE_COMPOSITE)
              if (changeDependencyFor(TypeRelationId, typeOid,
                                  NamespaceRelationId, oldNspOid, nspOid) != 1)
                  elog(ERROR, "failed to change schema dependency for type %s",
--- 2538,2544 ----
           * Update dependency on schema, if any --- a table rowtype has not got
           * one.
           */
!         if (typform->typtype != TYPTYPE_COMPOSITE || typform->typrelid == InvalidOid)
              if (changeDependencyFor(TypeRelationId, typeOid,
                                  NamespaceRelationId, oldNspOid, nspOid) != 1)
                  elog(ERROR, "failed to change schema dependency for type %s",
Index: src/test/regress/expected/alter_table.out
===================================================================
RCS file: /cvsroot/pgsql/src/test/regress/expected/alter_table.out,v
retrieving revision 1.101
diff -c -r1.101 alter_table.out
*** src/test/regress/expected/alter_table.out    14 Feb 2007 01:58:58 -0000    1.101
--- src/test/regress/expected/alter_table.out    7 May 2007 17:17:41 -0000
***************
*** 1456,1468 ****
--- 1456,1471 ----

  -- clean up
  drop schema alter2 cascade;
+ NOTICE:  drop cascades to type alter2.ctype[]
  NOTICE:  drop cascades to composite type alter2.ctype
  NOTICE:  drop cascades to type alter2.ctype
  NOTICE:  drop cascades to type alter2.posint
  NOTICE:  drop cascades to function alter2.plus1(integer)
+ NOTICE:  drop cascades to type alter2.v1[]
  NOTICE:  drop cascades to view alter2.v1
  NOTICE:  drop cascades to rule _RETURN on view alter2.v1
  NOTICE:  drop cascades to sequence alter2.t1_f1_seq
  NOTICE:  drop cascades to default for table alter2.t1 column f1
+ NOTICE:  drop cascades to type alter2.t1[]
  NOTICE:  drop cascades to table alter2.t1
  NOTICE:  drop cascades to constraint t1_f2_check on table alter2.t1
Index: src/test/regress/expected/type_sanity.out
===================================================================
RCS file: /cvsroot/pgsql/src/test/regress/expected/type_sanity.out,v
retrieving revision 1.29
diff -c -r1.29 type_sanity.out
*** src/test/regress/expected/type_sanity.out    2 Apr 2007 03:49:42 -0000    1.29
--- src/test/regress/expected/type_sanity.out    7 May 2007 17:17:41 -0000
***************
*** 49,55 ****
  -- or basic types that do.
  SELECT p1.oid, p1.typname
  FROM pg_type as p1
! WHERE (p1.typtype = 'c' AND p1.typrelid = 0) OR
      (p1.typtype != 'c' AND p1.typrelid != 0);
   oid | typname
  -----+---------
--- 49,55 ----
  -- or basic types that do.
  SELECT p1.oid, p1.typname
  FROM pg_type as p1
! WHERE (p1.typtype = 'c' AND p1.typrelid = 0 AND p1.typname !~ '^_') OR
      (p1.typtype != 'c' AND p1.typrelid != 0);
   oid | typname
  -----+---------
Index: src/test/regress/sql/type_sanity.sql
===================================================================
RCS file: /cvsroot/pgsql/src/test/regress/sql/type_sanity.sql,v
retrieving revision 1.29
diff -c -r1.29 type_sanity.sql
*** src/test/regress/sql/type_sanity.sql    2 Apr 2007 03:49:42 -0000    1.29
--- src/test/regress/sql/type_sanity.sql    7 May 2007 17:17:41 -0000
***************
*** 46,52 ****

  SELECT p1.oid, p1.typname
  FROM pg_type as p1
! WHERE (p1.typtype = 'c' AND p1.typrelid = 0) OR
      (p1.typtype != 'c' AND p1.typrelid != 0);

  -- Look for basic or enum types that don't have an array type.
--- 46,52 ----

  SELECT p1.oid, p1.typname
  FROM pg_type as p1
! WHERE (p1.typtype = 'c' AND p1.typrelid = 0 AND p1.typname !~ '^_') OR
      (p1.typtype != 'c' AND p1.typrelid != 0);

  -- Look for basic or enum types that don't have an array type.

Re: updated WIP: arrays of composites

From
Tom Lane
Date:
Andrew Dunstan <andrew@dunslane.net> writes:
> I'm still wondering if we can get away without a catalog change on that
> - e.g. could we look up an array type by looking for a pg_type entry
> containing the base type's oid in the typelem field? Or would that be
> too slow?

(a) too slow, (b) not unique.

            regards, tom lane

Re: updated WIP: arrays of composites

From
Andrew Dunstan
Date:

I wrote:
>
> Attached is my rework of David Fetter's array of composites patch. It
> has all the agreed modifications and checks, except altering the name
> mangling.
>
>

Here is the latest with the name mangling piece done - it's got quite
large with the catalog rewrite :-)

It could do with some extra eyeballs - especially the error codes.

I'm not sure if we need to adjust the test in pg_dump.c - maybe we
should look at using the same test as the backend (typlen == -1) to
disambiguate real arrays from subscriptable base types.

cheers

andrew
Index: doc/src/sgml/array.sgml
===================================================================
RCS file: /cvsroot/pgsql/doc/src/sgml/array.sgml,v
retrieving revision 1.60
diff -c -r1.60 array.sgml
*** doc/src/sgml/array.sgml    6 Apr 2007 19:22:38 -0000    1.60
--- doc/src/sgml/array.sgml    9 May 2007 00:38:12 -0000
***************
*** 11,17 ****
    <productname>PostgreSQL</productname> allows columns of a table to be
    defined as variable-length multidimensional arrays. Arrays of any
    built-in or user-defined base type or enum type can be created.
!   (Arrays of composite types or domains are not yet supported, however.)
   </para>

   <sect2>
--- 11,18 ----
    <productname>PostgreSQL</productname> allows columns of a table to be
    defined as variable-length multidimensional arrays. Arrays of any
    built-in or user-defined base type or enum type can be created.
!   Arrays of composite types are now supported.  Arrays of domains are
!   not yet supported.
   </para>

   <sect2>
Index: src/backend/catalog/heap.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/catalog/heap.c,v
retrieving revision 1.318
diff -c -r1.318 heap.c
*** src/backend/catalog/heap.c    2 Apr 2007 03:49:37 -0000    1.318
--- src/backend/catalog/heap.c    9 May 2007 00:38:13 -0000
***************
*** 45,50 ****
--- 45,51 ----
  #include "catalog/pg_statistic.h"
  #include "catalog/pg_type.h"
  #include "commands/tablecmds.h"
+ #include "commands/typecmds.h"
  #include "miscadmin.h"
  #include "optimizer/clauses.h"
  #include "optimizer/var.h"
***************
*** 69,75 ****
  static Oid AddNewRelationType(const char *typeName,
                     Oid typeNamespace,
                     Oid new_rel_oid,
!                    char new_rel_kind);
  static void RelationRemoveInheritance(Oid relid);
  static void StoreRelCheck(Relation rel, char *ccname, char *ccbin);
  static void StoreConstraints(Relation rel, TupleDesc tupdesc);
--- 70,78 ----
  static Oid AddNewRelationType(const char *typeName,
                     Oid typeNamespace,
                     Oid new_rel_oid,
!                    char new_rel_kind,
!                    Oid new_array_type
!              );
  static void RelationRemoveInheritance(Oid relid);
  static void StoreRelCheck(Relation rel, char *ccname, char *ccbin);
  static void StoreConstraints(Relation rel, TupleDesc tupdesc);
***************
*** 402,417 ****
      char        att_typtype = get_typtype(atttypid);

      /*
!      * Warn user, but don't fail, if column to be created has UNKNOWN type
!      * (usually as a result of a 'retrieve into' - jolly)
       *
!      * Refuse any attempt to create a pseudo-type column.
       */
!     if (atttypid == UNKNOWNOID)
          ereport(WARNING,
                  (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
                   errmsg("column \"%s\" has type \"unknown\"", attname),
                   errdetail("Proceeding with relation creation anyway.")));
      else if (att_typtype == TYPTYPE_PSEUDO)
      {
          /* Special hack for pg_statistic: allow ANYARRAY during initdb */
--- 405,444 ----
      char        att_typtype = get_typtype(atttypid);

      /*
!      * For a composite type, recurse into its attributes. Otherwise,
       *
!      * a) warn user, but don't fail, if column to be created has UNKNOWN type
!      *    (usually as a result of a 'retrieve into' - jolly)
!      *
!      * b) Refuse any attempt to create a pseudo-type column, except for
!      *    pg_statistic hack.
       */
!     if (att_typtype == TYPTYPE_COMPOSITE)
!     {
!         Relation relation;
!         TupleDesc tupdesc;
!         int i;
!
!         relation = RelationIdGetRelation(get_typ_typrelid(atttypid));
!
!         tupdesc = RelationGetDescr(relation);
!
!         for (i = 0; i < tupdesc->natts; i++)
!         {
!             if (tupdesc->attrs[i]->attisdropped)
!                 continue;
!             CheckAttributeType(attname, tupdesc->attrs[i]->atttypid);
!         }
!
!         RelationClose(relation);
!     }
!     else if (atttypid == UNKNOWNOID)
!     {
          ereport(WARNING,
                  (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
                   errmsg("column \"%s\" has type \"unknown\"", attname),
                   errdetail("Proceeding with relation creation anyway.")));
+     }
      else if (att_typtype == TYPTYPE_PSEUDO)
      {
          /* Special hack for pg_statistic: allow ANYARRAY during initdb */
***************
*** 710,716 ****
  AddNewRelationType(const char *typeName,
                     Oid typeNamespace,
                     Oid new_rel_oid,
!                    char new_rel_kind)
  {
      return
          TypeCreate(typeName,    /* type name */
--- 737,744 ----
  AddNewRelationType(const char *typeName,
                     Oid typeNamespace,
                     Oid new_rel_oid,
!                    char new_rel_kind,
!                    Oid new_array_type)
  {
      return
          TypeCreate(typeName,    /* type name */
***************
*** 736,742 ****
                     'x',            /* fully TOASTable */
                     -1,            /* typmod */
                     0,            /* array dimensions for typBaseType */
!                    false);        /* Type NOT NULL */
  }

  /* --------------------------------
--- 764,773 ----
                     'x',            /* fully TOASTable */
                     -1,            /* typmod */
                     0,            /* array dimensions for typBaseType */
!                    false,        /* Type NOT NULL */
!                    new_array_type, /* oid of type we are about to make */
!                    false           /* no this is not an array type */
!             );
  }

  /* --------------------------------
***************
*** 763,768 ****
--- 794,801 ----
      Relation    pg_class_desc;
      Relation    new_rel_desc;
      Oid            new_type_oid;
+     Oid         new_array_oid = InvalidOid;
+

      pg_class_desc = heap_open(RelationRelationId, RowExclusiveLock);

***************
*** 804,809 ****
--- 837,853 ----

      Assert(relid == RelationGetRelid(new_rel_desc));

+     /* Get an oid for the array type of necessary */
+     if (IsUnderPostmaster && (relkind == RELKIND_RELATION ||
+                               relkind == RELKIND_VIEW ||
+                               relkind == RELKIND_COMPOSITE_TYPE))
+     {
+         Relation pg_type = heap_open(TypeRelationId, RowExclusiveLock);
+         new_array_oid = GetNewOid(pg_type);
+         heap_close(pg_type, RowExclusiveLock);
+     }
+
+
      /*
       * since defining a relation also defines a complex type, we add a new
       * system type corresponding to the new relation.
***************
*** 814,820 ****
      new_type_oid = AddNewRelationType(relname,
                                        relnamespace,
                                        relid,
!                                       relkind);

      /*
       * now create an entry in pg_class for the relation.
--- 858,906 ----
      new_type_oid = AddNewRelationType(relname,
                                        relnamespace,
                                        relid,
!                                       relkind,
!                                       new_array_oid);
!     /*
!      * Add in the corresponding array types if appropriate.
!      */
!     if (IsUnderPostmaster && (relkind == RELKIND_RELATION ||
!                               relkind == RELKIND_VIEW ||
!                               relkind == RELKIND_COMPOSITE_TYPE))
!     {
!         char       *relarrayname;
!
!         relarrayname = makeArrayTypeName(relname, relnamespace);
!
!         TypeCreate(relarrayname,        /* Array type name */
!                    relnamespace,        /* Same namespace as parent */
!                    InvalidOid,            /* Not composite, no relationOid */
!                    0,                    /* relkind, also N/A here */
!                    -1,                    /* Internal size, unlimited */
!                    TYPTYPE_BASE,        /* Not composite - typelem is */
!                    DEFAULT_TYPDELIM,    /* Use the default */
!                    F_ARRAY_IN,            /* array input proc */
!                    F_ARRAY_OUT,            /* array output proc */
!                    F_ARRAY_RECV,        /* array recv (bin) proc */
!                    F_ARRAY_SEND,        /* array send (bin) proc */
!                    InvalidOid,            /* No input typmod */
!                    InvalidOid,            /* No output typmod */
!                    InvalidOid,            /* Default ANALYZE procedure */
!                    new_type_oid,        /* The OID just created */
!                    InvalidOid,            /* No base type--not a DOMAIN */
!                    NULL,                /* No default type value */
!                    NULL,                /* Don't send binary */
!                    false,                /* Never passed by value */
!                    'd',                    /* Type align. Max for safety */
!                    'x',                    /* Always TOASTable */
!                    -1,                    /* No typMod for non-domain */
!                    0,                    /* Array dims of typbasetype */
!                    false,                /* Type NOT NULL */
!                    new_array_oid,       /* oid of this type entry */
!                    true                 /* yes, this is an array type */
!             );
!
!         pfree(relarrayname);
!     }

      /*
       * now create an entry in pg_class for the relation.
***************
*** 887,893 ****
       */
      heap_close(new_rel_desc, NoLock);    /* do not unlock till end of xact */
      heap_close(pg_class_desc, RowExclusiveLock);
!
      return relid;
  }

--- 973,979 ----
       */
      heap_close(new_rel_desc, NoLock);    /* do not unlock till end of xact */
      heap_close(pg_class_desc, RowExclusiveLock);
!
      return relid;
  }

Index: src/backend/catalog/pg_type.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/catalog/pg_type.c,v
retrieving revision 1.111
diff -c -r1.111 pg_type.c
*** src/backend/catalog/pg_type.c    2 Apr 2007 03:49:37 -0000    1.111
--- src/backend/catalog/pg_type.c    9 May 2007 00:38:14 -0000
***************
*** 90,95 ****
--- 90,96 ----
      values[i++] = CharGetDatum(DEFAULT_TYPDELIM);        /* typdelim */
      values[i++] = ObjectIdGetDatum(InvalidOid); /* typrelid */
      values[i++] = ObjectIdGetDatum(InvalidOid); /* typelem */
+     values[i++] = ObjectIdGetDatum(InvalidOid); /* typarray */
      values[i++] = ObjectIdGetDatum(F_SHELL_IN); /* typinput */
      values[i++] = ObjectIdGetDatum(F_SHELL_OUT);        /* typoutput */
      values[i++] = ObjectIdGetDatum(InvalidOid); /* typreceive */
***************
*** 180,186 ****
             char storage,
             int32 typeMod,
             int32 typNDims,        /* Array dimensions for baseType */
!            bool typeNotNull)
  {
      Relation    pg_type_desc;
      Oid            typeObjectId;
--- 181,190 ----
             char storage,
             int32 typeMod,
             int32 typNDims,        /* Array dimensions for baseType */
!            bool typeNotNull,
!            Oid arrayType,
!            bool is_array_type
! )
  {
      Relation    pg_type_desc;
      Oid            typeObjectId;
***************
*** 246,251 ****
--- 250,257 ----
      values[i++] = ObjectIdGetDatum(typeType == TYPTYPE_COMPOSITE ?
                                     relationOid : InvalidOid); /* typrelid */
      values[i++] = ObjectIdGetDatum(elementType);        /* typelem */
+     values[i++] = ObjectIdGetDatum(is_array_type ?
+                                    InvalidOid : arrayType); /* typarray */
      values[i++] = ObjectIdGetDatum(inputProcedure);        /* typinput */
      values[i++] = ObjectIdGetDatum(outputProcedure);    /* typoutput */
      values[i++] = ObjectIdGetDatum(receiveProcedure);    /* typreceive */
***************
*** 331,336 ****
--- 337,347 ----
                               values,
                               nulls);

+         /* should only happen if it's not a shell type */
+         if (is_array_type)
+             HeapTupleSetOid(tup, arrayType);
+
+
          typeObjectId = simple_heap_insert(pg_type_desc, tup);
      }

***************
*** 571,590 ****
  }

  /*
   * makeArrayTypeName(typeName);
   *      - given a base type name, make an array of type name out of it
   *
   * the caller is responsible for pfreeing the result
   */
  char *
! makeArrayTypeName(const char *typeName)
  {
      char       *arr;

      if (!typeName)
          return NULL;
      arr = palloc(NAMEDATALEN);
!     snprintf(arr, NAMEDATALEN,
!              "_%.*s", NAMEDATALEN - 2, typeName);
      return arr;
  }
--- 582,660 ----
  }

  /*
+  * find the mb-safe substring length that is not greater than max
+  */
+ static int
+ mb_substr_len(char * str, int max)
+ {
+     int result = 0;
+     char * crsr = str;
+     int len = strlen(str);
+
+     if (max > len)
+         max = len;
+
+     if (pg_database_encoding_max_length() == 1)
+         return max;
+     if (crsr == NULL)
+         return 0;
+     while (*crsr)
+     {
+         len = pg_mblen(crsr);
+         if (result + len > max)
+             break;
+         result += len;
+         crsr += len;
+     }
+     return result;
+ }
+
+
+
+ /*
   * makeArrayTypeName(typeName);
   *      - given a base type name, make an array of type name out of it
   *
   * the caller is responsible for pfreeing the result
   */
  char *
! makeArrayTypeName(const char *typeName, Oid typeNamespace)
  {
      char       *arr;
+     int        i, safelen;
+     bool       found = false;
+     Relation    pg_type_desc;
+
+     pg_type_desc = heap_open(TypeRelationId, RowExclusiveLock);
+

      if (!typeName)
          return NULL;
+
      arr = palloc(NAMEDATALEN);
!
!     for (i = 1; i < NAMEDATALEN / 2; i++)
!     {
!         arr[i - 1] = '_';
!         safelen = mb_substr_len(typeName, NAMEDATALEN - (i + 1));
!         snprintf(arr+i, NAMEDATALEN - 1, "%.*s",  safelen, typeName);
!         if (SearchSysCacheExists(TYPENAMENSP,
!                              CStringGetDatum(arr),
!                              ObjectIdGetDatum(typeNamespace),
!                              0, 0))
!             continue;
!         found = true;
!         break;
!     }
!
!     heap_close(pg_type_desc, RowExclusiveLock);
!
!     if (! found)
!         ereport(ERROR,
!                 (errcode(ERRCODE_DUPLICATE_OBJECT),
!                  errmsg("could not form array type name for type \"%s\"",
!                         typeName)));
!
!
      return arr;
  }
Index: src/backend/commands/tablecmds.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v
retrieving revision 1.219
diff -c -r1.219 tablecmds.c
*** src/backend/commands/tablecmds.c    8 Apr 2007 01:26:32 -0000    1.219
--- src/backend/commands/tablecmds.c    9 May 2007 00:38:18 -0000
***************
*** 287,298 ****
      Datum        reloptions;
      ListCell   *listptr;
      AttrNumber    attnum;

      /*
!      * Truncate relname to appropriate length (probably a waste of time, as
!      * parser should have done this already).
       */
!     StrNCpy(relname, stmt->relation->relname, NAMEDATALEN);

      /*
       * Check consistency of arguments
--- 287,309 ----
      Datum        reloptions;
      ListCell   *listptr;
      AttrNumber    attnum;
+     char       *relarrayname;

      /*
!      * Truncate relname to appropriate length (probably a waste of time, as *
!      * parser should have done this already).  Because tables and views now get
!      * an array type, this depends on the relkind.
       */
!     if (relkind == RELKIND_RELATION ||
!         relkind == RELKIND_VIEW ||
!         relkind == RELKIND_COMPOSITE_TYPE)
!     {
!         StrNCpy(relname, stmt->relation->relname, NAMEDATALEN-2);
!     }
!     else
!     {
!         StrNCpy(relname, stmt->relation->relname, NAMEDATALEN);
!     }

      /*
       * Check consistency of arguments
***************
*** 6461,6468 ****

      AlterRelationNamespaceInternal(classRel, relid, oldNspOid, nspOid, true);

!     /* Fix the table's rowtype too */
      AlterTypeNamespaceInternal(rel->rd_rel->reltype, nspOid, false);

      /* Fix other dependent stuff */
      if (rel->rd_rel->relkind == RELKIND_RELATION)
--- 6472,6480 ----

      AlterRelationNamespaceInternal(classRel, relid, oldNspOid, nspOid, true);

!     /* Fix the table's types too */
      AlterTypeNamespaceInternal(rel->rd_rel->reltype, nspOid, false);
+     AlterTypeNamespaceInternal(get_array_type(rel->rd_rel->reltype), nspOid, false);

      /* Fix other dependent stuff */
      if (rel->rd_rel->relkind == RELKIND_RELATION)
Index: src/backend/commands/typecmds.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/commands/typecmds.c,v
retrieving revision 1.101
diff -c -r1.101 typecmds.c
*** src/backend/commands/typecmds.c    2 Apr 2007 03:49:38 -0000    1.101
--- src/backend/commands/typecmds.c    9 May 2007 00:38:20 -0000
***************
*** 34,39 ****
--- 34,40 ----
  #include "access/genam.h"
  #include "access/heapam.h"
  #include "access/xact.h"
+ #include "catalog/catalog.h"
  #include "catalog/dependency.h"
  #include "catalog/heap.h"
  #include "catalog/indexing.h"
***************
*** 119,127 ****
--- 120,130 ----
      Oid            typmodoutOid = InvalidOid;
      Oid            analyzeOid = InvalidOid;
      char       *shadow_type;
+     Oid         shadow_oid;
      ListCell   *pl;
      Oid            typoid;
      Oid            resulttype;
+     Relation    pg_type;

      /* Convert list of names to a name and namespace */
      typeNamespace = QualifiedNameGetCreationNamespace(names, &typeName);
***************
*** 396,401 ****
--- 399,408 ----
          aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_PROC,
                         NameListToString(analyzeName));

+     pg_type = heap_open(TypeRelationId, RowExclusiveLock);
+     shadow_oid = GetNewOid(pg_type);
+     heap_close(pg_type, RowExclusiveLock);
+
      /*
       * now have TypeCreate do all the real work.
       */
***************
*** 423,465 ****
                     storage,        /* TOAST strategy */
                     -1,            /* typMod (Domains only) */
                     0,            /* Array Dimensions of typbasetype */
!                    false);        /* Type NOT NULL */

      /*
       * When we create a base type (as opposed to a complex type) we need to
       * have an array entry for it in pg_type as well.
       */
!     shadow_type = makeArrayTypeName(typeName);

      /* alignment must be 'i' or 'd' for arrays */
      alignment = (alignment == 'd') ? 'd' : 'i';

!     TypeCreate(shadow_type,        /* type name */
!                typeNamespace,    /* namespace */
!                InvalidOid,        /* relation oid (n/a here) */
!                0,                /* relation kind (ditto) */
!                -1,                /* internal size */
!                TYPTYPE_BASE,    /* type-type (base type) */
!                DEFAULT_TYPDELIM,    /* array element delimiter */
!                F_ARRAY_IN,        /* input procedure */
!                F_ARRAY_OUT,        /* output procedure */
!                F_ARRAY_RECV,    /* receive procedure */
!                F_ARRAY_SEND,    /* send procedure */
!                typmodinOid,        /* typmodin procedure */
!                typmodoutOid,    /* typmodout procedure */
!                InvalidOid,        /* analyze procedure - default */
!                typoid,            /* element type ID */
!                InvalidOid,        /* base type ID */
!                NULL,            /* never a default type value */
!                NULL,            /* binary default isn't sent either */
!                false,            /* never passed by value */
!                alignment,        /* see above */
!                'x',                /* ARRAY is always toastable */
!                -1,                /* typMod (Domains only) */
!                0,                /* Array dimensions of typbasetype */
!                false);            /* Type NOT NULL */

      pfree(shadow_type);
  }


--- 430,479 ----
                     storage,        /* TOAST strategy */
                     -1,            /* typMod (Domains only) */
                     0,            /* Array Dimensions of typbasetype */
!                    false,        /* Type NOT NULL */
!                    shadow_oid,  /* array type we are about to create */
!                    false        /* this is not an array type */
!             );

      /*
       * When we create a base type (as opposed to a complex type) we need to
       * have an array entry for it in pg_type as well.
       */
!     shadow_type = makeArrayTypeName(typeName, typeNamespace);

      /* alignment must be 'i' or 'd' for arrays */
      alignment = (alignment == 'd') ? 'd' : 'i';

!    TypeCreate(shadow_type,        /* type name */
!               typeNamespace,    /* namespace */
!               InvalidOid,        /* relation oid (n/a here) */
!               0,                /* relation kind (ditto) */
!               -1,                /* internal size */
!               TYPTYPE_BASE,    /* type-type (base type) */
!               DEFAULT_TYPDELIM,    /* array element delimiter */
!               F_ARRAY_IN,        /* input procedure */
!               F_ARRAY_OUT,        /* output procedure */
!               F_ARRAY_RECV,    /* receive procedure */
!               F_ARRAY_SEND,    /* send procedure */
!               typmodinOid,        /* typmodin procedure */
!               typmodoutOid,    /* typmodout procedure */
!               InvalidOid,        /* analyze procedure - default */
!               typoid,            /* element type ID */
!               InvalidOid,        /* base type ID */
!               NULL,            /* never a default type value */
!               NULL,            /* binary default isn't sent either */
!               false,            /* never passed by value */
!               alignment,        /* see above */
!               'x',                /* ARRAY is always toastable */
!               -1,                /* typMod (Domains only) */
!               0,                /* Array dimensions of typbasetype */
!               false,            /* Type NOT NULL */
!               shadow_oid,       /* oid for this entry */
!               true              /* yes this is an array type */
!        );

      pfree(shadow_type);
+
  }


***************
*** 474,479 ****
--- 488,494 ----
      Oid            typeoid;
      HeapTuple    tup;
      ObjectAddress object;
+     Form_pg_type typ;

      /* Make a TypeName so we can use standard type lookup machinery */
      typename = makeTypeNameFromNameList(names);
***************
*** 505,513 ****
      if (!HeapTupleIsValid(tup))
          elog(ERROR, "cache lookup failed for type %u", typeoid);

      /* Permission check: must own type or its namespace */
      if (!pg_type_ownercheck(typeoid, GetUserId()) &&
!       !pg_namespace_ownercheck(((Form_pg_type) GETSTRUCT(tup))->typnamespace,
                                 GetUserId()))
          aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TYPE,
                         TypeNameToString(typename));
--- 520,538 ----
      if (!HeapTupleIsValid(tup))
          elog(ERROR, "cache lookup failed for type %u", typeoid);

+     typ = (Form_pg_type) GETSTRUCT(tup);
+
+     /* don't alow direct deletion of array types */
+     if (typ->typelem != 0 && typ->typlen == -1)
+             ereport(ERROR,
+                     (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
+                      errmsg("cannot delete array type \"%s\" ",
+                             TypeNameToString(typename))));
+
+
      /* Permission check: must own type or its namespace */
      if (!pg_type_ownercheck(typeoid, GetUserId()) &&
!       !pg_namespace_ownercheck(typ->typnamespace,
                                 GetUserId()))
          aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TYPE,
                         TypeNameToString(typename));
***************
*** 545,551 ****
      simple_heap_delete(relation, &tup->t_self);

      /*
!      * If it is an enum, delete the pg_enum entries too; we don't bother
       * with making dependency entries for those, so it has to be done
       * "by hand" here.
       */
--- 570,576 ----
      simple_heap_delete(relation, &tup->t_self);

      /*
!      * If it is an enum delete the pg_enum entries too; we don't bother
       * with making dependency entries for those, so it has to be done
       * "by hand" here.
       */
***************
*** 828,835 ****
                     storage,        /* TOAST strategy */
                     basetypeMod, /* typeMod value */
                     typNDims,    /* Array dimensions for base type */
!                    typNotNull); /* Type NOT NULL */
!
      /*
       * Process constraints which refer to the domain ID returned by TypeCreate
       */
--- 853,862 ----
                     storage,        /* TOAST strategy */
                     basetypeMod, /* typeMod value */
                     typNDims,    /* Array dimensions for base type */
!                    typNotNull, /* Type NOT NULL */
!                    InvalidOid, /* no arrays for domains */
!                    false       /* this isn't an array */
!             );
      /*
       * Process constraints which refer to the domain ID returned by TypeCreate
       */
***************
*** 949,954 ****
--- 976,983 ----
      Oid        enumNamespace;
      Oid        enumTypeOid;
      AclResult    aclresult;
+     Oid     enumArrayOid;
+     Relation pg_type;

      /* Convert list of names to a name and namespace */
      enumNamespace = QualifiedNameGetCreationNamespace(stmt->typename,
***************
*** 970,975 ****
--- 999,1009 ----
                   errmsg("type names must be %d characters or less",
                          NAMEDATALEN - 2)));

+
+     pg_type = heap_open(TypeRelationId, RowExclusiveLock);
+     enumArrayOid = GetNewOid(pg_type);
+     heap_close(pg_type, RowExclusiveLock);
+
      /* Create the pg_type entry */
      enumTypeOid =
          TypeCreate(enumName,        /* type name */
***************
*** 995,1007 ****
                     'p',                /* TOAST strategy always plain */
                     -1,                /* typMod (Domains only) */
                     0,                /* Array dimensions of typbasetype */
!                    false);            /* Type NOT NULL */

      /* Enter the enum's values into pg_enum */
      EnumValuesCreate(enumTypeOid, stmt->vals);

      /* Create array type for enum */
!     enumArrayName = makeArrayTypeName(enumName);

      TypeCreate(enumArrayName,   /* type name */
                 enumNamespace,   /* namespace */
--- 1029,1044 ----
                     'p',                /* TOAST strategy always plain */
                     -1,                /* typMod (Domains only) */
                     0,                /* Array dimensions of typbasetype */
!                    false,            /* Type NOT NULL */
!                    enumArrayOid,    /* oid of entry we are about to create */
!                    false            /* this is not an array */
!             );

      /* Enter the enum's values into pg_enum */
      EnumValuesCreate(enumTypeOid, stmt->vals);

      /* Create array type for enum */
!     enumArrayName = makeArrayTypeName(enumName, enumNamespace);

      TypeCreate(enumArrayName,   /* type name */
                 enumNamespace,   /* namespace */
***************
*** 1026,1032 ****
                 'x',             /* ARRAY is always toastable */
                 -1,              /* typMod (Domains only) */
                 0,               /* Array dimensions of typbasetype */
!                false);          /* Type NOT NULL */

      pfree(enumArrayName);
  }
--- 1063,1072 ----
                 'x',             /* ARRAY is always toastable */
                 -1,              /* typMod (Domains only) */
                 0,               /* Array dimensions of typbasetype */
!                false,           /* Type NOT NULL */
!                enumArrayOid,    /* oid to use for this entry */
!                true             /* this is an array */
!         );

      pfree(enumArrayName);
  }
***************
*** 2249,2254 ****
--- 2289,2302 ----
          elog(ERROR, "cache lookup failed for type %u", typeOid);
      typTup = (Form_pg_type) GETSTRUCT(tup);

+     /* don't allow direct alteration of array types */
+     if (typTup->typelem != 0 && typTup->typlen == -1)
+             ereport(ERROR,
+                     (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
+                      errmsg("cannot alter array type \"%s\" ",
+                             TypeNameToString(typename))));
+
+
      /*
       * If it's a composite type, we need to check that it really is a
       * free-standing composite type, and not a table's underlying type. We
***************
*** 2352,2357 ****
--- 2400,2408 ----
      TypeName   *typename;
      Oid            typeOid;
      Oid            nspOid;
+     Relation    rel;
+     HeapTuple    tup;
+     Form_pg_type typ;

      /* Make a TypeName so we can use standard type lookup machinery */
      typename = makeTypeNameFromNameList(names);
***************
*** 2365,2372 ****
--- 2416,2449 ----
      /* get schema OID and check its permissions */
      nspOid = LookupCreationNamespace(newschema);

+     /* don't allow direct alteration of array types */
+
+     rel = heap_open(TypeRelationId, RowExclusiveLock);
+
+     tup = SearchSysCacheCopy(TYPEOID,
+                              ObjectIdGetDatum(typeOid),
+                              0, 0, 0);
+     if (!HeapTupleIsValid(tup))
+         elog(ERROR, "cache lookup failed for type %u", typeOid);
+
+     typ = (Form_pg_type) GETSTRUCT(tup);
+
+     if (typ->typelem != 0 && typ->typlen == -1)
+             ereport(ERROR,
+                     (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
+                      errmsg("cannot alter array type \"%s\" ",
+                             TypeNameToString(typename))));
+
+
+     heap_freetuple(tup);
+
+     heap_close(rel, RowExclusiveLock);
+
      /* and do the work */
      AlterTypeNamespaceInternal(typeOid, nspOid, true);
+     typeOid = get_array_type(typeOid);
+     if (typeOid != InvalidOid)
+         AlterTypeNamespaceInternal(typeOid, nspOid, true);
  }

  /*
***************
*** 2431,2442 ****

      /* Detect whether type is a composite type (but not a table rowtype) */
      isCompositeType =
!         (typform->typtype == TYPTYPE_COMPOSITE &&
           get_rel_relkind(typform->typrelid) == RELKIND_COMPOSITE_TYPE);

      /* Enforce not-table-type if requested */
      if (typform->typtype == TYPTYPE_COMPOSITE && !isCompositeType &&
!         errorOnTableType)
          ereport(ERROR,
                  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
                   errmsg("%s is a table's row type",
--- 2508,2519 ----

      /* Detect whether type is a composite type (but not a table rowtype) */
      isCompositeType =
!         (typform->typtype == TYPTYPE_COMPOSITE && typform->typrelid != InvalidOid &&
           get_rel_relkind(typform->typrelid) == RELKIND_COMPOSITE_TYPE);

      /* Enforce not-table-type if requested */
      if (typform->typtype == TYPTYPE_COMPOSITE && !isCompositeType &&
!         typform->typrelid != InvalidOid && errorOnTableType)
          ereport(ERROR,
                  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
                   errmsg("%s is a table's row type",
***************
*** 2457,2463 ****
       * We need to modify the pg_class tuple as well to reflect the change of
       * schema.
       */
!     if (isCompositeType)
      {
          Relation    classRel;

--- 2534,2540 ----
       * We need to modify the pg_class tuple as well to reflect the change of
       * schema.
       */
!     if (isCompositeType && typform->typrelid != InvalidOid)
      {
          Relation    classRel;

***************
*** 2490,2496 ****
           * Update dependency on schema, if any --- a table rowtype has not got
           * one.
           */
!         if (typform->typtype != TYPTYPE_COMPOSITE)
              if (changeDependencyFor(TypeRelationId, typeOid,
                                  NamespaceRelationId, oldNspOid, nspOid) != 1)
                  elog(ERROR, "failed to change schema dependency for type %s",
--- 2567,2573 ----
           * Update dependency on schema, if any --- a table rowtype has not got
           * one.
           */
!         if (typform->typtype != TYPTYPE_COMPOSITE || typform->typrelid == InvalidOid)
              if (changeDependencyFor(TypeRelationId, typeOid,
                                  NamespaceRelationId, oldNspOid, nspOid) != 1)
                  elog(ERROR, "failed to change schema dependency for type %s",
Index: src/backend/parser/parse_type.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/parser/parse_type.c,v
retrieving revision 1.89
diff -c -r1.89 parse_type.c
*** src/backend/parser/parse_type.c    27 Apr 2007 22:05:48 -0000    1.89
--- src/backend/parser/parse_type.c    9 May 2007 00:38:20 -0000
***************
*** 116,125 ****
          /* deconstruct the name list */
          DeconstructQualifiedName(typename->names, &schemaname, &typname);

-         /* If an array reference, look up the array type instead */
-         if (typename->arrayBounds != NIL)
-             typname = makeArrayTypeName(typname);
-
          if (schemaname)
          {
              /* Look in specific schema only */
--- 116,121 ----
***************
*** 136,141 ****
--- 132,142 ----
              /* Unqualified type name, so search the search path */
              restype = TypenameGetTypid(typname);
          }
+
+         /* If an array reference, return the array type instead */
+         if (typename->arrayBounds != NIL)
+             restype = get_array_type(restype);
+
      }

      return restype;
Index: src/backend/utils/cache/lsyscache.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v
retrieving revision 1.151
diff -c -r1.151 lsyscache.c
*** src/backend/utils/cache/lsyscache.c    2 Apr 2007 03:49:39 -0000    1.151
--- src/backend/utils/cache/lsyscache.c    9 May 2007 00:38:23 -0000
***************
*** 2206,2252 ****
   *        Given the type OID, get the corresponding array type.
   *        Returns InvalidOid if no array type can be found.
   *
-  * NB: this only considers varlena arrays to be true arrays.
   */
  Oid
  get_array_type(Oid typid)
  {
      HeapTuple    tp;

      tp = SearchSysCache(TYPEOID,
                          ObjectIdGetDatum(typid),
                          0, 0, 0);
      if (HeapTupleIsValid(tp))
      {
!         Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
!         char       *array_typename;
!         Oid            namespaceId;
!
!         array_typename = makeArrayTypeName(NameStr(typtup->typname));
!         namespaceId = typtup->typnamespace;
          ReleaseSysCache(tp);
-
-         tp = SearchSysCache(TYPENAMENSP,
-                             PointerGetDatum(array_typename),
-                             ObjectIdGetDatum(namespaceId),
-                             0, 0);
-
-         pfree(array_typename);
-
-         if (HeapTupleIsValid(tp))
-         {
-             Oid            result;
-
-             typtup = (Form_pg_type) GETSTRUCT(tp);
-             if (typtup->typlen == -1 && typtup->typelem == typid)
-                 result = HeapTupleGetOid(tp);
-             else
-                 result = InvalidOid;
-             ReleaseSysCache(tp);
-             return result;
-         }
      }
!     return InvalidOid;
  }

  /*
--- 2206,2227 ----
   *        Given the type OID, get the corresponding array type.
   *        Returns InvalidOid if no array type can be found.
   *
   */
  Oid
  get_array_type(Oid typid)
  {
      HeapTuple    tp;
+     Oid result = InvalidOid;

      tp = SearchSysCache(TYPEOID,
                          ObjectIdGetDatum(typid),
                          0, 0, 0);
      if (HeapTupleIsValid(tp))
      {
!         result = ((Form_pg_type) GETSTRUCT(tp))->typarray;
          ReleaseSysCache(tp);
      }
!     return result;
  }

  /*
Index: src/include/catalog/catversion.h
===================================================================
RCS file: /cvsroot/pgsql/src/include/catalog/catversion.h,v
retrieving revision 1.404
diff -c -r1.404 catversion.h
*** src/include/catalog/catversion.h    15 Apr 2007 10:56:27 -0000    1.404
--- src/include/catalog/catversion.h    9 May 2007 00:38:23 -0000
***************
*** 53,58 ****
   */

  /*                            yyyymmddN */
! #define CATALOG_VERSION_NO    200704151

  #endif
--- 53,58 ----
   */

  /*                            yyyymmddN */
! #define CATALOG_VERSION_NO    200705061

  #endif
Index: src/include/catalog/pg_attribute.h
===================================================================
RCS file: /cvsroot/pgsql/src/include/catalog/pg_attribute.h,v
retrieving revision 1.130
diff -c -r1.130 pg_attribute.h
*** src/include/catalog/pg_attribute.h    22 Jan 2007 01:35:21 -0000    1.130
--- src/include/catalog/pg_attribute.h    9 May 2007 00:38:23 -0000
***************
*** 232,252 ****
  { 1247, {"typdelim"},       18, -1,    1,    8, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
  { 1247, {"typrelid"},       26, -1,    4,    9, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
  { 1247, {"typelem"},       26, -1,    4, 10, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
! { 1247, {"typinput"},       24, -1,    4, 11, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
! { 1247, {"typoutput"},       24, -1,    4, 12, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
! { 1247, {"typreceive"},    24, -1,    4, 13, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
! { 1247, {"typsend"},       24, -1,    4, 14, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
! { 1247, {"typmodin"},       24, -1,    4, 15, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
! { 1247, {"typmodout"},       24, -1,    4, 16, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
! { 1247, {"typanalyze"},    24, -1,    4, 17, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
! { 1247, {"typalign"},       18, -1,    1, 18, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
! { 1247, {"typstorage"},    18, -1,    1, 19, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
! { 1247, {"typnotnull"},    16, -1,    1, 20, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
! { 1247, {"typbasetype"},   26, -1,    4, 21, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
! { 1247, {"typtypmod"},       23, -1,    4, 22, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
! { 1247, {"typndims"},       23, -1,    4, 23, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
! { 1247, {"typdefaultbin"}, 25, -1, -1, 24, 0, -1, -1, false, 'x', 'i', false, false, false, true, 0 }, \
! { 1247, {"typdefault"},    25, -1, -1, 25, 0, -1, -1, false, 'x', 'i', false, false, false, true, 0 }

  DATA(insert ( 1247 typname            19 -1 NAMEDATALEN    1 0 -1 -1 f p i t f f t 0));
  DATA(insert ( 1247 typnamespace        26 -1 4   2 0 -1 -1 t p i t f f t 0));
--- 232,253 ----
  { 1247, {"typdelim"},       18, -1,    1,    8, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
  { 1247, {"typrelid"},       26, -1,    4,    9, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
  { 1247, {"typelem"},       26, -1,    4, 10, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
! { 1247, {"typarray"},       26, -1,    4, 11, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
! { 1247, {"typinput"},       24, -1,    4, 12, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
! { 1247, {"typoutput"},       24, -1,    4, 13, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
! { 1247, {"typreceive"},    24, -1,    4, 14, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
! { 1247, {"typsend"},       24, -1,    4, 15, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
! { 1247, {"typmodin"},       24, -1,    4, 16, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
! { 1247, {"typmodout"},       24, -1,    4, 17, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
! { 1247, {"typanalyze"},    24, -1,    4, 18, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
! { 1247, {"typalign"},       18, -1,    1, 19, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
! { 1247, {"typstorage"},    18, -1,    1, 20, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
! { 1247, {"typnotnull"},    16, -1,    1, 21, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
! { 1247, {"typbasetype"},   26, -1,    4, 22, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
! { 1247, {"typtypmod"},       23, -1,    4, 23, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
! { 1247, {"typndims"},       23, -1,    4, 24, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
! { 1247, {"typdefaultbin"}, 25, -1, -1, 25, 0, -1, -1, false, 'x', 'i', false, false, false, true, 0 }, \
! { 1247, {"typdefault"},    25, -1, -1, 26, 0, -1, -1, false, 'x', 'i', false, false, false, true, 0 }

  DATA(insert ( 1247 typname            19 -1 NAMEDATALEN    1 0 -1 -1 f p i t f f t 0));
  DATA(insert ( 1247 typnamespace        26 -1 4   2 0 -1 -1 t p i t f f t 0));
***************
*** 258,278 ****
  DATA(insert ( 1247 typdelim            18 -1 1   8 0 -1 -1 t p c t f f t 0));
  DATA(insert ( 1247 typrelid            26 -1 4   9 0 -1 -1 t p i t f f t 0));
  DATA(insert ( 1247 typelem            26 -1 4  10 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1247 typinput            24 -1 4  11 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1247 typoutput        24 -1 4  12 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1247 typreceive        24 -1 4  13 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1247 typsend            24 -1 4  14 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1247 typmodin            24 -1 4  15 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1247 typmodout        24 -1 4  16 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1247 typanalyze        24 -1 4  17 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1247 typalign            18 -1 1  18 0 -1 -1 t p c t f f t 0));
! DATA(insert ( 1247 typstorage        18 -1 1  19 0 -1 -1 t p c t f f t 0));
! DATA(insert ( 1247 typnotnull        16 -1 1  20 0 -1 -1 t p c t f f t 0));
! DATA(insert ( 1247 typbasetype        26 -1 4  21 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1247 typtypmod        23 -1 4  22 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1247 typndims            23 -1 4  23 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1247 typdefaultbin    25 -1 -1 24 0 -1 -1 f x i f f f t 0));
! DATA(insert ( 1247 typdefault        25 -1 -1 25 0 -1 -1 f x i f f f t 0));
  DATA(insert ( 1247 ctid                27 0  6  -1 0 -1 -1 f p s t f f t 0));
  DATA(insert ( 1247 oid                26 0  4  -2 0 -1 -1 t p i t f f t 0));
  DATA(insert ( 1247 xmin                28 0  4  -3 0 -1 -1 t p i t f f t 0));
--- 259,280 ----
  DATA(insert ( 1247 typdelim            18 -1 1   8 0 -1 -1 t p c t f f t 0));
  DATA(insert ( 1247 typrelid            26 -1 4   9 0 -1 -1 t p i t f f t 0));
  DATA(insert ( 1247 typelem            26 -1 4  10 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1247 typarray            26 -1 4  11 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1247 typinput            24 -1 4  12 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1247 typoutput        24 -1 4  13 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1247 typreceive        24 -1 4  14 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1247 typsend            24 -1 4  15 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1247 typmodin            24 -1 4  16 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1247 typmodout        24 -1 4  17 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1247 typanalyze        24 -1 4  18 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1247 typalign            18 -1 1  19 0 -1 -1 t p c t f f t 0));
! DATA(insert ( 1247 typstorage        18 -1 1  20 0 -1 -1 t p c t f f t 0));
! DATA(insert ( 1247 typnotnull        16 -1 1  21 0 -1 -1 t p c t f f t 0));
! DATA(insert ( 1247 typbasetype        26 -1 4  22 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1247 typtypmod        23 -1 4  23 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1247 typndims            23 -1 4  24 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1247 typdefaultbin    25 -1 -1 25 0 -1 -1 f x i f f f t 0));
! DATA(insert ( 1247 typdefault        25 -1 -1 26 0 -1 -1 f x i f f f t 0));
  DATA(insert ( 1247 ctid                27 0  6  -1 0 -1 -1 f p s t f f t 0));
  DATA(insert ( 1247 oid                26 0  4  -2 0 -1 -1 t p i t f f t 0));
  DATA(insert ( 1247 xmin                28 0  4  -3 0 -1 -1 t p i t f f t 0));
Index: src/include/catalog/pg_class.h
===================================================================
RCS file: /cvsroot/pgsql/src/include/catalog/pg_class.h,v
retrieving revision 1.100
diff -c -r1.100 pg_class.h
*** src/include/catalog/pg_class.h    22 Jan 2007 01:35:22 -0000    1.100
--- src/include/catalog/pg_class.h    9 May 2007 00:38:24 -0000
***************
*** 132,138 ****
   */

  /* Note: "3" in the relfrozenxid column stands for FirstNormalTransactionId */
! DATA(insert OID = 1247 (  pg_type        PGNSP 71 PGUID 0 1247 0 0 0 0 0 f f r 25 0 0 0 0 0 t f f f 3   _null_ _null_
));
  DESCR("");
  DATA(insert OID = 1249 (  pg_attribute    PGNSP 75 PGUID 0 1249 0 0 0 0 0 f f r 17 0 0 0 0 0 f f f f 3 _null_ _null_
));
  DESCR("");
--- 132,138 ----
   */

  /* Note: "3" in the relfrozenxid column stands for FirstNormalTransactionId */
! DATA(insert OID = 1247 (  pg_type        PGNSP 71 PGUID 0 1247 0 0 0 0 0 f f r 26 0 0 0 0 0 t f f f 3   _null_ _null_
));
  DESCR("");
  DATA(insert OID = 1249 (  pg_attribute    PGNSP 75 PGUID 0 1249 0 0 0 0 0 f f r 17 0 0 0 0 0 f f f f 3 _null_ _null_
));
  DESCR("");
Index: src/include/catalog/pg_type.h
===================================================================
RCS file: /cvsroot/pgsql/src/include/catalog/pg_type.h,v
retrieving revision 1.182
diff -c -r1.182 pg_type.h
*** src/include/catalog/pg_type.h    6 Apr 2007 04:21:43 -0000    1.182
--- src/include/catalog/pg_type.h    9 May 2007 00:38:24 -0000
***************
*** 97,102 ****
--- 97,105 ----
       */
      Oid            typelem;

+     /* Oid of array type, or 0 if it does not exist */
+     Oid         typarray;
+
      /*
       * I/O conversion procedures for the datatype.
       */
***************
*** 214,220 ****
   *        compiler constants for pg_type
   * ----------------
   */
! #define Natts_pg_type                    25
  #define Anum_pg_type_typname            1
  #define Anum_pg_type_typnamespace        2
  #define Anum_pg_type_typowner            3
--- 217,223 ----
   *        compiler constants for pg_type
   * ----------------
   */
! #define Natts_pg_type                    26
  #define Anum_pg_type_typname            1
  #define Anum_pg_type_typnamespace        2
  #define Anum_pg_type_typowner            3
***************
*** 225,245 ****
  #define Anum_pg_type_typdelim            8
  #define Anum_pg_type_typrelid            9
  #define Anum_pg_type_typelem            10
! #define Anum_pg_type_typinput            11
! #define Anum_pg_type_typoutput            12
! #define Anum_pg_type_typreceive            13
! #define Anum_pg_type_typsend            14
! #define Anum_pg_type_typmodin            15
! #define Anum_pg_type_typmodout            16
! #define Anum_pg_type_typanalyze            17
! #define Anum_pg_type_typalign            18
! #define Anum_pg_type_typstorage            19
! #define Anum_pg_type_typnotnull            20
! #define Anum_pg_type_typbasetype        21
! #define Anum_pg_type_typtypmod            22
! #define Anum_pg_type_typndims            23
! #define Anum_pg_type_typdefaultbin        24
! #define Anum_pg_type_typdefault            25


  /* ----------------
--- 228,249 ----
  #define Anum_pg_type_typdelim            8
  #define Anum_pg_type_typrelid            9
  #define Anum_pg_type_typelem            10
! #define Anum_pg_type_typarray            11
! #define Anum_pg_type_typinput            12
! #define Anum_pg_type_typoutput            13
! #define Anum_pg_type_typreceive            14
! #define Anum_pg_type_typsend            15
! #define Anum_pg_type_typmodin            16
! #define Anum_pg_type_typmodout            17
! #define Anum_pg_type_typanalyze            18
! #define Anum_pg_type_typalign            19
! #define Anum_pg_type_typstorage            20
! #define Anum_pg_type_typnotnull            21
! #define Anum_pg_type_typbasetype        22
! #define Anum_pg_type_typtypmod            23
! #define Anum_pg_type_typndims            24
! #define Anum_pg_type_typdefaultbin        25
! #define Anum_pg_type_typdefault            26


  /* ----------------
***************
*** 255,340 ****
  */

  /* OIDS 1 - 99 */
! DATA(insert OID = 16 (    bool       PGNSP PGUID    1 t b t \054 0     0 boolin boolout boolrecv boolsend - - - c p f
0-1 0 _null_ _null_ )); 
  DESCR("boolean, 'true'/'false'");
  #define BOOLOID            16

! DATA(insert OID = 17 (    bytea       PGNSP PGUID -1 f b t \054 0    0 byteain byteaout bytearecv byteasend - - - i x
f0 -1 0 _null_ _null_ )); 
  DESCR("variable-length string, binary values escaped");
  #define BYTEAOID        17

! DATA(insert OID = 18 (    char       PGNSP PGUID    1 t b t \054 0     0 charin charout charrecv charsend - - - c p f
0-1 0 _null_ _null_ )); 
  DESCR("single character");
  #define CHAROID            18

! DATA(insert OID = 19 (    name       PGNSP PGUID NAMEDATALEN f b t \054 0 18 namein nameout namerecv namesend - - - i
pf 0 -1 0 _null_ _null_ )); 
  DESCR("63-character type for storing system identifiers");
  #define NAMEOID            19

! DATA(insert OID = 20 (    int8       PGNSP PGUID    8 f b t \054 0     0 int8in int8out int8recv int8send - - - d p f
0-1 0 _null_ _null_ )); 
  DESCR("~18 digit integer, 8-byte storage");
  #define INT8OID            20

! DATA(insert OID = 21 (    int2       PGNSP PGUID    2 t b t \054 0     0 int2in int2out int2recv int2send - - - s p f
0-1 0 _null_ _null_ )); 
  DESCR("-32 thousand to 32 thousand, 2-byte storage");
  #define INT2OID            21

! DATA(insert OID = 22 (    int2vector PGNSP PGUID -1 f b t \054 0    21 int2vectorin int2vectorout int2vectorrecv
int2vectorsend- - - i p f 0 -1 0 _null_ _null_ )); 
  DESCR("array of int2, used in system tables");
  #define INT2VECTOROID    22

! DATA(insert OID = 23 (    int4       PGNSP PGUID    4 t b t \054 0     0 int4in int4out int4recv int4send - - - i p f
0-1 0 _null_ _null_ )); 
  DESCR("-2 billion to 2 billion integer, 4-byte storage");
  #define INT4OID            23

! DATA(insert OID = 24 (    regproc    PGNSP PGUID    4 t b t \054 0     0 regprocin regprocout regprocrecv regprocsend
-- - i p f 0 -1 0 _null_ _null_ )); 
  DESCR("registered procedure");
  #define REGPROCOID        24

! DATA(insert OID = 25 (    text       PGNSP PGUID -1 f b t \054 0    0 textin textout textrecv textsend - - - i x f 0
-10 _null_ _null_ )); 
  DESCR("variable-length string, no limit specified");
  #define TEXTOID            25

! DATA(insert OID = 26 (    oid           PGNSP PGUID    4 t b t \054 0     0 oidin oidout oidrecv oidsend - - - i p f
0-1 0 _null_ _null_ )); 
  DESCR("object identifier(oid), maximum 4 billion");
  #define OIDOID            26

! DATA(insert OID = 27 (    tid           PGNSP PGUID    6 f b t \054 0     0 tidin tidout tidrecv tidsend - - - s p f
0-1 0 _null_ _null_ )); 
  DESCR("(Block, offset), physical location of tuple");
  #define TIDOID        27

! DATA(insert OID = 28 (    xid           PGNSP PGUID    4 t b t \054 0     0 xidin xidout xidrecv xidsend - - - i p f
0-1 0 _null_ _null_ )); 
  DESCR("transaction id");
  #define XIDOID 28

! DATA(insert OID = 29 (    cid           PGNSP PGUID    4 t b t \054 0     0 cidin cidout cidrecv cidsend - - - i p f
0-1 0 _null_ _null_ )); 
  DESCR("command identifier type, sequence in transaction id");
  #define CIDOID 29

! DATA(insert OID = 30 (    oidvector  PGNSP PGUID -1 f b t \054 0    26 oidvectorin oidvectorout oidvectorrecv
oidvectorsend- - - i p f 0 -1 0 _null_ _null_ )); 
  DESCR("array of oids, used in system tables");
  #define OIDVECTOROID    30

  /* hand-built rowtype entries for bootstrapped catalogs: */

! DATA(insert OID = 71 (    pg_type            PGNSP PGUID -1 f c t \054 1247 0 record_in record_out record_recv
record_send- - - d x f 0 -1 0 _null_ _null_ )); 
  #define PG_TYPE_RELTYPE_OID 71
! DATA(insert OID = 75 (    pg_attribute    PGNSP PGUID -1 f c t \054 1249 0 record_in record_out record_recv
record_send- - - d x f 0 -1 0 _null_ _null_ )); 
  #define PG_ATTRIBUTE_RELTYPE_OID 75
! DATA(insert OID = 81 (    pg_proc            PGNSP PGUID -1 f c t \054 1255 0 record_in record_out record_recv
record_send- - - d x f 0 -1 0 _null_ _null_ )); 
  #define PG_PROC_RELTYPE_OID 81
! DATA(insert OID = 83 (    pg_class        PGNSP PGUID -1 f c t \054 1259 0 record_in record_out record_recv
record_send- - - d x f 0 -1 0 _null_ _null_ )); 
  #define PG_CLASS_RELTYPE_OID 83

  /* OIDS 100 - 199 */
! DATA(insert OID = 142 ( xml           PGNSP PGUID -1 f b t \054 0 0 xml_in xml_out xml_recv xml_send - - - i x f 0 -1
0_null_ _null_ )); 
  DESCR("XML content");
  #define XMLOID 142
! DATA(insert OID = 143 ( _xml       PGNSP PGUID -1 f b t \054 0 142 array_in array_out array_recv array_send - - - i x
f0 -1 0 _null_ _null_ )); 

  /* OIDS 200 - 299 */

! DATA(insert OID = 210 (  smgr       PGNSP PGUID 2 t b t \054 0 0 smgrin smgrout - - - - - s p f 0 -1 0 _null_ _null_
));
  DESCR("storage manager");

  /* OIDS 300 - 399 */
--- 259,344 ----
  */

  /* OIDS 1 - 99 */
! DATA(insert OID = 16 (    bool       PGNSP PGUID    1 t b t \054 0     0 1000 boolin boolout boolrecv boolsend - - -
cp f 0 -1 0 _null_ _null_ )); 
  DESCR("boolean, 'true'/'false'");
  #define BOOLOID            16

! DATA(insert OID = 17 (    bytea       PGNSP PGUID -1 f b t \054 0    0 1001 byteain byteaout bytearecv byteasend - -
-i x f 0 -1 0 _null_ _null_ )); 
  DESCR("variable-length string, binary values escaped");
  #define BYTEAOID        17

! DATA(insert OID = 18 (    char       PGNSP PGUID    1 t b t \054 0     0 1002 charin charout charrecv charsend - - -
cp f 0 -1 0 _null_ _null_ )); 
  DESCR("single character");
  #define CHAROID            18

! DATA(insert OID = 19 (    name       PGNSP PGUID NAMEDATALEN f b t \054 0 18 1003 namein nameout namerecv namesend -
-- i p f 0 -1 0 _null_ _null_ )); 
  DESCR("63-character type for storing system identifiers");
  #define NAMEOID            19

! DATA(insert OID = 20 (    int8       PGNSP PGUID    8 f b t \054 0     0 1016 int8in int8out int8recv int8send - - -
dp f 0 -1 0 _null_ _null_ )); 
  DESCR("~18 digit integer, 8-byte storage");
  #define INT8OID            20

! DATA(insert OID = 21 (    int2       PGNSP PGUID    2 t b t \054 0     0 1005 int2in int2out int2recv int2send - - -
sp f 0 -1 0 _null_ _null_ )); 
  DESCR("-32 thousand to 32 thousand, 2-byte storage");
  #define INT2OID            21

! DATA(insert OID = 22 (    int2vector PGNSP PGUID -1 f b t \054 0    21 1006 int2vectorin int2vectorout int2vectorrecv
int2vectorsend- - - i p f 0 -1 0 _null_ _null_ )); 
  DESCR("array of int2, used in system tables");
  #define INT2VECTOROID    22

! DATA(insert OID = 23 (    int4       PGNSP PGUID    4 t b t \054 0     0 1007 int4in int4out int4recv int4send - - -
ip f 0 -1 0 _null_ _null_ )); 
  DESCR("-2 billion to 2 billion integer, 4-byte storage");
  #define INT4OID            23

! DATA(insert OID = 24 (    regproc    PGNSP PGUID    4 t b t \054 0     0 1008 regprocin regprocout regprocrecv
regprocsend- - - i p f 0 -1 0 _null_ _null_ )); 
  DESCR("registered procedure");
  #define REGPROCOID        24

! DATA(insert OID = 25 (    text       PGNSP PGUID -1 f b t \054 0    0 1009 textin textout textrecv textsend - - - i x
f0 -1 0 _null_ _null_ )); 
  DESCR("variable-length string, no limit specified");
  #define TEXTOID            25

! DATA(insert OID = 26 (    oid           PGNSP PGUID    4 t b t \054 0     0 1028 oidin oidout oidrecv oidsend - - - i
pf 0 -1 0 _null_ _null_ )); 
  DESCR("object identifier(oid), maximum 4 billion");
  #define OIDOID            26

! DATA(insert OID = 27 (    tid           PGNSP PGUID    6 f b t \054 0     0 1010 tidin tidout tidrecv tidsend - - - s
pf 0 -1 0 _null_ _null_ )); 
  DESCR("(Block, offset), physical location of tuple");
  #define TIDOID        27

! DATA(insert OID = 28 (    xid           PGNSP PGUID    4 t b t \054 0     0 1011 xidin xidout xidrecv xidsend - - - i
pf 0 -1 0 _null_ _null_ )); 
  DESCR("transaction id");
  #define XIDOID 28

! DATA(insert OID = 29 (    cid           PGNSP PGUID    4 t b t \054 0     0 1012 cidin cidout cidrecv cidsend - - - i
pf 0 -1 0 _null_ _null_ )); 
  DESCR("command identifier type, sequence in transaction id");
  #define CIDOID 29

! DATA(insert OID = 30 (    oidvector  PGNSP PGUID -1 f b t \054 0    26 1013 oidvectorin oidvectorout oidvectorrecv
oidvectorsend- - - i p f 0 -1 0 _null_ _null_ )); 
  DESCR("array of oids, used in system tables");
  #define OIDVECTOROID    30

  /* hand-built rowtype entries for bootstrapped catalogs: */

! DATA(insert OID = 71 (    pg_type            PGNSP PGUID -1 f c t \054 1247 0 0 record_in record_out record_recv
record_send- - - d x f 0 -1 0 _null_ _null_ )); 
  #define PG_TYPE_RELTYPE_OID 71
! DATA(insert OID = 75 (    pg_attribute    PGNSP PGUID -1 f c t \054 1249 0 0 record_in record_out record_recv
record_send- - - d x f 0 -1 0 _null_ _null_ )); 
  #define PG_ATTRIBUTE_RELTYPE_OID 75
! DATA(insert OID = 81 (    pg_proc            PGNSP PGUID -1 f c t \054 1255 0 0 record_in record_out record_recv
record_send- - - d x f 0 -1 0 _null_ _null_ )); 
  #define PG_PROC_RELTYPE_OID 81
! DATA(insert OID = 83 (    pg_class        PGNSP PGUID -1 f c t \054 1259 0 0 record_in record_out record_recv
record_send- - - d x f 0 -1 0 _null_ _null_ )); 
  #define PG_CLASS_RELTYPE_OID 83

  /* OIDS 100 - 199 */
! DATA(insert OID = 142 ( xml           PGNSP PGUID -1 f b t \054 0 0 143 xml_in xml_out xml_recv xml_send - - - i x f
0-1 0 _null_ _null_ )); 
  DESCR("XML content");
  #define XMLOID 142
! DATA(insert OID = 143 ( _xml       PGNSP PGUID -1 f b t \054 0 142 0 array_in array_out array_recv array_send - - - i
xf 0 -1 0 _null_ _null_ )); 

  /* OIDS 200 - 299 */

! DATA(insert OID = 210 (  smgr       PGNSP PGUID 2 t b t \054 0 0 0 smgrin smgrout - - - - - s p f 0 -1 0 _null_
_null_)); 
  DESCR("storage manager");

  /* OIDS 300 - 399 */
***************
*** 344,543 ****
  /* OIDS 500 - 599 */

  /* OIDS 600 - 699 */
! DATA(insert OID = 600 (  point       PGNSP PGUID 16 f b t \054 0 701 point_in point_out point_recv point_send - - - d
pf 0 -1 0 _null_ _null_ )); 
  DESCR("geometric point '(x, y)'");
  #define POINTOID        600
! DATA(insert OID = 601 (  lseg       PGNSP PGUID 32 f b t \054 0 600 lseg_in lseg_out lseg_recv lseg_send - - - d p f
0-1 0 _null_ _null_ )); 
  DESCR("geometric line segment '(pt1,pt2)'");
  #define LSEGOID            601
! DATA(insert OID = 602 (  path       PGNSP PGUID -1 f b t \054 0 0 path_in path_out path_recv path_send - - - d x f 0
-10 _null_ _null_ )); 
  DESCR("geometric path '(pt1,...)'");
  #define PATHOID            602
! DATA(insert OID = 603 (  box       PGNSP PGUID 32 f b t \073 0 600 box_in box_out box_recv box_send - - - d p f 0 -1
0_null_ _null_ )); 
  DESCR("geometric box '(lower left,upper right)'");
  #define BOXOID            603
! DATA(insert OID = 604 (  polygon   PGNSP PGUID -1 f b t \054 0     0 poly_in poly_out poly_recv poly_send - - - d x f
0-1 0 _null_ _null_ )); 
  DESCR("geometric polygon '(pt1,...)'");
  #define POLYGONOID        604

! DATA(insert OID = 628 (  line       PGNSP PGUID 32 f b t \054 0 701 line_in line_out line_recv line_send - - - d p f
0-1 0 _null_ _null_ )); 
  DESCR("geometric line (not implemented)'");
  #define LINEOID            628
! DATA(insert OID = 629 (  _line       PGNSP PGUID    -1 f b t \054 0 628 array_in array_out array_recv array_send - -
-d x f 0 -1 0 _null_ _null_ )); 
  DESCR("");

  /* OIDS 700 - 799 */

! DATA(insert OID = 700 (  float4    PGNSP PGUID    4 f b t \054 0     0 float4in float4out float4recv float4send - - -
ip f 0 -1 0 _null_ _null_ )); 
  DESCR("single-precision floating point number, 4-byte storage");
  #define FLOAT4OID 700
! DATA(insert OID = 701 (  float8    PGNSP PGUID    8 f b t \054 0     0 float8in float8out float8recv float8send - - -
dp f 0 -1 0 _null_ _null_ )); 
  DESCR("double-precision floating point number, 8-byte storage");
  #define FLOAT8OID 701
! DATA(insert OID = 702 (  abstime   PGNSP PGUID    4 t b t \054 0     0 abstimein abstimeout abstimerecv abstimesend -
-- i p f 0 -1 0 _null_ _null_ )); 
  DESCR("absolute, limited-range date and time (Unix system time)");
  #define ABSTIMEOID        702
! DATA(insert OID = 703 (  reltime   PGNSP PGUID    4 t b t \054 0     0 reltimein reltimeout reltimerecv reltimesend -
-- i p f 0 -1 0 _null_ _null_ )); 
  DESCR("relative, limited-range time interval (Unix delta time)");
  #define RELTIMEOID        703
! DATA(insert OID = 704 (  tinterval PGNSP PGUID 12 f b t \054 0     0 tintervalin tintervalout tintervalrecv
tintervalsend- - - i p f 0 -1 0 _null_ _null_ )); 
  DESCR("(abstime,abstime), time interval");
  #define TINTERVALOID    704
! DATA(insert OID = 705 (  unknown   PGNSP PGUID -2 f b t \054 0     0 unknownin unknownout unknownrecv unknownsend - -
-c p f 0 -1 0 _null_ _null_ )); 
  DESCR("");
  #define UNKNOWNOID        705

! DATA(insert OID = 718 (  circle    PGNSP PGUID    24 f b t \054 0 0 circle_in circle_out circle_recv circle_send - -
-d p f 0 -1 0 _null_ _null_ )); 
  DESCR("geometric circle '(center,radius)'");
  #define CIRCLEOID        718
! DATA(insert OID = 719 (  _circle   PGNSP PGUID    -1 f b t \054 0  718 array_in array_out array_recv array_send - - -
dx f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 790 (  money       PGNSP PGUID     8 f b t \054 0 0 cash_in cash_out cash_recv cash_send - - - d p
f0 -1 0 _null_ _null_ )); 
  DESCR("monetary amounts, $d,ddd.cc");
  #define CASHOID 790
! DATA(insert OID = 791 (  _money    PGNSP PGUID    -1 f b t \054 0  790 array_in array_out array_recv array_send - - -
dx f 0 -1 0 _null_ _null_ )); 

  /* OIDS 800 - 899 */
! DATA(insert OID = 829 ( macaddr    PGNSP PGUID    6 f b t \054 0 0 macaddr_in macaddr_out macaddr_recv macaddr_send -
-- i p f 0 -1 0 _null_ _null_ )); 
  DESCR("XX:XX:XX:XX:XX:XX, MAC address");
  #define MACADDROID 829
! DATA(insert OID = 869 ( inet       PGNSP PGUID    -1 f b t \054 0 0 inet_in inet_out inet_recv inet_send - - - i m f
0-1 0 _null_ _null_ )); 
  DESCR("IP address/netmask, host address, netmask optional");
  #define INETOID 869
! DATA(insert OID = 650 ( cidr       PGNSP PGUID    -1 f b t \054 0 0 cidr_in cidr_out cidr_recv cidr_send - - - i m f
0-1 0 _null_ _null_ )); 
  DESCR("network IP address/netmask, network address");
  #define CIDROID 650

  /* OIDS 900 - 999 */

  /* OIDS 1000 - 1099 */
! DATA(insert OID = 1000 (  _bool         PGNSP PGUID -1 f b t \054 0    16 array_in array_out array_recv array_send -
-- i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1001 (  _bytea     PGNSP PGUID -1 f b t \054 0    17 array_in array_out array_recv array_send - - -
ix f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1002 (  _char         PGNSP PGUID -1 f b t \054 0    18 array_in array_out array_recv array_send -
-- i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1003 (  _name         PGNSP PGUID -1 f b t \054 0    19 array_in array_out array_recv array_send -
-- i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1005 (  _int2         PGNSP PGUID -1 f b t \054 0    21 array_in array_out array_recv array_send -
-- i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1006 (  _int2vector PGNSP PGUID -1 f b t \054 0    22 array_in array_out array_recv array_send - -
-i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1007 (  _int4         PGNSP PGUID -1 f b t \054 0    23 array_in array_out array_recv array_send -
-- i x f 0 -1 0 _null_ _null_ )); 
  #define INT4ARRAYOID        1007
! DATA(insert OID = 1008 (  _regproc     PGNSP PGUID -1 f b t \054 0    24 array_in array_out array_recv array_send - -
-i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1009 (  _text         PGNSP PGUID -1 f b t \054 0    25 array_in array_out array_recv array_send -
-- i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1028 (  _oid         PGNSP PGUID -1 f b t \054 0    26 array_in array_out array_recv array_send - -
-i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1010 (  _tid         PGNSP PGUID -1 f b t \054 0    27 array_in array_out array_recv array_send - -
-i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1011 (  _xid         PGNSP PGUID -1 f b t \054 0    28 array_in array_out array_recv array_send - -
-i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1012 (  _cid         PGNSP PGUID -1 f b t \054 0    29 array_in array_out array_recv array_send - -
-i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1013 (  _oidvector PGNSP PGUID -1 f b t \054 0    30 array_in array_out array_recv array_send - - -
ix f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1014 (  _bpchar     PGNSP PGUID -1 f b t \054 0 1042 array_in array_out array_recv array_send
bpchartypmodinbpchartypmodout - i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1015 (  _varchar     PGNSP PGUID -1 f b t \054 0 1043 array_in array_out array_recv array_send
varchartypmodinvarchartypmodout - i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1016 (  _int8         PGNSP PGUID -1 f b t \054 0    20 array_in array_out array_recv array_send -
-- d x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1017 (  _point     PGNSP PGUID -1 f b t \054 0 600 array_in array_out array_recv array_send - - - d
xf 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1018 (  _lseg         PGNSP PGUID -1 f b t \054 0 601 array_in array_out array_recv array_send - -
-d x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1019 (  _path         PGNSP PGUID -1 f b t \054 0 602 array_in array_out array_recv array_send - -
-d x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1020 (  _box         PGNSP PGUID -1 f b t \073 0 603 array_in array_out array_recv array_send - - -
dx f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1021 (  _float4     PGNSP PGUID -1 f b t \054 0 700 array_in array_out array_recv array_send - - -
ix f 0 -1 0 _null_ _null_ )); 
  #define FLOAT4ARRAYOID 1021
! DATA(insert OID = 1022 (  _float8     PGNSP PGUID -1 f b t \054 0 701 array_in array_out array_recv array_send - - -
dx f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1023 (  _abstime     PGNSP PGUID -1 f b t \054 0 702 array_in array_out array_recv array_send - - -
ix f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1024 (  _reltime     PGNSP PGUID -1 f b t \054 0 703 array_in array_out array_recv array_send - - -
ix f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1025 (  _tinterval PGNSP PGUID -1 f b t \054 0 704 array_in array_out array_recv array_send - - - i
xf 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1027 (  _polygon     PGNSP PGUID -1 f b t \054 0 604 array_in array_out array_recv array_send - - -
dx f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1033 (  aclitem     PGNSP PGUID 12 f b t \054 0 0 aclitemin aclitemout - - - - - i p f 0 -1 0
_null__null_ )); 
  DESCR("access control list");
  #define ACLITEMOID        1033
! DATA(insert OID = 1034 (  _aclitem     PGNSP PGUID -1 f b t \054 0 1033 array_in array_out array_recv array_send - -
-i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1040 (  _macaddr     PGNSP PGUID -1 f b t \054 0  829 array_in array_out array_recv array_send - -
-i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1041 (  _inet    PGNSP PGUID -1 f b t \054 0    869 array_in array_out array_recv array_send - - -
ix f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 651  (  _cidr    PGNSP PGUID -1 f b t \054 0    650 array_in array_out array_recv array_send - - -
ix f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1042 ( bpchar         PGNSP PGUID -1 f b t \054 0    0 bpcharin bpcharout bpcharrecv bpcharsend
bpchartypmodinbpchartypmodout - i x f 0 -1 0 _null_ _null_ )); 
  DESCR("char(length), blank-padded string, fixed storage length");
  #define BPCHAROID        1042
! DATA(insert OID = 1043 ( varchar     PGNSP PGUID -1 f b t \054 0    0 varcharin varcharout varcharrecv varcharsend
varchartypmodinvarchartypmodout - i x f 0 -1 0 _null_ _null_ )); 
  DESCR("varchar(length), non-blank-padded string, variable storage length");
  #define VARCHAROID        1043

! DATA(insert OID = 1082 ( date         PGNSP PGUID    4 t b t \054 0    0 date_in date_out date_recv date_send - - - i
pf 0 -1 0 _null_ _null_ )); 
  DESCR("ANSI SQL date");
  #define DATEOID            1082
! DATA(insert OID = 1083 ( time         PGNSP PGUID    8 f b t \054 0    0 time_in time_out time_recv time_send
timetypmodintimetypmodout - d p f 0 -1 0 _null_ _null_ )); 
  DESCR("hh:mm:ss, ANSI SQL time");
  #define TIMEOID            1083

  /* OIDS 1100 - 1199 */
! DATA(insert OID = 1114 ( timestamp     PGNSP PGUID    8 f b t \054 0    0 timestamp_in timestamp_out timestamp_recv
timestamp_sendtimestamptypmodin timestamptypmodout - d p f 0 -1 0 _null_ _null_ )); 
  DESCR("date and time");
  #define TIMESTAMPOID    1114
! DATA(insert OID = 1115 ( _timestamp  PGNSP PGUID    -1 f b t \054 0 1114 array_in array_out array_recv array_send
timestamptypmodintimestamptypmodout - d x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1182 ( _date         PGNSP PGUID    -1 f b t \054 0 1082 array_in array_out array_recv array_send -
-- i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1183 ( _time         PGNSP PGUID    -1 f b t \054 0 1083 array_in array_out array_recv array_send
timetypmodintimetypmodout - d x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1184 ( timestamptz PGNSP PGUID    8 f b t \054 0    0 timestamptz_in timestamptz_out
timestamptz_recvtimestamptz_send timestamptztypmodin timestamptztypmodout - d p f 0 -1 0 _null_ _null_ )); 
  DESCR("date and time with time zone");
  #define TIMESTAMPTZOID    1184
! DATA(insert OID = 1185 ( _timestamptz PGNSP PGUID -1 f b t \054 0    1184 array_in array_out array_recv array_send
timestamptztypmodintimestamptztypmodout - d x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1186 ( interval     PGNSP PGUID 16 f b t \054 0    0 interval_in interval_out interval_recv
interval_sendintervaltypmodin intervaltypmodout - d p f 0 -1 0 _null_ _null_ )); 
  DESCR("@ <number> <units>, time interval");
  #define INTERVALOID        1186
! DATA(insert OID = 1187 ( _interval     PGNSP PGUID    -1 f b t \054 0 1186 array_in array_out array_recv array_send
intervaltypmodinintervaltypmodout - d x f 0 -1 0 _null_ _null_ )); 

  /* OIDS 1200 - 1299 */
! DATA(insert OID = 1231 (  _numeric     PGNSP PGUID -1 f b t \054 0    1700 array_in array_out array_recv array_send
numerictypmodinnumerictypmodout - i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1266 ( timetz         PGNSP PGUID 12 f b t \054 0    0 timetz_in timetz_out timetz_recv timetz_send
timetztypmodintimetztypmodout - d p f 0 -1 0 _null_ _null_ )); 
  DESCR("hh:mm:ss, ANSI SQL time");
  #define TIMETZOID        1266
! DATA(insert OID = 1270 ( _timetz     PGNSP PGUID -1 f b t \054 0    1266 array_in array_out array_recv array_send
timetztypmodintimetztypmodout - d x f 0 -1 0 _null_ _null_ )); 

  /* OIDS 1500 - 1599 */
! DATA(insert OID = 1560 ( bit         PGNSP PGUID -1 f b t \054 0    0 bit_in bit_out bit_recv bit_send bittypmodin
bittypmodout- i x f 0 -1 0 _null_ _null_ )); 
  DESCR("fixed-length bit string");
  #define BITOID     1560
! DATA(insert OID = 1561 ( _bit         PGNSP PGUID -1 f b t \054 0    1560 array_in array_out array_recv array_send
bittypmodinbittypmodout - i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1562 ( varbit         PGNSP PGUID -1 f b t \054 0    0 varbit_in varbit_out varbit_recv varbit_send
varbittypmodinvarbittypmodout - i x f 0 -1 0 _null_ _null_ )); 
  DESCR("variable-length bit string");
  #define VARBITOID      1562
! DATA(insert OID = 1563 ( _varbit     PGNSP PGUID -1 f b t \054 0    1562 array_in array_out array_recv array_send
varbittypmodinvarbittypmodout - i x f 0 -1 0 _null_ _null_ )); 

  /* OIDS 1600 - 1699 */

  /* OIDS 1700 - 1799 */
! DATA(insert OID = 1700 ( numeric       PGNSP PGUID -1 f b t \054 0    0 numeric_in numeric_out numeric_recv
numeric_sendnumerictypmodin numerictypmodout - i m f 0 -1 0 _null_ _null_ )); 
  DESCR("numeric(precision, decimal), arbitrary precision number");
  #define NUMERICOID        1700

! DATA(insert OID = 1790 ( refcursor       PGNSP PGUID -1 f b t \054 0    0 textin textout textrecv textsend - - - i x
f0 -1 0 _null_ _null_ )); 
  DESCR("reference cursor (portal name)");
  #define REFCURSOROID    1790

  /* OIDS 2200 - 2299 */
! DATA(insert OID = 2201 ( _refcursor    PGNSP PGUID -1 f b t \054 0 1790 array_in array_out array_recv array_send - -
-i x f 0 -1 0 _null_ _null_ )); 

! DATA(insert OID = 2202 ( regprocedure  PGNSP PGUID    4 t b t \054 0     0 regprocedurein regprocedureout
regprocedurerecvregproceduresend - - - i p f 0 -1 0 _null_ _null_ )); 
  DESCR("registered procedure (with args)");
  #define REGPROCEDUREOID 2202

! DATA(insert OID = 2203 ( regoper       PGNSP PGUID    4 t b t \054 0     0 regoperin regoperout regoperrecv
regopersend- - - i p f 0 -1 0 _null_ _null_ )); 
  DESCR("registered operator");
  #define REGOPEROID        2203

! DATA(insert OID = 2204 ( regoperator   PGNSP PGUID    4 t b t \054 0     0 regoperatorin regoperatorout
regoperatorrecvregoperatorsend - - - i p f 0 -1 0 _null_ _null_ )); 
  DESCR("registered operator (with args)");
  #define REGOPERATOROID    2204

! DATA(insert OID = 2205 ( regclass       PGNSP PGUID    4 t b t \054 0     0 regclassin regclassout regclassrecv
regclasssend- - - i p f 0 -1 0 _null_ _null_ )); 
  DESCR("registered class");
  #define REGCLASSOID        2205

! DATA(insert OID = 2206 ( regtype       PGNSP PGUID    4 t b t \054 0     0 regtypein regtypeout regtyperecv
regtypesend- - - i p f 0 -1 0 _null_ _null_ )); 
  DESCR("registered type");
  #define REGTYPEOID        2206

! DATA(insert OID = 2207 ( _regprocedure PGNSP PGUID -1 f b t \054 0 2202 array_in array_out array_recv array_send - -
-i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 2208 ( _regoper       PGNSP PGUID -1 f b t \054 0 2203 array_in array_out array_recv array_send - -
-i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 2209 ( _regoperator  PGNSP PGUID -1 f b t \054 0 2204 array_in array_out array_recv array_send - -
-i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 2210 ( _regclass       PGNSP PGUID -1 f b t \054 0 2205 array_in array_out array_recv array_send -
-- i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 2211 ( _regtype       PGNSP PGUID -1 f b t \054 0 2206 array_in array_out array_recv array_send - -
-i x f 0 -1 0 _null_ _null_ )); 
  #define REGTYPEARRAYOID 2211

  /* uuid */
! DATA(insert OID = 2950 ( uuid            PGNSP PGUID 16 f b t \054 0 0 uuid_in uuid_out uuid_recv uuid_send - - - c p
f0 -1 0 _null_ _null_ )); 
  DESCR("UUID datatype");
! DATA(insert OID = 2951 ( _uuid            PGNSP PGUID -1 f b t \054 0 2950 array_in array_out array_recv array_send -
-- i x f 0 -1 0 _null_ _null_ )); 

  /*
   * pseudo-types
--- 348,547 ----
  /* OIDS 500 - 599 */

  /* OIDS 600 - 699 */
! DATA(insert OID = 600 (  point       PGNSP PGUID 16 f b t \054 0 701 1017 point_in point_out point_recv point_send -
-- d p f 0 -1 0 _null_ _null_ )); 
  DESCR("geometric point '(x, y)'");
  #define POINTOID        600
! DATA(insert OID = 601 (  lseg       PGNSP PGUID 32 f b t \054 0 600 1018 lseg_in lseg_out lseg_recv lseg_send - - - d
pf 0 -1 0 _null_ _null_ )); 
  DESCR("geometric line segment '(pt1,pt2)'");
  #define LSEGOID            601
! DATA(insert OID = 602 (  path       PGNSP PGUID -1 f b t \054 0 0 1019 path_in path_out path_recv path_send - - - d x
f0 -1 0 _null_ _null_ )); 
  DESCR("geometric path '(pt1,...)'");
  #define PATHOID            602
! DATA(insert OID = 603 (  box       PGNSP PGUID 32 f b t \073 0 600 1020 box_in box_out box_recv box_send - - - d p f
0-1 0 _null_ _null_ )); 
  DESCR("geometric box '(lower left,upper right)'");
  #define BOXOID            603
! DATA(insert OID = 604 (  polygon   PGNSP PGUID -1 f b t \054 0     0 1027 poly_in poly_out poly_recv poly_send - - -
dx f 0 -1 0 _null_ _null_ )); 
  DESCR("geometric polygon '(pt1,...)'");
  #define POLYGONOID        604

! DATA(insert OID = 628 (  line       PGNSP PGUID 32 f b t \054 0 701 629 line_in line_out line_recv line_send - - - d
pf 0 -1 0 _null_ _null_ )); 
  DESCR("geometric line (not implemented)'");
  #define LINEOID            628
! DATA(insert OID = 629 (  _line       PGNSP PGUID    -1 f b t \054 0 628 0 array_in array_out array_recv array_send -
-- d x f 0 -1 0 _null_ _null_ )); 
  DESCR("");

  /* OIDS 700 - 799 */

! DATA(insert OID = 700 (  float4    PGNSP PGUID    4 f b t \054 0     0 1021 float4in float4out float4recv float4send
-- - i p f 0 -1 0 _null_ _null_ )); 
  DESCR("single-precision floating point number, 4-byte storage");
  #define FLOAT4OID 700
! DATA(insert OID = 701 (  float8    PGNSP PGUID    8 f b t \054 0     0 1022 float8in float8out float8recv float8send
-- - d p f 0 -1 0 _null_ _null_ )); 
  DESCR("double-precision floating point number, 8-byte storage");
  #define FLOAT8OID 701
! DATA(insert OID = 702 (  abstime   PGNSP PGUID    4 t b t \054 0     0 1023 abstimein abstimeout abstimerecv
abstimesend- - - i p f 0 -1 0 _null_ _null_ )); 
  DESCR("absolute, limited-range date and time (Unix system time)");
  #define ABSTIMEOID        702
! DATA(insert OID = 703 (  reltime   PGNSP PGUID    4 t b t \054 0     0 1024 reltimein reltimeout reltimerecv
reltimesend- - - i p f 0 -1 0 _null_ _null_ )); 
  DESCR("relative, limited-range time interval (Unix delta time)");
  #define RELTIMEOID        703
! DATA(insert OID = 704 (  tinterval PGNSP PGUID 12 f b t \054 0     0 1025 tintervalin tintervalout tintervalrecv
tintervalsend- - - i p f 0 -1 0 _null_ _null_ )); 
  DESCR("(abstime,abstime), time interval");
  #define TINTERVALOID    704
! DATA(insert OID = 705 (  unknown   PGNSP PGUID -2 f b t \054 0     0 0 unknownin unknownout unknownrecv unknownsend -
-- c p f 0 -1 0 _null_ _null_ )); 
  DESCR("");
  #define UNKNOWNOID        705

! DATA(insert OID = 718 (  circle    PGNSP PGUID    24 f b t \054 0 0 719 circle_in circle_out circle_recv circle_send
-- - d p f 0 -1 0 _null_ _null_ )); 
  DESCR("geometric circle '(center,radius)'");
  #define CIRCLEOID        718
! DATA(insert OID = 719 (  _circle   PGNSP PGUID    -1 f b t \054 0  718 0 array_in array_out array_recv array_send - -
-d x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 790 (  money       PGNSP PGUID     8 f b t \054 0 0 791 cash_in cash_out cash_recv cash_send - - -
dp f 0 -1 0 _null_ _null_ )); 
  DESCR("monetary amounts, $d,ddd.cc");
  #define CASHOID 790
! DATA(insert OID = 791 (  _money    PGNSP PGUID    -1 f b t \054 0  790 0 array_in array_out array_recv array_send - -
-d x f 0 -1 0 _null_ _null_ )); 

  /* OIDS 800 - 899 */
! DATA(insert OID = 829 ( macaddr    PGNSP PGUID    6 f b t \054 0 0 1040 macaddr_in macaddr_out macaddr_recv
macaddr_send- - - i p f 0 -1 0 _null_ _null_ )); 
  DESCR("XX:XX:XX:XX:XX:XX, MAC address");
  #define MACADDROID 829
! DATA(insert OID = 869 ( inet       PGNSP PGUID    -1 f b t \054 0 0 1041 inet_in inet_out inet_recv inet_send - - - i
mf 0 -1 0 _null_ _null_ )); 
  DESCR("IP address/netmask, host address, netmask optional");
  #define INETOID 869
! DATA(insert OID = 650 ( cidr       PGNSP PGUID    -1 f b t \054 0 0 651 cidr_in cidr_out cidr_recv cidr_send - - - i
mf 0 -1 0 _null_ _null_ )); 
  DESCR("network IP address/netmask, network address");
  #define CIDROID 650

  /* OIDS 900 - 999 */

  /* OIDS 1000 - 1099 */
! DATA(insert OID = 1000 (  _bool         PGNSP PGUID -1 f b t \054 0    16 0 array_in array_out array_recv array_send
-- - i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1001 (  _bytea     PGNSP PGUID -1 f b t \054 0    17 0 array_in array_out array_recv array_send - -
-i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1002 (  _char         PGNSP PGUID -1 f b t \054 0    18 0 array_in array_out array_recv array_send
-- - i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1003 (  _name         PGNSP PGUID -1 f b t \054 0    19 0 array_in array_out array_recv array_send
-- - i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1005 (  _int2         PGNSP PGUID -1 f b t \054 0    21 0 array_in array_out array_recv array_send
-- - i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1006 (  _int2vector PGNSP PGUID -1 f b t \054 0    22 0 array_in array_out array_recv array_send -
-- i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1007 (  _int4         PGNSP PGUID -1 f b t \054 0    23 0 array_in array_out array_recv array_send
-- - i x f 0 -1 0 _null_ _null_ )); 
  #define INT4ARRAYOID        1007
! DATA(insert OID = 1008 (  _regproc     PGNSP PGUID -1 f b t \054 0    24 0 array_in array_out array_recv array_send -
-- i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1009 (  _text         PGNSP PGUID -1 f b t \054 0    25 0 array_in array_out array_recv array_send
-- - i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1028 (  _oid         PGNSP PGUID -1 f b t \054 0    26 0 array_in array_out array_recv array_send -
-- i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1010 (  _tid         PGNSP PGUID -1 f b t \054 0    27 0 array_in array_out array_recv array_send -
-- i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1011 (  _xid         PGNSP PGUID -1 f b t \054 0    28 0 array_in array_out array_recv array_send -
-- i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1012 (  _cid         PGNSP PGUID -1 f b t \054 0    29 0 array_in array_out array_recv array_send -
-- i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1013 (  _oidvector PGNSP PGUID -1 f b t \054 0    30 0 array_in array_out array_recv array_send - -
-i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1014 (  _bpchar     PGNSP PGUID -1 f b t \054 0 1042 0 array_in array_out array_recv array_send
bpchartypmodinbpchartypmodout - i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1015 (  _varchar     PGNSP PGUID -1 f b t \054 0 1043 0 array_in array_out array_recv array_send
varchartypmodinvarchartypmodout - i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1016 (  _int8         PGNSP PGUID -1 f b t \054 0    20 0 array_in array_out array_recv array_send
-- - d x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1017 (  _point     PGNSP PGUID -1 f b t \054 0 600 0 array_in array_out array_recv array_send - - -
dx f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1018 (  _lseg         PGNSP PGUID -1 f b t \054 0 601 0 array_in array_out array_recv array_send -
-- d x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1019 (  _path         PGNSP PGUID -1 f b t \054 0 602 0 array_in array_out array_recv array_send -
-- d x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1020 (  _box         PGNSP PGUID -1 f b t \073 0 603 0 array_in array_out array_recv array_send - -
-d x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1021 (  _float4     PGNSP PGUID -1 f b t \054 0 700 0 array_in array_out array_recv array_send - -
-i x f 0 -1 0 _null_ _null_ )); 
  #define FLOAT4ARRAYOID 1021
! DATA(insert OID = 1022 (  _float8     PGNSP PGUID -1 f b t \054 0 701 0 array_in array_out array_recv array_send - -
-d x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1023 (  _abstime     PGNSP PGUID -1 f b t \054 0 702 0 array_in array_out array_recv array_send - -
-i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1024 (  _reltime     PGNSP PGUID -1 f b t \054 0 703 0 array_in array_out array_recv array_send - -
-i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1025 (  _tinterval PGNSP PGUID -1 f b t \054 0 704 0 array_in array_out array_recv array_send - - -
ix f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1027 (  _polygon     PGNSP PGUID -1 f b t \054 0 604 0 array_in array_out array_recv array_send - -
-d x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1033 (  aclitem     PGNSP PGUID 12 f b t \054 0 0 1034 aclitemin aclitemout - - - - - i p f 0 -1 0
_null__null_ )); 
  DESCR("access control list");
  #define ACLITEMOID        1033
! DATA(insert OID = 1034 (  _aclitem     PGNSP PGUID -1 f b t \054 0 1033 0 array_in array_out array_recv array_send -
-- i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1040 (  _macaddr     PGNSP PGUID -1 f b t \054 0  829 0 array_in array_out array_recv array_send -
-- i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1041 (  _inet    PGNSP PGUID -1 f b t \054 0    869 0 array_in array_out array_recv array_send - -
-i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 651  (  _cidr    PGNSP PGUID -1 f b t \054 0    650 0 array_in array_out array_recv array_send - -
-i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1042 ( bpchar         PGNSP PGUID -1 f b t \054 0    0 1014 bpcharin bpcharout bpcharrecv
bpcharsendbpchartypmodin bpchartypmodout - i x f 0 -1 0 _null_ _null_ )); 
  DESCR("char(length), blank-padded string, fixed storage length");
  #define BPCHAROID        1042
! DATA(insert OID = 1043 ( varchar     PGNSP PGUID -1 f b t \054 0    0 1015 varcharin varcharout varcharrecv
varcharsendvarchartypmodin varchartypmodout - i x f 0 -1 0 _null_ _null_ )); 
  DESCR("varchar(length), non-blank-padded string, variable storage length");
  #define VARCHAROID        1043

! DATA(insert OID = 1082 ( date         PGNSP PGUID    4 t b t \054 0    0 1182 date_in date_out date_recv date_send -
-- i p f 0 -1 0 _null_ _null_ )); 
  DESCR("ANSI SQL date");
  #define DATEOID            1082
! DATA(insert OID = 1083 ( time         PGNSP PGUID    8 f b t \054 0    0 1183 time_in time_out time_recv time_send
timetypmodintimetypmodout - d p f 0 -1 0 _null_ _null_ )); 
  DESCR("hh:mm:ss, ANSI SQL time");
  #define TIMEOID            1083

  /* OIDS 1100 - 1199 */
! DATA(insert OID = 1114 ( timestamp     PGNSP PGUID    8 f b t \054 0    0 1115 timestamp_in timestamp_out
timestamp_recvtimestamp_send timestamptypmodin timestamptypmodout - d p f 0 -1 0 _null_ _null_ )); 
  DESCR("date and time");
  #define TIMESTAMPOID    1114
! DATA(insert OID = 1115 ( _timestamp  PGNSP PGUID    -1 f b t \054 0 1114 0 array_in array_out array_recv array_send
timestamptypmodintimestamptypmodout - d x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1182 ( _date         PGNSP PGUID    -1 f b t \054 0 1082 0 array_in array_out array_recv array_send
-- - i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1183 ( _time         PGNSP PGUID    -1 f b t \054 0 1083 0 array_in array_out array_recv array_send
timetypmodintimetypmodout - d x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1184 ( timestamptz PGNSP PGUID    8 f b t \054 0    0 1185 timestamptz_in timestamptz_out
timestamptz_recvtimestamptz_send timestamptztypmodin timestamptztypmodout - d p f 0 -1 0 _null_ _null_ )); 
  DESCR("date and time with time zone");
  #define TIMESTAMPTZOID    1184
! DATA(insert OID = 1185 ( _timestamptz PGNSP PGUID -1 f b t \054 0    1184 0 array_in array_out array_recv array_send
timestamptztypmodintimestamptztypmodout - d x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1186 ( interval     PGNSP PGUID 16 f b t \054 0    0 1187 interval_in interval_out interval_recv
interval_sendintervaltypmodin intervaltypmodout - d p f 0 -1 0 _null_ _null_ )); 
  DESCR("@ <number> <units>, time interval");
  #define INTERVALOID        1186
! DATA(insert OID = 1187 ( _interval     PGNSP PGUID    -1 f b t \054 0 1186 0 array_in array_out array_recv array_send
intervaltypmodinintervaltypmodout - d x f 0 -1 0 _null_ _null_ )); 

  /* OIDS 1200 - 1299 */
! DATA(insert OID = 1231 (  _numeric     PGNSP PGUID -1 f b t \054 0    1700 0 array_in array_out array_recv array_send
numerictypmodinnumerictypmodout - i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1266 ( timetz         PGNSP PGUID 12 f b t \054 0    0 1270 timetz_in timetz_out timetz_recv
timetz_sendtimetztypmodin timetztypmodout - d p f 0 -1 0 _null_ _null_ )); 
  DESCR("hh:mm:ss, ANSI SQL time");
  #define TIMETZOID        1266
! DATA(insert OID = 1270 ( _timetz     PGNSP PGUID -1 f b t \054 0    1266 0 array_in array_out array_recv array_send
timetztypmodintimetztypmodout - d x f 0 -1 0 _null_ _null_ )); 

  /* OIDS 1500 - 1599 */
! DATA(insert OID = 1560 ( bit         PGNSP PGUID -1 f b t \054 0    0 1561 bit_in bit_out bit_recv bit_send
bittypmodinbittypmodout - i x f 0 -1 0 _null_ _null_ )); 
  DESCR("fixed-length bit string");
  #define BITOID     1560
! DATA(insert OID = 1561 ( _bit         PGNSP PGUID -1 f b t \054 0    1560 0 array_in array_out array_recv array_send
bittypmodinbittypmodout - i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1562 ( varbit         PGNSP PGUID -1 f b t \054 0    0 1563 varbit_in varbit_out varbit_recv
varbit_sendvarbittypmodin varbittypmodout - i x f 0 -1 0 _null_ _null_ )); 
  DESCR("variable-length bit string");
  #define VARBITOID      1562
! DATA(insert OID = 1563 ( _varbit     PGNSP PGUID -1 f b t \054 0    1562 0 array_in array_out array_recv array_send
varbittypmodinvarbittypmodout - i x f 0 -1 0 _null_ _null_ )); 

  /* OIDS 1600 - 1699 */

  /* OIDS 1700 - 1799 */
! DATA(insert OID = 1700 ( numeric       PGNSP PGUID -1 f b t \054 0    0 1231 numeric_in numeric_out numeric_recv
numeric_sendnumerictypmodin numerictypmodout - i m f 0 -1 0 _null_ _null_ )); 
  DESCR("numeric(precision, decimal), arbitrary precision number");
  #define NUMERICOID        1700

! DATA(insert OID = 1790 ( refcursor       PGNSP PGUID -1 f b t \054 0    0 2201 textin textout textrecv textsend - - -
ix f 0 -1 0 _null_ _null_ )); 
  DESCR("reference cursor (portal name)");
  #define REFCURSOROID    1790

  /* OIDS 2200 - 2299 */
! DATA(insert OID = 2201 ( _refcursor    PGNSP PGUID -1 f b t \054 0 1790 0 array_in array_out array_recv array_send -
-- i x f 0 -1 0 _null_ _null_ )); 

! DATA(insert OID = 2202 ( regprocedure  PGNSP PGUID    4 t b t \054 0     0 2207 regprocedurein regprocedureout
regprocedurerecvregproceduresend - - - i p f 0 -1 0 _null_ _null_ )); 
  DESCR("registered procedure (with args)");
  #define REGPROCEDUREOID 2202

! DATA(insert OID = 2203 ( regoper       PGNSP PGUID    4 t b t \054 0     0 2208 regoperin regoperout regoperrecv
regopersend- - - i p f 0 -1 0 _null_ _null_ )); 
  DESCR("registered operator");
  #define REGOPEROID        2203

! DATA(insert OID = 2204 ( regoperator   PGNSP PGUID    4 t b t \054 0     0 2209 regoperatorin regoperatorout
regoperatorrecvregoperatorsend - - - i p f 0 -1 0 _null_ _null_ )); 
  DESCR("registered operator (with args)");
  #define REGOPERATOROID    2204

! DATA(insert OID = 2205 ( regclass       PGNSP PGUID    4 t b t \054 0     0 2210 regclassin regclassout regclassrecv
regclasssend- - - i p f 0 -1 0 _null_ _null_ )); 
  DESCR("registered class");
  #define REGCLASSOID        2205

! DATA(insert OID = 2206 ( regtype       PGNSP PGUID    4 t b t \054 0     0 2211 regtypein regtypeout regtyperecv
regtypesend- - - i p f 0 -1 0 _null_ _null_ )); 
  DESCR("registered type");
  #define REGTYPEOID        2206

! DATA(insert OID = 2207 ( _regprocedure PGNSP PGUID -1 f b t \054 0 2202 0 array_in array_out array_recv array_send -
-- i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 2208 ( _regoper       PGNSP PGUID -1 f b t \054 0 2203 0 array_in array_out array_recv array_send -
-- i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 2209 ( _regoperator  PGNSP PGUID -1 f b t \054 0 2204 0 array_in array_out array_recv array_send -
-- i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 2210 ( _regclass       PGNSP PGUID -1 f b t \054 0 2205 0 array_in array_out array_recv array_send
-- - i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 2211 ( _regtype       PGNSP PGUID -1 f b t \054 0 2206 0 array_in array_out array_recv array_send -
-- i x f 0 -1 0 _null_ _null_ )); 
  #define REGTYPEARRAYOID 2211

  /* uuid */
! DATA(insert OID = 2950 ( uuid            PGNSP PGUID 16 f b t \054 0 0 2951 uuid_in uuid_out uuid_recv uuid_send - -
-c p f 0 -1 0 _null_ _null_ )); 
  DESCR("UUID datatype");
! DATA(insert OID = 2951 ( _uuid            PGNSP PGUID -1 f b t \054 0 2950 0 array_in array_out array_recv array_send
-- - i x f 0 -1 0 _null_ _null_ )); 

  /*
   * pseudo-types
***************
*** 548,574 ****
   * argument and result types (if supported by the function's implementation
   * language).
   */
! DATA(insert OID = 2249 ( record            PGNSP PGUID -1 f p t \054 0 0 record_in record_out record_recv record_send
-- - d x f 0 -1 0 _null_ _null_ )); 
  #define RECORDOID        2249
! DATA(insert OID = 2275 ( cstring        PGNSP PGUID -2 f p t \054 0 0 cstring_in cstring_out cstring_recv
cstring_send- - - c p f 0 -1 0 _null_ _null_ )); 
  #define CSTRINGOID        2275
! DATA(insert OID = 2276 ( any            PGNSP PGUID  4 t p t \054 0 0 any_in any_out - - - - - i p f 0 -1 0 _null_
_null_)); 
  #define ANYOID            2276
! DATA(insert OID = 2277 ( anyarray        PGNSP PGUID -1 f p t \054 0 0 anyarray_in anyarray_out anyarray_recv
anyarray_send- - - d x f 0 -1 0 _null_ _null_ )); 
  #define ANYARRAYOID        2277
! DATA(insert OID = 2278 ( void            PGNSP PGUID  4 t p t \054 0 0 void_in void_out - - - - - i p f 0 -1 0 _null_
_null_)); 
  #define VOIDOID            2278
! DATA(insert OID = 2279 ( trigger        PGNSP PGUID  4 t p t \054 0 0 trigger_in trigger_out - - - - - i p f 0 -1 0
_null__null_ )); 
  #define TRIGGEROID        2279
! DATA(insert OID = 2280 ( language_handler    PGNSP PGUID  4 t p t \054 0 0 language_handler_in language_handler_out -
-- - - i p f 0 -1 0 _null_ _null_ )); 
  #define LANGUAGE_HANDLEROID        2280
! DATA(insert OID = 2281 ( internal        PGNSP PGUID  4 t p t \054 0 0 internal_in internal_out - - - - - i p f 0 -1
0_null_ _null_ )); 
  #define INTERNALOID        2281
! DATA(insert OID = 2282 ( opaque            PGNSP PGUID  4 t p t \054 0 0 opaque_in opaque_out - - - - - i p f 0 -1 0
_null__null_ )); 
  #define OPAQUEOID        2282
! DATA(insert OID = 2283 ( anyelement        PGNSP PGUID  4 t p t \054 0 0 anyelement_in anyelement_out - - - - - i p f
0-1 0 _null_ _null_ )); 
  #define ANYELEMENTOID    2283
! DATA(insert OID = 3500 ( anyenum        PGNSP PGUID  4 t p t \054 0 0 anyenum_in anyenum_out - - - - - i p f 0 -1 0
_null__null_ )); 
  #define ANYENUMOID        3500


--- 552,578 ----
   * argument and result types (if supported by the function's implementation
   * language).
   */
! DATA(insert OID = 2249 ( record            PGNSP PGUID -1 f p t \054 0 0 0 record_in record_out record_recv
record_send- - - d x f 0 -1 0 _null_ _null_ )); 
  #define RECORDOID        2249
! DATA(insert OID = 2275 ( cstring        PGNSP PGUID -2 f p t \054 0 0 0 cstring_in cstring_out cstring_recv
cstring_send- - - c p f 0 -1 0 _null_ _null_ )); 
  #define CSTRINGOID        2275
! DATA(insert OID = 2276 ( any            PGNSP PGUID  4 t p t \054 0 0 0 any_in any_out - - - - - i p f 0 -1 0 _null_
_null_)); 
  #define ANYOID            2276
! DATA(insert OID = 2277 ( anyarray        PGNSP PGUID -1 f p t \054 0 0 0 anyarray_in anyarray_out anyarray_recv
anyarray_send- - - d x f 0 -1 0 _null_ _null_ )); 
  #define ANYARRAYOID        2277
! DATA(insert OID = 2278 ( void            PGNSP PGUID  4 t p t \054 0 0 0 void_in void_out - - - - - i p f 0 -1 0
_null__null_ )); 
  #define VOIDOID            2278
! DATA(insert OID = 2279 ( trigger        PGNSP PGUID  4 t p t \054 0 0 0 trigger_in trigger_out - - - - - i p f 0 -1 0
_null__null_ )); 
  #define TRIGGEROID        2279
! DATA(insert OID = 2280 ( language_handler    PGNSP PGUID  4 t p t \054 0 0 0 language_handler_in language_handler_out
-- - - - i p f 0 -1 0 _null_ _null_ )); 
  #define LANGUAGE_HANDLEROID        2280
! DATA(insert OID = 2281 ( internal        PGNSP PGUID  4 t p t \054 0 0 0 internal_in internal_out - - - - - i p f 0
-10 _null_ _null_ )); 
  #define INTERNALOID        2281
! DATA(insert OID = 2282 ( opaque            PGNSP PGUID  4 t p t \054 0 0 0 opaque_in opaque_out - - - - - i p f 0 -1
0_null_ _null_ )); 
  #define OPAQUEOID        2282
! DATA(insert OID = 2283 ( anyelement        PGNSP PGUID  4 t p t \054 0 0 0 anyelement_in anyelement_out - - - - - i p
f0 -1 0 _null_ _null_ )); 
  #define ANYELEMENTOID    2283
! DATA(insert OID = 3500 ( anyenum        PGNSP PGUID  4 t p t \054 0 0 0 anyenum_in anyenum_out - - - - - i p f 0 -1 0
_null__null_ )); 
  #define ANYENUMOID        3500


***************
*** 592,621 ****
   */
  extern Oid    TypeShellMake(const char *typeName, Oid typeNamespace);

! extern Oid TypeCreate(const char *typeName,
!            Oid typeNamespace,
!            Oid relationOid,
!            char relationKind,
!            int16 internalSize,
!            char typeType,
!            char typDelim,
!            Oid inputProcedure,
!            Oid outputProcedure,
!            Oid receiveProcedure,
!            Oid sendProcedure,
!            Oid typmodinProcedure,
!            Oid typmodoutProcedure,
!            Oid analyzeProcedure,
!            Oid elementType,
!            Oid baseType,
!            const char *defaultTypeValue,
!            char *defaultTypeBin,
!            bool passedByValue,
!            char alignment,
!            char storage,
!            int32 typeMod,
!            int32 typNDims,
!            bool typeNotNull);

  extern void GenerateTypeDependencies(Oid typeNamespace,
                           Oid typeObjectId,
--- 596,629 ----
   */
  extern Oid    TypeShellMake(const char *typeName, Oid typeNamespace);

! extern Oid TypeCreate(
!     const char *typeName,
!     Oid typeNamespace,
!     Oid relationOid,
!     char relationKind,
!     int16 internalSize,
!     char typeType,
!     char typDelim,
!     Oid inputProcedure,
!     Oid outputProcedure,
!     Oid receiveProcedure,
!     Oid sendProcedure,
!     Oid typmodinProcedure,
!     Oid typmodoutProcedure,
!     Oid analyzeProcedure,
!     Oid elementType,
!     Oid baseType,
!     const char *defaultTypeValue,
!     char *defaultTypeBin,
!     bool passedByValue,
!     char alignment,
!     char storage,
!     int32 typeMod,
!     int32 typNDims,
!     bool typeNotNull,
!     Oid arrayType,
!     bool is_array_type
! );

  extern void GenerateTypeDependencies(Oid typeNamespace,
                           Oid typeObjectId,
***************
*** 637,642 ****
  extern void TypeRename(const char *oldTypeName, Oid typeNamespace,
             const char *newTypeName);

! extern char *makeArrayTypeName(const char *typeName);

  #endif   /* PG_TYPE_H */
--- 645,650 ----
  extern void TypeRename(const char *oldTypeName, Oid typeNamespace,
             const char *newTypeName);

! extern char *makeArrayTypeName(const char *typeName, Oid typeNamespace);

  #endif   /* PG_TYPE_H */
Index: src/test/regress/expected/alter_table.out
===================================================================
RCS file: /cvsroot/pgsql/src/test/regress/expected/alter_table.out,v
retrieving revision 1.101
diff -c -r1.101 alter_table.out
*** src/test/regress/expected/alter_table.out    14 Feb 2007 01:58:58 -0000    1.101
--- src/test/regress/expected/alter_table.out    9 May 2007 00:38:27 -0000
***************
*** 1456,1468 ****
--- 1456,1471 ----

  -- clean up
  drop schema alter2 cascade;
+ NOTICE:  drop cascades to type alter2.ctype[]
  NOTICE:  drop cascades to composite type alter2.ctype
  NOTICE:  drop cascades to type alter2.ctype
  NOTICE:  drop cascades to type alter2.posint
  NOTICE:  drop cascades to function alter2.plus1(integer)
+ NOTICE:  drop cascades to type alter2.v1[]
  NOTICE:  drop cascades to view alter2.v1
  NOTICE:  drop cascades to rule _RETURN on view alter2.v1
  NOTICE:  drop cascades to sequence alter2.t1_f1_seq
  NOTICE:  drop cascades to default for table alter2.t1 column f1
+ NOTICE:  drop cascades to type alter2.t1[]
  NOTICE:  drop cascades to table alter2.t1
  NOTICE:  drop cascades to constraint t1_f2_check on table alter2.t1
Index: src/test/regress/expected/type_sanity.out
===================================================================
RCS file: /cvsroot/pgsql/src/test/regress/expected/type_sanity.out,v
retrieving revision 1.29
diff -c -r1.29 type_sanity.out
*** src/test/regress/expected/type_sanity.out    2 Apr 2007 03:49:42 -0000    1.29
--- src/test/regress/expected/type_sanity.out    9 May 2007 00:38:28 -0000
***************
*** 49,55 ****
  -- or basic types that do.
  SELECT p1.oid, p1.typname
  FROM pg_type as p1
! WHERE (p1.typtype = 'c' AND p1.typrelid = 0) OR
      (p1.typtype != 'c' AND p1.typrelid != 0);
   oid | typname
  -----+---------
--- 49,55 ----
  -- or basic types that do.
  SELECT p1.oid, p1.typname
  FROM pg_type as p1
! WHERE (p1.typtype = 'c' AND p1.typrelid = 0 AND p1.typname !~ '^_') OR
      (p1.typtype != 'c' AND p1.typrelid != 0);
   oid | typname
  -----+---------
***************
*** 69,74 ****
--- 69,84 ----
   705 | unknown
  (2 rows)

+ -- Make sure typarray points to a varlena array type of our own base
+ SELECT p1.oid, p1.typname as basetype, p2.typname as arraytype,
+        p2.typelem, p2.typlen
+ FROM   pg_type p1 left join pg_type p2 on (p1.typarray = p2.oid)
+ WHERE  p1.typarray <> 0 AND
+        (p2.oid IS NULL OR p2.typelem <> p1.oid OR p2.typlen <> -1);
+  oid | basetype | arraytype | typelem | typlen
+ -----+----------+-----------+---------+--------
+ (0 rows)
+
  -- Text conversion routines must be provided.
  SELECT p1.oid, p1.typname
  FROM pg_type as p1
Index: src/test/regress/sql/type_sanity.sql
===================================================================
RCS file: /cvsroot/pgsql/src/test/regress/sql/type_sanity.sql,v
retrieving revision 1.29
diff -c -r1.29 type_sanity.sql
*** src/test/regress/sql/type_sanity.sql    2 Apr 2007 03:49:42 -0000    1.29
--- src/test/regress/sql/type_sanity.sql    9 May 2007 00:38:28 -0000
***************
*** 46,52 ****

  SELECT p1.oid, p1.typname
  FROM pg_type as p1
! WHERE (p1.typtype = 'c' AND p1.typrelid = 0) OR
      (p1.typtype != 'c' AND p1.typrelid != 0);

  -- Look for basic or enum types that don't have an array type.
--- 46,52 ----

  SELECT p1.oid, p1.typname
  FROM pg_type as p1
! WHERE (p1.typtype = 'c' AND p1.typrelid = 0 AND p1.typname !~ '^_') OR
      (p1.typtype != 'c' AND p1.typrelid != 0);

  -- Look for basic or enum types that don't have an array type.
***************
*** 59,64 ****
--- 59,71 ----
       WHERE p2.typname = ('_' || p1.typname)::name AND
             p2.typelem = p1.oid);

+ -- Make sure typarray points to a varlena array type of our own base
+ SELECT p1.oid, p1.typname as basetype, p2.typname as arraytype,
+        p2.typelem, p2.typlen
+ FROM   pg_type p1 left join pg_type p2 on (p1.typarray = p2.oid)
+ WHERE  p1.typarray <> 0 AND
+        (p2.oid IS NULL OR p2.typelem <> p1.oid OR p2.typlen <> -1);
+
  -- Text conversion routines must be provided.

  SELECT p1.oid, p1.typname

Re: updated WIP: arrays of composites

From
Andrew Dunstan
Date:
>>
>> Attached is my rework of David Fetter's array of composites patch. It
>> has all the agreed modifications and checks, except altering the name
>> mangling.
>>
>>
>
> Here is the latest with the name mangling piece done - it's got quite
> large with the catalog rewrite :-)
>
> It could do with some extra eyeballs - especially the error codes.
>
> I'm not sure if we need to adjust the test in pg_dump.c - maybe we
> should look at using the same test as the backend (typlen == -1) to
> disambiguate real arrays from subscriptable base types.
>


The attached version removes all the places we had NAMEDATALEN - 2
restrictions on object names. If there's no objection I will commit this
shortly, as I think it now does all the previously agreed things.

cheers

andrew

Index: doc/src/sgml/array.sgml
===================================================================
RCS file: /cvsroot/pgsql/doc/src/sgml/array.sgml,v
retrieving revision 1.60
diff -c -r1.60 array.sgml
*** doc/src/sgml/array.sgml    6 Apr 2007 19:22:38 -0000    1.60
--- doc/src/sgml/array.sgml    9 May 2007 22:56:01 -0000
***************
*** 11,17 ****
    <productname>PostgreSQL</productname> allows columns of a table to be
    defined as variable-length multidimensional arrays. Arrays of any
    built-in or user-defined base type or enum type can be created.
!   (Arrays of composite types or domains are not yet supported, however.)
   </para>

   <sect2>
--- 11,18 ----
    <productname>PostgreSQL</productname> allows columns of a table to be
    defined as variable-length multidimensional arrays. Arrays of any
    built-in or user-defined base type or enum type can be created.
!   Arrays of composite types are now supported.  Arrays of domains are
!   not yet supported.
   </para>

   <sect2>
Index: src/backend/catalog/heap.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/catalog/heap.c,v
retrieving revision 1.318
diff -c -r1.318 heap.c
*** src/backend/catalog/heap.c    2 Apr 2007 03:49:37 -0000    1.318
--- src/backend/catalog/heap.c    9 May 2007 22:56:03 -0000
***************
*** 45,50 ****
--- 45,51 ----
  #include "catalog/pg_statistic.h"
  #include "catalog/pg_type.h"
  #include "commands/tablecmds.h"
+ #include "commands/typecmds.h"
  #include "miscadmin.h"
  #include "optimizer/clauses.h"
  #include "optimizer/var.h"
***************
*** 69,75 ****
  static Oid AddNewRelationType(const char *typeName,
                     Oid typeNamespace,
                     Oid new_rel_oid,
!                    char new_rel_kind);
  static void RelationRemoveInheritance(Oid relid);
  static void StoreRelCheck(Relation rel, char *ccname, char *ccbin);
  static void StoreConstraints(Relation rel, TupleDesc tupdesc);
--- 70,78 ----
  static Oid AddNewRelationType(const char *typeName,
                     Oid typeNamespace,
                     Oid new_rel_oid,
!                    char new_rel_kind,
!                    Oid new_array_type
!              );
  static void RelationRemoveInheritance(Oid relid);
  static void StoreRelCheck(Relation rel, char *ccname, char *ccbin);
  static void StoreConstraints(Relation rel, TupleDesc tupdesc);
***************
*** 402,417 ****
      char        att_typtype = get_typtype(atttypid);

      /*
!      * Warn user, but don't fail, if column to be created has UNKNOWN type
!      * (usually as a result of a 'retrieve into' - jolly)
       *
!      * Refuse any attempt to create a pseudo-type column.
       */
!     if (atttypid == UNKNOWNOID)
          ereport(WARNING,
                  (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
                   errmsg("column \"%s\" has type \"unknown\"", attname),
                   errdetail("Proceeding with relation creation anyway.")));
      else if (att_typtype == TYPTYPE_PSEUDO)
      {
          /* Special hack for pg_statistic: allow ANYARRAY during initdb */
--- 405,444 ----
      char        att_typtype = get_typtype(atttypid);

      /*
!      * For a composite type, recurse into its attributes. Otherwise,
       *
!      * a) warn user, but don't fail, if column to be created has UNKNOWN type
!      *    (usually as a result of a 'retrieve into' - jolly)
!      *
!      * b) Refuse any attempt to create a pseudo-type column, except for
!      *    pg_statistic hack.
       */
!     if (att_typtype == TYPTYPE_COMPOSITE)
!     {
!         Relation relation;
!         TupleDesc tupdesc;
!         int i;
!
!         relation = RelationIdGetRelation(get_typ_typrelid(atttypid));
!
!         tupdesc = RelationGetDescr(relation);
!
!         for (i = 0; i < tupdesc->natts; i++)
!         {
!             if (tupdesc->attrs[i]->attisdropped)
!                 continue;
!             CheckAttributeType(attname, tupdesc->attrs[i]->atttypid);
!         }
!
!         RelationClose(relation);
!     }
!     else if (atttypid == UNKNOWNOID)
!     {
          ereport(WARNING,
                  (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
                   errmsg("column \"%s\" has type \"unknown\"", attname),
                   errdetail("Proceeding with relation creation anyway.")));
+     }
      else if (att_typtype == TYPTYPE_PSEUDO)
      {
          /* Special hack for pg_statistic: allow ANYARRAY during initdb */
***************
*** 710,716 ****
  AddNewRelationType(const char *typeName,
                     Oid typeNamespace,
                     Oid new_rel_oid,
!                    char new_rel_kind)
  {
      return
          TypeCreate(typeName,    /* type name */
--- 737,744 ----
  AddNewRelationType(const char *typeName,
                     Oid typeNamespace,
                     Oid new_rel_oid,
!                    char new_rel_kind,
!                    Oid new_array_type)
  {
      return
          TypeCreate(typeName,    /* type name */
***************
*** 736,742 ****
                     'x',            /* fully TOASTable */
                     -1,            /* typmod */
                     0,            /* array dimensions for typBaseType */
!                    false);        /* Type NOT NULL */
  }

  /* --------------------------------
--- 764,773 ----
                     'x',            /* fully TOASTable */
                     -1,            /* typmod */
                     0,            /* array dimensions for typBaseType */
!                    false,        /* Type NOT NULL */
!                    new_array_type, /* oid of type we are about to make */
!                    false           /* no this is not an array type */
!             );
  }

  /* --------------------------------
***************
*** 763,768 ****
--- 794,801 ----
      Relation    pg_class_desc;
      Relation    new_rel_desc;
      Oid            new_type_oid;
+     Oid         new_array_oid = InvalidOid;
+

      pg_class_desc = heap_open(RelationRelationId, RowExclusiveLock);

***************
*** 804,809 ****
--- 837,853 ----

      Assert(relid == RelationGetRelid(new_rel_desc));

+     /* Get an oid for the array type of necessary */
+     if (IsUnderPostmaster && (relkind == RELKIND_RELATION ||
+                               relkind == RELKIND_VIEW ||
+                               relkind == RELKIND_COMPOSITE_TYPE))
+     {
+         Relation pg_type = heap_open(TypeRelationId, RowExclusiveLock);
+         new_array_oid = GetNewOid(pg_type);
+         heap_close(pg_type, RowExclusiveLock);
+     }
+
+
      /*
       * since defining a relation also defines a complex type, we add a new
       * system type corresponding to the new relation.
***************
*** 814,820 ****
      new_type_oid = AddNewRelationType(relname,
                                        relnamespace,
                                        relid,
!                                       relkind);

      /*
       * now create an entry in pg_class for the relation.
--- 858,906 ----
      new_type_oid = AddNewRelationType(relname,
                                        relnamespace,
                                        relid,
!                                       relkind,
!                                       new_array_oid);
!     /*
!      * Add in the corresponding array types if appropriate.
!      */
!     if (IsUnderPostmaster && (relkind == RELKIND_RELATION ||
!                               relkind == RELKIND_VIEW ||
!                               relkind == RELKIND_COMPOSITE_TYPE))
!     {
!         char       *relarrayname;
!
!         relarrayname = makeArrayTypeName(relname, relnamespace);
!
!         TypeCreate(relarrayname,        /* Array type name */
!                    relnamespace,        /* Same namespace as parent */
!                    InvalidOid,            /* Not composite, no relationOid */
!                    0,                    /* relkind, also N/A here */
!                    -1,                    /* Internal size, unlimited */
!                    TYPTYPE_BASE,        /* Not composite - typelem is */
!                    DEFAULT_TYPDELIM,    /* Use the default */
!                    F_ARRAY_IN,            /* array input proc */
!                    F_ARRAY_OUT,            /* array output proc */
!                    F_ARRAY_RECV,        /* array recv (bin) proc */
!                    F_ARRAY_SEND,        /* array send (bin) proc */
!                    InvalidOid,            /* No input typmod */
!                    InvalidOid,            /* No output typmod */
!                    InvalidOid,            /* Default ANALYZE procedure */
!                    new_type_oid,        /* The OID just created */
!                    InvalidOid,            /* No base type--not a DOMAIN */
!                    NULL,                /* No default type value */
!                    NULL,                /* Don't send binary */
!                    false,                /* Never passed by value */
!                    'd',                    /* Type align. Max for safety */
!                    'x',                    /* Always TOASTable */
!                    -1,                    /* No typMod for non-domain */
!                    0,                    /* Array dims of typbasetype */
!                    false,                /* Type NOT NULL */
!                    new_array_oid,       /* oid of this type entry */
!                    true                 /* yes, this is an array type */
!             );
!
!         pfree(relarrayname);
!     }

      /*
       * now create an entry in pg_class for the relation.
***************
*** 887,893 ****
       */
      heap_close(new_rel_desc, NoLock);    /* do not unlock till end of xact */
      heap_close(pg_class_desc, RowExclusiveLock);
!
      return relid;
  }

--- 973,979 ----
       */
      heap_close(new_rel_desc, NoLock);    /* do not unlock till end of xact */
      heap_close(pg_class_desc, RowExclusiveLock);
!
      return relid;
  }

Index: src/backend/catalog/pg_type.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/catalog/pg_type.c,v
retrieving revision 1.111
diff -c -r1.111 pg_type.c
*** src/backend/catalog/pg_type.c    2 Apr 2007 03:49:37 -0000    1.111
--- src/backend/catalog/pg_type.c    9 May 2007 22:56:03 -0000
***************
*** 90,95 ****
--- 90,96 ----
      values[i++] = CharGetDatum(DEFAULT_TYPDELIM);        /* typdelim */
      values[i++] = ObjectIdGetDatum(InvalidOid); /* typrelid */
      values[i++] = ObjectIdGetDatum(InvalidOid); /* typelem */
+     values[i++] = ObjectIdGetDatum(InvalidOid); /* typarray */
      values[i++] = ObjectIdGetDatum(F_SHELL_IN); /* typinput */
      values[i++] = ObjectIdGetDatum(F_SHELL_OUT);        /* typoutput */
      values[i++] = ObjectIdGetDatum(InvalidOid); /* typreceive */
***************
*** 180,186 ****
             char storage,
             int32 typeMod,
             int32 typNDims,        /* Array dimensions for baseType */
!            bool typeNotNull)
  {
      Relation    pg_type_desc;
      Oid            typeObjectId;
--- 181,190 ----
             char storage,
             int32 typeMod,
             int32 typNDims,        /* Array dimensions for baseType */
!            bool typeNotNull,
!            Oid arrayType,
!            bool is_array_type
! )
  {
      Relation    pg_type_desc;
      Oid            typeObjectId;
***************
*** 246,251 ****
--- 250,257 ----
      values[i++] = ObjectIdGetDatum(typeType == TYPTYPE_COMPOSITE ?
                                     relationOid : InvalidOid); /* typrelid */
      values[i++] = ObjectIdGetDatum(elementType);        /* typelem */
+     values[i++] = ObjectIdGetDatum(is_array_type ?
+                                    InvalidOid : arrayType); /* typarray */
      values[i++] = ObjectIdGetDatum(inputProcedure);        /* typinput */
      values[i++] = ObjectIdGetDatum(outputProcedure);    /* typoutput */
      values[i++] = ObjectIdGetDatum(receiveProcedure);    /* typreceive */
***************
*** 331,336 ****
--- 337,347 ----
                               values,
                               nulls);

+         /* should only happen if it's not a shell type */
+         if (is_array_type)
+             HeapTupleSetOid(tup, arrayType);
+
+
          typeObjectId = simple_heap_insert(pg_type_desc, tup);
      }

***************
*** 571,590 ****
  }

  /*
   * makeArrayTypeName(typeName);
   *      - given a base type name, make an array of type name out of it
   *
   * the caller is responsible for pfreeing the result
   */
  char *
! makeArrayTypeName(const char *typeName)
  {
      char       *arr;

      if (!typeName)
          return NULL;
      arr = palloc(NAMEDATALEN);
!     snprintf(arr, NAMEDATALEN,
!              "_%.*s", NAMEDATALEN - 2, typeName);
      return arr;
  }
--- 582,660 ----
  }

  /*
+  * find the mb-safe substring length that is not greater than max
+  */
+ static int
+ mb_substr_len(char * str, int max)
+ {
+     int result = 0;
+     char * crsr = str;
+     int len = strlen(str);
+
+     if (max > len)
+         max = len;
+
+     if (pg_database_encoding_max_length() == 1)
+         return max;
+     if (crsr == NULL)
+         return 0;
+     while (*crsr)
+     {
+         len = pg_mblen(crsr);
+         if (result + len > max)
+             break;
+         result += len;
+         crsr += len;
+     }
+     return result;
+ }
+
+
+
+ /*
   * makeArrayTypeName(typeName);
   *      - given a base type name, make an array of type name out of it
   *
   * the caller is responsible for pfreeing the result
   */
  char *
! makeArrayTypeName(const char *typeName, Oid typeNamespace)
  {
      char       *arr;
+     int        i, safelen;
+     bool       found = false;
+     Relation    pg_type_desc;
+
+     pg_type_desc = heap_open(TypeRelationId, RowExclusiveLock);
+

      if (!typeName)
          return NULL;
+
      arr = palloc(NAMEDATALEN);
!
!     for (i = 1; i < NAMEDATALEN / 2; i++)
!     {
!         arr[i - 1] = '_';
!         safelen = mb_substr_len(typeName, NAMEDATALEN - (i + 1));
!         snprintf(arr+i, NAMEDATALEN - 1, "%.*s",  safelen, typeName);
!         if (SearchSysCacheExists(TYPENAMENSP,
!                              CStringGetDatum(arr),
!                              ObjectIdGetDatum(typeNamespace),
!                              0, 0))
!             continue;
!         found = true;
!         break;
!     }
!
!     heap_close(pg_type_desc, RowExclusiveLock);
!
!     if (! found)
!         ereport(ERROR,
!                 (errcode(ERRCODE_DUPLICATE_OBJECT),
!                  errmsg("could not form array type name for type \"%s\"",
!                         typeName)));
!
!
      return arr;
  }
Index: src/backend/commands/tablecmds.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v
retrieving revision 1.219
diff -c -r1.219 tablecmds.c
*** src/backend/commands/tablecmds.c    8 Apr 2007 01:26:32 -0000    1.219
--- src/backend/commands/tablecmds.c    9 May 2007 22:56:08 -0000
***************
*** 287,296 ****
      Datum        reloptions;
      ListCell   *listptr;
      AttrNumber    attnum;

      /*
!      * Truncate relname to appropriate length (probably a waste of time, as
!      * parser should have done this already).
       */
      StrNCpy(relname, stmt->relation->relname, NAMEDATALEN);

--- 287,297 ----
      Datum        reloptions;
      ListCell   *listptr;
      AttrNumber    attnum;
+     char       *relarrayname;

      /*
!      * Truncate relname to appropriate length (probably a waste of time, as *
!      * parser should have done this already).
       */
      StrNCpy(relname, stmt->relation->relname, NAMEDATALEN);

***************
*** 6461,6468 ****

      AlterRelationNamespaceInternal(classRel, relid, oldNspOid, nspOid, true);

!     /* Fix the table's rowtype too */
      AlterTypeNamespaceInternal(rel->rd_rel->reltype, nspOid, false);

      /* Fix other dependent stuff */
      if (rel->rd_rel->relkind == RELKIND_RELATION)
--- 6462,6470 ----

      AlterRelationNamespaceInternal(classRel, relid, oldNspOid, nspOid, true);

!     /* Fix the table's types too */
      AlterTypeNamespaceInternal(rel->rd_rel->reltype, nspOid, false);
+     AlterTypeNamespaceInternal(get_array_type(rel->rd_rel->reltype), nspOid, false);

      /* Fix other dependent stuff */
      if (rel->rd_rel->relkind == RELKIND_RELATION)
Index: src/backend/commands/typecmds.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/commands/typecmds.c,v
retrieving revision 1.101
diff -c -r1.101 typecmds.c
*** src/backend/commands/typecmds.c    2 Apr 2007 03:49:38 -0000    1.101
--- src/backend/commands/typecmds.c    9 May 2007 22:56:09 -0000
***************
*** 34,39 ****
--- 34,40 ----
  #include "access/genam.h"
  #include "access/heapam.h"
  #include "access/xact.h"
+ #include "catalog/catalog.h"
  #include "catalog/dependency.h"
  #include "catalog/heap.h"
  #include "catalog/indexing.h"
***************
*** 119,127 ****
--- 120,130 ----
      Oid            typmodoutOid = InvalidOid;
      Oid            analyzeOid = InvalidOid;
      char       *shadow_type;
+     Oid         shadow_oid;
      ListCell   *pl;
      Oid            typoid;
      Oid            resulttype;
+     Relation    pg_type;

      /* Convert list of names to a name and namespace */
      typeNamespace = QualifiedNameGetCreationNamespace(names, &typeName);
***************
*** 133,148 ****
                         get_namespace_name(typeNamespace));

      /*
-      * Type names must be one character shorter than other names, allowing
-      * room to create the corresponding array type name with prepended "_".
-      */
-     if (strlen(typeName) > (NAMEDATALEN - 2))
-         ereport(ERROR,
-                 (errcode(ERRCODE_INVALID_NAME),
-                  errmsg("type names must be %d characters or less",
-                         NAMEDATALEN - 2)));
-
-     /*
       * Look to see if type already exists (presumably as a shell; if not,
       * TypeCreate will complain).  If it doesn't, create it as a shell, so
       * that the OID is known for use in the I/O function definitions.
--- 136,141 ----
***************
*** 396,401 ****
--- 389,398 ----
          aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_PROC,
                         NameListToString(analyzeName));

+     pg_type = heap_open(TypeRelationId, RowExclusiveLock);
+     shadow_oid = GetNewOid(pg_type);
+     heap_close(pg_type, RowExclusiveLock);
+
      /*
       * now have TypeCreate do all the real work.
       */
***************
*** 423,465 ****
                     storage,        /* TOAST strategy */
                     -1,            /* typMod (Domains only) */
                     0,            /* Array Dimensions of typbasetype */
!                    false);        /* Type NOT NULL */

      /*
       * When we create a base type (as opposed to a complex type) we need to
       * have an array entry for it in pg_type as well.
       */
!     shadow_type = makeArrayTypeName(typeName);

      /* alignment must be 'i' or 'd' for arrays */
      alignment = (alignment == 'd') ? 'd' : 'i';

!     TypeCreate(shadow_type,        /* type name */
!                typeNamespace,    /* namespace */
!                InvalidOid,        /* relation oid (n/a here) */
!                0,                /* relation kind (ditto) */
!                -1,                /* internal size */
!                TYPTYPE_BASE,    /* type-type (base type) */
!                DEFAULT_TYPDELIM,    /* array element delimiter */
!                F_ARRAY_IN,        /* input procedure */
!                F_ARRAY_OUT,        /* output procedure */
!                F_ARRAY_RECV,    /* receive procedure */
!                F_ARRAY_SEND,    /* send procedure */
!                typmodinOid,        /* typmodin procedure */
!                typmodoutOid,    /* typmodout procedure */
!                InvalidOid,        /* analyze procedure - default */
!                typoid,            /* element type ID */
!                InvalidOid,        /* base type ID */
!                NULL,            /* never a default type value */
!                NULL,            /* binary default isn't sent either */
!                false,            /* never passed by value */
!                alignment,        /* see above */
!                'x',                /* ARRAY is always toastable */
!                -1,                /* typMod (Domains only) */
!                0,                /* Array dimensions of typbasetype */
!                false);            /* Type NOT NULL */

      pfree(shadow_type);
  }


--- 420,469 ----
                     storage,        /* TOAST strategy */
                     -1,            /* typMod (Domains only) */
                     0,            /* Array Dimensions of typbasetype */
!                    false,        /* Type NOT NULL */
!                    shadow_oid,  /* array type we are about to create */
!                    false        /* this is not an array type */
!             );

      /*
       * When we create a base type (as opposed to a complex type) we need to
       * have an array entry for it in pg_type as well.
       */
!     shadow_type = makeArrayTypeName(typeName, typeNamespace);

      /* alignment must be 'i' or 'd' for arrays */
      alignment = (alignment == 'd') ? 'd' : 'i';

!    TypeCreate(shadow_type,        /* type name */
!               typeNamespace,    /* namespace */
!               InvalidOid,        /* relation oid (n/a here) */
!               0,                /* relation kind (ditto) */
!               -1,                /* internal size */
!               TYPTYPE_BASE,    /* type-type (base type) */
!               DEFAULT_TYPDELIM,    /* array element delimiter */
!               F_ARRAY_IN,        /* input procedure */
!               F_ARRAY_OUT,        /* output procedure */
!               F_ARRAY_RECV,    /* receive procedure */
!               F_ARRAY_SEND,    /* send procedure */
!               typmodinOid,        /* typmodin procedure */
!               typmodoutOid,    /* typmodout procedure */
!               InvalidOid,        /* analyze procedure - default */
!               typoid,            /* element type ID */
!               InvalidOid,        /* base type ID */
!               NULL,            /* never a default type value */
!               NULL,            /* binary default isn't sent either */
!               false,            /* never passed by value */
!               alignment,        /* see above */
!               'x',                /* ARRAY is always toastable */
!               -1,                /* typMod (Domains only) */
!               0,                /* Array dimensions of typbasetype */
!               false,            /* Type NOT NULL */
!               shadow_oid,       /* oid for this entry */
!               true              /* yes this is an array type */
!        );

      pfree(shadow_type);
+
  }


***************
*** 474,479 ****
--- 478,484 ----
      Oid            typeoid;
      HeapTuple    tup;
      ObjectAddress object;
+     Form_pg_type typ;

      /* Make a TypeName so we can use standard type lookup machinery */
      typename = makeTypeNameFromNameList(names);
***************
*** 505,513 ****
      if (!HeapTupleIsValid(tup))
          elog(ERROR, "cache lookup failed for type %u", typeoid);

      /* Permission check: must own type or its namespace */
      if (!pg_type_ownercheck(typeoid, GetUserId()) &&
!       !pg_namespace_ownercheck(((Form_pg_type) GETSTRUCT(tup))->typnamespace,
                                 GetUserId()))
          aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TYPE,
                         TypeNameToString(typename));
--- 510,528 ----
      if (!HeapTupleIsValid(tup))
          elog(ERROR, "cache lookup failed for type %u", typeoid);

+     typ = (Form_pg_type) GETSTRUCT(tup);
+
+     /* don't alow direct deletion of array types */
+     if (typ->typelem != 0 && typ->typlen == -1)
+             ereport(ERROR,
+                     (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
+                      errmsg("cannot delete array type \"%s\" ",
+                             TypeNameToString(typename))));
+
+
      /* Permission check: must own type or its namespace */
      if (!pg_type_ownercheck(typeoid, GetUserId()) &&
!       !pg_namespace_ownercheck(typ->typnamespace,
                                 GetUserId()))
          aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TYPE,
                         TypeNameToString(typename));
***************
*** 545,551 ****
      simple_heap_delete(relation, &tup->t_self);

      /*
!      * If it is an enum, delete the pg_enum entries too; we don't bother
       * with making dependency entries for those, so it has to be done
       * "by hand" here.
       */
--- 560,566 ----
      simple_heap_delete(relation, &tup->t_self);

      /*
!      * If it is an enum delete the pg_enum entries too; we don't bother
       * with making dependency entries for those, so it has to be done
       * "by hand" here.
       */
***************
*** 608,626 ****
                         get_namespace_name(domainNamespace));

      /*
-      * Domainnames, unlike typenames don't need to account for the '_' prefix.
-      * So they can be one character longer.  (This test is presently useless
-      * since the parser will have truncated the name to fit.  But leave it
-      * here since we may someday support arrays of domains, in which case
-      * we'll be back to needing to enforce NAMEDATALEN-2.)
-      */
-     if (strlen(domainName) > (NAMEDATALEN - 1))
-         ereport(ERROR,
-                 (errcode(ERRCODE_INVALID_NAME),
-                  errmsg("domain names must be %d characters or less",
-                         NAMEDATALEN - 1)));
-
-     /*
       * Look up the base type.
       */
      typeTup = typenameType(NULL, stmt->typename);
--- 623,628 ----
***************
*** 828,835 ****
                     storage,        /* TOAST strategy */
                     basetypeMod, /* typeMod value */
                     typNDims,    /* Array dimensions for base type */
!                    typNotNull); /* Type NOT NULL */
!
      /*
       * Process constraints which refer to the domain ID returned by TypeCreate
       */
--- 830,839 ----
                     storage,        /* TOAST strategy */
                     basetypeMod, /* typeMod value */
                     typNDims,    /* Array dimensions for base type */
!                    typNotNull, /* Type NOT NULL */
!                    InvalidOid, /* no arrays for domains */
!                    false       /* this isn't an array */
!             );
      /*
       * Process constraints which refer to the domain ID returned by TypeCreate
       */
***************
*** 949,954 ****
--- 953,960 ----
      Oid        enumNamespace;
      Oid        enumTypeOid;
      AclResult    aclresult;
+     Oid     enumArrayOid;
+     Relation pg_type;

      /* Convert list of names to a name and namespace */
      enumNamespace = QualifiedNameGetCreationNamespace(stmt->typename,
***************
*** 960,974 ****
          aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
                         get_namespace_name(enumNamespace));

!     /*
!      * Type names must be one character shorter than other names, allowing
!      * room to create the corresponding array type name with prepended "_".
!      */
!     if (strlen(enumName) > (NAMEDATALEN - 2))
!         ereport(ERROR,
!                 (errcode(ERRCODE_INVALID_NAME),
!                  errmsg("type names must be %d characters or less",
!                         NAMEDATALEN - 2)));

      /* Create the pg_type entry */
      enumTypeOid =
--- 966,974 ----
          aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
                         get_namespace_name(enumNamespace));

!     pg_type = heap_open(TypeRelationId, RowExclusiveLock);
!     enumArrayOid = GetNewOid(pg_type);
!     heap_close(pg_type, RowExclusiveLock);

      /* Create the pg_type entry */
      enumTypeOid =
***************
*** 995,1007 ****
                     'p',                /* TOAST strategy always plain */
                     -1,                /* typMod (Domains only) */
                     0,                /* Array dimensions of typbasetype */
!                    false);            /* Type NOT NULL */

      /* Enter the enum's values into pg_enum */
      EnumValuesCreate(enumTypeOid, stmt->vals);

      /* Create array type for enum */
!     enumArrayName = makeArrayTypeName(enumName);

      TypeCreate(enumArrayName,   /* type name */
                 enumNamespace,   /* namespace */
--- 995,1010 ----
                     'p',                /* TOAST strategy always plain */
                     -1,                /* typMod (Domains only) */
                     0,                /* Array dimensions of typbasetype */
!                    false,            /* Type NOT NULL */
!                    enumArrayOid,    /* oid of entry we are about to create */
!                    false            /* this is not an array */
!             );

      /* Enter the enum's values into pg_enum */
      EnumValuesCreate(enumTypeOid, stmt->vals);

      /* Create array type for enum */
!     enumArrayName = makeArrayTypeName(enumName, enumNamespace);

      TypeCreate(enumArrayName,   /* type name */
                 enumNamespace,   /* namespace */
***************
*** 1026,1032 ****
                 'x',             /* ARRAY is always toastable */
                 -1,              /* typMod (Domains only) */
                 0,               /* Array dimensions of typbasetype */
!                false);          /* Type NOT NULL */

      pfree(enumArrayName);
  }
--- 1029,1038 ----
                 'x',             /* ARRAY is always toastable */
                 -1,              /* typMod (Domains only) */
                 0,               /* Array dimensions of typbasetype */
!                false,           /* Type NOT NULL */
!                enumArrayOid,    /* oid to use for this entry */
!                true             /* this is an array */
!         );

      pfree(enumArrayName);
  }
***************
*** 2249,2254 ****
--- 2255,2268 ----
          elog(ERROR, "cache lookup failed for type %u", typeOid);
      typTup = (Form_pg_type) GETSTRUCT(tup);

+     /* don't allow direct alteration of array types */
+     if (typTup->typelem != 0 && typTup->typlen == -1)
+             ereport(ERROR,
+                     (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
+                      errmsg("cannot alter array type \"%s\" ",
+                             TypeNameToString(typename))));
+
+
      /*
       * If it's a composite type, we need to check that it really is a
       * free-standing composite type, and not a table's underlying type. We
***************
*** 2352,2357 ****
--- 2366,2374 ----
      TypeName   *typename;
      Oid            typeOid;
      Oid            nspOid;
+     Relation    rel;
+     HeapTuple    tup;
+     Form_pg_type typ;

      /* Make a TypeName so we can use standard type lookup machinery */
      typename = makeTypeNameFromNameList(names);
***************
*** 2365,2372 ****
--- 2382,2415 ----
      /* get schema OID and check its permissions */
      nspOid = LookupCreationNamespace(newschema);

+     /* don't allow direct alteration of array types */
+
+     rel = heap_open(TypeRelationId, RowExclusiveLock);
+
+     tup = SearchSysCacheCopy(TYPEOID,
+                              ObjectIdGetDatum(typeOid),
+                              0, 0, 0);
+     if (!HeapTupleIsValid(tup))
+         elog(ERROR, "cache lookup failed for type %u", typeOid);
+
+     typ = (Form_pg_type) GETSTRUCT(tup);
+
+     if (typ->typelem != 0 && typ->typlen == -1)
+             ereport(ERROR,
+                     (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
+                      errmsg("cannot alter array type \"%s\" ",
+                             TypeNameToString(typename))));
+
+
+     heap_freetuple(tup);
+
+     heap_close(rel, RowExclusiveLock);
+
      /* and do the work */
      AlterTypeNamespaceInternal(typeOid, nspOid, true);
+     typeOid = get_array_type(typeOid);
+     if (typeOid != InvalidOid)
+         AlterTypeNamespaceInternal(typeOid, nspOid, true);
  }

  /*
***************
*** 2431,2442 ****

      /* Detect whether type is a composite type (but not a table rowtype) */
      isCompositeType =
!         (typform->typtype == TYPTYPE_COMPOSITE &&
           get_rel_relkind(typform->typrelid) == RELKIND_COMPOSITE_TYPE);

      /* Enforce not-table-type if requested */
      if (typform->typtype == TYPTYPE_COMPOSITE && !isCompositeType &&
!         errorOnTableType)
          ereport(ERROR,
                  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
                   errmsg("%s is a table's row type",
--- 2474,2485 ----

      /* Detect whether type is a composite type (but not a table rowtype) */
      isCompositeType =
!         (typform->typtype == TYPTYPE_COMPOSITE && typform->typrelid != InvalidOid &&
           get_rel_relkind(typform->typrelid) == RELKIND_COMPOSITE_TYPE);

      /* Enforce not-table-type if requested */
      if (typform->typtype == TYPTYPE_COMPOSITE && !isCompositeType &&
!         typform->typrelid != InvalidOid && errorOnTableType)
          ereport(ERROR,
                  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
                   errmsg("%s is a table's row type",
***************
*** 2457,2463 ****
       * We need to modify the pg_class tuple as well to reflect the change of
       * schema.
       */
!     if (isCompositeType)
      {
          Relation    classRel;

--- 2500,2506 ----
       * We need to modify the pg_class tuple as well to reflect the change of
       * schema.
       */
!     if (isCompositeType && typform->typrelid != InvalidOid)
      {
          Relation    classRel;

***************
*** 2490,2496 ****
           * Update dependency on schema, if any --- a table rowtype has not got
           * one.
           */
!         if (typform->typtype != TYPTYPE_COMPOSITE)
              if (changeDependencyFor(TypeRelationId, typeOid,
                                  NamespaceRelationId, oldNspOid, nspOid) != 1)
                  elog(ERROR, "failed to change schema dependency for type %s",
--- 2533,2539 ----
           * Update dependency on schema, if any --- a table rowtype has not got
           * one.
           */
!         if (typform->typtype != TYPTYPE_COMPOSITE || typform->typrelid == InvalidOid)
              if (changeDependencyFor(TypeRelationId, typeOid,
                                  NamespaceRelationId, oldNspOid, nspOid) != 1)
                  elog(ERROR, "failed to change schema dependency for type %s",
Index: src/backend/parser/parse_type.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/parser/parse_type.c,v
retrieving revision 1.89
diff -c -r1.89 parse_type.c
*** src/backend/parser/parse_type.c    27 Apr 2007 22:05:48 -0000    1.89
--- src/backend/parser/parse_type.c    9 May 2007 22:56:10 -0000
***************
*** 116,125 ****
          /* deconstruct the name list */
          DeconstructQualifiedName(typename->names, &schemaname, &typname);

-         /* If an array reference, look up the array type instead */
-         if (typename->arrayBounds != NIL)
-             typname = makeArrayTypeName(typname);
-
          if (schemaname)
          {
              /* Look in specific schema only */
--- 116,121 ----
***************
*** 136,141 ****
--- 132,142 ----
              /* Unqualified type name, so search the search path */
              restype = TypenameGetTypid(typname);
          }
+
+         /* If an array reference, return the array type instead */
+         if (typename->arrayBounds != NIL)
+             restype = get_array_type(restype);
+
      }

      return restype;
Index: src/backend/utils/cache/lsyscache.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v
retrieving revision 1.151
diff -c -r1.151 lsyscache.c
*** src/backend/utils/cache/lsyscache.c    2 Apr 2007 03:49:39 -0000    1.151
--- src/backend/utils/cache/lsyscache.c    9 May 2007 22:56:12 -0000
***************
*** 2206,2252 ****
   *        Given the type OID, get the corresponding array type.
   *        Returns InvalidOid if no array type can be found.
   *
-  * NB: this only considers varlena arrays to be true arrays.
   */
  Oid
  get_array_type(Oid typid)
  {
      HeapTuple    tp;

      tp = SearchSysCache(TYPEOID,
                          ObjectIdGetDatum(typid),
                          0, 0, 0);
      if (HeapTupleIsValid(tp))
      {
!         Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
!         char       *array_typename;
!         Oid            namespaceId;
!
!         array_typename = makeArrayTypeName(NameStr(typtup->typname));
!         namespaceId = typtup->typnamespace;
          ReleaseSysCache(tp);
-
-         tp = SearchSysCache(TYPENAMENSP,
-                             PointerGetDatum(array_typename),
-                             ObjectIdGetDatum(namespaceId),
-                             0, 0);
-
-         pfree(array_typename);
-
-         if (HeapTupleIsValid(tp))
-         {
-             Oid            result;
-
-             typtup = (Form_pg_type) GETSTRUCT(tp);
-             if (typtup->typlen == -1 && typtup->typelem == typid)
-                 result = HeapTupleGetOid(tp);
-             else
-                 result = InvalidOid;
-             ReleaseSysCache(tp);
-             return result;
-         }
      }
!     return InvalidOid;
  }

  /*
--- 2206,2227 ----
   *        Given the type OID, get the corresponding array type.
   *        Returns InvalidOid if no array type can be found.
   *
   */
  Oid
  get_array_type(Oid typid)
  {
      HeapTuple    tp;
+     Oid result = InvalidOid;

      tp = SearchSysCache(TYPEOID,
                          ObjectIdGetDatum(typid),
                          0, 0, 0);
      if (HeapTupleIsValid(tp))
      {
!         result = ((Form_pg_type) GETSTRUCT(tp))->typarray;
          ReleaseSysCache(tp);
      }
!     return result;
  }

  /*
Index: src/include/catalog/catversion.h
===================================================================
RCS file: /cvsroot/pgsql/src/include/catalog/catversion.h,v
retrieving revision 1.404
diff -c -r1.404 catversion.h
*** src/include/catalog/catversion.h    15 Apr 2007 10:56:27 -0000    1.404
--- src/include/catalog/catversion.h    9 May 2007 22:56:13 -0000
***************
*** 53,58 ****
   */

  /*                            yyyymmddN */
! #define CATALOG_VERSION_NO    200704151

  #endif
--- 53,58 ----
   */

  /*                            yyyymmddN */
! #define CATALOG_VERSION_NO    200705061

  #endif
Index: src/include/catalog/pg_attribute.h
===================================================================
RCS file: /cvsroot/pgsql/src/include/catalog/pg_attribute.h,v
retrieving revision 1.130
diff -c -r1.130 pg_attribute.h
*** src/include/catalog/pg_attribute.h    22 Jan 2007 01:35:21 -0000    1.130
--- src/include/catalog/pg_attribute.h    9 May 2007 22:56:13 -0000
***************
*** 232,252 ****
  { 1247, {"typdelim"},       18, -1,    1,    8, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
  { 1247, {"typrelid"},       26, -1,    4,    9, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
  { 1247, {"typelem"},       26, -1,    4, 10, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
! { 1247, {"typinput"},       24, -1,    4, 11, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
! { 1247, {"typoutput"},       24, -1,    4, 12, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
! { 1247, {"typreceive"},    24, -1,    4, 13, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
! { 1247, {"typsend"},       24, -1,    4, 14, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
! { 1247, {"typmodin"},       24, -1,    4, 15, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
! { 1247, {"typmodout"},       24, -1,    4, 16, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
! { 1247, {"typanalyze"},    24, -1,    4, 17, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
! { 1247, {"typalign"},       18, -1,    1, 18, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
! { 1247, {"typstorage"},    18, -1,    1, 19, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
! { 1247, {"typnotnull"},    16, -1,    1, 20, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
! { 1247, {"typbasetype"},   26, -1,    4, 21, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
! { 1247, {"typtypmod"},       23, -1,    4, 22, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
! { 1247, {"typndims"},       23, -1,    4, 23, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
! { 1247, {"typdefaultbin"}, 25, -1, -1, 24, 0, -1, -1, false, 'x', 'i', false, false, false, true, 0 }, \
! { 1247, {"typdefault"},    25, -1, -1, 25, 0, -1, -1, false, 'x', 'i', false, false, false, true, 0 }

  DATA(insert ( 1247 typname            19 -1 NAMEDATALEN    1 0 -1 -1 f p i t f f t 0));
  DATA(insert ( 1247 typnamespace        26 -1 4   2 0 -1 -1 t p i t f f t 0));
--- 232,253 ----
  { 1247, {"typdelim"},       18, -1,    1,    8, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
  { 1247, {"typrelid"},       26, -1,    4,    9, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
  { 1247, {"typelem"},       26, -1,    4, 10, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
! { 1247, {"typarray"},       26, -1,    4, 11, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
! { 1247, {"typinput"},       24, -1,    4, 12, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
! { 1247, {"typoutput"},       24, -1,    4, 13, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
! { 1247, {"typreceive"},    24, -1,    4, 14, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
! { 1247, {"typsend"},       24, -1,    4, 15, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
! { 1247, {"typmodin"},       24, -1,    4, 16, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
! { 1247, {"typmodout"},       24, -1,    4, 17, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
! { 1247, {"typanalyze"},    24, -1,    4, 18, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
! { 1247, {"typalign"},       18, -1,    1, 19, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
! { 1247, {"typstorage"},    18, -1,    1, 20, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
! { 1247, {"typnotnull"},    16, -1,    1, 21, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
! { 1247, {"typbasetype"},   26, -1,    4, 22, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
! { 1247, {"typtypmod"},       23, -1,    4, 23, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
! { 1247, {"typndims"},       23, -1,    4, 24, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
! { 1247, {"typdefaultbin"}, 25, -1, -1, 25, 0, -1, -1, false, 'x', 'i', false, false, false, true, 0 }, \
! { 1247, {"typdefault"},    25, -1, -1, 26, 0, -1, -1, false, 'x', 'i', false, false, false, true, 0 }

  DATA(insert ( 1247 typname            19 -1 NAMEDATALEN    1 0 -1 -1 f p i t f f t 0));
  DATA(insert ( 1247 typnamespace        26 -1 4   2 0 -1 -1 t p i t f f t 0));
***************
*** 258,278 ****
  DATA(insert ( 1247 typdelim            18 -1 1   8 0 -1 -1 t p c t f f t 0));
  DATA(insert ( 1247 typrelid            26 -1 4   9 0 -1 -1 t p i t f f t 0));
  DATA(insert ( 1247 typelem            26 -1 4  10 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1247 typinput            24 -1 4  11 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1247 typoutput        24 -1 4  12 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1247 typreceive        24 -1 4  13 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1247 typsend            24 -1 4  14 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1247 typmodin            24 -1 4  15 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1247 typmodout        24 -1 4  16 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1247 typanalyze        24 -1 4  17 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1247 typalign            18 -1 1  18 0 -1 -1 t p c t f f t 0));
! DATA(insert ( 1247 typstorage        18 -1 1  19 0 -1 -1 t p c t f f t 0));
! DATA(insert ( 1247 typnotnull        16 -1 1  20 0 -1 -1 t p c t f f t 0));
! DATA(insert ( 1247 typbasetype        26 -1 4  21 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1247 typtypmod        23 -1 4  22 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1247 typndims            23 -1 4  23 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1247 typdefaultbin    25 -1 -1 24 0 -1 -1 f x i f f f t 0));
! DATA(insert ( 1247 typdefault        25 -1 -1 25 0 -1 -1 f x i f f f t 0));
  DATA(insert ( 1247 ctid                27 0  6  -1 0 -1 -1 f p s t f f t 0));
  DATA(insert ( 1247 oid                26 0  4  -2 0 -1 -1 t p i t f f t 0));
  DATA(insert ( 1247 xmin                28 0  4  -3 0 -1 -1 t p i t f f t 0));
--- 259,280 ----
  DATA(insert ( 1247 typdelim            18 -1 1   8 0 -1 -1 t p c t f f t 0));
  DATA(insert ( 1247 typrelid            26 -1 4   9 0 -1 -1 t p i t f f t 0));
  DATA(insert ( 1247 typelem            26 -1 4  10 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1247 typarray            26 -1 4  11 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1247 typinput            24 -1 4  12 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1247 typoutput        24 -1 4  13 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1247 typreceive        24 -1 4  14 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1247 typsend            24 -1 4  15 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1247 typmodin            24 -1 4  16 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1247 typmodout        24 -1 4  17 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1247 typanalyze        24 -1 4  18 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1247 typalign            18 -1 1  19 0 -1 -1 t p c t f f t 0));
! DATA(insert ( 1247 typstorage        18 -1 1  20 0 -1 -1 t p c t f f t 0));
! DATA(insert ( 1247 typnotnull        16 -1 1  21 0 -1 -1 t p c t f f t 0));
! DATA(insert ( 1247 typbasetype        26 -1 4  22 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1247 typtypmod        23 -1 4  23 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1247 typndims            23 -1 4  24 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1247 typdefaultbin    25 -1 -1 25 0 -1 -1 f x i f f f t 0));
! DATA(insert ( 1247 typdefault        25 -1 -1 26 0 -1 -1 f x i f f f t 0));
  DATA(insert ( 1247 ctid                27 0  6  -1 0 -1 -1 f p s t f f t 0));
  DATA(insert ( 1247 oid                26 0  4  -2 0 -1 -1 t p i t f f t 0));
  DATA(insert ( 1247 xmin                28 0  4  -3 0 -1 -1 t p i t f f t 0));
Index: src/include/catalog/pg_class.h
===================================================================
RCS file: /cvsroot/pgsql/src/include/catalog/pg_class.h,v
retrieving revision 1.100
diff -c -r1.100 pg_class.h
*** src/include/catalog/pg_class.h    22 Jan 2007 01:35:22 -0000    1.100
--- src/include/catalog/pg_class.h    9 May 2007 22:56:13 -0000
***************
*** 132,138 ****
   */

  /* Note: "3" in the relfrozenxid column stands for FirstNormalTransactionId */
! DATA(insert OID = 1247 (  pg_type        PGNSP 71 PGUID 0 1247 0 0 0 0 0 f f r 25 0 0 0 0 0 t f f f 3   _null_ _null_
));
  DESCR("");
  DATA(insert OID = 1249 (  pg_attribute    PGNSP 75 PGUID 0 1249 0 0 0 0 0 f f r 17 0 0 0 0 0 f f f f 3 _null_ _null_
));
  DESCR("");
--- 132,138 ----
   */

  /* Note: "3" in the relfrozenxid column stands for FirstNormalTransactionId */
! DATA(insert OID = 1247 (  pg_type        PGNSP 71 PGUID 0 1247 0 0 0 0 0 f f r 26 0 0 0 0 0 t f f f 3   _null_ _null_
));
  DESCR("");
  DATA(insert OID = 1249 (  pg_attribute    PGNSP 75 PGUID 0 1249 0 0 0 0 0 f f r 17 0 0 0 0 0 f f f f 3 _null_ _null_
));
  DESCR("");
Index: src/include/catalog/pg_type.h
===================================================================
RCS file: /cvsroot/pgsql/src/include/catalog/pg_type.h,v
retrieving revision 1.182
diff -c -r1.182 pg_type.h
*** src/include/catalog/pg_type.h    6 Apr 2007 04:21:43 -0000    1.182
--- src/include/catalog/pg_type.h    9 May 2007 22:56:14 -0000
***************
*** 97,102 ****
--- 97,105 ----
       */
      Oid            typelem;

+     /* Oid of array type, or 0 if it does not exist */
+     Oid         typarray;
+
      /*
       * I/O conversion procedures for the datatype.
       */
***************
*** 214,220 ****
   *        compiler constants for pg_type
   * ----------------
   */
! #define Natts_pg_type                    25
  #define Anum_pg_type_typname            1
  #define Anum_pg_type_typnamespace        2
  #define Anum_pg_type_typowner            3
--- 217,223 ----
   *        compiler constants for pg_type
   * ----------------
   */
! #define Natts_pg_type                    26
  #define Anum_pg_type_typname            1
  #define Anum_pg_type_typnamespace        2
  #define Anum_pg_type_typowner            3
***************
*** 225,245 ****
  #define Anum_pg_type_typdelim            8
  #define Anum_pg_type_typrelid            9
  #define Anum_pg_type_typelem            10
! #define Anum_pg_type_typinput            11
! #define Anum_pg_type_typoutput            12
! #define Anum_pg_type_typreceive            13
! #define Anum_pg_type_typsend            14
! #define Anum_pg_type_typmodin            15
! #define Anum_pg_type_typmodout            16
! #define Anum_pg_type_typanalyze            17
! #define Anum_pg_type_typalign            18
! #define Anum_pg_type_typstorage            19
! #define Anum_pg_type_typnotnull            20
! #define Anum_pg_type_typbasetype        21
! #define Anum_pg_type_typtypmod            22
! #define Anum_pg_type_typndims            23
! #define Anum_pg_type_typdefaultbin        24
! #define Anum_pg_type_typdefault            25


  /* ----------------
--- 228,249 ----
  #define Anum_pg_type_typdelim            8
  #define Anum_pg_type_typrelid            9
  #define Anum_pg_type_typelem            10
! #define Anum_pg_type_typarray            11
! #define Anum_pg_type_typinput            12
! #define Anum_pg_type_typoutput            13
! #define Anum_pg_type_typreceive            14
! #define Anum_pg_type_typsend            15
! #define Anum_pg_type_typmodin            16
! #define Anum_pg_type_typmodout            17
! #define Anum_pg_type_typanalyze            18
! #define Anum_pg_type_typalign            19
! #define Anum_pg_type_typstorage            20
! #define Anum_pg_type_typnotnull            21
! #define Anum_pg_type_typbasetype        22
! #define Anum_pg_type_typtypmod            23
! #define Anum_pg_type_typndims            24
! #define Anum_pg_type_typdefaultbin        25
! #define Anum_pg_type_typdefault            26


  /* ----------------
***************
*** 255,340 ****
  */

  /* OIDS 1 - 99 */
! DATA(insert OID = 16 (    bool       PGNSP PGUID    1 t b t \054 0     0 boolin boolout boolrecv boolsend - - - c p f
0-1 0 _null_ _null_ )); 
  DESCR("boolean, 'true'/'false'");
  #define BOOLOID            16

! DATA(insert OID = 17 (    bytea       PGNSP PGUID -1 f b t \054 0    0 byteain byteaout bytearecv byteasend - - - i x
f0 -1 0 _null_ _null_ )); 
  DESCR("variable-length string, binary values escaped");
  #define BYTEAOID        17

! DATA(insert OID = 18 (    char       PGNSP PGUID    1 t b t \054 0     0 charin charout charrecv charsend - - - c p f
0-1 0 _null_ _null_ )); 
  DESCR("single character");
  #define CHAROID            18

! DATA(insert OID = 19 (    name       PGNSP PGUID NAMEDATALEN f b t \054 0 18 namein nameout namerecv namesend - - - i
pf 0 -1 0 _null_ _null_ )); 
  DESCR("63-character type for storing system identifiers");
  #define NAMEOID            19

! DATA(insert OID = 20 (    int8       PGNSP PGUID    8 f b t \054 0     0 int8in int8out int8recv int8send - - - d p f
0-1 0 _null_ _null_ )); 
  DESCR("~18 digit integer, 8-byte storage");
  #define INT8OID            20

! DATA(insert OID = 21 (    int2       PGNSP PGUID    2 t b t \054 0     0 int2in int2out int2recv int2send - - - s p f
0-1 0 _null_ _null_ )); 
  DESCR("-32 thousand to 32 thousand, 2-byte storage");
  #define INT2OID            21

! DATA(insert OID = 22 (    int2vector PGNSP PGUID -1 f b t \054 0    21 int2vectorin int2vectorout int2vectorrecv
int2vectorsend- - - i p f 0 -1 0 _null_ _null_ )); 
  DESCR("array of int2, used in system tables");
  #define INT2VECTOROID    22

! DATA(insert OID = 23 (    int4       PGNSP PGUID    4 t b t \054 0     0 int4in int4out int4recv int4send - - - i p f
0-1 0 _null_ _null_ )); 
  DESCR("-2 billion to 2 billion integer, 4-byte storage");
  #define INT4OID            23

! DATA(insert OID = 24 (    regproc    PGNSP PGUID    4 t b t \054 0     0 regprocin regprocout regprocrecv regprocsend
-- - i p f 0 -1 0 _null_ _null_ )); 
  DESCR("registered procedure");
  #define REGPROCOID        24

! DATA(insert OID = 25 (    text       PGNSP PGUID -1 f b t \054 0    0 textin textout textrecv textsend - - - i x f 0
-10 _null_ _null_ )); 
  DESCR("variable-length string, no limit specified");
  #define TEXTOID            25

! DATA(insert OID = 26 (    oid           PGNSP PGUID    4 t b t \054 0     0 oidin oidout oidrecv oidsend - - - i p f
0-1 0 _null_ _null_ )); 
  DESCR("object identifier(oid), maximum 4 billion");
  #define OIDOID            26

! DATA(insert OID = 27 (    tid           PGNSP PGUID    6 f b t \054 0     0 tidin tidout tidrecv tidsend - - - s p f
0-1 0 _null_ _null_ )); 
  DESCR("(Block, offset), physical location of tuple");
  #define TIDOID        27

! DATA(insert OID = 28 (    xid           PGNSP PGUID    4 t b t \054 0     0 xidin xidout xidrecv xidsend - - - i p f
0-1 0 _null_ _null_ )); 
  DESCR("transaction id");
  #define XIDOID 28

! DATA(insert OID = 29 (    cid           PGNSP PGUID    4 t b t \054 0     0 cidin cidout cidrecv cidsend - - - i p f
0-1 0 _null_ _null_ )); 
  DESCR("command identifier type, sequence in transaction id");
  #define CIDOID 29

! DATA(insert OID = 30 (    oidvector  PGNSP PGUID -1 f b t \054 0    26 oidvectorin oidvectorout oidvectorrecv
oidvectorsend- - - i p f 0 -1 0 _null_ _null_ )); 
  DESCR("array of oids, used in system tables");
  #define OIDVECTOROID    30

  /* hand-built rowtype entries for bootstrapped catalogs: */

! DATA(insert OID = 71 (    pg_type            PGNSP PGUID -1 f c t \054 1247 0 record_in record_out record_recv
record_send- - - d x f 0 -1 0 _null_ _null_ )); 
  #define PG_TYPE_RELTYPE_OID 71
! DATA(insert OID = 75 (    pg_attribute    PGNSP PGUID -1 f c t \054 1249 0 record_in record_out record_recv
record_send- - - d x f 0 -1 0 _null_ _null_ )); 
  #define PG_ATTRIBUTE_RELTYPE_OID 75
! DATA(insert OID = 81 (    pg_proc            PGNSP PGUID -1 f c t \054 1255 0 record_in record_out record_recv
record_send- - - d x f 0 -1 0 _null_ _null_ )); 
  #define PG_PROC_RELTYPE_OID 81
! DATA(insert OID = 83 (    pg_class        PGNSP PGUID -1 f c t \054 1259 0 record_in record_out record_recv
record_send- - - d x f 0 -1 0 _null_ _null_ )); 
  #define PG_CLASS_RELTYPE_OID 83

  /* OIDS 100 - 199 */
! DATA(insert OID = 142 ( xml           PGNSP PGUID -1 f b t \054 0 0 xml_in xml_out xml_recv xml_send - - - i x f 0 -1
0_null_ _null_ )); 
  DESCR("XML content");
  #define XMLOID 142
! DATA(insert OID = 143 ( _xml       PGNSP PGUID -1 f b t \054 0 142 array_in array_out array_recv array_send - - - i x
f0 -1 0 _null_ _null_ )); 

  /* OIDS 200 - 299 */

! DATA(insert OID = 210 (  smgr       PGNSP PGUID 2 t b t \054 0 0 smgrin smgrout - - - - - s p f 0 -1 0 _null_ _null_
));
  DESCR("storage manager");

  /* OIDS 300 - 399 */
--- 259,344 ----
  */

  /* OIDS 1 - 99 */
! DATA(insert OID = 16 (    bool       PGNSP PGUID    1 t b t \054 0     0 1000 boolin boolout boolrecv boolsend - - -
cp f 0 -1 0 _null_ _null_ )); 
  DESCR("boolean, 'true'/'false'");
  #define BOOLOID            16

! DATA(insert OID = 17 (    bytea       PGNSP PGUID -1 f b t \054 0    0 1001 byteain byteaout bytearecv byteasend - -
-i x f 0 -1 0 _null_ _null_ )); 
  DESCR("variable-length string, binary values escaped");
  #define BYTEAOID        17

! DATA(insert OID = 18 (    char       PGNSP PGUID    1 t b t \054 0     0 1002 charin charout charrecv charsend - - -
cp f 0 -1 0 _null_ _null_ )); 
  DESCR("single character");
  #define CHAROID            18

! DATA(insert OID = 19 (    name       PGNSP PGUID NAMEDATALEN f b t \054 0 18 1003 namein nameout namerecv namesend -
-- i p f 0 -1 0 _null_ _null_ )); 
  DESCR("63-character type for storing system identifiers");
  #define NAMEOID            19

! DATA(insert OID = 20 (    int8       PGNSP PGUID    8 f b t \054 0     0 1016 int8in int8out int8recv int8send - - -
dp f 0 -1 0 _null_ _null_ )); 
  DESCR("~18 digit integer, 8-byte storage");
  #define INT8OID            20

! DATA(insert OID = 21 (    int2       PGNSP PGUID    2 t b t \054 0     0 1005 int2in int2out int2recv int2send - - -
sp f 0 -1 0 _null_ _null_ )); 
  DESCR("-32 thousand to 32 thousand, 2-byte storage");
  #define INT2OID            21

! DATA(insert OID = 22 (    int2vector PGNSP PGUID -1 f b t \054 0    21 1006 int2vectorin int2vectorout int2vectorrecv
int2vectorsend- - - i p f 0 -1 0 _null_ _null_ )); 
  DESCR("array of int2, used in system tables");
  #define INT2VECTOROID    22

! DATA(insert OID = 23 (    int4       PGNSP PGUID    4 t b t \054 0     0 1007 int4in int4out int4recv int4send - - -
ip f 0 -1 0 _null_ _null_ )); 
  DESCR("-2 billion to 2 billion integer, 4-byte storage");
  #define INT4OID            23

! DATA(insert OID = 24 (    regproc    PGNSP PGUID    4 t b t \054 0     0 1008 regprocin regprocout regprocrecv
regprocsend- - - i p f 0 -1 0 _null_ _null_ )); 
  DESCR("registered procedure");
  #define REGPROCOID        24

! DATA(insert OID = 25 (    text       PGNSP PGUID -1 f b t \054 0    0 1009 textin textout textrecv textsend - - - i x
f0 -1 0 _null_ _null_ )); 
  DESCR("variable-length string, no limit specified");
  #define TEXTOID            25

! DATA(insert OID = 26 (    oid           PGNSP PGUID    4 t b t \054 0     0 1028 oidin oidout oidrecv oidsend - - - i
pf 0 -1 0 _null_ _null_ )); 
  DESCR("object identifier(oid), maximum 4 billion");
  #define OIDOID            26

! DATA(insert OID = 27 (    tid           PGNSP PGUID    6 f b t \054 0     0 1010 tidin tidout tidrecv tidsend - - - s
pf 0 -1 0 _null_ _null_ )); 
  DESCR("(Block, offset), physical location of tuple");
  #define TIDOID        27

! DATA(insert OID = 28 (    xid           PGNSP PGUID    4 t b t \054 0     0 1011 xidin xidout xidrecv xidsend - - - i
pf 0 -1 0 _null_ _null_ )); 
  DESCR("transaction id");
  #define XIDOID 28

! DATA(insert OID = 29 (    cid           PGNSP PGUID    4 t b t \054 0     0 1012 cidin cidout cidrecv cidsend - - - i
pf 0 -1 0 _null_ _null_ )); 
  DESCR("command identifier type, sequence in transaction id");
  #define CIDOID 29

! DATA(insert OID = 30 (    oidvector  PGNSP PGUID -1 f b t \054 0    26 1013 oidvectorin oidvectorout oidvectorrecv
oidvectorsend- - - i p f 0 -1 0 _null_ _null_ )); 
  DESCR("array of oids, used in system tables");
  #define OIDVECTOROID    30

  /* hand-built rowtype entries for bootstrapped catalogs: */

! DATA(insert OID = 71 (    pg_type            PGNSP PGUID -1 f c t \054 1247 0 0 record_in record_out record_recv
record_send- - - d x f 0 -1 0 _null_ _null_ )); 
  #define PG_TYPE_RELTYPE_OID 71
! DATA(insert OID = 75 (    pg_attribute    PGNSP PGUID -1 f c t \054 1249 0 0 record_in record_out record_recv
record_send- - - d x f 0 -1 0 _null_ _null_ )); 
  #define PG_ATTRIBUTE_RELTYPE_OID 75
! DATA(insert OID = 81 (    pg_proc            PGNSP PGUID -1 f c t \054 1255 0 0 record_in record_out record_recv
record_send- - - d x f 0 -1 0 _null_ _null_ )); 
  #define PG_PROC_RELTYPE_OID 81
! DATA(insert OID = 83 (    pg_class        PGNSP PGUID -1 f c t \054 1259 0 0 record_in record_out record_recv
record_send- - - d x f 0 -1 0 _null_ _null_ )); 
  #define PG_CLASS_RELTYPE_OID 83

  /* OIDS 100 - 199 */
! DATA(insert OID = 142 ( xml           PGNSP PGUID -1 f b t \054 0 0 143 xml_in xml_out xml_recv xml_send - - - i x f
0-1 0 _null_ _null_ )); 
  DESCR("XML content");
  #define XMLOID 142
! DATA(insert OID = 143 ( _xml       PGNSP PGUID -1 f b t \054 0 142 0 array_in array_out array_recv array_send - - - i
xf 0 -1 0 _null_ _null_ )); 

  /* OIDS 200 - 299 */

! DATA(insert OID = 210 (  smgr       PGNSP PGUID 2 t b t \054 0 0 0 smgrin smgrout - - - - - s p f 0 -1 0 _null_
_null_)); 
  DESCR("storage manager");

  /* OIDS 300 - 399 */
***************
*** 344,543 ****
  /* OIDS 500 - 599 */

  /* OIDS 600 - 699 */
! DATA(insert OID = 600 (  point       PGNSP PGUID 16 f b t \054 0 701 point_in point_out point_recv point_send - - - d
pf 0 -1 0 _null_ _null_ )); 
  DESCR("geometric point '(x, y)'");
  #define POINTOID        600
! DATA(insert OID = 601 (  lseg       PGNSP PGUID 32 f b t \054 0 600 lseg_in lseg_out lseg_recv lseg_send - - - d p f
0-1 0 _null_ _null_ )); 
  DESCR("geometric line segment '(pt1,pt2)'");
  #define LSEGOID            601
! DATA(insert OID = 602 (  path       PGNSP PGUID -1 f b t \054 0 0 path_in path_out path_recv path_send - - - d x f 0
-10 _null_ _null_ )); 
  DESCR("geometric path '(pt1,...)'");
  #define PATHOID            602
! DATA(insert OID = 603 (  box       PGNSP PGUID 32 f b t \073 0 600 box_in box_out box_recv box_send - - - d p f 0 -1
0_null_ _null_ )); 
  DESCR("geometric box '(lower left,upper right)'");
  #define BOXOID            603
! DATA(insert OID = 604 (  polygon   PGNSP PGUID -1 f b t \054 0     0 poly_in poly_out poly_recv poly_send - - - d x f
0-1 0 _null_ _null_ )); 
  DESCR("geometric polygon '(pt1,...)'");
  #define POLYGONOID        604

! DATA(insert OID = 628 (  line       PGNSP PGUID 32 f b t \054 0 701 line_in line_out line_recv line_send - - - d p f
0-1 0 _null_ _null_ )); 
  DESCR("geometric line (not implemented)'");
  #define LINEOID            628
! DATA(insert OID = 629 (  _line       PGNSP PGUID    -1 f b t \054 0 628 array_in array_out array_recv array_send - -
-d x f 0 -1 0 _null_ _null_ )); 
  DESCR("");

  /* OIDS 700 - 799 */

! DATA(insert OID = 700 (  float4    PGNSP PGUID    4 f b t \054 0     0 float4in float4out float4recv float4send - - -
ip f 0 -1 0 _null_ _null_ )); 
  DESCR("single-precision floating point number, 4-byte storage");
  #define FLOAT4OID 700
! DATA(insert OID = 701 (  float8    PGNSP PGUID    8 f b t \054 0     0 float8in float8out float8recv float8send - - -
dp f 0 -1 0 _null_ _null_ )); 
  DESCR("double-precision floating point number, 8-byte storage");
  #define FLOAT8OID 701
! DATA(insert OID = 702 (  abstime   PGNSP PGUID    4 t b t \054 0     0 abstimein abstimeout abstimerecv abstimesend -
-- i p f 0 -1 0 _null_ _null_ )); 
  DESCR("absolute, limited-range date and time (Unix system time)");
  #define ABSTIMEOID        702
! DATA(insert OID = 703 (  reltime   PGNSP PGUID    4 t b t \054 0     0 reltimein reltimeout reltimerecv reltimesend -
-- i p f 0 -1 0 _null_ _null_ )); 
  DESCR("relative, limited-range time interval (Unix delta time)");
  #define RELTIMEOID        703
! DATA(insert OID = 704 (  tinterval PGNSP PGUID 12 f b t \054 0     0 tintervalin tintervalout tintervalrecv
tintervalsend- - - i p f 0 -1 0 _null_ _null_ )); 
  DESCR("(abstime,abstime), time interval");
  #define TINTERVALOID    704
! DATA(insert OID = 705 (  unknown   PGNSP PGUID -2 f b t \054 0     0 unknownin unknownout unknownrecv unknownsend - -
-c p f 0 -1 0 _null_ _null_ )); 
  DESCR("");
  #define UNKNOWNOID        705

! DATA(insert OID = 718 (  circle    PGNSP PGUID    24 f b t \054 0 0 circle_in circle_out circle_recv circle_send - -
-d p f 0 -1 0 _null_ _null_ )); 
  DESCR("geometric circle '(center,radius)'");
  #define CIRCLEOID        718
! DATA(insert OID = 719 (  _circle   PGNSP PGUID    -1 f b t \054 0  718 array_in array_out array_recv array_send - - -
dx f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 790 (  money       PGNSP PGUID     8 f b t \054 0 0 cash_in cash_out cash_recv cash_send - - - d p
f0 -1 0 _null_ _null_ )); 
  DESCR("monetary amounts, $d,ddd.cc");
  #define CASHOID 790
! DATA(insert OID = 791 (  _money    PGNSP PGUID    -1 f b t \054 0  790 array_in array_out array_recv array_send - - -
dx f 0 -1 0 _null_ _null_ )); 

  /* OIDS 800 - 899 */
! DATA(insert OID = 829 ( macaddr    PGNSP PGUID    6 f b t \054 0 0 macaddr_in macaddr_out macaddr_recv macaddr_send -
-- i p f 0 -1 0 _null_ _null_ )); 
  DESCR("XX:XX:XX:XX:XX:XX, MAC address");
  #define MACADDROID 829
! DATA(insert OID = 869 ( inet       PGNSP PGUID    -1 f b t \054 0 0 inet_in inet_out inet_recv inet_send - - - i m f
0-1 0 _null_ _null_ )); 
  DESCR("IP address/netmask, host address, netmask optional");
  #define INETOID 869
! DATA(insert OID = 650 ( cidr       PGNSP PGUID    -1 f b t \054 0 0 cidr_in cidr_out cidr_recv cidr_send - - - i m f
0-1 0 _null_ _null_ )); 
  DESCR("network IP address/netmask, network address");
  #define CIDROID 650

  /* OIDS 900 - 999 */

  /* OIDS 1000 - 1099 */
! DATA(insert OID = 1000 (  _bool         PGNSP PGUID -1 f b t \054 0    16 array_in array_out array_recv array_send -
-- i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1001 (  _bytea     PGNSP PGUID -1 f b t \054 0    17 array_in array_out array_recv array_send - - -
ix f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1002 (  _char         PGNSP PGUID -1 f b t \054 0    18 array_in array_out array_recv array_send -
-- i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1003 (  _name         PGNSP PGUID -1 f b t \054 0    19 array_in array_out array_recv array_send -
-- i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1005 (  _int2         PGNSP PGUID -1 f b t \054 0    21 array_in array_out array_recv array_send -
-- i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1006 (  _int2vector PGNSP PGUID -1 f b t \054 0    22 array_in array_out array_recv array_send - -
-i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1007 (  _int4         PGNSP PGUID -1 f b t \054 0    23 array_in array_out array_recv array_send -
-- i x f 0 -1 0 _null_ _null_ )); 
  #define INT4ARRAYOID        1007
! DATA(insert OID = 1008 (  _regproc     PGNSP PGUID -1 f b t \054 0    24 array_in array_out array_recv array_send - -
-i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1009 (  _text         PGNSP PGUID -1 f b t \054 0    25 array_in array_out array_recv array_send -
-- i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1028 (  _oid         PGNSP PGUID -1 f b t \054 0    26 array_in array_out array_recv array_send - -
-i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1010 (  _tid         PGNSP PGUID -1 f b t \054 0    27 array_in array_out array_recv array_send - -
-i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1011 (  _xid         PGNSP PGUID -1 f b t \054 0    28 array_in array_out array_recv array_send - -
-i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1012 (  _cid         PGNSP PGUID -1 f b t \054 0    29 array_in array_out array_recv array_send - -
-i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1013 (  _oidvector PGNSP PGUID -1 f b t \054 0    30 array_in array_out array_recv array_send - - -
ix f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1014 (  _bpchar     PGNSP PGUID -1 f b t \054 0 1042 array_in array_out array_recv array_send
bpchartypmodinbpchartypmodout - i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1015 (  _varchar     PGNSP PGUID -1 f b t \054 0 1043 array_in array_out array_recv array_send
varchartypmodinvarchartypmodout - i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1016 (  _int8         PGNSP PGUID -1 f b t \054 0    20 array_in array_out array_recv array_send -
-- d x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1017 (  _point     PGNSP PGUID -1 f b t \054 0 600 array_in array_out array_recv array_send - - - d
xf 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1018 (  _lseg         PGNSP PGUID -1 f b t \054 0 601 array_in array_out array_recv array_send - -
-d x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1019 (  _path         PGNSP PGUID -1 f b t \054 0 602 array_in array_out array_recv array_send - -
-d x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1020 (  _box         PGNSP PGUID -1 f b t \073 0 603 array_in array_out array_recv array_send - - -
dx f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1021 (  _float4     PGNSP PGUID -1 f b t \054 0 700 array_in array_out array_recv array_send - - -
ix f 0 -1 0 _null_ _null_ )); 
  #define FLOAT4ARRAYOID 1021
! DATA(insert OID = 1022 (  _float8     PGNSP PGUID -1 f b t \054 0 701 array_in array_out array_recv array_send - - -
dx f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1023 (  _abstime     PGNSP PGUID -1 f b t \054 0 702 array_in array_out array_recv array_send - - -
ix f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1024 (  _reltime     PGNSP PGUID -1 f b t \054 0 703 array_in array_out array_recv array_send - - -
ix f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1025 (  _tinterval PGNSP PGUID -1 f b t \054 0 704 array_in array_out array_recv array_send - - - i
xf 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1027 (  _polygon     PGNSP PGUID -1 f b t \054 0 604 array_in array_out array_recv array_send - - -
dx f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1033 (  aclitem     PGNSP PGUID 12 f b t \054 0 0 aclitemin aclitemout - - - - - i p f 0 -1 0
_null__null_ )); 
  DESCR("access control list");
  #define ACLITEMOID        1033
! DATA(insert OID = 1034 (  _aclitem     PGNSP PGUID -1 f b t \054 0 1033 array_in array_out array_recv array_send - -
-i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1040 (  _macaddr     PGNSP PGUID -1 f b t \054 0  829 array_in array_out array_recv array_send - -
-i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1041 (  _inet    PGNSP PGUID -1 f b t \054 0    869 array_in array_out array_recv array_send - - -
ix f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 651  (  _cidr    PGNSP PGUID -1 f b t \054 0    650 array_in array_out array_recv array_send - - -
ix f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1042 ( bpchar         PGNSP PGUID -1 f b t \054 0    0 bpcharin bpcharout bpcharrecv bpcharsend
bpchartypmodinbpchartypmodout - i x f 0 -1 0 _null_ _null_ )); 
  DESCR("char(length), blank-padded string, fixed storage length");
  #define BPCHAROID        1042
! DATA(insert OID = 1043 ( varchar     PGNSP PGUID -1 f b t \054 0    0 varcharin varcharout varcharrecv varcharsend
varchartypmodinvarchartypmodout - i x f 0 -1 0 _null_ _null_ )); 
  DESCR("varchar(length), non-blank-padded string, variable storage length");
  #define VARCHAROID        1043

! DATA(insert OID = 1082 ( date         PGNSP PGUID    4 t b t \054 0    0 date_in date_out date_recv date_send - - - i
pf 0 -1 0 _null_ _null_ )); 
  DESCR("ANSI SQL date");
  #define DATEOID            1082
! DATA(insert OID = 1083 ( time         PGNSP PGUID    8 f b t \054 0    0 time_in time_out time_recv time_send
timetypmodintimetypmodout - d p f 0 -1 0 _null_ _null_ )); 
  DESCR("hh:mm:ss, ANSI SQL time");
  #define TIMEOID            1083

  /* OIDS 1100 - 1199 */
! DATA(insert OID = 1114 ( timestamp     PGNSP PGUID    8 f b t \054 0    0 timestamp_in timestamp_out timestamp_recv
timestamp_sendtimestamptypmodin timestamptypmodout - d p f 0 -1 0 _null_ _null_ )); 
  DESCR("date and time");
  #define TIMESTAMPOID    1114
! DATA(insert OID = 1115 ( _timestamp  PGNSP PGUID    -1 f b t \054 0 1114 array_in array_out array_recv array_send
timestamptypmodintimestamptypmodout - d x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1182 ( _date         PGNSP PGUID    -1 f b t \054 0 1082 array_in array_out array_recv array_send -
-- i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1183 ( _time         PGNSP PGUID    -1 f b t \054 0 1083 array_in array_out array_recv array_send
timetypmodintimetypmodout - d x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1184 ( timestamptz PGNSP PGUID    8 f b t \054 0    0 timestamptz_in timestamptz_out
timestamptz_recvtimestamptz_send timestamptztypmodin timestamptztypmodout - d p f 0 -1 0 _null_ _null_ )); 
  DESCR("date and time with time zone");
  #define TIMESTAMPTZOID    1184
! DATA(insert OID = 1185 ( _timestamptz PGNSP PGUID -1 f b t \054 0    1184 array_in array_out array_recv array_send
timestamptztypmodintimestamptztypmodout - d x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1186 ( interval     PGNSP PGUID 16 f b t \054 0    0 interval_in interval_out interval_recv
interval_sendintervaltypmodin intervaltypmodout - d p f 0 -1 0 _null_ _null_ )); 
  DESCR("@ <number> <units>, time interval");
  #define INTERVALOID        1186
! DATA(insert OID = 1187 ( _interval     PGNSP PGUID    -1 f b t \054 0 1186 array_in array_out array_recv array_send
intervaltypmodinintervaltypmodout - d x f 0 -1 0 _null_ _null_ )); 

  /* OIDS 1200 - 1299 */
! DATA(insert OID = 1231 (  _numeric     PGNSP PGUID -1 f b t \054 0    1700 array_in array_out array_recv array_send
numerictypmodinnumerictypmodout - i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1266 ( timetz         PGNSP PGUID 12 f b t \054 0    0 timetz_in timetz_out timetz_recv timetz_send
timetztypmodintimetztypmodout - d p f 0 -1 0 _null_ _null_ )); 
  DESCR("hh:mm:ss, ANSI SQL time");
  #define TIMETZOID        1266
! DATA(insert OID = 1270 ( _timetz     PGNSP PGUID -1 f b t \054 0    1266 array_in array_out array_recv array_send
timetztypmodintimetztypmodout - d x f 0 -1 0 _null_ _null_ )); 

  /* OIDS 1500 - 1599 */
! DATA(insert OID = 1560 ( bit         PGNSP PGUID -1 f b t \054 0    0 bit_in bit_out bit_recv bit_send bittypmodin
bittypmodout- i x f 0 -1 0 _null_ _null_ )); 
  DESCR("fixed-length bit string");
  #define BITOID     1560
! DATA(insert OID = 1561 ( _bit         PGNSP PGUID -1 f b t \054 0    1560 array_in array_out array_recv array_send
bittypmodinbittypmodout - i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1562 ( varbit         PGNSP PGUID -1 f b t \054 0    0 varbit_in varbit_out varbit_recv varbit_send
varbittypmodinvarbittypmodout - i x f 0 -1 0 _null_ _null_ )); 
  DESCR("variable-length bit string");
  #define VARBITOID      1562
! DATA(insert OID = 1563 ( _varbit     PGNSP PGUID -1 f b t \054 0    1562 array_in array_out array_recv array_send
varbittypmodinvarbittypmodout - i x f 0 -1 0 _null_ _null_ )); 

  /* OIDS 1600 - 1699 */

  /* OIDS 1700 - 1799 */
! DATA(insert OID = 1700 ( numeric       PGNSP PGUID -1 f b t \054 0    0 numeric_in numeric_out numeric_recv
numeric_sendnumerictypmodin numerictypmodout - i m f 0 -1 0 _null_ _null_ )); 
  DESCR("numeric(precision, decimal), arbitrary precision number");
  #define NUMERICOID        1700

! DATA(insert OID = 1790 ( refcursor       PGNSP PGUID -1 f b t \054 0    0 textin textout textrecv textsend - - - i x
f0 -1 0 _null_ _null_ )); 
  DESCR("reference cursor (portal name)");
  #define REFCURSOROID    1790

  /* OIDS 2200 - 2299 */
! DATA(insert OID = 2201 ( _refcursor    PGNSP PGUID -1 f b t \054 0 1790 array_in array_out array_recv array_send - -
-i x f 0 -1 0 _null_ _null_ )); 

! DATA(insert OID = 2202 ( regprocedure  PGNSP PGUID    4 t b t \054 0     0 regprocedurein regprocedureout
regprocedurerecvregproceduresend - - - i p f 0 -1 0 _null_ _null_ )); 
  DESCR("registered procedure (with args)");
  #define REGPROCEDUREOID 2202

! DATA(insert OID = 2203 ( regoper       PGNSP PGUID    4 t b t \054 0     0 regoperin regoperout regoperrecv
regopersend- - - i p f 0 -1 0 _null_ _null_ )); 
  DESCR("registered operator");
  #define REGOPEROID        2203

! DATA(insert OID = 2204 ( regoperator   PGNSP PGUID    4 t b t \054 0     0 regoperatorin regoperatorout
regoperatorrecvregoperatorsend - - - i p f 0 -1 0 _null_ _null_ )); 
  DESCR("registered operator (with args)");
  #define REGOPERATOROID    2204

! DATA(insert OID = 2205 ( regclass       PGNSP PGUID    4 t b t \054 0     0 regclassin regclassout regclassrecv
regclasssend- - - i p f 0 -1 0 _null_ _null_ )); 
  DESCR("registered class");
  #define REGCLASSOID        2205

! DATA(insert OID = 2206 ( regtype       PGNSP PGUID    4 t b t \054 0     0 regtypein regtypeout regtyperecv
regtypesend- - - i p f 0 -1 0 _null_ _null_ )); 
  DESCR("registered type");
  #define REGTYPEOID        2206

! DATA(insert OID = 2207 ( _regprocedure PGNSP PGUID -1 f b t \054 0 2202 array_in array_out array_recv array_send - -
-i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 2208 ( _regoper       PGNSP PGUID -1 f b t \054 0 2203 array_in array_out array_recv array_send - -
-i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 2209 ( _regoperator  PGNSP PGUID -1 f b t \054 0 2204 array_in array_out array_recv array_send - -
-i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 2210 ( _regclass       PGNSP PGUID -1 f b t \054 0 2205 array_in array_out array_recv array_send -
-- i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 2211 ( _regtype       PGNSP PGUID -1 f b t \054 0 2206 array_in array_out array_recv array_send - -
-i x f 0 -1 0 _null_ _null_ )); 
  #define REGTYPEARRAYOID 2211

  /* uuid */
! DATA(insert OID = 2950 ( uuid            PGNSP PGUID 16 f b t \054 0 0 uuid_in uuid_out uuid_recv uuid_send - - - c p
f0 -1 0 _null_ _null_ )); 
  DESCR("UUID datatype");
! DATA(insert OID = 2951 ( _uuid            PGNSP PGUID -1 f b t \054 0 2950 array_in array_out array_recv array_send -
-- i x f 0 -1 0 _null_ _null_ )); 

  /*
   * pseudo-types
--- 348,547 ----
  /* OIDS 500 - 599 */

  /* OIDS 600 - 699 */
! DATA(insert OID = 600 (  point       PGNSP PGUID 16 f b t \054 0 701 1017 point_in point_out point_recv point_send -
-- d p f 0 -1 0 _null_ _null_ )); 
  DESCR("geometric point '(x, y)'");
  #define POINTOID        600
! DATA(insert OID = 601 (  lseg       PGNSP PGUID 32 f b t \054 0 600 1018 lseg_in lseg_out lseg_recv lseg_send - - - d
pf 0 -1 0 _null_ _null_ )); 
  DESCR("geometric line segment '(pt1,pt2)'");
  #define LSEGOID            601
! DATA(insert OID = 602 (  path       PGNSP PGUID -1 f b t \054 0 0 1019 path_in path_out path_recv path_send - - - d x
f0 -1 0 _null_ _null_ )); 
  DESCR("geometric path '(pt1,...)'");
  #define PATHOID            602
! DATA(insert OID = 603 (  box       PGNSP PGUID 32 f b t \073 0 600 1020 box_in box_out box_recv box_send - - - d p f
0-1 0 _null_ _null_ )); 
  DESCR("geometric box '(lower left,upper right)'");
  #define BOXOID            603
! DATA(insert OID = 604 (  polygon   PGNSP PGUID -1 f b t \054 0     0 1027 poly_in poly_out poly_recv poly_send - - -
dx f 0 -1 0 _null_ _null_ )); 
  DESCR("geometric polygon '(pt1,...)'");
  #define POLYGONOID        604

! DATA(insert OID = 628 (  line       PGNSP PGUID 32 f b t \054 0 701 629 line_in line_out line_recv line_send - - - d
pf 0 -1 0 _null_ _null_ )); 
  DESCR("geometric line (not implemented)'");
  #define LINEOID            628
! DATA(insert OID = 629 (  _line       PGNSP PGUID    -1 f b t \054 0 628 0 array_in array_out array_recv array_send -
-- d x f 0 -1 0 _null_ _null_ )); 
  DESCR("");

  /* OIDS 700 - 799 */

! DATA(insert OID = 700 (  float4    PGNSP PGUID    4 f b t \054 0     0 1021 float4in float4out float4recv float4send
-- - i p f 0 -1 0 _null_ _null_ )); 
  DESCR("single-precision floating point number, 4-byte storage");
  #define FLOAT4OID 700
! DATA(insert OID = 701 (  float8    PGNSP PGUID    8 f b t \054 0     0 1022 float8in float8out float8recv float8send
-- - d p f 0 -1 0 _null_ _null_ )); 
  DESCR("double-precision floating point number, 8-byte storage");
  #define FLOAT8OID 701
! DATA(insert OID = 702 (  abstime   PGNSP PGUID    4 t b t \054 0     0 1023 abstimein abstimeout abstimerecv
abstimesend- - - i p f 0 -1 0 _null_ _null_ )); 
  DESCR("absolute, limited-range date and time (Unix system time)");
  #define ABSTIMEOID        702
! DATA(insert OID = 703 (  reltime   PGNSP PGUID    4 t b t \054 0     0 1024 reltimein reltimeout reltimerecv
reltimesend- - - i p f 0 -1 0 _null_ _null_ )); 
  DESCR("relative, limited-range time interval (Unix delta time)");
  #define RELTIMEOID        703
! DATA(insert OID = 704 (  tinterval PGNSP PGUID 12 f b t \054 0     0 1025 tintervalin tintervalout tintervalrecv
tintervalsend- - - i p f 0 -1 0 _null_ _null_ )); 
  DESCR("(abstime,abstime), time interval");
  #define TINTERVALOID    704
! DATA(insert OID = 705 (  unknown   PGNSP PGUID -2 f b t \054 0     0 0 unknownin unknownout unknownrecv unknownsend -
-- c p f 0 -1 0 _null_ _null_ )); 
  DESCR("");
  #define UNKNOWNOID        705

! DATA(insert OID = 718 (  circle    PGNSP PGUID    24 f b t \054 0 0 719 circle_in circle_out circle_recv circle_send
-- - d p f 0 -1 0 _null_ _null_ )); 
  DESCR("geometric circle '(center,radius)'");
  #define CIRCLEOID        718
! DATA(insert OID = 719 (  _circle   PGNSP PGUID    -1 f b t \054 0  718 0 array_in array_out array_recv array_send - -
-d x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 790 (  money       PGNSP PGUID     8 f b t \054 0 0 791 cash_in cash_out cash_recv cash_send - - -
dp f 0 -1 0 _null_ _null_ )); 
  DESCR("monetary amounts, $d,ddd.cc");
  #define CASHOID 790
! DATA(insert OID = 791 (  _money    PGNSP PGUID    -1 f b t \054 0  790 0 array_in array_out array_recv array_send - -
-d x f 0 -1 0 _null_ _null_ )); 

  /* OIDS 800 - 899 */
! DATA(insert OID = 829 ( macaddr    PGNSP PGUID    6 f b t \054 0 0 1040 macaddr_in macaddr_out macaddr_recv
macaddr_send- - - i p f 0 -1 0 _null_ _null_ )); 
  DESCR("XX:XX:XX:XX:XX:XX, MAC address");
  #define MACADDROID 829
! DATA(insert OID = 869 ( inet       PGNSP PGUID    -1 f b t \054 0 0 1041 inet_in inet_out inet_recv inet_send - - - i
mf 0 -1 0 _null_ _null_ )); 
  DESCR("IP address/netmask, host address, netmask optional");
  #define INETOID 869
! DATA(insert OID = 650 ( cidr       PGNSP PGUID    -1 f b t \054 0 0 651 cidr_in cidr_out cidr_recv cidr_send - - - i
mf 0 -1 0 _null_ _null_ )); 
  DESCR("network IP address/netmask, network address");
  #define CIDROID 650

  /* OIDS 900 - 999 */

  /* OIDS 1000 - 1099 */
! DATA(insert OID = 1000 (  _bool         PGNSP PGUID -1 f b t \054 0    16 0 array_in array_out array_recv array_send
-- - i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1001 (  _bytea     PGNSP PGUID -1 f b t \054 0    17 0 array_in array_out array_recv array_send - -
-i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1002 (  _char         PGNSP PGUID -1 f b t \054 0    18 0 array_in array_out array_recv array_send
-- - i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1003 (  _name         PGNSP PGUID -1 f b t \054 0    19 0 array_in array_out array_recv array_send
-- - i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1005 (  _int2         PGNSP PGUID -1 f b t \054 0    21 0 array_in array_out array_recv array_send
-- - i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1006 (  _int2vector PGNSP PGUID -1 f b t \054 0    22 0 array_in array_out array_recv array_send -
-- i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1007 (  _int4         PGNSP PGUID -1 f b t \054 0    23 0 array_in array_out array_recv array_send
-- - i x f 0 -1 0 _null_ _null_ )); 
  #define INT4ARRAYOID        1007
! DATA(insert OID = 1008 (  _regproc     PGNSP PGUID -1 f b t \054 0    24 0 array_in array_out array_recv array_send -
-- i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1009 (  _text         PGNSP PGUID -1 f b t \054 0    25 0 array_in array_out array_recv array_send
-- - i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1028 (  _oid         PGNSP PGUID -1 f b t \054 0    26 0 array_in array_out array_recv array_send -
-- i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1010 (  _tid         PGNSP PGUID -1 f b t \054 0    27 0 array_in array_out array_recv array_send -
-- i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1011 (  _xid         PGNSP PGUID -1 f b t \054 0    28 0 array_in array_out array_recv array_send -
-- i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1012 (  _cid         PGNSP PGUID -1 f b t \054 0    29 0 array_in array_out array_recv array_send -
-- i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1013 (  _oidvector PGNSP PGUID -1 f b t \054 0    30 0 array_in array_out array_recv array_send - -
-i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1014 (  _bpchar     PGNSP PGUID -1 f b t \054 0 1042 0 array_in array_out array_recv array_send
bpchartypmodinbpchartypmodout - i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1015 (  _varchar     PGNSP PGUID -1 f b t \054 0 1043 0 array_in array_out array_recv array_send
varchartypmodinvarchartypmodout - i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1016 (  _int8         PGNSP PGUID -1 f b t \054 0    20 0 array_in array_out array_recv array_send
-- - d x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1017 (  _point     PGNSP PGUID -1 f b t \054 0 600 0 array_in array_out array_recv array_send - - -
dx f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1018 (  _lseg         PGNSP PGUID -1 f b t \054 0 601 0 array_in array_out array_recv array_send -
-- d x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1019 (  _path         PGNSP PGUID -1 f b t \054 0 602 0 array_in array_out array_recv array_send -
-- d x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1020 (  _box         PGNSP PGUID -1 f b t \073 0 603 0 array_in array_out array_recv array_send - -
-d x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1021 (  _float4     PGNSP PGUID -1 f b t \054 0 700 0 array_in array_out array_recv array_send - -
-i x f 0 -1 0 _null_ _null_ )); 
  #define FLOAT4ARRAYOID 1021
! DATA(insert OID = 1022 (  _float8     PGNSP PGUID -1 f b t \054 0 701 0 array_in array_out array_recv array_send - -
-d x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1023 (  _abstime     PGNSP PGUID -1 f b t \054 0 702 0 array_in array_out array_recv array_send - -
-i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1024 (  _reltime     PGNSP PGUID -1 f b t \054 0 703 0 array_in array_out array_recv array_send - -
-i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1025 (  _tinterval PGNSP PGUID -1 f b t \054 0 704 0 array_in array_out array_recv array_send - - -
ix f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1027 (  _polygon     PGNSP PGUID -1 f b t \054 0 604 0 array_in array_out array_recv array_send - -
-d x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1033 (  aclitem     PGNSP PGUID 12 f b t \054 0 0 1034 aclitemin aclitemout - - - - - i p f 0 -1 0
_null__null_ )); 
  DESCR("access control list");
  #define ACLITEMOID        1033
! DATA(insert OID = 1034 (  _aclitem     PGNSP PGUID -1 f b t \054 0 1033 0 array_in array_out array_recv array_send -
-- i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1040 (  _macaddr     PGNSP PGUID -1 f b t \054 0  829 0 array_in array_out array_recv array_send -
-- i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1041 (  _inet    PGNSP PGUID -1 f b t \054 0    869 0 array_in array_out array_recv array_send - -
-i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 651  (  _cidr    PGNSP PGUID -1 f b t \054 0    650 0 array_in array_out array_recv array_send - -
-i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1042 ( bpchar         PGNSP PGUID -1 f b t \054 0    0 1014 bpcharin bpcharout bpcharrecv
bpcharsendbpchartypmodin bpchartypmodout - i x f 0 -1 0 _null_ _null_ )); 
  DESCR("char(length), blank-padded string, fixed storage length");
  #define BPCHAROID        1042
! DATA(insert OID = 1043 ( varchar     PGNSP PGUID -1 f b t \054 0    0 1015 varcharin varcharout varcharrecv
varcharsendvarchartypmodin varchartypmodout - i x f 0 -1 0 _null_ _null_ )); 
  DESCR("varchar(length), non-blank-padded string, variable storage length");
  #define VARCHAROID        1043

! DATA(insert OID = 1082 ( date         PGNSP PGUID    4 t b t \054 0    0 1182 date_in date_out date_recv date_send -
-- i p f 0 -1 0 _null_ _null_ )); 
  DESCR("ANSI SQL date");
  #define DATEOID            1082
! DATA(insert OID = 1083 ( time         PGNSP PGUID    8 f b t \054 0    0 1183 time_in time_out time_recv time_send
timetypmodintimetypmodout - d p f 0 -1 0 _null_ _null_ )); 
  DESCR("hh:mm:ss, ANSI SQL time");
  #define TIMEOID            1083

  /* OIDS 1100 - 1199 */
! DATA(insert OID = 1114 ( timestamp     PGNSP PGUID    8 f b t \054 0    0 1115 timestamp_in timestamp_out
timestamp_recvtimestamp_send timestamptypmodin timestamptypmodout - d p f 0 -1 0 _null_ _null_ )); 
  DESCR("date and time");
  #define TIMESTAMPOID    1114
! DATA(insert OID = 1115 ( _timestamp  PGNSP PGUID    -1 f b t \054 0 1114 0 array_in array_out array_recv array_send
timestamptypmodintimestamptypmodout - d x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1182 ( _date         PGNSP PGUID    -1 f b t \054 0 1082 0 array_in array_out array_recv array_send
-- - i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1183 ( _time         PGNSP PGUID    -1 f b t \054 0 1083 0 array_in array_out array_recv array_send
timetypmodintimetypmodout - d x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1184 ( timestamptz PGNSP PGUID    8 f b t \054 0    0 1185 timestamptz_in timestamptz_out
timestamptz_recvtimestamptz_send timestamptztypmodin timestamptztypmodout - d p f 0 -1 0 _null_ _null_ )); 
  DESCR("date and time with time zone");
  #define TIMESTAMPTZOID    1184
! DATA(insert OID = 1185 ( _timestamptz PGNSP PGUID -1 f b t \054 0    1184 0 array_in array_out array_recv array_send
timestamptztypmodintimestamptztypmodout - d x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1186 ( interval     PGNSP PGUID 16 f b t \054 0    0 1187 interval_in interval_out interval_recv
interval_sendintervaltypmodin intervaltypmodout - d p f 0 -1 0 _null_ _null_ )); 
  DESCR("@ <number> <units>, time interval");
  #define INTERVALOID        1186
! DATA(insert OID = 1187 ( _interval     PGNSP PGUID    -1 f b t \054 0 1186 0 array_in array_out array_recv array_send
intervaltypmodinintervaltypmodout - d x f 0 -1 0 _null_ _null_ )); 

  /* OIDS 1200 - 1299 */
! DATA(insert OID = 1231 (  _numeric     PGNSP PGUID -1 f b t \054 0    1700 0 array_in array_out array_recv array_send
numerictypmodinnumerictypmodout - i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1266 ( timetz         PGNSP PGUID 12 f b t \054 0    0 1270 timetz_in timetz_out timetz_recv
timetz_sendtimetztypmodin timetztypmodout - d p f 0 -1 0 _null_ _null_ )); 
  DESCR("hh:mm:ss, ANSI SQL time");
  #define TIMETZOID        1266
! DATA(insert OID = 1270 ( _timetz     PGNSP PGUID -1 f b t \054 0    1266 0 array_in array_out array_recv array_send
timetztypmodintimetztypmodout - d x f 0 -1 0 _null_ _null_ )); 

  /* OIDS 1500 - 1599 */
! DATA(insert OID = 1560 ( bit         PGNSP PGUID -1 f b t \054 0    0 1561 bit_in bit_out bit_recv bit_send
bittypmodinbittypmodout - i x f 0 -1 0 _null_ _null_ )); 
  DESCR("fixed-length bit string");
  #define BITOID     1560
! DATA(insert OID = 1561 ( _bit         PGNSP PGUID -1 f b t \054 0    1560 0 array_in array_out array_recv array_send
bittypmodinbittypmodout - i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 1562 ( varbit         PGNSP PGUID -1 f b t \054 0    0 1563 varbit_in varbit_out varbit_recv
varbit_sendvarbittypmodin varbittypmodout - i x f 0 -1 0 _null_ _null_ )); 
  DESCR("variable-length bit string");
  #define VARBITOID      1562
! DATA(insert OID = 1563 ( _varbit     PGNSP PGUID -1 f b t \054 0    1562 0 array_in array_out array_recv array_send
varbittypmodinvarbittypmodout - i x f 0 -1 0 _null_ _null_ )); 

  /* OIDS 1600 - 1699 */

  /* OIDS 1700 - 1799 */
! DATA(insert OID = 1700 ( numeric       PGNSP PGUID -1 f b t \054 0    0 1231 numeric_in numeric_out numeric_recv
numeric_sendnumerictypmodin numerictypmodout - i m f 0 -1 0 _null_ _null_ )); 
  DESCR("numeric(precision, decimal), arbitrary precision number");
  #define NUMERICOID        1700

! DATA(insert OID = 1790 ( refcursor       PGNSP PGUID -1 f b t \054 0    0 2201 textin textout textrecv textsend - - -
ix f 0 -1 0 _null_ _null_ )); 
  DESCR("reference cursor (portal name)");
  #define REFCURSOROID    1790

  /* OIDS 2200 - 2299 */
! DATA(insert OID = 2201 ( _refcursor    PGNSP PGUID -1 f b t \054 0 1790 0 array_in array_out array_recv array_send -
-- i x f 0 -1 0 _null_ _null_ )); 

! DATA(insert OID = 2202 ( regprocedure  PGNSP PGUID    4 t b t \054 0     0 2207 regprocedurein regprocedureout
regprocedurerecvregproceduresend - - - i p f 0 -1 0 _null_ _null_ )); 
  DESCR("registered procedure (with args)");
  #define REGPROCEDUREOID 2202

! DATA(insert OID = 2203 ( regoper       PGNSP PGUID    4 t b t \054 0     0 2208 regoperin regoperout regoperrecv
regopersend- - - i p f 0 -1 0 _null_ _null_ )); 
  DESCR("registered operator");
  #define REGOPEROID        2203

! DATA(insert OID = 2204 ( regoperator   PGNSP PGUID    4 t b t \054 0     0 2209 regoperatorin regoperatorout
regoperatorrecvregoperatorsend - - - i p f 0 -1 0 _null_ _null_ )); 
  DESCR("registered operator (with args)");
  #define REGOPERATOROID    2204

! DATA(insert OID = 2205 ( regclass       PGNSP PGUID    4 t b t \054 0     0 2210 regclassin regclassout regclassrecv
regclasssend- - - i p f 0 -1 0 _null_ _null_ )); 
  DESCR("registered class");
  #define REGCLASSOID        2205

! DATA(insert OID = 2206 ( regtype       PGNSP PGUID    4 t b t \054 0     0 2211 regtypein regtypeout regtyperecv
regtypesend- - - i p f 0 -1 0 _null_ _null_ )); 
  DESCR("registered type");
  #define REGTYPEOID        2206

! DATA(insert OID = 2207 ( _regprocedure PGNSP PGUID -1 f b t \054 0 2202 0 array_in array_out array_recv array_send -
-- i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 2208 ( _regoper       PGNSP PGUID -1 f b t \054 0 2203 0 array_in array_out array_recv array_send -
-- i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 2209 ( _regoperator  PGNSP PGUID -1 f b t \054 0 2204 0 array_in array_out array_recv array_send -
-- i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 2210 ( _regclass       PGNSP PGUID -1 f b t \054 0 2205 0 array_in array_out array_recv array_send
-- - i x f 0 -1 0 _null_ _null_ )); 
! DATA(insert OID = 2211 ( _regtype       PGNSP PGUID -1 f b t \054 0 2206 0 array_in array_out array_recv array_send -
-- i x f 0 -1 0 _null_ _null_ )); 
  #define REGTYPEARRAYOID 2211

  /* uuid */
! DATA(insert OID = 2950 ( uuid            PGNSP PGUID 16 f b t \054 0 0 2951 uuid_in uuid_out uuid_recv uuid_send - -
-c p f 0 -1 0 _null_ _null_ )); 
  DESCR("UUID datatype");
! DATA(insert OID = 2951 ( _uuid            PGNSP PGUID -1 f b t \054 0 2950 0 array_in array_out array_recv array_send
-- - i x f 0 -1 0 _null_ _null_ )); 

  /*
   * pseudo-types
***************
*** 548,574 ****
   * argument and result types (if supported by the function's implementation
   * language).
   */
! DATA(insert OID = 2249 ( record            PGNSP PGUID -1 f p t \054 0 0 record_in record_out record_recv record_send
-- - d x f 0 -1 0 _null_ _null_ )); 
  #define RECORDOID        2249
! DATA(insert OID = 2275 ( cstring        PGNSP PGUID -2 f p t \054 0 0 cstring_in cstring_out cstring_recv
cstring_send- - - c p f 0 -1 0 _null_ _null_ )); 
  #define CSTRINGOID        2275
! DATA(insert OID = 2276 ( any            PGNSP PGUID  4 t p t \054 0 0 any_in any_out - - - - - i p f 0 -1 0 _null_
_null_)); 
  #define ANYOID            2276
! DATA(insert OID = 2277 ( anyarray        PGNSP PGUID -1 f p t \054 0 0 anyarray_in anyarray_out anyarray_recv
anyarray_send- - - d x f 0 -1 0 _null_ _null_ )); 
  #define ANYARRAYOID        2277
! DATA(insert OID = 2278 ( void            PGNSP PGUID  4 t p t \054 0 0 void_in void_out - - - - - i p f 0 -1 0 _null_
_null_)); 
  #define VOIDOID            2278
! DATA(insert OID = 2279 ( trigger        PGNSP PGUID  4 t p t \054 0 0 trigger_in trigger_out - - - - - i p f 0 -1 0
_null__null_ )); 
  #define TRIGGEROID        2279
! DATA(insert OID = 2280 ( language_handler    PGNSP PGUID  4 t p t \054 0 0 language_handler_in language_handler_out -
-- - - i p f 0 -1 0 _null_ _null_ )); 
  #define LANGUAGE_HANDLEROID        2280
! DATA(insert OID = 2281 ( internal        PGNSP PGUID  4 t p t \054 0 0 internal_in internal_out - - - - - i p f 0 -1
0_null_ _null_ )); 
  #define INTERNALOID        2281
! DATA(insert OID = 2282 ( opaque            PGNSP PGUID  4 t p t \054 0 0 opaque_in opaque_out - - - - - i p f 0 -1 0
_null__null_ )); 
  #define OPAQUEOID        2282
! DATA(insert OID = 2283 ( anyelement        PGNSP PGUID  4 t p t \054 0 0 anyelement_in anyelement_out - - - - - i p f
0-1 0 _null_ _null_ )); 
  #define ANYELEMENTOID    2283
! DATA(insert OID = 3500 ( anyenum        PGNSP PGUID  4 t p t \054 0 0 anyenum_in anyenum_out - - - - - i p f 0 -1 0
_null__null_ )); 
  #define ANYENUMOID        3500


--- 552,578 ----
   * argument and result types (if supported by the function's implementation
   * language).
   */
! DATA(insert OID = 2249 ( record            PGNSP PGUID -1 f p t \054 0 0 0 record_in record_out record_recv
record_send- - - d x f 0 -1 0 _null_ _null_ )); 
  #define RECORDOID        2249
! DATA(insert OID = 2275 ( cstring        PGNSP PGUID -2 f p t \054 0 0 0 cstring_in cstring_out cstring_recv
cstring_send- - - c p f 0 -1 0 _null_ _null_ )); 
  #define CSTRINGOID        2275
! DATA(insert OID = 2276 ( any            PGNSP PGUID  4 t p t \054 0 0 0 any_in any_out - - - - - i p f 0 -1 0 _null_
_null_)); 
  #define ANYOID            2276
! DATA(insert OID = 2277 ( anyarray        PGNSP PGUID -1 f p t \054 0 0 0 anyarray_in anyarray_out anyarray_recv
anyarray_send- - - d x f 0 -1 0 _null_ _null_ )); 
  #define ANYARRAYOID        2277
! DATA(insert OID = 2278 ( void            PGNSP PGUID  4 t p t \054 0 0 0 void_in void_out - - - - - i p f 0 -1 0
_null__null_ )); 
  #define VOIDOID            2278
! DATA(insert OID = 2279 ( trigger        PGNSP PGUID  4 t p t \054 0 0 0 trigger_in trigger_out - - - - - i p f 0 -1 0
_null__null_ )); 
  #define TRIGGEROID        2279
! DATA(insert OID = 2280 ( language_handler    PGNSP PGUID  4 t p t \054 0 0 0 language_handler_in language_handler_out
-- - - - i p f 0 -1 0 _null_ _null_ )); 
  #define LANGUAGE_HANDLEROID        2280
! DATA(insert OID = 2281 ( internal        PGNSP PGUID  4 t p t \054 0 0 0 internal_in internal_out - - - - - i p f 0
-10 _null_ _null_ )); 
  #define INTERNALOID        2281
! DATA(insert OID = 2282 ( opaque            PGNSP PGUID  4 t p t \054 0 0 0 opaque_in opaque_out - - - - - i p f 0 -1
0_null_ _null_ )); 
  #define OPAQUEOID        2282
! DATA(insert OID = 2283 ( anyelement        PGNSP PGUID  4 t p t \054 0 0 0 anyelement_in anyelement_out - - - - - i p
f0 -1 0 _null_ _null_ )); 
  #define ANYELEMENTOID    2283
! DATA(insert OID = 3500 ( anyenum        PGNSP PGUID  4 t p t \054 0 0 0 anyenum_in anyenum_out - - - - - i p f 0 -1 0
_null__null_ )); 
  #define ANYENUMOID        3500


***************
*** 592,621 ****
   */
  extern Oid    TypeShellMake(const char *typeName, Oid typeNamespace);

! extern Oid TypeCreate(const char *typeName,
!            Oid typeNamespace,
!            Oid relationOid,
!            char relationKind,
!            int16 internalSize,
!            char typeType,
!            char typDelim,
!            Oid inputProcedure,
!            Oid outputProcedure,
!            Oid receiveProcedure,
!            Oid sendProcedure,
!            Oid typmodinProcedure,
!            Oid typmodoutProcedure,
!            Oid analyzeProcedure,
!            Oid elementType,
!            Oid baseType,
!            const char *defaultTypeValue,
!            char *defaultTypeBin,
!            bool passedByValue,
!            char alignment,
!            char storage,
!            int32 typeMod,
!            int32 typNDims,
!            bool typeNotNull);

  extern void GenerateTypeDependencies(Oid typeNamespace,
                           Oid typeObjectId,
--- 596,629 ----
   */
  extern Oid    TypeShellMake(const char *typeName, Oid typeNamespace);

! extern Oid TypeCreate(
!     const char *typeName,
!     Oid typeNamespace,
!     Oid relationOid,
!     char relationKind,
!     int16 internalSize,
!     char typeType,
!     char typDelim,
!     Oid inputProcedure,
!     Oid outputProcedure,
!     Oid receiveProcedure,
!     Oid sendProcedure,
!     Oid typmodinProcedure,
!     Oid typmodoutProcedure,
!     Oid analyzeProcedure,
!     Oid elementType,
!     Oid baseType,
!     const char *defaultTypeValue,
!     char *defaultTypeBin,
!     bool passedByValue,
!     char alignment,
!     char storage,
!     int32 typeMod,
!     int32 typNDims,
!     bool typeNotNull,
!     Oid arrayType,
!     bool is_array_type
! );

  extern void GenerateTypeDependencies(Oid typeNamespace,
                           Oid typeObjectId,
***************
*** 637,642 ****
  extern void TypeRename(const char *oldTypeName, Oid typeNamespace,
             const char *newTypeName);

! extern char *makeArrayTypeName(const char *typeName);

  #endif   /* PG_TYPE_H */
--- 645,650 ----
  extern void TypeRename(const char *oldTypeName, Oid typeNamespace,
             const char *newTypeName);

! extern char *makeArrayTypeName(const char *typeName, Oid typeNamespace);

  #endif   /* PG_TYPE_H */
Index: src/test/regress/expected/alter_table.out
===================================================================
RCS file: /cvsroot/pgsql/src/test/regress/expected/alter_table.out,v
retrieving revision 1.101
diff -c -r1.101 alter_table.out
*** src/test/regress/expected/alter_table.out    14 Feb 2007 01:58:58 -0000    1.101
--- src/test/regress/expected/alter_table.out    9 May 2007 22:56:17 -0000
***************
*** 1456,1468 ****
--- 1456,1471 ----

  -- clean up
  drop schema alter2 cascade;
+ NOTICE:  drop cascades to type alter2.ctype[]
  NOTICE:  drop cascades to composite type alter2.ctype
  NOTICE:  drop cascades to type alter2.ctype
  NOTICE:  drop cascades to type alter2.posint
  NOTICE:  drop cascades to function alter2.plus1(integer)
+ NOTICE:  drop cascades to type alter2.v1[]
  NOTICE:  drop cascades to view alter2.v1
  NOTICE:  drop cascades to rule _RETURN on view alter2.v1
  NOTICE:  drop cascades to sequence alter2.t1_f1_seq
  NOTICE:  drop cascades to default for table alter2.t1 column f1
+ NOTICE:  drop cascades to type alter2.t1[]
  NOTICE:  drop cascades to table alter2.t1
  NOTICE:  drop cascades to constraint t1_f2_check on table alter2.t1
Index: src/test/regress/expected/type_sanity.out
===================================================================
RCS file: /cvsroot/pgsql/src/test/regress/expected/type_sanity.out,v
retrieving revision 1.29
diff -c -r1.29 type_sanity.out
*** src/test/regress/expected/type_sanity.out    2 Apr 2007 03:49:42 -0000    1.29
--- src/test/regress/expected/type_sanity.out    9 May 2007 22:56:17 -0000
***************
*** 49,55 ****
  -- or basic types that do.
  SELECT p1.oid, p1.typname
  FROM pg_type as p1
! WHERE (p1.typtype = 'c' AND p1.typrelid = 0) OR
      (p1.typtype != 'c' AND p1.typrelid != 0);
   oid | typname
  -----+---------
--- 49,55 ----
  -- or basic types that do.
  SELECT p1.oid, p1.typname
  FROM pg_type as p1
! WHERE (p1.typtype = 'c' AND p1.typrelid = 0 AND p1.typname !~ '^_') OR
      (p1.typtype != 'c' AND p1.typrelid != 0);
   oid | typname
  -----+---------
***************
*** 69,74 ****
--- 69,84 ----
   705 | unknown
  (2 rows)

+ -- Make sure typarray points to a varlena array type of our own base
+ SELECT p1.oid, p1.typname as basetype, p2.typname as arraytype,
+        p2.typelem, p2.typlen
+ FROM   pg_type p1 left join pg_type p2 on (p1.typarray = p2.oid)
+ WHERE  p1.typarray <> 0 AND
+        (p2.oid IS NULL OR p2.typelem <> p1.oid OR p2.typlen <> -1);
+  oid | basetype | arraytype | typelem | typlen
+ -----+----------+-----------+---------+--------
+ (0 rows)
+
  -- Text conversion routines must be provided.
  SELECT p1.oid, p1.typname
  FROM pg_type as p1
Index: src/test/regress/sql/type_sanity.sql
===================================================================
RCS file: /cvsroot/pgsql/src/test/regress/sql/type_sanity.sql,v
retrieving revision 1.29
diff -c -r1.29 type_sanity.sql
*** src/test/regress/sql/type_sanity.sql    2 Apr 2007 03:49:42 -0000    1.29
--- src/test/regress/sql/type_sanity.sql    9 May 2007 22:56:17 -0000
***************
*** 46,52 ****

  SELECT p1.oid, p1.typname
  FROM pg_type as p1
! WHERE (p1.typtype = 'c' AND p1.typrelid = 0) OR
      (p1.typtype != 'c' AND p1.typrelid != 0);

  -- Look for basic or enum types that don't have an array type.
--- 46,52 ----

  SELECT p1.oid, p1.typname
  FROM pg_type as p1
! WHERE (p1.typtype = 'c' AND p1.typrelid = 0 AND p1.typname !~ '^_') OR
      (p1.typtype != 'c' AND p1.typrelid != 0);

  -- Look for basic or enum types that don't have an array type.
***************
*** 59,64 ****
--- 59,71 ----
       WHERE p2.typname = ('_' || p1.typname)::name AND
             p2.typelem = p1.oid);

+ -- Make sure typarray points to a varlena array type of our own base
+ SELECT p1.oid, p1.typname as basetype, p2.typname as arraytype,
+        p2.typelem, p2.typlen
+ FROM   pg_type p1 left join pg_type p2 on (p1.typarray = p2.oid)
+ WHERE  p1.typarray <> 0 AND
+        (p2.oid IS NULL OR p2.typelem <> p1.oid OR p2.typlen <> -1);
+
  -- Text conversion routines must be provided.

  SELECT p1.oid, p1.typname

Re: updated WIP: arrays of composites

From
Tom Lane
Date:
Andrew Dunstan <andrew@dunslane.net> writes:
> The attached version removes all the places we had NAMEDATALEN - 2
> restrictions on object names. If there's no objection I will commit this
> shortly, as I think it now does all the previously agreed things.

It needs some work yet, but I'll go over it and commit it.

BTW, just idly looking at this, I'm wondering whether we couldn't
now support arrays of domains too.  If record_in/record_out work for
array elements, why wouldn't domain_in/domain_out?

            regards, tom lane

Re: updated WIP: arrays of composites

From
Andrew Dunstan
Date:

Tom Lane wrote:
> Andrew Dunstan <andrew@dunslane.net> writes:
>
>> The attached version removes all the places we had NAMEDATALEN - 2
>> restrictions on object names. If there's no objection I will commit this
>> shortly, as I think it now does all the previously agreed things.
>>
>
> It needs some work yet, but I'll go over it and commit it.
>
> BTW, just idly looking at this, I'm wondering whether we couldn't
> now support arrays of domains too.  If record_in/record_out work for
> array elements, why wouldn't domain_in/domain_out?
>
>
>

Good question. I'm all in favor of doing that. Presumably we would not
in the case of a domain of an array type?

cheers

andrew

Re: updated WIP: arrays of composites

From
Tom Lane
Date:
Andrew Dunstan <andrew@dunslane.net> writes:
>>> Attached is my rework of David Fetter's array of composites patch. It
>>> has all the agreed modifications and checks, except altering the name
>>> mangling.

Applied with revisions.  There are some loose ends yet:

* I didn't do anything about arrays of domains.  Although I think they'd
basically work, there's one nasty fly in the ointment, which is ALTER
DOMAIN ADD CONSTRAINT.  get_rels_with_domain() is not smart enough to
detect arrays of domains, and its callers are not nearly smart enough to
apply their checks to arrays.  So I think this had better wait for 8.4.

BTW, I realized there's an existing bug here as of 8.2: when I enabled
domains over domains I didn't do anything with get_rels_with_domain().
Fortunately this is a relatively easy thing to deal with, we can just
recurse to find columns of derived domain types, which the callers don't
really need to treat any differently than they do now.  I'll go fix
that part.

* The feature leaves something to be desired in terms of usability,
because array[row()] doesn't work:

regression=# create type foo as (f1 int, f2 int);
CREATE TYPE
regression=# create table bar (ff1 foo[]);
CREATE TABLE
regression=# insert into bar values(array[row(1,2),row(3,4)]);
ERROR:  could not find array type for data type record
regression=#

You can only get it to work if you plaster ::foo onto *each* row()
construct.  Ugh.  This didn't seem trivial to improve.

* I'm a bit concerned about dump order.  If a user wants to create
types named "foo" and "_foo", he can, but it will only work if he
makes "_foo" first --- else the derived type for foo is in the way.
Since pg_dump has no clue about that constraint, it might easily
dump "foo" first leading to an unrestorable dump.  The most usable
solution would be to auto-rename previously created array types,
but I dunno how implementable that would be.

            regards, tom lane

Re: updated WIP: arrays of composites

From
Gregory Stark
Date:
"Tom Lane" <tgl@sss.pgh.pa.us> writes:

> * I'm a bit concerned about dump order.  If a user wants to create
> types named "foo" and "_foo", he can, but it will only work if he
> makes "_foo" first --- else the derived type for foo is in the way.
> Since pg_dump has no clue about that constraint, it might easily
> dump "foo" first leading to an unrestorable dump.  The most usable
> solution would be to auto-rename previously created array types,
> but I dunno how implementable that would be.

BTW, why exactly do we need array types to have names at all? The only
user-visible way to refer to these types is always by foo[] isn't it?

--
  Gregory Stark
  EnterpriseDB          http://www.enterprisedb.com


Re: updated WIP: arrays of composites

From
Tom Lane
Date:
Andrew Dunstan <andrew@dunslane.net> writes:
> Tom Lane wrote:
>> That's not really the most preferable solution, I think, seeing that it
>> still leaves the user with the problem of having to create the types in
>> the right order to start with.

> I'm not sure we can keep the _foo convention and avoid that.

Auto-rename.  I'm working on a patch now, and it doesn't look like it'll
be too awful.  Will post it for comments when it's working.

> ... I'd vote to revert the new name
> mangling piece (but keep the typarray mapping column), deprecate the use
> of the _foo convention, and abandon it next release.

I came across a comment in the source that says PG has been using _foo
for arrays since 3.1 (!).  I don't think we can get away with changing
it, certainly not with only one release cycle's notice.

The current code is OK from a compatibility point of view, since it only
changes _foo to something else in situations where the old way would've
failed outright.  I think we need to preserve that property ...

            regards, tom lane

Re: updated WIP: arrays of composites

From
Andrew Dunstan
Date:

Tom Lane wrote:
> Andrew Dunstan <andrew@dunslane.net> writes:
>
>> Tom Lane wrote:
>>
>>> That's not really the most preferable solution, I think, seeing that it
>>> still leaves the user with the problem of having to create the types in
>>> the right order to start with.
>>>
>
>
>> I'm not sure we can keep the _foo convention and avoid that.
>>
>
> Auto-rename.  I'm working on a patch now, and it doesn't look like it'll
> be too awful.  Will post it for comments when it's working.
>


Ok, cool. I look forward to it.

cheers

andrew

Re: updated WIP: arrays of composites

From
Andrew Dunstan
Date:
Tom Lane wrote:
>
> There is *tons* of legacy code that uses _foo, mainly because there was
> a time when we didn't support the [] notation in a lot of places where
> types can be named.  There still are some places, in fact:
>
> regression=# alter type widget[] set schema public;
> ERROR:  syntax error at or near "["
> LINE 1: alter type widget[] set schema public;
>                          ^
> regression=# alter type _widget set schema public;
> ERROR:  cannot alter array type widget[]
> HINT:  You can alter type widget, which will alter the array type as well.
> regression=#
>
> That particular one may not need fixed (anymore) but the real problem is
> the torches-and-pitchforks session that will ensue if we break legacy
> code for no reason beyond cosmetics.
>
> IIRC some of the contrib modules still have instances of _foo in
> their SQL scripts.
>

Then I think we need to work out a way to make pg_dump smart enough to
dump things in the right order.

Can we perhaps explicitly deprecate using the type name to refer to
array types?

cheers

andrew


Re: updated WIP: arrays of composites

From
Andrew Dunstan
Date:

Tom Lane wrote:
> Andrew Dunstan <andrew@dunslane.net> writes:
>
>> Then I think we need to work out a way to make pg_dump smart enough to
>> dump things in the right order.
>>
>
> That's not really the most preferable solution, I think, seeing that it
> still leaves the user with the problem of having to create the types in
> the right order to start with.
>
>
>

I'm not sure we can keep the _foo convention and avoid that. If we can't
find something sensible pretty quickly, I'd vote to revert the new name
mangling piece (but keep the typarray mapping column), deprecate the use
of the _foo convention, and abandon it next release. It would be a pity
though.

cheers

andrew

Re: updated WIP: arrays of composites

From
Tom Lane
Date:
Andrew Dunstan <andrew@dunslane.net> writes:
> Then I think we need to work out a way to make pg_dump smart enough to
> dump things in the right order.

That's not really the most preferable solution, I think, seeing that it
still leaves the user with the problem of having to create the types in
the right order to start with.

            regards, tom lane

Re: updated WIP: arrays of composites

From
Tom Lane
Date:
Andrew Dunstan <andrew@dunslane.net> writes:
> Tom Lane wrote:
>> Auto-rename.  I'm working on a patch now, and it doesn't look like it'll
>> be too awful.  Will post it for comments when it's working.

> Ok, cool. I look forward to it.

Here's a bare-bones patch (no doc or regression tests).  Seems to work.
Anyone think this is too ugly a way to proceed?

            regards, tom lane

Index: src/backend/catalog/heap.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/catalog/heap.c,v
retrieving revision 1.319
diff -c -r1.319 heap.c
*** src/backend/catalog/heap.c    11 May 2007 17:57:11 -0000    1.319
--- src/backend/catalog/heap.c    11 May 2007 23:18:51 -0000
***************
*** 797,802 ****
--- 797,803 ----
  {
      Relation    pg_class_desc;
      Relation    new_rel_desc;
+     Oid            old_type_oid;
      Oid            new_type_oid;
      Oid         new_array_oid = InvalidOid;

***************
*** 815,820 ****
--- 816,842 ----
                   errmsg("relation \"%s\" already exists", relname)));

      /*
+      * Since we are going to create a rowtype as well, also check for
+      * collision with an existing type name.  If there is one and it's
+      * an autogenerated array, we can rename it out of the way; otherwise
+      * we can at least give a good error message.
+      */
+     old_type_oid = GetSysCacheOid(TYPENAMENSP,
+                                   CStringGetDatum(relname),
+                                   ObjectIdGetDatum(relnamespace),
+                                   0, 0);
+     if (OidIsValid(old_type_oid))
+     {
+         if (!moveArrayTypeName(old_type_oid, relname, relnamespace))
+             ereport(ERROR,
+                     (errcode(ERRCODE_DUPLICATE_OBJECT),
+                      errmsg("type \"%s\" already exists", relname),
+                      errhint("A relation has an associated type of the same name, "
+                              "so you must use a name that doesn't conflict "
+                              "with any existing type.")));
+     }
+
+     /*
       * Allocate an OID for the relation, unless we were told what to use.
       *
       * The OID will be the relfilenode as well, so make sure it doesn't
***************
*** 861,868 ****
       * Since defining a relation also defines a complex type, we add a new
       * system type corresponding to the new relation.
       *
!      * NOTE: we could get a unique-index failure here, in case the same name
!      * has already been used for a type.
       */
      new_type_oid = AddNewRelationType(relname,
                                        relnamespace,
--- 883,891 ----
       * Since defining a relation also defines a complex type, we add a new
       * system type corresponding to the new relation.
       *
!      * NOTE: we could get a unique-index failure here, in case someone else is
!      * creating the same type name in parallel but hadn't committed yet
!      * when we checked for a duplicate name above.
       */
      new_type_oid = AddNewRelationType(relname,
                                        relnamespace,
Index: src/backend/catalog/pg_type.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/catalog/pg_type.c,v
retrieving revision 1.112
diff -c -r1.112 pg_type.c
*** src/backend/catalog/pg_type.c    11 May 2007 17:57:12 -0000    1.112
--- src/backend/catalog/pg_type.c    11 May 2007 23:18:51 -0000
***************
*** 15,20 ****
--- 15,21 ----
  #include "postgres.h"

  #include "access/heapam.h"
+ #include "access/xact.h"
  #include "catalog/dependency.h"
  #include "catalog/indexing.h"
  #include "catalog/pg_namespace.h"
***************
*** 26,31 ****
--- 27,33 ----
  #include "utils/acl.h"
  #include "utils/builtins.h"
  #include "utils/fmgroids.h"
+ #include "utils/lsyscache.h"
  #include "utils/syscache.h"


***************
*** 551,580 ****

  /*
   * TypeRename
!  *        This renames a type
   *
!  * Note: any associated array type is *not* renamed; caller must make
!  * another call to handle that case.  Currently this is only used for
!  * renaming types associated with tables, for which there are no arrays.
   */
  void
! TypeRename(const char *oldTypeName, Oid typeNamespace,
!            const char *newTypeName)
  {
      Relation    pg_type_desc;
      HeapTuple    tuple;

      pg_type_desc = heap_open(TypeRelationId, RowExclusiveLock);

!     tuple = SearchSysCacheCopy(TYPENAMENSP,
!                                CStringGetDatum(oldTypeName),
!                                ObjectIdGetDatum(typeNamespace),
!                                0, 0);
      if (!HeapTupleIsValid(tuple))
!         ereport(ERROR,
!                 (errcode(ERRCODE_UNDEFINED_OBJECT),
!                  errmsg("type \"%s\" does not exist", oldTypeName)));

      if (SearchSysCacheExists(TYPENAMENSP,
                               CStringGetDatum(newTypeName),
                               ObjectIdGetDatum(typeNamespace),
--- 553,587 ----

  /*
   * TypeRename
!  *        This renames a type, as well as any associated array type.
   *
!  * Note: this isn't intended to be a user-exposed function; it doesn't check
!  * permissions etc.  (Perhaps TypeRenameInternal would be a better name.)
!  * Currently this is only used for renaming table rowtypes.
   */
  void
! TypeRename(Oid typeOid, const char *newTypeName, Oid typeNamespace)
  {
      Relation    pg_type_desc;
      HeapTuple    tuple;
+     Form_pg_type typ;
+     Oid            arrayOid;

      pg_type_desc = heap_open(TypeRelationId, RowExclusiveLock);

!     tuple = SearchSysCacheCopy(TYPEOID,
!                                ObjectIdGetDatum(typeOid),
!                                0, 0, 0);
      if (!HeapTupleIsValid(tuple))
!         elog(ERROR, "cache lookup failed for type %u", typeOid);
!     typ = (Form_pg_type) GETSTRUCT(tuple);
!
!     /* We are not supposed to be changing schemas here */
!     Assert(typeNamespace == typ->typnamespace);

+     arrayOid = typ->typarray;
+
+     /* Just to give a more friendly error than unique-index violation */
      if (SearchSysCacheExists(TYPENAMENSP,
                               CStringGetDatum(newTypeName),
                               ObjectIdGetDatum(typeNamespace),
***************
*** 583,589 ****
                  (errcode(ERRCODE_DUPLICATE_OBJECT),
                   errmsg("type \"%s\" already exists", newTypeName)));

!     namestrcpy(&(((Form_pg_type) GETSTRUCT(tuple))->typname), newTypeName);

      simple_heap_update(pg_type_desc, &tuple->t_self, tuple);

--- 590,597 ----
                  (errcode(ERRCODE_DUPLICATE_OBJECT),
                   errmsg("type \"%s\" already exists", newTypeName)));

!     /* OK, do the rename --- tuple is a copy, so OK to scribble on it */
!     namestrcpy(&(typ->typname), newTypeName);

      simple_heap_update(pg_type_desc, &tuple->t_self, tuple);

***************
*** 592,602 ****

      heap_freetuple(tuple);
      heap_close(pg_type_desc, RowExclusiveLock);
  }


  /*
!  * makeArrayTypeName(typeName)
   *      - given a base type name, make an array type name for it
   *
   * the caller is responsible for pfreeing the result
--- 600,619 ----

      heap_freetuple(tuple);
      heap_close(pg_type_desc, RowExclusiveLock);
+
+     /* If the type has an array type, recurse to handle that */
+     if (OidIsValid(arrayOid))
+     {
+         char   *arrname = makeArrayTypeName(newTypeName, typeNamespace);
+
+         TypeRename(arrayOid, arrname, typeNamespace);
+         pfree(arrname);
+     }
  }


  /*
!  * makeArrayTypeName
   *      - given a base type name, make an array type name for it
   *
   * the caller is responsible for pfreeing the result
***************
*** 638,640 ****
--- 655,712 ----

      return arr;
  }
+
+
+ /*
+  * moveArrayTypeName
+  *      - try to reassign an array type name that the user wants to use.
+  *
+  * The given type name has been discovered to already exist (with the given
+  * OID).  If it is an autogenerated array type, change the array type's name
+  * to not conflict.  This allows the user to create type "foo" followed by
+  * type "_foo" without problems.  (Of course, there are race conditions if
+  * two backends try to create similarly-named types concurrently, but the
+  * worst that can happen is an unnecessary failure --- anything we do here
+  * will be rolled back if the type creation fails due to conflicting names.)
+  *
+  * Note that this must be called *before* calling makeArrayTypeName to
+  * determine the new type's own array type name; else the latter will
+  * certainly pick the same name.
+  *
+  * Returns TRUE if successfully moved the type, FALSE if not.
+  */
+ bool
+ moveArrayTypeName(Oid typeOid, const char *typeName, Oid typeNamespace)
+ {
+     Oid            elemOid;
+     char       *newname;
+
+     /*
+      * Can't change it if it's not an autogenerated array type.
+      */
+     elemOid = get_element_type(typeOid);
+     if (!OidIsValid(elemOid) ||
+         get_array_type(elemOid) != typeOid)
+         return false;
+
+     /*
+      * OK, use makeArrayTypeName to pick an unused modification of the
+      * name.  Note that since makeArrayTypeName is an iterative process,
+      * this will produce a name that it might have produced the first time,
+      * had the conflicting type we are about to create already existed.
+      */
+     newname = makeArrayTypeName(typeName, typeNamespace);
+
+     /* Apply the rename */
+     TypeRename(typeOid, newname, typeNamespace);
+
+     /*
+      * We must bump the command counter so that any subsequent use of
+      * makeArrayTypeName sees what we just did and doesn't pick the same name.
+      */
+     CommandCounterIncrement();
+
+     pfree(newname);
+
+     return true;
+ }
Index: src/backend/commands/tablecmds.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v
retrieving revision 1.221
diff -c -r1.221 tablecmds.c
*** src/backend/commands/tablecmds.c    11 May 2007 20:16:36 -0000    1.221
--- src/backend/commands/tablecmds.c    11 May 2007 23:18:52 -0000
***************
*** 1626,1631 ****
--- 1626,1632 ----
      Relation    targetrelation;
      Relation    relrelation;    /* for RELATION relation */
      HeapTuple    reltup;
+     Form_pg_class relform;
      Oid            namespaceId;
      char       *oldrelname;
      char        relkind;
***************
*** 1655,1664 ****
      relrelation = heap_open(RelationRelationId, RowExclusiveLock);

      reltup = SearchSysCacheCopy(RELOID,
!                                 PointerGetDatum(myrelid),
                                  0, 0, 0);
      if (!HeapTupleIsValid(reltup))        /* shouldn't happen */
          elog(ERROR, "cache lookup failed for relation %u", myrelid);

      if (get_relname_relid(newrelname, namespaceId) != InvalidOid)
          ereport(ERROR,
--- 1656,1666 ----
      relrelation = heap_open(RelationRelationId, RowExclusiveLock);

      reltup = SearchSysCacheCopy(RELOID,
!                                 ObjectIdGetDatum(myrelid),
                                  0, 0, 0);
      if (!HeapTupleIsValid(reltup))        /* shouldn't happen */
          elog(ERROR, "cache lookup failed for relation %u", myrelid);
+     relform = (Form_pg_class) GETSTRUCT(reltup);

      if (get_relname_relid(newrelname, namespaceId) != InvalidOid)
          ereport(ERROR,
***************
*** 1670,1676 ****
       * Update pg_class tuple with new relname.    (Scribbling on reltup is OK
       * because it's a copy...)
       */
!     namestrcpy(&(((Form_pg_class) GETSTRUCT(reltup))->relname), newrelname);

      simple_heap_update(relrelation, &reltup->t_self, reltup);

--- 1672,1678 ----
       * Update pg_class tuple with new relname.    (Scribbling on reltup is OK
       * because it's a copy...)
       */
!     namestrcpy(&(relform->relname), newrelname);

      simple_heap_update(relrelation, &reltup->t_self, reltup);

***************
*** 1683,1690 ****
      /*
       * Also rename the associated type, if any.
       */
!     if (relkind != RELKIND_INDEX)
!         TypeRename(oldrelname, namespaceId, newrelname);

      /*
       * Close rel, but keep exclusive lock!
--- 1685,1692 ----
      /*
       * Also rename the associated type, if any.
       */
!     if (OidIsValid(targetrelation->rd_rel->reltype))
!         TypeRename(targetrelation->rd_rel->reltype, newrelname, namespaceId);

      /*
       * Close rel, but keep exclusive lock!
Index: src/backend/commands/typecmds.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/commands/typecmds.c,v
retrieving revision 1.103
diff -c -r1.103 typecmds.c
*** src/backend/commands/typecmds.c    11 May 2007 20:16:54 -0000    1.103
--- src/backend/commands/typecmds.c    11 May 2007 23:18:52 -0000
***************
*** 137,149 ****

      /*
       * Look to see if type already exists (presumably as a shell; if not,
!      * TypeCreate will complain).  If it doesn't, create it as a shell, so
!      * that the OID is known for use in the I/O function definitions.
       */
      typoid = GetSysCacheOid(TYPENAMENSP,
                              CStringGetDatum(typeName),
                              ObjectIdGetDatum(typeNamespace),
                              0, 0);
      if (!OidIsValid(typoid))
      {
          typoid = TypeShellMake(typeName, typeNamespace);
--- 137,163 ----

      /*
       * Look to see if type already exists (presumably as a shell; if not,
!      * TypeCreate will complain).
       */
      typoid = GetSysCacheOid(TYPENAMENSP,
                              CStringGetDatum(typeName),
                              ObjectIdGetDatum(typeNamespace),
                              0, 0);
+
+     /*
+      * If it's not a shell, see if it's an autogenerated array type,
+      * and if so rename it out of the way.
+      */
+     if (OidIsValid(typoid) && get_typisdefined(typoid))
+     {
+         if (moveArrayTypeName(typoid, typeName, typeNamespace))
+             typoid = InvalidOid;
+     }
+
+     /*
+      * If it doesn't exist, create it as a shell, so that the OID is known
+      * for use in the I/O function definitions.
+      */
      if (!OidIsValid(typoid))
      {
          typoid = TypeShellMake(typeName, typeNamespace);
***************
*** 602,607 ****
--- 616,622 ----
      ListCell   *listptr;
      Oid            basetypeoid;
      Oid            domainoid;
+     Oid            old_type_oid;
      Form_pg_type baseType;
      int32        basetypeMod;

***************
*** 617,622 ****
--- 632,653 ----
                         get_namespace_name(domainNamespace));

      /*
+      * Check for collision with an existing type name.  If there is one and
+      * it's an autogenerated array, we can rename it out of the way.
+      */
+     old_type_oid = GetSysCacheOid(TYPENAMENSP,
+                                   CStringGetDatum(domainName),
+                                   ObjectIdGetDatum(domainNamespace),
+                                   0, 0);
+     if (OidIsValid(old_type_oid))
+     {
+         if (!moveArrayTypeName(old_type_oid, domainName, domainNamespace))
+             ereport(ERROR,
+                     (errcode(ERRCODE_DUPLICATE_OBJECT),
+                      errmsg("type \"%s\" already exists", domainName)));
+     }
+
+     /*
       * Look up the base type.
       */
      typeTup = typenameType(NULL, stmt->typename);
***************
*** 948,953 ****
--- 979,985 ----
      Oid        enumNamespace;
      Oid        enumTypeOid;
      AclResult    aclresult;
+     Oid        old_type_oid;
      Oid     enumArrayOid;
      Relation pg_type;

***************
*** 961,966 ****
--- 993,1014 ----
          aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
                         get_namespace_name(enumNamespace));

+     /*
+      * Check for collision with an existing type name.  If there is one and
+      * it's an autogenerated array, we can rename it out of the way.
+      */
+     old_type_oid = GetSysCacheOid(TYPENAMENSP,
+                                   CStringGetDatum(enumName),
+                                   ObjectIdGetDatum(enumNamespace),
+                                   0, 0);
+     if (OidIsValid(old_type_oid))
+     {
+         if (!moveArrayTypeName(old_type_oid, enumName, enumNamespace))
+             ereport(ERROR,
+                     (errcode(ERRCODE_DUPLICATE_OBJECT),
+                      errmsg("type \"%s\" already exists", enumName)));
+     }
+
      /* Preassign array type OID so we can insert it in pg_type.typarray */
      pg_type = heap_open(TypeRelationId, AccessShareLock);
      enumArrayOid = GetNewOid(pg_type);
Index: src/include/catalog/pg_type.h
===================================================================
RCS file: /cvsroot/pgsql/src/include/catalog/pg_type.h,v
retrieving revision 1.183
diff -c -r1.183 pg_type.h
*** src/include/catalog/pg_type.h    11 May 2007 17:57:13 -0000    1.183
--- src/include/catalog/pg_type.h    11 May 2007 23:18:52 -0000
***************
*** 645,653 ****
                           Node *defaultExpr,
                           bool rebuild);

! extern void TypeRename(const char *oldTypeName, Oid typeNamespace,
!            const char *newTypeName);

  extern char *makeArrayTypeName(const char *typeName, Oid typeNamespace);

  #endif   /* PG_TYPE_H */
--- 645,656 ----
                           Node *defaultExpr,
                           bool rebuild);

! extern void TypeRename(Oid typeOid, const char *newTypeName,
!                        Oid typeNamespace);

  extern char *makeArrayTypeName(const char *typeName, Oid typeNamespace);

+ extern bool moveArrayTypeName(Oid typeOid, const char *typeName,
+                               Oid typeNamespace);
+
  #endif   /* PG_TYPE_H */

Re: updated WIP: arrays of composites

From
Andrew Dunstan
Date:

Gregory Stark wrote:
> "Tom Lane" <tgl@sss.pgh.pa.us> writes:
>
>
>> * I'm a bit concerned about dump order.  If a user wants to create
>> types named "foo" and "_foo", he can, but it will only work if he
>> makes "_foo" first --- else the derived type for foo is in the way.
>> Since pg_dump has no clue about that constraint, it might easily
>> dump "foo" first leading to an unrestorable dump.  The most usable
>> solution would be to auto-rename previously created array types,
>> but I dunno how implementable that would be.
>>
>
> BTW, why exactly do we need array types to have names at all? The only
> user-visible way to refer to these types is always by foo[] isn't it?
>
>

I think you can use the _foo name, but it would certainly be an odd
thing to do.

I'd be happy to get rid of the name, or at least make it something very
unlikely indeed, but Tom didn't want to move too far from our present
naming convention. I am now wondering if we shouldn't at lest append
_arr or some such to the array type name, similarly to what we do for
generated sequence and index names.

cheers

andrew

Re: updated WIP: arrays of composites

From
Andrew Dunstan
Date:

Tom Lane wrote:
> Andrew Dunstan <andrew@dunslane.net> writes:
>
>> Tom Lane wrote:
>>
>>> Auto-rename.  I'm working on a patch now, and it doesn't look like it'll
>>> be too awful.  Will post it for comments when it's working.
>>>
>
>
>> Ok, cool. I look forward to it.
>>
>
> Here's a bare-bones patch (no doc or regression tests).  Seems to work.
> Anyone think this is too ugly a way to proceed?
>
>
>

Summarising the behaviour as I understand it:

. if you never name a type/table with a name beginning with underscore,
behaviour is as expected - type foo gets array type _foo
. if you create a type foo and then create a type _foo, the array type
for foo will first be renamed to __foo, and the new array type for _foo
will be ___foo
. if you create type _foo and then create type foo, the corresponding
array types will be __foo and ___foo as per my patch, with no renaming
required.

I think I like it. Certainly seems to get round the ordering problem nicely.

cheers

andrew


Re: updated WIP: arrays of composites

From
Tom Lane
Date:
Andrew Dunstan <andrew@dunslane.net> writes:
> Summarising the behaviour as I understand it:

> . if you never name a type/table with a name beginning with underscore,
> behaviour is as expected - type foo gets array type _foo
> . if you create a type foo and then create a type _foo, the array type
> for foo will first be renamed to __foo, and the new array type for _foo
> will be ___foo
> . if you create type _foo and then create type foo, the corresponding
> array types will be __foo and ___foo as per my patch, with no renaming
> required.

> I think I like it. Certainly seems to get round the ordering problem nicely.

At least as far as the user's names are concerned.  There's some
ordering dependency for the names that the array types end up with,
but we had that problem already; and AFAIK it shouldn't create any
big issue for dump/restore.

BTW, I forgot to mention that this patch also fixes an oversight in the
original patch: we all missed the fact that ALTER TABLE RENAME didn't
rename the rowtype's array type.

            regards, tom lane

Re: updated WIP: arrays of composites

From
Andrew Dunstan
Date:

Tom Lane wrote:
>
>> I think I like it. Certainly seems to get round the ordering problem nicely.
>>
>
> At least as far as the user's names are concerned.  There's some
> ordering dependency for the names that the array types end up with,
> but we had that problem already; and AFAIK it shouldn't create any
> big issue for dump/restore.
>

There will only be an issue if you use table/type names beginning with
underscore, right? And I don't think it will matter because nobody has
been relying on that to date as we haven't had array types for those. We
should probably document that relying on the array name is both fragile
and unnecessary.

> BTW, I forgot to mention that this patch also fixes an oversight in the
> original patch: we all missed the fact that ALTER TABLE RENAME didn't
> rename the rowtype's array type.
>
>

Oh, good catch. Sorry about that.

cheers

andrew

Re: updated WIP: arrays of composites

From
Tom Lane
Date:
Andrew Dunstan <andrew@dunslane.net> writes:
> Gregory Stark wrote:
>> BTW, why exactly do we need array types to have names at all?

Because typname is part of the primary key for pg_type ...

>> The only
>> user-visible way to refer to these types is always by foo[] isn't it?

> I think you can use the _foo name, but it would certainly be an odd
> thing to do.

There is *tons* of legacy code that uses _foo, mainly because there was
a time when we didn't support the [] notation in a lot of places where
types can be named.  There still are some places, in fact:

regression=# alter type widget[] set schema public;
ERROR:  syntax error at or near "["
LINE 1: alter type widget[] set schema public;
                         ^
regression=# alter type _widget set schema public;
ERROR:  cannot alter array type widget[]
HINT:  You can alter type widget, which will alter the array type as well.
regression=#

That particular one may not need fixed (anymore) but the real problem is
the torches-and-pitchforks session that will ensue if we break legacy
code for no reason beyond cosmetics.

IIRC some of the contrib modules still have instances of _foo in
their SQL scripts.

            regards, tom lane

Re: updated WIP: arrays of composites

From
Tom Lane
Date:
Andrew Dunstan <andrew@dunslane.net> writes:
> There will only be an issue if you use table/type names beginning with
> underscore, right? And I don't think it will matter because nobody has
> been relying on that to date as we haven't had array types for those. We
> should probably document that relying on the array name is both fragile
> and unnecessary.

I added this to the CREATE TYPE reference page, which AFAIR is the only
place that mentions the naming convention at all:

  <para>
   Before <productname>PostgreSQL</productname> version 8.3, the name of
   a generated array type was always exactly the element type's name with one
   underscore character (<literal>_</literal>) prepended.  (Type names were
   therefore restricted in length to one less character than other names.)
   While this is still usually the case, the array type name may vary from
   this in case of maximum-length names or collisions with user type names
   that begin with underscore.  Writing code that depends on this convention
   is therefore deprecated.  Instead, use
   <structname>pg_type</>.<structfield>typarray</> to locate the array type
   associated with a given type.
  </para>

  <para>
   It may be advisable to avoid using type and table names that begin with
   underscore.  While the server will change generated array type names to
   avoid collisions with user-given names, there is still risk of confusion,
   particularly with old client software that may assume that type names
   beginning with underscores always represent arrays.
  </para>

            regards, tom lane

Re: updated WIP: arrays of composites

From
Bruce Momjian
Date:
TODO marked as done:

        o -Add support for arrays of complex types

I assume this is _not_ done, as stated below:

        o Add support for arrays of domains

I will add a URL for this item:

    http://archives.postgresql.org/pgsql-patches/2007-05/msg00114.php

---------------------------------------------------------------------------

Tom Lane wrote:
> Andrew Dunstan <andrew@dunslane.net> writes:
> >>> Attached is my rework of David Fetter's array of composites patch. It
> >>> has all the agreed modifications and checks, except altering the name
> >>> mangling.
>
> Applied with revisions.  There are some loose ends yet:
>
> * I didn't do anything about arrays of domains.  Although I think they'd
> basically work, there's one nasty fly in the ointment, which is ALTER
> DOMAIN ADD CONSTRAINT.  get_rels_with_domain() is not smart enough to
> detect arrays of domains, and its callers are not nearly smart enough to
> apply their checks to arrays.  So I think this had better wait for 8.4.
>
> BTW, I realized there's an existing bug here as of 8.2: when I enabled
> domains over domains I didn't do anything with get_rels_with_domain().
> Fortunately this is a relatively easy thing to deal with, we can just
> recurse to find columns of derived domain types, which the callers don't
> really need to treat any differently than they do now.  I'll go fix
> that part.
>
> * The feature leaves something to be desired in terms of usability,
> because array[row()] doesn't work:
>
> regression=# create type foo as (f1 int, f2 int);
> CREATE TYPE
> regression=# create table bar (ff1 foo[]);
> CREATE TABLE
> regression=# insert into bar values(array[row(1,2),row(3,4)]);
> ERROR:  could not find array type for data type record
> regression=#
>
> You can only get it to work if you plaster ::foo onto *each* row()
> construct.  Ugh.  This didn't seem trivial to improve.
>
> * I'm a bit concerned about dump order.  If a user wants to create
> types named "foo" and "_foo", he can, but it will only work if he
> makes "_foo" first --- else the derived type for foo is in the way.
> Since pg_dump has no clue about that constraint, it might easily
> dump "foo" first leading to an unrestorable dump.  The most usable
> solution would be to auto-rename previously created array types,
> but I dunno how implementable that would be.
>
>             regards, tom lane
>
> ---------------------------(end of broadcast)---------------------------
> TIP 2: Don't 'kill -9' the postmaster

--
  Bruce Momjian  <bruce@momjian.us>          http://momjian.us
  EnterpriseDB                               http://www.enterprisedb.com

  + If your life is a hard drive, Christ can be your backup. +