]> granicus.if.org Git - postgresql/commitdiff
Support type modifiers for user-defined types, and pull most knowledge
authorTom Lane <tgl@sss.pgh.pa.us>
Sat, 30 Dec 2006 21:21:56 +0000 (21:21 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Sat, 30 Dec 2006 21:21:56 +0000 (21:21 +0000)
about typmod representation for standard types out into type-specific
typmod I/O functions.  Teodor Sigaev, with some editorialization by
Tom Lane.

47 files changed:
doc/src/sgml/catalogs.sgml
doc/src/sgml/keywords.sgml
doc/src/sgml/ref/create_type.sgml
src/backend/access/common/tupdesc.c
src/backend/catalog/heap.c
src/backend/catalog/pg_type.c
src/backend/commands/tablecmds.c
src/backend/commands/typecmds.c
src/backend/nodes/copyfuncs.c
src/backend/nodes/equalfuncs.c
src/backend/nodes/makefuncs.c
src/backend/nodes/outfuncs.c
src/backend/parser/gram.y
src/backend/parser/parse_expr.c
src/backend/parser/parse_relation.c
src/backend/parser/parse_type.c
src/backend/utils/adt/arrayutils.c
src/backend/utils/adt/date.c
src/backend/utils/adt/format_type.c
src/backend/utils/adt/numeric.c
src/backend/utils/adt/timestamp.c
src/backend/utils/adt/varbit.c
src/backend/utils/adt/varchar.c
src/backend/utils/cache/lsyscache.c
src/backend/utils/misc/guc.c
src/bin/pg_dump/pg_dump.c
src/include/catalog/catversion.h
src/include/catalog/pg_attribute.h
src/include/catalog/pg_class.h
src/include/catalog/pg_proc.h
src/include/catalog/pg_type.h
src/include/nodes/parsenodes.h
src/include/parser/parse_type.h
src/include/utils/array.h
src/include/utils/builtins.h
src/include/utils/date.h
src/include/utils/lsyscache.h
src/include/utils/timestamp.h
src/include/utils/varbit.h
src/test/regress/expected/create_type.out
src/test/regress/expected/horology.out
src/test/regress/expected/oidjoins.out
src/test/regress/expected/type_sanity.out
src/test/regress/sql/create_type.sql
src/test/regress/sql/oidjoins.sql
src/test/regress/sql/type_sanity.sql
src/tools/findoidjoins/README

index a906623ac9afe3e1787da19fd85a61f75a8aa244..2d42280f50e198f5f1edce246cefcc3ef01bdbfa 100644 (file)
@@ -1,4 +1,4 @@
-<!-- $PostgreSQL: pgsql/doc/src/sgml/catalogs.sgml,v 2.139 2006/12/23 00:43:08 tgl Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/catalogs.sgml,v 2.140 2006/12/30 21:21:52 tgl Exp $ -->
 <!--
  Documentation of the system catalogs, directed toward PostgreSQL developers
  -->
       <entry>Output conversion function (binary format), or 0 if none</entry>
      </row>
 
+     <row>
+      <entry><structfield>typmodin</structfield></entry>
+      <entry><type>regproc</type></entry>
+      <entry><literal><link linkend="catalog-pg-proc"><structname>pg_proc</structname></link>.oid</literal></entry>
+      <entry>Type modifier input function, or 0 if type does not support modifiers</entry>
+     </row>
+
+     <row>
+      <entry><structfield>typmodout</structfield></entry>
+      <entry><type>regproc</type></entry>
+      <entry><literal><link linkend="catalog-pg-proc"><structname>pg_proc</structname></link>.oid</literal></entry>
+      <entry>Type modifier output function, or 0 to use the standard format</entry>
+     </row>
+
      <row>
       <entry><structfield>typanalyze</structfield></entry>
       <entry><type>regproc</type></entry>
index c82b3b6f1b9da950167dac3c1a0380bf0ac2757e..b9565b3283cd85b7801a3759c85479616d330f05 100644 (file)
@@ -1,4 +1,4 @@
-<!-- $PostgreSQL: pgsql/doc/src/sgml/keywords.sgml,v 2.18 2006/10/08 20:51:52 petere Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/keywords.sgml,v 2.19 2006/12/30 21:21:52 tgl Exp $ -->
 
 <appendix id="sql-keywords-appendix">
  <title><acronym>SQL</acronym> Key Words</title>
   In <xref linkend="keywords-table"> in the column for
   <productname>PostgreSQL</productname> we classify as
   <quote>non-reserved</quote> those key words that are explicitly
-  known to the parser but are allowed in most or all contexts where an
-  identifier is expected.  Some key words that are otherwise
+  known to the parser but are allowed as column or table names.
+  Some key words that are otherwise
   non-reserved cannot be used as function or data type names and are
   marked accordingly.  (Most of these words represent built-in
   functions or data types with special syntax.  The function or type
   is still available but it cannot be redefined by the user.)  Labeled
-  <quote>reserved</quote> are those tokens that are only allowed as
-  <quote>AS</quote> column label names (and perhaps in very few other
-  contexts).  Some reserved key words are allowable as names for
-  functions; this is also shown in the table.
+  <quote>reserved</quote> are those tokens that are not allowed as
+  column or table names.  Some reserved key words are
+  allowable as names for functions or data types; this is also shown in the
+  table.  If not so marked, a reserved key word is only allowed as an
+  <quote>AS</quote> column label name.
  </para>
 
  <para>
    </row>
    <row>
     <entry><token>AUTHORIZATION</token></entry>
-    <entry>reserved (can be function)</entry>
+    <entry>reserved (can be function or type)</entry>
     <entry>reserved</entry>
     <entry>reserved</entry>
     <entry>reserved</entry>
    </row>
    <row>
     <entry><token>BETWEEN</token></entry>
-    <entry>reserved (can be function)</entry>
+    <entry>reserved (can be function or type)</entry>
     <entry>reserved</entry>
     <entry>non-reserved</entry>
     <entry>reserved</entry>
    </row>
    <row>
     <entry><token>BINARY</token></entry>
-    <entry>reserved (can be function)</entry>
+    <entry>reserved (can be function or type)</entry>
     <entry>reserved</entry>
     <entry>reserved</entry>
     <entry></entry>
    </row>
    <row>
     <entry><token>CROSS</token></entry>
-    <entry>reserved (can be function)</entry>
+    <entry>reserved (can be function or type)</entry>
     <entry>reserved</entry>
     <entry>reserved</entry>
     <entry>reserved</entry>
    </row>
    <row>
     <entry><token>FREEZE</token></entry>
-    <entry>reserved (can be function)</entry>
+    <entry>reserved (can be function or type)</entry>
     <entry></entry>
     <entry></entry>
     <entry></entry>
    </row>
    <row>
     <entry><token>FULL</token></entry>
-    <entry>reserved (can be function)</entry>
+    <entry>reserved (can be function or type)</entry>
     <entry>reserved</entry>
     <entry>reserved</entry>
     <entry>reserved</entry>
    </row>
    <row>
     <entry><token>ILIKE</token></entry>
-    <entry>reserved (can be function)</entry>
+    <entry>reserved (can be function or type)</entry>
     <entry></entry>
     <entry></entry>
     <entry></entry>
    </row>
    <row>
     <entry><token>INNER</token></entry>
-    <entry>reserved (can be function)</entry>
+    <entry>reserved (can be function or type)</entry>
     <entry>reserved</entry>
     <entry>reserved</entry>
     <entry>reserved</entry>
    </row>
    <row>
     <entry><token>IS</token></entry>
-    <entry>reserved (can be function)</entry>
+    <entry>reserved (can be function or type)</entry>
     <entry>reserved</entry>
     <entry>reserved</entry>
     <entry>reserved</entry>
    </row>
    <row>
     <entry><token>ISNULL</token></entry>
-    <entry>reserved (can be function)</entry>
+    <entry>reserved (can be function or type)</entry>
     <entry></entry>
     <entry></entry>
     <entry></entry>
    </row>
    <row>
     <entry><token>JOIN</token></entry>
-    <entry>reserved (can be function)</entry>
+    <entry>reserved (can be function or type)</entry>
     <entry>reserved</entry>
     <entry>reserved</entry>
     <entry>reserved</entry>
    </row>
    <row>
     <entry><token>LEFT</token></entry>
-    <entry>reserved (can be function)</entry>
+    <entry>reserved (can be function or type)</entry>
     <entry>reserved</entry>
     <entry>reserved</entry>
     <entry>reserved</entry>
    </row>
    <row>
     <entry><token>LIKE</token></entry>
-    <entry>reserved (can be function)</entry>
+    <entry>reserved (can be function or type)</entry>
     <entry>reserved</entry>
     <entry>reserved</entry>
     <entry>reserved</entry>
    </row>
    <row>
     <entry><token>NATURAL</token></entry>
-    <entry>reserved (can be function)</entry>
+    <entry>reserved (can be function or type)</entry>
     <entry>reserved</entry>
     <entry>reserved</entry>
     <entry>reserved</entry>
    </row>
    <row>
     <entry><token>NOTNULL</token></entry>
-    <entry>reserved (can be function)</entry>
+    <entry>reserved (can be function or type)</entry>
     <entry></entry>
     <entry></entry>
     <entry></entry>
    </row>
    <row>
     <entry><token>OUTER</token></entry>
-    <entry>reserved (can be function)</entry>
+    <entry>reserved (can be function or type)</entry>
     <entry>reserved</entry>
     <entry>reserved</entry>
     <entry>reserved</entry>
    </row>
    <row>
     <entry><token>OVERLAPS</token></entry>
-    <entry>reserved (can be function)</entry>
+    <entry>reserved (can be function or type)</entry>
     <entry>reserved</entry>
     <entry>non-reserved</entry>
     <entry>reserved</entry>
    </row>
    <row>
     <entry><token>RIGHT</token></entry>
-    <entry>reserved (can be function)</entry>
+    <entry>reserved (can be function or type)</entry>
     <entry>reserved</entry>
     <entry>reserved</entry>
     <entry>reserved</entry>
    </row>
    <row>
     <entry><token>SIMILAR</token></entry>
-    <entry>reserved (can be function)</entry>
+    <entry>reserved (can be function or type)</entry>
     <entry>reserved</entry>
     <entry>non-reserved</entry>
     <entry></entry>
    </row>
    <row>
     <entry><token>VERBOSE</token></entry>
-    <entry>reserved (can be function)</entry>
+    <entry>reserved (can be function or type)</entry>
     <entry></entry>
     <entry></entry>
     <entry></entry>
index e85c94dbe74d908756bca6f9652b5ce219bb2f00..2f1f6eab3c415d1c15cb5f26c639efe016e461b4 100644 (file)
@@ -1,5 +1,5 @@
 <!--
-$PostgreSQL: pgsql/doc/src/sgml/ref/create_type.sgml,v 1.65 2006/12/23 01:28:09 momjian Exp $
+$PostgreSQL: pgsql/doc/src/sgml/ref/create_type.sgml,v 1.66 2006/12/30 21:21:52 tgl Exp $
 PostgreSQL documentation
 -->
 
@@ -28,6 +28,8 @@ CREATE TYPE <replaceable class="parameter">name</replaceable> (
     OUTPUT = <replaceable class="parameter">output_function</replaceable>
     [ , RECEIVE = <replaceable class="parameter">receive_function</replaceable> ]
     [ , SEND = <replaceable class="parameter">send_function</replaceable> ]
+    [ , TYPMOD_IN = <replaceable class="parameter">type_modifier_input_function</replaceable> ]
+    [ , TYPMOD_OUT = <replaceable class="parameter">type_modifier_output_function</replaceable> ]
     [ , ANALYZE = <replaceable class="parameter">analyze_function</replaceable> ]
     [ , INTERNALLENGTH = { <replaceable class="parameter">internallength</replaceable> | VARIABLE } ]
     [ , PASSEDBYVALUE ]
@@ -83,12 +85,14 @@ CREATE TYPE <replaceable class="parameter">name</replaceable>
    (scalar type).  The parameters may appear in any order, not only that
    illustrated above, and most are optional.  You must register
    two or more functions (using <command>CREATE FUNCTION</command>) before
-   defining the type.  The support functions 
+   defining the type.  The support functions
    <replaceable class="parameter">input_function</replaceable> and
    <replaceable class="parameter">output_function</replaceable>
    are required, while the functions
    <replaceable class="parameter">receive_function</replaceable>,
-   <replaceable class="parameter">send_function</replaceable> and
+   <replaceable class="parameter">send_function</replaceable>,
+   <replaceable class="parameter">type_modifier_input_function</replaceable>,
+   <replaceable class="parameter">type_modifier_output_function</replaceable> and
    <replaceable class="parameter">analyze_function</replaceable>
    are optional.  Generally these functions have to be coded in C
    or another low-level language.
@@ -169,6 +173,34 @@ CREATE TYPE <replaceable class="parameter">name</replaceable>
    used normally.
   </para>
 
+  <para>
+   The optional
+   <replaceable class="parameter">type_modifier_input_function</replaceable>
+   and <replaceable class="parameter">type_modifier_output_function</replaceable>
+   are needed if the type supports modifiers, that is optional constraints
+   attached to a type declaration, such as <literal>char(5)</> or
+   <literal>numeric(30,2)</>.  <productname>PostgreSQL</productname> allows
+   user-defined types to take one or more integer constants as modifiers;
+   however, this information must be capable of being packed into a single
+   non-negative integer value for storage in the system catalogs.  The
+   <replaceable class="parameter">type_modifier_input_function</replaceable>
+   is passed the declared modifier(s) in the form of an <type>integer</>
+   array.  It must check the values for validity (throwing an error if they
+   are wrong), and if they are correct, return a single non-negative
+   <type>integer</> value that will be stored as the column <quote>typmod</>.
+   Type modifiers will be rejected if the type does not have a
+   <replaceable class="parameter">type_modifier_input_function</replaceable>.
+   The <replaceable class="parameter">type_modifier_output_function</replaceable>
+   converts the internal integer typmod value back to the correct form for
+   user display.  It must return a <type>cstring</> value that is the exact
+   string to append to the type name; for example <type>numeric</>'s
+   function might return <literal>(30,2)</>.
+   It is allowed to omit the
+   <replaceable class="parameter">type_modifier_output_function</replaceable>,
+   in which case the default display format is just the stored typmod value
+   enclosed in parentheses.
+  </para>
+
   <para>
    The optional <replaceable class="parameter">analyze_function</replaceable>
    performs type-specific statistics collection for columns of the data type.
@@ -265,7 +297,7 @@ CREATE TYPE <replaceable class="parameter">name</replaceable>
    <title>Array Types</title>
 
    <para>
-    Whenever a user-defined base data type is created, 
+    Whenever a user-defined base data type is created,
     <productname>PostgreSQL</productname> automatically creates an
     associated array type, whose name consists of the base type's
     name prepended with an underscore.  The parser understands this
@@ -298,7 +330,7 @@ CREATE TYPE <replaceable class="parameter">name</replaceable>
    </para>
   </refsect2>
  </refsect1>
-  
+
  <refsect1>
   <title>Parameters</title>
 
@@ -371,6 +403,26 @@ CREATE TYPE <replaceable class="parameter">name</replaceable>
     </listitem>
    </varlistentry>
 
+   <varlistentry>
+    <term><replaceable class="parameter">type_modifier_input_function</replaceable></term>
+    <listitem>
+     <para>
+      The name of a function that converts numeric modifier(s) for the type
+      into internal form.
+     </para>
+    </listitem>
+   </varlistentry>
+
+   <varlistentry>
+    <term><replaceable class="parameter">type_modifier_output_function</replaceable></term>
+    <listitem>
+     <para>
+      The name of a function that converts the internal form of the type's
+      modifier(s) to external textual form.
+     </para>
+    </listitem>
+   </varlistentry>
+
    <varlistentry>
     <term><replaceable class="parameter">analyze_function</replaceable></term>
     <listitem>
@@ -499,7 +551,7 @@ CREATE TYPE <replaceable class="parameter">name</replaceable>
   </para>
 
  </refsect1>
+
  <refsect1>
   <title>Examples</title>
 
index 6242afa20f34ba948f0479cf58075eed8fdbb330..be5665db79cd9e39d5ecb06f987d3069453159d7 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/access/common/tupdesc.c,v 1.118 2006/07/14 14:52:16 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/access/common/tupdesc.c,v 1.119 2006/12/30 21:21:52 tgl Exp $
  *
  * NOTES
  *       some of the executor utility code such as "ExecTypeFromTL" should be
@@ -508,6 +508,7 @@ BuildDescForRelation(List *schema)
        AttrDefault *attrdef = NULL;
        TupleConstr *constr = (TupleConstr *) palloc0(sizeof(TupleConstr));
        char       *attname;
+       Oid                     atttypid;
        int32           atttypmod;
        int                     attdim;
        int                     ndef = 0;
@@ -533,7 +534,8 @@ BuildDescForRelation(List *schema)
                attnum++;
 
                attname = entry->colname;
-               atttypmod = entry->typename->typmod;
+               atttypid = typenameTypeId(NULL, entry->typename);
+               atttypmod = typenameTypeMod(NULL, entry->typename, atttypid);
                attdim = list_length(entry->typename->arrayBounds);
 
                if (entry->typename->setof)
@@ -543,8 +545,7 @@ BuildDescForRelation(List *schema)
                                                        attname)));
 
                TupleDescInitEntry(desc, attnum, attname,
-                                                  typenameTypeId(NULL, entry->typename),
-                                                  atttypmod, attdim);
+                                                  atttypid, atttypmod, attdim);
 
                /* Fill in additional stuff not handled by TupleDescInitEntry */
                if (entry->is_not_null)
index d6822c73c698fc4af7c529f6e0188247e36c50c4..41ef41c7c17291cea560dca3f04fa9f737e2471a 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/catalog/heap.c,v 1.314 2006/11/05 22:42:08 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/catalog/heap.c,v 1.315 2006/12/30 21:21:52 tgl Exp $
  *
  *
  * INTERFACE ROUTINES
@@ -724,6 +724,8 @@ AddNewRelationType(const char *typeName,
                                   F_RECORD_OUT,        /* output procedure */
                                   F_RECORD_RECV,               /* receive procedure */
                                   F_RECORD_SEND,               /* send procedure */
+                                  InvalidOid,  /* typmodin procedure - none */
+                                  InvalidOid,  /* typmodout procedure - none */
                                   InvalidOid,  /* analyze procedure - default */
                                   InvalidOid,  /* array element type - irrelevant */
                                   InvalidOid,  /* domain base type - irrelevant */
index 32de0b90dc1f14d2808299454ee254bb4a5fe96d..74517124fbd58c1cadd385b091d07f7d7621c833 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/catalog/pg_type.c,v 1.108 2006/10/04 00:29:50 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/catalog/pg_type.c,v 1.109 2006/12/30 21:21:53 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -94,6 +94,8 @@ TypeShellMake(const char *typeName, Oid typeNamespace)
        values[i++] = ObjectIdGetDatum(F_SHELL_OUT);            /* typoutput */
        values[i++] = ObjectIdGetDatum(InvalidOid); /* typreceive */
        values[i++] = ObjectIdGetDatum(InvalidOid); /* typsend */
+       values[i++] = ObjectIdGetDatum(InvalidOid); /* typmodin */
+       values[i++] = ObjectIdGetDatum(InvalidOid); /* typmodout */
        values[i++] = ObjectIdGetDatum(InvalidOid); /* typanalyze */
        values[i++] = CharGetDatum('i');        /* typalign */
        values[i++] = CharGetDatum('p');        /* typstorage */
@@ -132,6 +134,8 @@ TypeShellMake(const char *typeName, Oid typeNamespace)
                                                                 InvalidOid,
                                                                 InvalidOid,
                                                                 InvalidOid,
+                                                                InvalidOid,
+                                                                InvalidOid,
                                                                 NULL,
                                                                 false);
 
@@ -164,6 +168,8 @@ TypeCreate(const char *typeName,
                   Oid outputProcedure,
                   Oid receiveProcedure,
                   Oid sendProcedure,
+                  Oid typmodinProcedure,
+                  Oid typmodoutProcedure,
                   Oid analyzeProcedure,
                   Oid elementType,
                   Oid baseType,
@@ -243,6 +249,8 @@ TypeCreate(const char *typeName,
        values[i++] = ObjectIdGetDatum(outputProcedure);        /* typoutput */
        values[i++] = ObjectIdGetDatum(receiveProcedure);       /* typreceive */
        values[i++] = ObjectIdGetDatum(sendProcedure);          /* typsend */
+       values[i++] = ObjectIdGetDatum(typmodinProcedure);      /* typmodin */
+       values[i++] = ObjectIdGetDatum(typmodoutProcedure);     /* typmodout */
        values[i++] = ObjectIdGetDatum(analyzeProcedure);       /* typanalyze */
        values[i++] = CharGetDatum(alignment);          /* typalign */
        values[i++] = CharGetDatum(storage);            /* typstorage */
@@ -341,6 +349,8 @@ TypeCreate(const char *typeName,
                                                                 outputProcedure,
                                                                 receiveProcedure,
                                                                 sendProcedure,
+                                                                typmodinProcedure,
+                                                                typmodoutProcedure,
                                                                 analyzeProcedure,
                                                                 elementType,
                                                                 baseType,
@@ -374,6 +384,8 @@ GenerateTypeDependencies(Oid typeNamespace,
                                                 Oid outputProcedure,
                                                 Oid receiveProcedure,
                                                 Oid sendProcedure,
+                                                Oid typmodinProcedure,
+                                                Oid typmodoutProcedure,
                                                 Oid analyzeProcedure,
                                                 Oid elementType,
                                                 Oid baseType,
@@ -436,6 +448,22 @@ GenerateTypeDependencies(Oid typeNamespace,
                recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
        }
 
+       if (OidIsValid(typmodinProcedure))
+       {
+               referenced.classId = ProcedureRelationId;
+               referenced.objectId = typmodinProcedure;
+               referenced.objectSubId = 0;
+               recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+       }
+
+       if (OidIsValid(typmodoutProcedure))
+       {
+               referenced.classId = ProcedureRelationId;
+               referenced.objectId = typmodoutProcedure;
+               referenced.objectSubId = 0;
+               recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+       }
+
        if (OidIsValid(analyzeProcedure))
        {
                referenced.classId = ProcedureRelationId;
index 2a1116f75800c66d238f9caa694f8a474130527b..c30aa69c5558f5b9542b0c745829188bede86983 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.207 2006/12/23 00:43:09 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.208 2006/12/30 21:21:53 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -889,6 +889,9 @@ MergeAttributes(List *schema, List *supers, bool istemp,
                        exist_attno = findAttrByName(attributeName, inhSchema);
                        if (exist_attno > 0)
                        {
+                               Oid             defTypeId;
+                               int32   deftypmod;
+
                                /*
                                 * Yes, try to merge the two column definitions. They must
                                 * have the same type and typmod.
@@ -897,8 +900,10 @@ MergeAttributes(List *schema, List *supers, bool istemp,
                                                (errmsg("merging multiple inherited definitions of column \"%s\"",
                                                                attributeName)));
                                def = (ColumnDef *) list_nth(inhSchema, exist_attno - 1);
-                               if (typenameTypeId(NULL, def->typename) != attribute->atttypid ||
-                                       def->typename->typmod != attribute->atttypmod)
+                               defTypeId = typenameTypeId(NULL, def->typename);
+                               deftypmod = typenameTypeMod(NULL, def->typename, defTypeId);
+                               if (defTypeId != attribute->atttypid ||
+                                       deftypmod != attribute->atttypmod)
                                        ereport(ERROR,
                                                        (errcode(ERRCODE_DATATYPE_MISMATCH),
                                                errmsg("inherited column \"%s\" has a type conflict",
@@ -1029,6 +1034,8 @@ MergeAttributes(List *schema, List *supers, bool istemp,
                        if (exist_attno > 0)
                        {
                                ColumnDef  *def;
+                               Oid     defTypeId, newTypeId;
+                               int32 deftypmod, newtypmod;
 
                                /*
                                 * Yes, try to merge the two column definitions. They must
@@ -1038,8 +1045,11 @@ MergeAttributes(List *schema, List *supers, bool istemp,
                                   (errmsg("merging column \"%s\" with inherited definition",
                                                   attributeName)));
                                def = (ColumnDef *) list_nth(inhSchema, exist_attno - 1);
-                               if (typenameTypeId(NULL, def->typename) != typenameTypeId(NULL, newdef->typename) ||
-                                       def->typename->typmod != newdef->typename->typmod)
+                               defTypeId = typenameTypeId(NULL, def->typename);
+                               deftypmod = typenameTypeMod(NULL, def->typename, defTypeId);
+                               newTypeId = typenameTypeId(NULL, newdef->typename);
+                               newtypmod = typenameTypeMod(NULL, newdef->typename, newTypeId);
+                               if (defTypeId != newTypeId || deftypmod != newtypmod)
                                        ereport(ERROR,
                                                        (errcode(ERRCODE_DATATYPE_MISMATCH),
                                                         errmsg("column \"%s\" has a type conflict",
@@ -3092,6 +3102,7 @@ ATExecAddColumn(AlteredTableInfo *tab, Relation rel,
                                maxatts;
        HeapTuple       typeTuple;
        Oid                     typeOid;
+       int32           typmod;
        Form_pg_type tform;
        Expr       *defval;
 
@@ -3110,10 +3121,14 @@ ATExecAddColumn(AlteredTableInfo *tab, Relation rel,
                if (HeapTupleIsValid(tuple))
                {
                        Form_pg_attribute childatt = (Form_pg_attribute) GETSTRUCT(tuple);
+                       Oid             ctypeId;
+                       int32   ctypmod;
 
                        /* Okay if child matches by type */
-                       if (typenameTypeId(NULL, colDef->typename) != childatt->atttypid ||
-                               colDef->typename->typmod != childatt->atttypmod)
+                       ctypeId = typenameTypeId(NULL, colDef->typename);
+                       ctypmod = typenameTypeMod(NULL, colDef->typename, ctypeId);
+                       if (ctypeId != childatt->atttypid ||
+                               ctypmod != childatt->atttypmod)
                                ereport(ERROR,
                                                (errcode(ERRCODE_DATATYPE_MISMATCH),
                                                 errmsg("child table \"%s\" has different type for column \"%s\"",
@@ -3169,6 +3184,7 @@ ATExecAddColumn(AlteredTableInfo *tab, Relation rel,
        typeTuple = typenameType(NULL, colDef->typename);
        tform = (Form_pg_type) GETSTRUCT(typeTuple);
        typeOid = HeapTupleGetOid(typeTuple);
+       typmod = typenameTypeMod(NULL, colDef->typename, typeOid);
 
        /* make sure datatype is legal for a column */
        CheckAttributeType(colDef->colname, typeOid);
@@ -3186,7 +3202,7 @@ ATExecAddColumn(AlteredTableInfo *tab, Relation rel,
        attribute->attstattarget = -1;
        attribute->attlen = tform->typlen;
        attribute->attcacheoff = -1;
-       attribute->atttypmod = colDef->typename->typmod;
+       attribute->atttypmod = typmod;
        attribute->attnum = i;
        attribute->attbyval = tform->typbyval;
        attribute->attndims = list_length(colDef->typename->arrayBounds);
@@ -3278,7 +3294,7 @@ ATExecAddColumn(AlteredTableInfo *tab, Relation rel,
                                                                                                (Node *) defval,
                                                                                                basetype,
                                                                                                typeOid,
-                                                                                               colDef->typename->typmod,
+                                                                                               typmod,
                                                                                                COERCION_ASSIGNMENT,
                                                                                                COERCE_IMPLICIT_CAST);
                if (defval == NULL)             /* should not happen */
@@ -4877,6 +4893,7 @@ ATPrepAlterColumnType(List **wqueue,
        Form_pg_attribute attTup;
        AttrNumber      attnum;
        Oid                     targettype;
+       int32           targettypmod;
        Node       *transform;
        NewColumnValue *newval;
        ParseState *pstate = make_parsestate(NULL);
@@ -4907,6 +4924,7 @@ ATPrepAlterColumnType(List **wqueue,
 
        /* Look up the target type */
        targettype = typenameTypeId(NULL, typename);
+       targettypmod = typenameTypeMod(NULL, typename, targettype);
 
        /* make sure datatype is legal for a column */
        CheckAttributeType(colName, targettype);
@@ -4958,7 +4976,7 @@ ATPrepAlterColumnType(List **wqueue,
 
        transform = coerce_to_target_type(pstate,
                                                                          transform, exprType(transform),
-                                                                         targettype, typename->typmod,
+                                                                         targettype, targettypmod,
                                                                          COERCION_ASSIGNMENT,
                                                                          COERCE_IMPLICIT_CAST);
        if (transform == NULL)
@@ -5004,6 +5022,7 @@ ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel,
        HeapTuple       typeTuple;
        Form_pg_type tform;
        Oid                     targettype;
+       int32           targettypmod;
        Node       *defaultexpr;
        Relation        attrelation;
        Relation        depRel;
@@ -5035,6 +5054,7 @@ ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel,
        typeTuple = typenameType(NULL, typename);
        tform = (Form_pg_type) GETSTRUCT(typeTuple);
        targettype = HeapTupleGetOid(typeTuple);
+       targettypmod = typenameTypeMod(NULL, typename, targettype);
 
        /*
         * If there is a default expression for the column, get it and ensure we
@@ -5055,7 +5075,7 @@ ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel,
                defaultexpr = strip_implicit_coercions(defaultexpr);
                defaultexpr = coerce_to_target_type(NULL,               /* no UNKNOWN params */
                                                                                  defaultexpr, exprType(defaultexpr),
-                                                                                       targettype, typename->typmod,
+                                                                                       targettype, targettypmod,
                                                                                        COERCION_ASSIGNMENT,
                                                                                        COERCE_IMPLICIT_CAST);
                if (defaultexpr == NULL)
@@ -5272,7 +5292,7 @@ ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel,
         * copy of the syscache entry, so okay to scribble on.)
         */
        attTup->atttypid = targettype;
-       attTup->atttypmod = typename->typmod;
+       attTup->atttypmod = targettypmod;
        attTup->attndims = list_length(typename->arrayBounds);
        attTup->attlen = tform->typlen;
        attTup->attbyval = tform->typbyval;
index 53cca73a9dd6a87ea350de3854a539094565b01c..2b26f2dfa14a8937d5996b9e105d632946024d0a 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/commands/typecmds.c,v 1.97 2006/10/04 00:29:51 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/commands/typecmds.c,v 1.98 2006/12/30 21:21:53 tgl Exp $
  *
  * DESCRIPTION
  *       The "DefineFoo" routines take the parse tree and pick out the
@@ -75,6 +75,8 @@ static Oid    findTypeInputFunction(List *procname, Oid typeOid);
 static Oid     findTypeOutputFunction(List *procname, Oid typeOid);
 static Oid     findTypeReceiveFunction(List *procname, Oid typeOid);
 static Oid     findTypeSendFunction(List *procname, Oid typeOid);
+static Oid     findTypeTypmodinFunction(List *procname);
+static Oid     findTypeTypmodoutFunction(List *procname);
 static Oid     findTypeAnalyzeFunction(List *procname, Oid typeOid);
 static List *get_rels_with_domain(Oid domainOid, LOCKMODE lockmode);
 static void checkDomainOwner(HeapTuple tup, TypeName *typename);
@@ -100,6 +102,8 @@ DefineType(List *names, List *parameters)
        List       *outputName = NIL;
        List       *receiveName = NIL;
        List       *sendName = NIL;
+       List       *typmodinName = NIL;
+       List       *typmodoutName = NIL;
        List       *analyzeName = NIL;
        char       *defaultValue = NULL;
        bool            byValue = false;
@@ -110,6 +114,8 @@ DefineType(List *names, List *parameters)
        Oid                     outputOid;
        Oid                     receiveOid = InvalidOid;
        Oid                     sendOid = InvalidOid;
+       Oid                     typmodinOid = InvalidOid;
+       Oid                     typmodoutOid = InvalidOid;
        Oid                     analyzeOid = InvalidOid;
        char       *shadow_type;
        ListCell   *pl;
@@ -182,6 +188,10 @@ DefineType(List *names, List *parameters)
                        receiveName = defGetQualifiedName(defel);
                else if (pg_strcasecmp(defel->defname, "send") == 0)
                        sendName = defGetQualifiedName(defel);
+               else if (pg_strcasecmp(defel->defname, "typmod_in") == 0)
+                       typmodinName = defGetQualifiedName(defel);
+               else if (pg_strcasecmp(defel->defname, "typmod_out") == 0)
+                       typmodoutName = defGetQualifiedName(defel);
                else if (pg_strcasecmp(defel->defname, "analyze") == 0 ||
                                 pg_strcasecmp(defel->defname, "analyse") == 0)
                        analyzeName = defGetQualifiedName(defel);
@@ -268,6 +278,11 @@ DefineType(List *names, List *parameters)
                                (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
                                 errmsg("type output function must be specified")));
 
+       if (typmodinName == NIL && typmodoutName != NIL)
+               ereport(ERROR,
+                               (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+                                errmsg("type modifier output function is useless without a type modifier input function")));
+
        /*
         * Convert I/O proc names to OIDs
         */
@@ -335,6 +350,14 @@ DefineType(List *names, List *parameters)
                                                  NameListToString(sendName))));
        }
 
+       /*
+        * Convert typmodin/out function proc names to OIDs.
+        */
+       if (typmodinName)
+               typmodinOid = findTypeTypmodinFunction(typmodinName);
+       if (typmodoutName)
+               typmodoutOid = findTypeTypmodoutFunction(typmodoutName);
+
        /*
         * Convert analysis function proc name to an OID. If no analysis function
         * is specified, we'll use zero to select the built-in default algorithm.
@@ -362,6 +385,12 @@ DefineType(List *names, List *parameters)
        if (sendOid && !pg_proc_ownercheck(sendOid, GetUserId()))
                aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_PROC,
                                           NameListToString(sendName));
+       if (typmodinOid && !pg_proc_ownercheck(typmodinOid, GetUserId()))
+               aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_PROC,
+                                          NameListToString(typmodinName));
+       if (typmodoutOid && !pg_proc_ownercheck(typmodoutOid, GetUserId()))
+               aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_PROC,
+                                          NameListToString(typmodoutName));
        if (analyzeOid && !pg_proc_ownercheck(analyzeOid, GetUserId()))
                aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_PROC,
                                           NameListToString(analyzeName));
@@ -381,6 +410,8 @@ DefineType(List *names, List *parameters)
                                   outputOid,   /* output procedure */
                                   receiveOid,  /* receive procedure */
                                   sendOid,             /* send procedure */
+                                  typmodinOid, /* typmodin procedure */
+                                  typmodoutOid,/* typmodout procedure */
                                   analyzeOid,  /* analyze procedure */
                                   elemType,    /* element type ID */
                                   InvalidOid,  /* base type ID (only for domains) */
@@ -413,6 +444,8 @@ DefineType(List *names, List *parameters)
                           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 */
@@ -552,6 +585,7 @@ DefineDomain(CreateDomainStmt *stmt)
        Oid                     basetypeoid;
        Oid                     domainoid;
        Form_pg_type baseType;
+       int32           basetypeMod;
 
        /* Convert list of names to a name and namespace */
        domainNamespace = QualifiedNameGetCreationNamespace(stmt->domainname,
@@ -581,9 +615,9 @@ DefineDomain(CreateDomainStmt *stmt)
         * Look up the base type.
         */
        typeTup = typenameType(NULL, stmt->typename);
-
        baseType = (Form_pg_type) GETSTRUCT(typeTup);
        basetypeoid = HeapTupleGetOid(typeTup);
+       basetypeMod = typenameTypeMod(NULL, stmt->typename, basetypeoid);
 
        /*
         * Base type must be a plain base type or another domain.  Domains over
@@ -621,6 +655,8 @@ DefineDomain(CreateDomainStmt *stmt)
        receiveProcedure = F_DOMAIN_RECV;
        sendProcedure = baseType->typsend;
 
+       /* Domains never accept typmods, so no typmodin/typmodout needed */
+
        /* Analysis function */
        analyzeProcedure = baseType->typanalyze;
 
@@ -681,7 +717,7 @@ DefineDomain(CreateDomainStmt *stmt)
                                 */
                                defaultExpr = cookDefault(pstate, constr->raw_expr,
                                                                                  basetypeoid,
-                                                                                 stmt->typename->typmod,
+                                                                                 basetypeMod,
                                                                                  domainName);
 
                                /*
@@ -768,6 +804,8 @@ DefineDomain(CreateDomainStmt *stmt)
                                   outputProcedure,             /* output procedure */
                                   receiveProcedure,    /* receive procedure */
                                   sendProcedure,               /* send procedure */
+                                  InvalidOid,                  /* typmodin procedure - none */
+                                  InvalidOid,                  /* typmodout procedure - none */
                                   analyzeProcedure,    /* analyze procedure */
                                   typelem,             /* element type ID */
                                   basetypeoid, /* base type ID */
@@ -776,7 +814,7 @@ DefineDomain(CreateDomainStmt *stmt)
                                   byValue,             /* passed by value */
                                   alignment,   /* required alignment */
                                   storage,             /* TOAST strategy */
-                                  stmt->typename->typmod,              /* typeMod value */
+                                  basetypeMod, /* typeMod value */
                                   typNDims,    /* Array dimensions for base type */
                                   typNotNull); /* Type NOT NULL */
 
@@ -793,7 +831,7 @@ DefineDomain(CreateDomainStmt *stmt)
                {
                        case CONSTR_CHECK:
                                domainAddConstraint(domainoid, domainNamespace,
-                                                                       basetypeoid, stmt->typename->typmod,
+                                                                       basetypeoid, basetypeMod,
                                                                        constr, domainName);
                                break;
 
@@ -1067,6 +1105,60 @@ findTypeSendFunction(List *procname, Oid typeOid)
        return InvalidOid;                      /* keep compiler quiet */
 }
 
+static Oid
+findTypeTypmodinFunction(List *procname)
+{
+       Oid                     argList[1];
+       Oid                     procOid;
+
+       /*
+        * typmodin functions always take one int4[] argument and return int4.
+        */
+       argList[0] = INT4ARRAYOID;
+
+       procOid = LookupFuncName(procname, 1, argList, true);
+       if (!OidIsValid(procOid))
+               ereport(ERROR,
+                               (errcode(ERRCODE_UNDEFINED_FUNCTION),
+                                errmsg("function %s does not exist",
+                                               func_signature_string(procname, 1, argList))));
+
+       if (get_func_rettype(procOid) != INT4OID)
+               ereport(ERROR,
+                               (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+                                errmsg("typmod_in function %s must return type \"integer\"",
+                                               NameListToString(procname))));
+
+       return procOid;
+}
+
+static Oid
+findTypeTypmodoutFunction(List *procname)
+{
+       Oid                     argList[1];
+       Oid                     procOid;
+
+       /*
+        * typmodout functions always take one int4 argument and return cstring.
+        */
+       argList[0] = INT4OID;
+
+       procOid = LookupFuncName(procname, 1, argList, true);
+       if (!OidIsValid(procOid))
+               ereport(ERROR,
+                               (errcode(ERRCODE_UNDEFINED_FUNCTION),
+                                errmsg("function %s does not exist",
+                                               func_signature_string(procname, 1, argList))));
+
+       if (get_func_rettype(procOid) != CSTRINGOID)
+               ereport(ERROR,
+                               (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+                                errmsg("typmod_out function %s must return type \"cstring\"",
+                                               NameListToString(procname))));
+
+       return procOid;
+}
+
 static Oid
 findTypeAnalyzeFunction(List *procname, Oid typeOid)
 {
@@ -1244,6 +1336,8 @@ AlterDomainDefault(List *names, Node *defaultRaw)
                                                         typTup->typoutput,
                                                         typTup->typreceive,
                                                         typTup->typsend,
+                                                        typTup->typmodin,
+                                                        typTup->typmodout,
                                                         typTup->typanalyze,
                                                         typTup->typelem,
                                                         typTup->typbasetype,
index d46ed57d830e0b7a85622fd0bb32024bf857701a..c8c9b907c9cd0efe4afca652dd54f8fb05f2bfb6 100644 (file)
@@ -15,7 +15,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.357 2006/12/24 00:29:18 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.358 2006/12/30 21:21:53 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1584,7 +1584,8 @@ _copyTypeName(TypeName *from)
        COPY_SCALAR_FIELD(timezone);
        COPY_SCALAR_FIELD(setof);
        COPY_SCALAR_FIELD(pct_type);
-       COPY_SCALAR_FIELD(typmod);
+       COPY_NODE_FIELD(typmods);
+       COPY_SCALAR_FIELD(typemod);
        COPY_NODE_FIELD(arrayBounds);
        COPY_SCALAR_FIELD(location);
 
index 29bff448c7f53ce4387cb401cc66c13aa0876427..57e61f0e2a204e671fc36f7779cb1f3b92c0ace0 100644 (file)
@@ -18,7 +18,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.291 2006/12/24 00:29:18 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.292 2006/12/30 21:21:53 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1614,7 +1614,8 @@ _equalTypeName(TypeName *a, TypeName *b)
        COMPARE_SCALAR_FIELD(timezone);
        COMPARE_SCALAR_FIELD(setof);
        COMPARE_SCALAR_FIELD(pct_type);
-       COMPARE_SCALAR_FIELD(typmod);
+       COMPARE_NODE_FIELD(typmods);
+       COMPARE_SCALAR_FIELD(typemod);
        COMPARE_NODE_FIELD(arrayBounds);
        COMPARE_SCALAR_FIELD(location);
 
index 9f6aa22707b500ddd7d250c17b8822c3bf5c2067..277103e4a1800e9ccd67c62aa4e3fa900184e97c 100644 (file)
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/nodes/makefuncs.c,v 1.52 2006/10/04 00:29:53 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/nodes/makefuncs.c,v 1.53 2006/12/30 21:21:53 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -262,12 +262,7 @@ makeRangeVar(char *schemaname, char *relname)
 TypeName *
 makeTypeName(char *typnam)
 {
-       TypeName   *n = makeNode(TypeName);
-
-       n->names = list_make1(makeString(typnam));
-       n->typmod = -1;
-       n->location = -1;
-       return n;
+       return makeTypeNameFromNameList(list_make1(makeString(typnam)));
 }
 
 /*
@@ -282,14 +277,15 @@ makeTypeNameFromNameList(List *names)
        TypeName   *n = makeNode(TypeName);
 
        n->names = names;
-       n->typmod = -1;
+       n->typmods = NIL;
+       n->typemod = -1;
        n->location = -1;
        return n;
 }
 
 /*
  * makeTypeNameFromOid -
- *     build a TypeName node to represent a type already known by OID.
+ *     build a TypeName node to represent a type already known by OID/typmod.
  */
 TypeName *
 makeTypeNameFromOid(Oid typeid, int32 typmod)
@@ -297,7 +293,7 @@ makeTypeNameFromOid(Oid typeid, int32 typmod)
        TypeName   *n = makeNode(TypeName);
 
        n->typeid = typeid;
-       n->typmod = typmod;
+       n->typemod = typmod;
        n->location = -1;
        return n;
 }
index 4911d6ed4044c33a197fe268836e5847783c213c..2b21eae6a10f29d928f51ba23a21dfebaa648df2 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.289 2006/12/24 00:29:18 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.290 2006/12/30 21:21:53 tgl Exp $
  *
  * NOTES
  *       Every node type that can appear in stored rules' parsetrees *must*
@@ -1476,7 +1476,8 @@ _outTypeName(StringInfo str, TypeName *node)
        WRITE_BOOL_FIELD(timezone);
        WRITE_BOOL_FIELD(setof);
        WRITE_BOOL_FIELD(pct_type);
-       WRITE_INT_FIELD(typmod);
+       WRITE_NODE_FIELD(typmods);
+       WRITE_INT_FIELD(typemod);
        WRITE_NODE_FIELD(arrayBounds);
        WRITE_INT_FIELD(location);
 }
index a1511870f28a425bd6f37e69b33313d9bca2a9c8..c4820190f0789f869e9a9cc669be52b7956201af 100644 (file)
@@ -11,7 +11,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.570 2006/12/24 00:29:18 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.571 2006/12/30 21:21:53 tgl Exp $
  *
  * HISTORY
  *       AUTHOR                        DATE                    MAJOR EVENT
@@ -206,7 +206,7 @@ static Node *makeXmlExpr(XmlExprOp op, char *name, List *named_args, List *args)
 
 %type <str>            relation_name copy_file_name
                                database_name access_method_clause access_method attr_name
-                               index_name name function_name file_name
+                               index_name name file_name
 
 %type <list>   func_name handler_name qual_Op qual_all_Op subquery_Op
                                opt_class opt_validator
@@ -242,7 +242,7 @@ static Node *makeXmlExpr(XmlExprOp op, char *name, List *named_args, List *args)
                                group_clause TriggerFuncArgs select_limit
                                opt_select_limit opclass_item_list
                                transaction_mode_list_or_empty
-                               TableFuncElementList
+                               TableFuncElementList opt_type_modifiers
                                prep_type_clause prep_type_list
                                execute_param_clause using_clause returning_clause
 
@@ -319,20 +319,19 @@ static Node *makeXmlExpr(XmlExprOp op, char *name, List *named_args, List *args)
 %type <str>            character
 %type <str>            extract_arg
 %type <str>            opt_charset
-%type <ival>   opt_numeric opt_decimal
 %type <boolean> opt_varying opt_timezone
 
 %type <ival>   Iconst SignedIconst
 %type <str>            Sconst comment_text
 %type <str>            RoleId opt_granted_by opt_boolean ColId_or_Sconst
 %type <list>   var_list var_list_or_default
-%type <str>            ColId ColLabel var_name type_name param_name
+%type <str>            ColId ColLabel var_name type_function_name param_name
 %type <node>   var_value zone_value
 
-%type <keyword> unreserved_keyword func_name_keyword
+%type <keyword> unreserved_keyword type_func_name_keyword
 %type <keyword> col_name_keyword reserved_keyword
 
-%type <node>   TableConstraint TableLikeClause 
+%type <node>   TableConstraint TableLikeClause
 %type <list>   TableLikeOptionList
 %type <ival>   TableLikeOption
 %type <list>   ColQualList
@@ -1180,35 +1179,20 @@ zone_value:
                                                        ereport(ERROR,
                                                                        (errcode(ERRCODE_SYNTAX_ERROR),
                                                                         errmsg("time zone interval must be HOUR or HOUR TO MINUTE")));
-                                               n->typename->typmod = INTERVAL_TYPMOD(INTERVAL_FULL_PRECISION, $3);
+                                               n->typename->typmods = list_make1(makeIntConst($3));
                                        }
                                        $$ = (Node *)n;
                                }
                        | ConstInterval '(' Iconst ')' Sconst opt_interval
                                {
                                        A_Const *n = (A_Const *) makeStringConst($5, $1);
-                                       if ($3 < 0)
-                                               ereport(ERROR,
-                                                               (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-                                                                errmsg("INTERVAL(%d) precision must not be negative",
-                                                                               $3)));
-                                       if ($3 > MAX_INTERVAL_PRECISION)
-                                       {
-                                               ereport(WARNING,
-                                                               (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-                                                                errmsg("INTERVAL(%d) precision reduced to maximum allowed, %d",
-                                                                               $3, MAX_INTERVAL_PRECISION)));
-                                               $3 = MAX_INTERVAL_PRECISION;
-                                       }
-
                                        if (($6 != INTERVAL_FULL_RANGE)
                                                && (($6 & ~(INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE))) != 0))
                                                ereport(ERROR,
                                                                (errcode(ERRCODE_SYNTAX_ERROR),
                                                                 errmsg("time zone interval must be HOUR or HOUR TO MINUTE")));
-
-                                       n->typename->typmod = INTERVAL_TYPMOD($3, $6);
-
+                                       n->typename->typmods = list_make2(makeIntConst($6),
+                                                                                                         makeIntConst($3));
                                        $$ = (Node *)n;
                                }
                        | NumericOnly                                                   { $$ = makeAConst($1); }
@@ -2823,7 +2807,7 @@ DefineStmt:
                                        n->definition = $4;
                                        $$ = (Node *)n;
                                }
-                       | CREATE TYPE_P any_name 
+                       | CREATE TYPE_P any_name
                                {
                                        /* Shell type (identified by lack of definition) */
                                        DefineStmt *n = makeNode(DefineStmt);
@@ -2889,7 +2873,6 @@ def_elem:  ColLabel '=' def_arg
 
 /* Note: any simple identifier will be returned as a type name! */
 def_arg:       func_type                                               { $$ = (Node *)$1; }
-                       | func_name_keyword                             { $$ = (Node *)makeString(pstrdup($1)); }
                        | reserved_keyword                              { $$ = (Node *)makeString(pstrdup($1)); }
                        | qual_all_Op                                   { $$ = (Node *)$1; }
                        | NumericOnly                                   { $$ = (Node *)$1; }
@@ -3047,7 +3030,7 @@ ReassignOwnedStmt:
  *
  *             QUERY:
  *
- *             DROP itemtype [ IF EXISTS ] itemname [, itemname ...] 
+ *             DROP itemtype [ IF EXISTS ] itemname [, itemname ...]
  *           [ RESTRICT | CASCADE ]
  *
  *****************************************************************************/
@@ -3872,7 +3855,7 @@ arg_class:        IN_P                                                                    { $$ = FUNC_PARAM_IN; }
 /*
  * Ideally param_name should be ColId, but that causes too many conflicts.
  */
-param_name:    function_name
+param_name:    type_function_name
                ;
 
 func_return:
@@ -3888,23 +3871,20 @@ func_return:
 
 /*
  * We would like to make the %TYPE productions here be ColId attrs etc,
- * but that causes reduce/reduce conflicts.  type_name is next best choice.
+ * but that causes reduce/reduce conflicts.  type_function_name
+ * is next best choice.
  */
 func_type:     Typename                                                                { $$ = $1; }
-                       | type_name attrs '%' TYPE_P
+                       | type_function_name attrs '%' TYPE_P
                                {
-                                       $$ = makeNode(TypeName);
-                                       $$->names = lcons(makeString($1), $2);
+                                       $$ = makeTypeNameFromNameList(lcons(makeString($1), $2));
                                        $$->pct_type = true;
-                                       $$->typmod = -1;
                                        $$->location = @1;
                                }
-                       | SETOF type_name attrs '%' TYPE_P
+                       | SETOF type_function_name attrs '%' TYPE_P
                                {
-                                       $$ = makeNode(TypeName);
-                                       $$->names = lcons(makeString($2), $3);
+                                       $$ = makeTypeNameFromNameList(lcons(makeString($2), $3));
                                        $$->pct_type = true;
-                                       $$->typmod = -1;
                                        $$->setof = TRUE;
                                        $$->location = @2;
                                }
@@ -5552,7 +5532,7 @@ multiple_set_clause:
 
                                                res_col->val = res_val;
                                        }
-                                   
+
                                        $$ = $2;
                                }
                ;
@@ -6363,14 +6343,6 @@ opt_array_bounds:
                                        {  $$ = NIL; }
                ;
 
-/*
- * XXX ideally, the production for a qualified typename should be ColId attrs
- * (there's no obvious reason why the first name should need to be restricted)
- * and should be an alternative of GenericType (so that it can be used to
- * specify a type for a literal in AExprConst).  However doing either causes
- * reduce/reduce conflicts that I haven't been able to find a workaround
- * for.  FIXME later.
- */
 SimpleTypename:
                        GenericType                                                             { $$ = $1; }
                        | Numeric                                                               { $$ = $1; }
@@ -6381,32 +6353,13 @@ SimpleTypename:
                                {
                                        $$ = $1;
                                        if ($2 != INTERVAL_FULL_RANGE)
-                                               $$->typmod = INTERVAL_TYPMOD(INTERVAL_FULL_PRECISION, $2);
+                                               $$->typmods = list_make1(makeIntConst($2));
                                }
                        | ConstInterval '(' Iconst ')' opt_interval
                                {
                                        $$ = $1;
-                                       if ($3 < 0)
-                                               ereport(ERROR,
-                                                               (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-                                                                errmsg("INTERVAL(%d) precision must not be negative",
-                                                                               $3)));
-                                       if ($3 > MAX_INTERVAL_PRECISION)
-                                       {
-                                               ereport(WARNING,
-                                                               (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-                                                                errmsg("INTERVAL(%d) precision reduced to maximum allowed, %d",
-                                                                               $3, MAX_INTERVAL_PRECISION)));
-                                               $3 = MAX_INTERVAL_PRECISION;
-                                       }
-                                       $$->typmod = INTERVAL_TYPMOD($3, $5);
-                               }
-                       | type_name attrs
-                               {
-                                       $$ = makeNode(TypeName);
-                                       $$->names = lcons(makeString($1), $2);
-                                       $$->typmod = -1;
-                                       $$->location = @1;
+                                       $$->typmods = list_make2(makeIntConst($5),
+                                                                                        makeIntConst($3));
                                }
                ;
 
@@ -6417,80 +6370,112 @@ SimpleTypename:
  * where there is an obvious better choice to make.
  * Note that ConstInterval is not included here since it must
  * be pushed up higher in the rules to accomodate the postfix
- * options (e.g. INTERVAL '1' YEAR).
+ * options (e.g. INTERVAL '1' YEAR). Likewise, we have to handle
+ * the generic-type-name case in AExprConst to avoid premature
+ * reduce/reduce conflicts against function names.
  */
 ConstTypename:
-                       GenericType                                                             { $$ = $1; }
-                       | Numeric                                                               { $$ = $1; }
+                       Numeric                                                                 { $$ = $1; }
                        | ConstBit                                                              { $$ = $1; }
                        | ConstCharacter                                                { $$ = $1; }
                        | ConstDatetime                                                 { $$ = $1; }
                ;
 
+/*
+ * GenericType covers all type names that don't have special syntax mandated
+ * by the standard, including qualified names.  We also allow type modifiers.
+ * To avoid parsing conflicts against function invocations, the modifiers
+ * have to be shown as expr_list here, but parse analysis will only accept
+ * integer constants for them.
+ */
 GenericType:
-                       type_name
+                       type_function_name opt_type_modifiers
                                {
                                        $$ = makeTypeName($1);
+                                       $$->typmods = $2;
+                                       $$->location = @1;
+                               }
+                       | type_function_name attrs opt_type_modifiers
+                               {
+                                       $$ = makeTypeNameFromNameList(lcons(makeString($1), $2));
+                                       $$->typmods = $3;
                                        $$->location = @1;
                                }
                ;
 
-/* SQL92 numeric data types
- * Check FLOAT() precision limits assuming IEEE floating types.
- * - thomas 1997-09-18
- * Provide real DECIMAL() and NUMERIC() implementations now - Jan 1998-12-30
+opt_type_modifiers: '(' expr_list ')'                          { $$ = $2; }
+                                       | /* EMPTY */                                   { $$ = NIL; }
+               ;
+
+/*
+ * SQL92 numeric data types
  */
 Numeric:       INT_P
                                {
                                        $$ = SystemTypeName("int4");
+                                       $$->location = @1;
                                }
                        | INTEGER
                                {
                                        $$ = SystemTypeName("int4");
+                                       $$->location = @1;
                                }
                        | SMALLINT
                                {
                                        $$ = SystemTypeName("int2");
+                                       $$->location = @1;
                                }
                        | BIGINT
                                {
                                        $$ = SystemTypeName("int8");
+                                       $$->location = @1;
                                }
                        | REAL
                                {
                                        $$ = SystemTypeName("float4");
+                                       $$->location = @1;
                                }
                        | FLOAT_P opt_float
                                {
                                        $$ = $2;
+                                       $$->location = @1;
                                }
                        | DOUBLE_P PRECISION
                                {
                                        $$ = SystemTypeName("float8");
+                                       $$->location = @1;
                                }
-                       | DECIMAL_P opt_decimal
+                       | DECIMAL_P opt_type_modifiers
                                {
                                        $$ = SystemTypeName("numeric");
-                                       $$->typmod = $2;
+                                       $$->typmods = $2;
+                                       $$->location = @1;
                                }
-                       | DEC opt_decimal
+                       | DEC opt_type_modifiers
                                {
                                        $$ = SystemTypeName("numeric");
-                                       $$->typmod = $2;
+                                       $$->typmods = $2;
+                                       $$->location = @1;
                                }
-                       | NUMERIC opt_numeric
+                       | NUMERIC opt_type_modifiers
                                {
                                        $$ = SystemTypeName("numeric");
-                                       $$->typmod = $2;
+                                       $$->typmods = $2;
+                                       $$->location = @1;
                                }
                        | BOOLEAN_P
                                {
                                        $$ = SystemTypeName("bool");
+                                       $$->location = @1;
                                }
                ;
 
 opt_float:     '(' Iconst ')'
                                {
+                                       /*
+                                        * Check FLOAT() precision limits assuming IEEE floating
+                                        * types - thomas 1997-09-18
+                                        */
                                        if ($2 < 1)
                                                ereport(ERROR,
                                                                (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
@@ -6510,73 +6495,6 @@ opt_float:       '(' Iconst ')'
                                }
                ;
 
-opt_numeric:
-                       '(' Iconst ',' Iconst ')'
-                               {
-                                       if ($2 < 1 || $2 > NUMERIC_MAX_PRECISION)
-                                               ereport(ERROR,
-                                                               (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-                                                                errmsg("NUMERIC precision %d must be between 1 and %d",
-                                                                               $2, NUMERIC_MAX_PRECISION)));
-                                       if ($4 < 0 || $4 > $2)
-                                               ereport(ERROR,
-                                                               (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-                                                                errmsg("NUMERIC scale %d must be between 0 and precision %d",
-                                                                               $4, $2)));
-
-                                       $$ = (($2 << 16) | $4) + VARHDRSZ;
-                               }
-                       | '(' Iconst ')'
-                               {
-                                       if ($2 < 1 || $2 > NUMERIC_MAX_PRECISION)
-                                               ereport(ERROR,
-                                                               (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-                                                                errmsg("NUMERIC precision %d must be between 1 and %d",
-                                                                               $2, NUMERIC_MAX_PRECISION)));
-
-                                       $$ = ($2 << 16) + VARHDRSZ;
-                               }
-                       | /*EMPTY*/
-                               {
-                                       /* Insert "-1" meaning "no limit" */
-                                       $$ = -1;
-                               }
-               ;
-
-opt_decimal:
-                       '(' Iconst ',' Iconst ')'
-                               {
-                                       if ($2 < 1 || $2 > NUMERIC_MAX_PRECISION)
-                                               ereport(ERROR,
-                                                               (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-                                                                errmsg("DECIMAL precision %d must be between 1 and %d",
-                                                                               $2, NUMERIC_MAX_PRECISION)));
-                                       if ($4 < 0 || $4 > $2)
-                                               ereport(ERROR,
-                                                               (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-                                                                errmsg("DECIMAL scale %d must be between 0 and precision %d",
-                                                                               $4, $2)));
-
-                                       $$ = (($2 << 16) | $4) + VARHDRSZ;
-                               }
-                       | '(' Iconst ')'
-                               {
-                                       if ($2 < 1 || $2 > NUMERIC_MAX_PRECISION)
-                                               ereport(ERROR,
-                                                               (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-                                                                errmsg("DECIMAL precision %d must be between 1 and %d",
-                                                                               $2, NUMERIC_MAX_PRECISION)));
-
-                                       $$ = ($2 << 16) + VARHDRSZ;
-                               }
-                       | /*EMPTY*/
-                               {
-                                       /* Insert "-1" meaning "no limit" */
-                                       $$ = -1;
-                               }
-               ;
-
-
 /*
  * SQL92 bit-field data types
  * The following implements BIT() and BIT VARYING().
@@ -6600,28 +6518,19 @@ ConstBit:       BitWithLength
                        | BitWithoutLength
                                {
                                        $$ = $1;
-                                       $$->typmod = -1;
+                                       $$->typmods = NIL;
                                }
                ;
 
 BitWithLength:
-                       BIT opt_varying '(' Iconst ')'
+                       BIT opt_varying '(' expr_list ')'
                                {
                                        char *typname;
 
                                        typname = $2 ? "varbit" : "bit";
                                        $$ = SystemTypeName(typname);
-                                       if ($4 < 1)
-                                               ereport(ERROR,
-                                                               (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-                                                                errmsg("length for type %s must be at least 1",
-                                                                               typname)));
-                                       else if ($4 > (MaxAttrSize * BITS_PER_BYTE))
-                                               ereport(ERROR,
-                                                               (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-                                                                errmsg("length for type %s cannot exceed %d",
-                                                                               typname, MaxAttrSize * BITS_PER_BYTE)));
-                                       $$->typmod = $4;
+                                       $$->typmods = $4;
+                                       $$->location = @1;
                                }
                ;
 
@@ -6632,13 +6541,13 @@ BitWithoutLength:
                                        if ($2)
                                        {
                                                $$ = SystemTypeName("varbit");
-                                               $$->typmod = -1;
                                        }
                                        else
                                        {
                                                $$ = SystemTypeName("bit");
-                                               $$->typmod = 1;
+                                               $$->typmods = list_make1(makeIntConst(1));
                                        }
+                                       $$->location = @1;
                                }
                ;
 
@@ -6670,7 +6579,7 @@ ConstCharacter:  CharacterWithLength
                                         * was not specified.
                                         */
                                        $$ = $1;
-                                       $$->typmod = -1;
+                                       $$->typmods = NIL;
                                }
                ;
 
@@ -6688,24 +6597,8 @@ CharacterWithLength:  character '(' Iconst ')' opt_charset
                                        }
 
                                        $$ = SystemTypeName($1);
-
-                                       if ($3 < 1)
-                                               ereport(ERROR,
-                                                               (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-                                                                errmsg("length for type %s must be at least 1",
-                                                                               $1)));
-                                       else if ($3 > MaxAttrSize)
-                                               ereport(ERROR,
-                                                               (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-                                                                errmsg("length for type %s cannot exceed %d",
-                                                                               $1, MaxAttrSize)));
-
-                                       /* we actually implement these like a varlen, so
-                                        * the first 4 bytes is the length. (the difference
-                                        * between these and "text" is that we blank-pad and
-                                        * truncate where necessary)
-                                        */
-                                       $$->typmod = VARHDRSZ + $3;
+                                       $$->typmods = list_make1(makeIntConst($3));
+                                       $$->location = @1;
                                }
                ;
 
@@ -6726,9 +6619,9 @@ CharacterWithoutLength:    character opt_charset
 
                                        /* char defaults to char(1), varchar to no limit */
                                        if (strcmp($1, "bpchar") == 0)
-                                               $$->typmod = VARHDRSZ + 1;
-                                       else
-                                               $$->typmod = -1;
+                                               $$->typmods = list_make1(makeIntConst(1));
+
+                                       $$->location = @1;
                                }
                ;
 
@@ -6756,6 +6649,9 @@ opt_charset:
                        | /*EMPTY*/                                                             { $$ = NULL; }
                ;
 
+/*
+ * SQL92 date/time types
+ */
 ConstDatetime:
                        TIMESTAMP '(' Iconst ')' opt_timezone
                                {
@@ -6767,21 +6663,8 @@ ConstDatetime:
                                         * - thomas 2001-09-06
                                         */
                                        $$->timezone = $5;
-                                       if ($3 < 0)
-                                               ereport(ERROR,
-                                                               (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-                                                                errmsg("TIMESTAMP(%d)%s precision must not be negative",
-                                                                               $3, ($5 ? " WITH TIME ZONE": ""))));
-                                       if ($3 > MAX_TIMESTAMP_PRECISION)
-                                       {
-                                               ereport(WARNING,
-                                                               (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-                                                                errmsg("TIMESTAMP(%d)%s precision reduced to maximum allowed, %d",
-                                                                               $3, ($5 ? " WITH TIME ZONE": ""),
-                                                                               MAX_TIMESTAMP_PRECISION)));
-                                               $3 = MAX_TIMESTAMP_PRECISION;
-                                       }
-                                       $$->typmod = $3;
+                                       $$->typmods = list_make1(makeIntConst($3));
+                                       $$->location = @1;
                                }
                        | TIMESTAMP opt_timezone
                                {
@@ -6793,6 +6676,7 @@ ConstDatetime:
                                         * - thomas 2001-09-06
                                         */
                                        $$->timezone = $2;
+                                       $$->location = @1;
                                }
                        | TIME '(' Iconst ')' opt_timezone
                                {
@@ -6800,21 +6684,8 @@ ConstDatetime:
                                                $$ = SystemTypeName("timetz");
                                        else
                                                $$ = SystemTypeName("time");
-                                       if ($3 < 0)
-                                               ereport(ERROR,
-                                                               (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-                                                                errmsg("TIME(%d)%s precision must not be negative",
-                                                                               $3, ($5 ? " WITH TIME ZONE": ""))));
-                                       if ($3 > MAX_TIME_PRECISION)
-                                       {
-                                               ereport(WARNING,
-                                                               (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-                                                                errmsg("TIME(%d)%s precision reduced to maximum allowed, %d",
-                                                                               $3, ($5 ? " WITH TIME ZONE": ""),
-                                                                               MAX_TIME_PRECISION)));
-                                               $3 = MAX_TIME_PRECISION;
-                                       }
-                                       $$->typmod = $3;
+                                       $$->typmods = list_make1(makeIntConst($3));
+                                       $$->location = @1;
                                }
                        | TIME opt_timezone
                                {
@@ -6822,11 +6693,16 @@ ConstDatetime:
                                                $$ = SystemTypeName("timetz");
                                        else
                                                $$ = SystemTypeName("time");
+                                       $$->location = @1;
                                }
                ;
 
 ConstInterval:
-                       INTERVAL                                                                { $$ = SystemTypeName("interval"); }
+                       INTERVAL
+                               {
+                                       $$ = SystemTypeName("interval");
+                                       $$->location = @1;
+                               }
                ;
 
 opt_timezone:
@@ -7520,20 +7396,7 @@ func_expr:       func_name '(' ')'
                                        s->val.val.str = "now";
                                        s->typename = SystemTypeName("text");
                                        d = SystemTypeName("timetz");
-                                       if ($3 < 0)
-                                               ereport(ERROR,
-                                                               (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-                                                                errmsg("CURRENT_TIME(%d) precision must not be negative",
-                                                                               $3)));
-                                       if ($3 > MAX_TIME_PRECISION)
-                                       {
-                                               ereport(WARNING,
-                                                               (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-                                                                errmsg("CURRENT_TIME(%d) precision reduced to maximum allowed, %d",
-                                                                               $3, MAX_TIME_PRECISION)));
-                                               $3 = MAX_TIME_PRECISION;
-                                       }
-                                       d->typmod = $3;
+                                       d->typmods = list_make1(makeIntConst($3));
 
                                        $$ = (Node *)makeTypeCast((Node *)s, d);
                                }
@@ -7565,20 +7428,7 @@ func_expr:       func_name '(' ')'
                                        s->typename = SystemTypeName("text");
 
                                        d = SystemTypeName("timestamptz");
-                                       if ($3 < 0)
-                                               ereport(ERROR,
-                                                               (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-                                                                errmsg("CURRENT_TIMESTAMP(%d) precision must not be negative",
-                                                                               $3)));
-                                       if ($3 > MAX_TIMESTAMP_PRECISION)
-                                       {
-                                               ereport(WARNING,
-                                                               (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-                                                                errmsg("CURRENT_TIMESTAMP(%d) precision reduced to maximum allowed, %d",
-                                                                               $3, MAX_TIMESTAMP_PRECISION)));
-                                               $3 = MAX_TIMESTAMP_PRECISION;
-                                       }
-                                       d->typmod = $3;
+                                       d->typmods = list_make1(makeIntConst($3));
 
                                        $$ = (Node *)makeTypeCast((Node *)s, d);
                                }
@@ -7612,20 +7462,7 @@ func_expr:       func_name '(' ')'
                                        s->val.val.str = "now";
                                        s->typename = SystemTypeName("text");
                                        d = SystemTypeName("time");
-                                       if ($3 < 0)
-                                               ereport(ERROR,
-                                                               (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-                                                                errmsg("LOCALTIME(%d) precision must not be negative",
-                                                                               $3)));
-                                       if ($3 > MAX_TIME_PRECISION)
-                                       {
-                                               ereport(WARNING,
-                                                               (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-                                                                errmsg("LOCALTIME(%d) precision reduced to maximum allowed, %d",
-                                                                               $3, MAX_TIME_PRECISION)));
-                                               $3 = MAX_TIME_PRECISION;
-                                       }
-                                       d->typmod = $3;
+                                       d->typmods = list_make1(makeIntConst($3));
 
                                        $$ = (Node *)makeTypeCast((Node *)s, d);
                                }
@@ -7660,20 +7497,7 @@ func_expr:       func_name '(' ')'
                                        s->typename = SystemTypeName("text");
 
                                        d = SystemTypeName("timestamp");
-                                       if ($3 < 0)
-                                               ereport(ERROR,
-                                                               (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-                                                                errmsg("LOCALTIMESTAMP(%d) precision must not be negative",
-                                                                               $3)));
-                                       if ($3 > MAX_TIMESTAMP_PRECISION)
-                                       {
-                                               ereport(WARNING,
-                                                               (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-                                                                errmsg("LOCALTIMESTAMP(%d) precision reduced to maximum allowed, %d",
-                                                                               $3, MAX_TIMESTAMP_PRECISION)));
-                                               $3 = MAX_TIMESTAMP_PRECISION;
-                                       }
-                                       d->typmod = $3;
+                                       d->typmods = list_make1(makeIntConst($3));
 
                                        $$ = (Node *)makeTypeCast((Node *)s, d);
                                }
@@ -7880,7 +7704,7 @@ func_expr:        func_name '(' ')'
                                        $$ = (Node *)v;
                                }
                        | XMLCONCAT '(' expr_list ')'
-                               {               
+                               {
                                        $$ = makeXmlExpr(IS_XMLCONCAT, NULL, NIL, $3);
                                }
                        | XMLELEMENT '(' NAME_P ColLabel ')'
@@ -7985,7 +7809,7 @@ xml_attribute_el: a_expr AS ColLabel
                                        $$ = makeNode(ResTarget);
                                        $$->name = NULL;
                                        $$->indirection = NULL;
-                                       $$->val = (Node *) $1;                          
+                                       $$->val = (Node *) $1;
                                        $$->location = @1;
                                }
                ;
@@ -8486,12 +8310,12 @@ file_name:      Sconst                                                                  { $$ = $1; };
 /*
  * The production for a qualified func_name has to exactly match the
  * production for a qualified columnref, because we cannot tell which we
- * are parsing until we see what comes after it ('(' for a func_name,
+ * are parsing until we see what comes after it ('(' or Sconst for a func_name,
  * anything else for a columnref).  Therefore we allow 'indirection' which
  * may contain subscripts, and reject that case in the C code.  (If we
  * ever implement SQL99-like methods, such syntax may actually become legal!)
  */
-func_name:     function_name
+func_name:     type_function_name
                                        { $$ = list_make1(makeString($1)); }
                        | relation_name indirection
                                        { $$ = check_func_name(lcons(makeString($1), $2)); }
@@ -8541,6 +8365,27 @@ AexprConst: Iconst
                                        n->val.val.str = $1;
                                        $$ = (Node *)n;
                                }
+                       | func_name Sconst
+                               {
+                                       /* generic type 'literal' syntax */
+                                       A_Const *n = makeNode(A_Const);
+                                       n->typename = makeTypeNameFromNameList($1);
+                                       n->typename->location = @1;
+                                       n->val.type = T_String;
+                                       n->val.val.str = $2;
+                                       $$ = (Node *)n;
+                               }
+                       | func_name '(' expr_list ')' Sconst
+                               {
+                                       /* generic syntax with a type modifier */
+                                       A_Const *n = makeNode(A_Const);
+                                       n->typename = makeTypeNameFromNameList($1);
+                                       n->typename->typmods = $3;
+                                       n->typename->location = @1;
+                                       n->val.type = T_String;
+                                       n->val.val.str = $5;
+                                       $$ = (Node *)n;
+                               }
                        | ConstTypename Sconst
                                {
                                        A_Const *n = makeNode(A_Const);
@@ -8557,7 +8402,7 @@ AexprConst: Iconst
                                        n->val.val.str = $2;
                                        /* precision is not specified, but fields may be... */
                                        if ($3 != INTERVAL_FULL_RANGE)
-                                               n->typename->typmod = INTERVAL_TYPMOD(INTERVAL_FULL_PRECISION, $3);
+                                               n->typename->typmods = list_make1(makeIntConst($3));
                                        $$ = (Node *)n;
                                }
                        | ConstInterval '(' Iconst ')' Sconst opt_interval
@@ -8566,21 +8411,8 @@ AexprConst: Iconst
                                        n->typename = $1;
                                        n->val.type = T_String;
                                        n->val.val.str = $5;
-                                       /* precision specified, and fields may be... */
-                                       if ($3 < 0)
-                                               ereport(ERROR,
-                                                               (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-                                                                errmsg("INTERVAL(%d) precision must not be negative",
-                                                                               $3)));
-                                       if ($3 > MAX_INTERVAL_PRECISION)
-                                       {
-                                               ereport(WARNING,
-                                                               (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-                                                                errmsg("INTERVAL(%d) precision reduced to maximum allowed, %d",
-                                                                               $3, MAX_INTERVAL_PRECISION)));
-                                               $3 = MAX_INTERVAL_PRECISION;
-                                       }
-                                       n->typename->typmod = INTERVAL_TYPMOD($3, $6);
+                                       n->typename->typmods = list_make2(makeIntConst($6),
+                                                                                                         makeIntConst($3));
                                        $$ = (Node *)n;
                                }
                        | TRUE_P
@@ -8625,18 +8457,11 @@ ColId:          IDENT                                                                   { $$ = $1; }
                        | col_name_keyword                                              { $$ = pstrdup($1); }
                ;
 
-/* Type identifier --- names that can be type names.
- */
-type_name:     IDENT                                                                   { $$ = $1; }
-                       | unreserved_keyword                                    { $$ = pstrdup($1); }
-               ;
-
-/* Function identifier --- names that can be function names.
+/* Type/function identifier --- names that can be type or function names.
  */
-function_name:
-                       IDENT                                                                   { $$ = $1; }
+type_function_name:    IDENT                                                   { $$ = $1; }
                        | unreserved_keyword                                    { $$ = pstrdup($1); }
-                       | func_name_keyword                                             { $$ = pstrdup($1); }
+                       | type_func_name_keyword                                { $$ = pstrdup($1); }
                ;
 
 /* Column label --- allowed labels in "AS" clauses.
@@ -8645,7 +8470,7 @@ function_name:
 ColLabel:      IDENT                                                                   { $$ = $1; }
                        | unreserved_keyword                                    { $$ = pstrdup($1); }
                        | col_name_keyword                                              { $$ = pstrdup($1); }
-                       | func_name_keyword                                             { $$ = pstrdup($1); }
+                       | type_func_name_keyword                                { $$ = pstrdup($1); }
                        | reserved_keyword                                              { $$ = pstrdup($1); }
                ;
 
@@ -8940,7 +8765,7 @@ col_name_keyword:
                        | XMLSERIALIZE
                ;
 
-/* Function identifier --- keywords that can be function names.
+/* Type/function identifier --- keywords that can be type or function names.
  *
  * Most of these are keywords that are used as operators in expressions;
  * in general such keywords can't be column names because they would be
@@ -8950,7 +8775,7 @@ col_name_keyword:
  * productions in a_expr to support the goofy SQL9x argument syntax.
  * - thomas 2000-11-28
  */
-func_name_keyword:
+type_func_name_keyword:
                          AUTHORIZATION
                        | BETWEEN
                        | BINARY
@@ -9383,12 +9208,8 @@ SystemFuncName(char *name)
 TypeName *
 SystemTypeName(char *name)
 {
-       TypeName   *n = makeNode(TypeName);
-
-       n->names = list_make2(makeString("pg_catalog"), makeString(name));
-       n->typmod = -1;
-       n->location = -1;
-       return n;
+       return makeTypeNameFromNameList(list_make2(makeString("pg_catalog"),
+                                                                                          makeString(name)));
 }
 
 /* parser_init()
index 7dbbb9a33a8637b97338756d22cd8cf027dc2416..383013c9a10134878acebeb6566d7f78fd64a802 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/parser/parse_expr.c,v 1.202 2006/12/24 00:29:19 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/parser/parse_expr.c,v 1.203 2006/12/30 21:21:53 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1810,29 +1810,6 @@ exprTypmod(Node *expr)
        {
                case T_Var:
                        return ((Var *) expr)->vartypmod;
-               case T_Const:
-                       {
-                               /* Be smart about string constants... */
-                               Const      *con = (Const *) expr;
-
-                               switch (con->consttype)
-                               {
-                                       case BPCHAROID:
-                                               if (!con->constisnull)
-                                               {
-                                                       int32           len = VARSIZE(DatumGetPointer(con->constvalue)) - VARHDRSZ;
-
-                                                       /* if multi-byte, take len and find # characters */
-                                                       if (pg_database_encoding_max_length() > 1)
-                                                               len = pg_mbstrlen_with_len(VARDATA(DatumGetPointer(con->constvalue)), len);
-                                                       return len + VARHDRSZ;
-                                               }
-                                               break;
-                                       default:
-                                               break;
-                               }
-                       }
-                       break;
                case T_Param:
                        return ((Param *) expr)->paramtypmod;
                case T_FuncExpr:
@@ -2024,14 +2001,16 @@ typecast_expression(ParseState *pstate, Node *expr, TypeName *typename)
 {
        Oid                     inputType = exprType(expr);
        Oid                     targetType;
+       int32           targetTypmod;
 
        targetType = typenameTypeId(pstate, typename);
+       targetTypmod = typenameTypeMod(pstate, typename, targetType);
 
        if (inputType == InvalidOid)
                return expr;                    /* do nothing if NULL input */
 
        expr = coerce_to_target_type(pstate, expr, inputType,
-                                                                targetType, typename->typmod,
+                                                                targetType, targetTypmod,
                                                                 COERCION_EXPLICIT,
                                                                 COERCE_EXPLICIT_CAST);
        if (expr == NULL)
index 75d5a50702a50e24d07914fc19c43e6fa89099e6..f6d4fcae4aa80fce8e4470993ede1dcab50a980b 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/parser/parse_relation.c,v 1.125 2006/10/04 00:29:56 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/parser/parse_relation.c,v 1.126 2006/12/30 21:21:54 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -901,9 +901,9 @@ addRangeTableEntryForFunction(ParseState *pstate,
                                                (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
                                                 errmsg("column \"%s\" cannot be declared SETOF",
                                                                attrname)));
-                       eref->colnames = lappend(eref->colnames, makeString(attrname));
                        attrtype = typenameTypeId(pstate, n->typename);
-                       attrtypmod = n->typename->typmod;
+                       attrtypmod = typenameTypeMod(pstate, n->typename, attrtype);
+                       eref->colnames = lappend(eref->colnames, makeString(attrname));
                        rte->funccoltypes = lappend_oid(rte->funccoltypes, attrtype);
                        rte->funccoltypmods = lappend_int(rte->funccoltypmods, attrtypmod);
                }
index 93c7db6b52a8f46a6ffd8c30ef1332d52b2b1651..6aeabb5749827413aa0ed70f0155e1361ca64843 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/parser/parse_type.c,v 1.85 2006/10/04 00:29:56 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/parser/parse_type.c,v 1.86 2006/12/30 21:21:54 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -20,6 +20,7 @@
 #include "nodes/makefuncs.h"
 #include "parser/parser.h"
 #include "parser/parse_type.h"
+#include "utils/array.h"
 #include "utils/builtins.h"
 #include "utils/lsyscache.h"
 #include "utils/syscache.h"
@@ -245,9 +246,81 @@ typenameTypeId(ParseState *pstate, const TypeName *typename)
                                 errmsg("type \"%s\" is only a shell",
                                                TypeNameToString(typename)),
                                 parser_errposition(pstate, typename->location)));
+
        return typoid;
 }
 
+/*
+ * typenameTypeMod - given a TypeName, return the internal typmod value
+ *
+ * This will throw an error if the TypeName includes type modifiers that are
+ * illegal for the data type.
+ *
+ * The actual type OID represented by the TypeName must already have been
+ * determined (usually by typenameTypeId()), and is passed as typeId.
+ *
+ * pstate is only used for error location info, and may be NULL.
+ */
+int32
+typenameTypeMod(ParseState *pstate, const TypeName *typename,
+                               Oid typeId)
+{
+       int32           result;
+       Oid                     typmodin;
+       Datum      *datums;
+       int                     n;
+       ListCell   *l;
+       ArrayType  *arrtypmod;
+
+       Assert(OidIsValid(typeId));
+
+       /* Return prespecified typmod if no typmod expressions */
+       if (typename->typmods == NIL)
+               return typename->typemod;
+
+       /* Else, type had better accept typmods */
+       typmodin = get_typmodin(typeId);
+
+       if (typmodin == InvalidOid)
+               ereport(ERROR,
+                               (errcode(ERRCODE_SYNTAX_ERROR),
+                                errmsg("type modifier is not allowed for type \"%s\"",
+                                               TypeNameToString(typename)),
+                                parser_errposition(pstate, typename->location)));
+
+       /*
+        * Convert the list of (raw grammar output) expressions to an integer
+        * array.  Currently, we only allow simple integer constants, though
+        * possibly this could be extended.
+        */
+       datums = (Datum *) palloc(list_length(typename->typmods) * sizeof(Datum));
+       n = 0;
+       foreach(l, typename->typmods)
+       {
+               A_Const *ac = (A_Const *) lfirst(l);
+
+               if (!IsA(ac, A_Const) ||
+                       !IsA(&ac->val, Integer))
+                       ereport(ERROR,
+                                       (errcode(ERRCODE_SYNTAX_ERROR),
+                                        errmsg("type modifiers must be integer constants"),
+                                        parser_errposition(pstate, typename->location)));
+               datums[n++] = Int32GetDatum(ac->val.val.ival);
+       }
+
+       /* hardwired knowledge about int4's representation details here */
+       arrtypmod = construct_array(datums, n, INT4OID,
+                                                               sizeof(int4), true, 'i');
+
+       result = DatumGetInt32(OidFunctionCall1(typmodin,
+                                                                                       PointerGetDatum(arrtypmod)));
+
+       pfree(datums);
+       pfree(arrtypmod);
+
+       return result;
+}
+
 /*
  * typenameType - given a TypeName, return a Type structure
  *
@@ -490,7 +563,7 @@ parseTypeString(const char *str, Oid *type_id, int32 *typmod)
                goto fail;
 
        *type_id = typenameTypeId(NULL, typename);
-       *typmod = typename->typmod;
+       *typmod = typenameTypeMod(NULL, typename, *type_id);
 
        pfree(buf.data);
 
index 2a732ad63bbf4e217d0c6acd91a43a82fe2ed5a9..2913d0a1d8b59d0afca3b6e74254febfce84ce6e 100644 (file)
@@ -8,13 +8,14 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/utils/adt/arrayutils.c,v 1.21 2006/03/05 15:58:41 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/utils/adt/arrayutils.c,v 1.22 2006/12/30 21:21:54 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 
 #include "postgres.h"
 
+#include "catalog/pg_type.h"
 #include "utils/array.h"
 #include "utils/memutils.h"
 
@@ -188,3 +189,30 @@ mda_next_tuple(int n, int *curr, const int *span)
 
        return -1;
 }
+
+/*
+ * ArrayGetTypmods: verify that argument is a 1-D integer array,
+ * return its length and a pointer to the first contained integer.
+ */
+int32 *
+ArrayGetTypmods(ArrayType *arr, int *n)
+{
+       if (ARR_ELEMTYPE(arr) != INT4OID)
+               ereport(ERROR,
+                               (errcode(ERRCODE_ARRAY_ELEMENT_ERROR),
+                                errmsg("typmod array must be type integer[]")));
+
+       if (ARR_NDIM(arr) != 1)
+               ereport(ERROR,
+                               (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
+                                errmsg("typmod array must be one-dimensional")));
+
+       if (ARR_HASNULL(arr))
+               ereport(ERROR,
+                               (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
+                                errmsg("typmod array must not contain nulls")));
+
+       *n = ArrayGetNItems(ARR_NDIM(arr), ARR_DIMS(arr));
+
+       return (int32 *) ARR_DATA_PTR(arr);
+}
index 9efc7125b19d397f92418b58849bd401562bc27e..e2781dec485093367fef8838c68aef6641955154 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/utils/adt/date.c,v 1.125 2006/07/14 14:52:23 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/utils/adt/date.c,v 1.126 2006/12/30 21:21:54 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -24,6 +24,7 @@
 #include "libpq/pqformat.h"
 #include "miscadmin.h"
 #include "parser/scansup.h"
+#include "utils/array.h"
 #include "utils/builtins.h"
 #include "utils/date.h"
 #include "utils/nabstime.h"
@@ -43,6 +44,60 @@ static int   tm2time(struct pg_tm * tm, fsec_t fsec, TimeADT *result);
 static int     tm2timetz(struct pg_tm * tm, fsec_t fsec, int tz, TimeTzADT *result);
 static void AdjustTimeForTypmod(TimeADT *time, int32 typmod);
 
+
+/* common code for timetypmodin and timetztypmodin */
+static int32
+anytime_typmodin(bool istz, ArrayType *ta)
+{
+       int32   typmod;
+       int32   *tl;
+       int             n;
+
+       tl = ArrayGetTypmods(ta, &n);
+
+       /*
+        * we're not too tense about good error message here because grammar
+        * shouldn't allow wrong number of modifiers for TIME
+        */
+       if (n != 1)
+               ereport(ERROR,
+                               (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+                                errmsg("invalid type modifier")));
+
+       if (*tl < 0)
+               ereport(ERROR,
+                               (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+                                errmsg("TIME(%d)%s precision must not be negative",
+                                               *tl, (istz ? " WITH TIME ZONE" : ""))));
+       if (*tl > MAX_TIME_PRECISION)
+       {
+               ereport(WARNING,
+                               (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+                                errmsg("TIME(%d)%s precision reduced to maximum allowed, %d",
+                                               *tl, (istz ? " WITH TIME ZONE" : "" ),
+                                               MAX_TIME_PRECISION)));
+               typmod = MAX_TIME_PRECISION;
+       } else
+               typmod = *tl;
+
+       return typmod;
+}
+
+/* common code for timetypmodout and timetztypmodout */
+static char *
+anytime_typmodout(bool istz, int32 typmod)
+{
+       char    *res = (char *) palloc(64);
+       const char *tz = istz ? " with time zone" : " without time zone";
+
+       if (typmod >= 0)
+               snprintf(res, 64, "(%d)%s", (int) typmod, tz);
+       else
+               snprintf(res, 64, "%s", tz);
+       return res;
+}
+
+
 /*****************************************************************************
  *      Date ADT
  *****************************************************************************/
@@ -1029,6 +1084,22 @@ time_send(PG_FUNCTION_ARGS)
        PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
 }
 
+Datum
+timetypmodin(PG_FUNCTION_ARGS)
+{
+       ArrayType *ta = PG_GETARG_ARRAYTYPE_P(0);
+
+       PG_RETURN_INT32(anytime_typmodin(false, ta));
+}
+
+Datum
+timetypmodout(PG_FUNCTION_ARGS)
+{
+       int32 typmod = PG_GETARG_INT32(0);
+
+       PG_RETURN_CSTRING(anytime_typmodout(false, typmod));
+}
+
 
 /* time_scale()
  * Adjust time type for specified scale factor.
@@ -1830,6 +1901,22 @@ timetz_send(PG_FUNCTION_ARGS)
        PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
 }
 
+Datum
+timetztypmodin(PG_FUNCTION_ARGS)
+{
+       ArrayType *ta = PG_GETARG_ARRAYTYPE_P(0);
+
+       PG_RETURN_INT32(anytime_typmodin(true, ta));
+}
+
+Datum
+timetztypmodout(PG_FUNCTION_ARGS)
+{
+       int32 typmod = PG_GETARG_INT32(0);
+
+       PG_RETURN_CSTRING(anytime_typmodout(true, typmod));
+}
+
 
 /* timetz2tm()
  * Convert TIME WITH TIME ZONE data type to POSIX time structure.
index 22d9bc156f6d641282355be43c32814042727cdc..d2b6323f0f27b23bd42413b6f61a1f432fb09571 100644 (file)
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/utils/adt/format_type.c,v 1.44 2006/07/14 14:52:24 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/utils/adt/format_type.c,v 1.45 2006/12/30 21:21:54 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -20,7 +20,6 @@
 #include "catalog/namespace.h"
 #include "catalog/pg_type.h"
 #include "utils/builtins.h"
-#include "utils/datetime.h"
 #include "utils/lsyscache.h"
 #include "utils/numeric.h"
 #include "utils/syscache.h"
@@ -31,6 +30,7 @@
 
 static char *format_type_internal(Oid type_oid, int32 typemod,
                                         bool typemod_given, bool allow_invalid);
+static char *printTypmod(const char *typname, int32 typmod, Oid typmodout);
 static char *
 psnprintf(size_t len, const char *fmt,...)
 /* This lets gcc check the format string for consistency. */
@@ -186,8 +186,7 @@ format_type_internal(Oid type_oid, int32 typemod,
        {
                case BITOID:
                        if (with_typemod)
-                               buf = psnprintf(5 + MAX_INT32_LEN + 1, "bit(%d)",
-                                                               (int) typemod);
+                               buf = printTypmod("bit", typemod, typeform->typmodout);
                        else if (typemod_given)
                        {
                                /*
@@ -206,8 +205,7 @@ format_type_internal(Oid type_oid, int32 typemod,
 
                case BPCHAROID:
                        if (with_typemod)
-                               buf = psnprintf(11 + MAX_INT32_LEN + 1, "character(%d)",
-                                                               (int) (typemod - VARHDRSZ));
+                               buf = printTypmod("character", typemod, typeform->typmodout);
                        else if (typemod_given)
                        {
                                /*
@@ -242,136 +240,56 @@ format_type_internal(Oid type_oid, int32 typemod,
 
                case NUMERICOID:
                        if (with_typemod)
-                               buf = psnprintf(10 + 2 * MAX_INT32_LEN + 1, "numeric(%d,%d)",
-                                                               ((typemod - VARHDRSZ) >> 16) & 0xffff,
-                                                               (typemod - VARHDRSZ) & 0xffff);
+                               buf = printTypmod("numeric", typemod, typeform->typmodout);
                        else
                                buf = pstrdup("numeric");
                        break;
 
                case INTERVALOID:
                        if (with_typemod)
-                       {
-                               int                     fields = INTERVAL_RANGE(typemod);
-                               int                     precision = INTERVAL_PRECISION(typemod);
-                               const char *fieldstr;
-
-                               switch (fields)
-                               {
-                                       case INTERVAL_MASK(YEAR):
-                                               fieldstr = " year";
-                                               break;
-                                       case INTERVAL_MASK(MONTH):
-                                               fieldstr = " month";
-                                               break;
-                                       case INTERVAL_MASK(DAY):
-                                               fieldstr = " day";
-                                               break;
-                                       case INTERVAL_MASK(HOUR):
-                                               fieldstr = " hour";
-                                               break;
-                                       case INTERVAL_MASK(MINUTE):
-                                               fieldstr = " minute";
-                                               break;
-                                       case INTERVAL_MASK(SECOND):
-                                               fieldstr = " second";
-                                               break;
-                                               case INTERVAL_MASK(YEAR)
-                                       | INTERVAL_MASK(MONTH):
-                                               fieldstr = " year to month";
-                                               break;
-                                               case INTERVAL_MASK(DAY)
-                                       | INTERVAL_MASK(HOUR):
-                                               fieldstr = " day to hour";
-                                               break;
-                                               case INTERVAL_MASK(DAY)
-                                                       | INTERVAL_MASK(HOUR)
-                                       | INTERVAL_MASK(MINUTE):
-                                               fieldstr = " day to minute";
-                                               break;
-                                               case INTERVAL_MASK(DAY)
-                                                       | INTERVAL_MASK(HOUR)
-                                                       | INTERVAL_MASK(MINUTE)
-                                       | INTERVAL_MASK(SECOND):
-                                               fieldstr = " day to second";
-                                               break;
-                                               case INTERVAL_MASK(HOUR)
-                                       | INTERVAL_MASK(MINUTE):
-                                               fieldstr = " hour to minute";
-                                               break;
-                                               case INTERVAL_MASK(HOUR)
-                                                       | INTERVAL_MASK(MINUTE)
-                                       | INTERVAL_MASK(SECOND):
-                                               fieldstr = " hour to second";
-                                               break;
-                                               case INTERVAL_MASK(MINUTE)
-                                       | INTERVAL_MASK(SECOND):
-                                               fieldstr = " minute to second";
-                                               break;
-                                       case INTERVAL_FULL_RANGE:
-                                               fieldstr = "";
-                                               break;
-                                       default:
-                                               elog(ERROR, "invalid INTERVAL typmod: 0x%x", typemod);
-                                               fieldstr = "";
-                                               break;
-                               }
-                               if (precision != INTERVAL_FULL_PRECISION)
-                                       buf = psnprintf(100, "interval(%d)%s",
-                                                                       precision, fieldstr);
-                               else
-                                       buf = psnprintf(100, "interval%s",
-                                                                       fieldstr);
-                       }
+                               buf = printTypmod("interval", typemod, typeform->typmodout);
                        else
                                buf = pstrdup("interval");
                        break;
 
                case TIMEOID:
                        if (with_typemod)
-                               buf = psnprintf(50, "time(%d) without time zone",
-                                                               typemod);
+                               buf = printTypmod("time", typemod, typeform->typmodout);
                        else
                                buf = pstrdup("time without time zone");
                        break;
 
                case TIMETZOID:
                        if (with_typemod)
-                               buf = psnprintf(50, "time(%d) with time zone",
-                                                               typemod);
+                               buf = printTypmod("time", typemod, typeform->typmodout);
                        else
                                buf = pstrdup("time with time zone");
                        break;
 
                case TIMESTAMPOID:
                        if (with_typemod)
-                               buf = psnprintf(50, "timestamp(%d) without time zone",
-                                                               typemod);
+                               buf = printTypmod("timestamp", typemod, typeform->typmodout);
                        else
                                buf = pstrdup("timestamp without time zone");
                        break;
 
                case TIMESTAMPTZOID:
                        if (with_typemod)
-                               buf = psnprintf(50, "timestamp(%d) with time zone",
-                                                               typemod);
+                               buf = printTypmod("timestamp", typemod, typeform->typmodout);
                        else
                                buf = pstrdup("timestamp with time zone");
                        break;
 
                case VARBITOID:
                        if (with_typemod)
-                               buf = psnprintf(13 + MAX_INT32_LEN + 1, "bit varying(%d)",
-                                                               (int) typemod);
+                               buf = printTypmod("bit varying", typemod, typeform->typmodout);
                        else
                                buf = pstrdup("bit varying");
                        break;
 
                case VARCHAROID:
                        if (with_typemod)
-                               buf = psnprintf(19 + MAX_INT32_LEN + 1,
-                                                               "character varying(%d)",
-                                                               (int) (typemod - VARHDRSZ));
+                               buf = printTypmod("character varying", typemod, typeform->typmodout);
                        else
                                buf = pstrdup("character varying");
                        break;
@@ -396,6 +314,9 @@ format_type_internal(Oid type_oid, int32 typemod,
                typname = NameStr(typeform->typname);
 
                buf = quote_qualified_identifier(nspname, typname);
+
+               if (with_typemod)
+                       buf = printTypmod(buf, typemod, typeform->typmodout);
        }
 
        if (is_array)
@@ -407,6 +328,38 @@ format_type_internal(Oid type_oid, int32 typemod,
 }
 
 
+/*
+ * Add typmod decoration to the basic type name
+ */
+static char *
+printTypmod(const char *typname, int32 typmod, Oid typmodout)
+{
+       char    *res;
+
+       /* Shouldn't be called if typmod is -1 */
+       Assert(typmod >= 0);
+
+       if (typmodout == InvalidOid)
+       {
+               /* Default behavior: just print the integer typmod with parens */
+               res = psnprintf(strlen(typname) + MAX_INT32_LEN + 3, "%s(%d)",
+                                               typname, (int) typmod);
+       }
+       else
+       {
+               /* Use the type-specific typmodout procedure */
+               char *tmstr;
+
+               tmstr = DatumGetCString(OidFunctionCall1(typmodout,
+                                                                                                Int32GetDatum(typmod)));
+               res = psnprintf(strlen(typname) + strlen(tmstr) + 1, "%s%s",
+                                               typname, tmstr);
+       }
+
+       return res;
+}
+
+
 /*
  * type_maximum_size --- determine maximum width of a variable-width column
  *
@@ -417,7 +370,9 @@ format_type_internal(Oid type_oid, int32 typemod,
  *
  * This may appear unrelated to format_type(), but in fact the two routines
  * share knowledge of the encoding of typmod for different types, so it's
- * convenient to keep them together.
+ * convenient to keep them together.  (XXX now that most of this knowledge
+ * has been pushed out of format_type into the typmodout functions, it's
+ * interesting to wonder if it's worth trying to factor this code too...)
  */
 int32
 type_maximum_size(Oid type_oid, int32 typemod)
index 35b0221b85dc61677b8513bbd0f06d4e8c7da615..11dd881011fde0543f649398c0cd85409615be06 100644 (file)
@@ -14,7 +14,7 @@
  * Copyright (c) 1998-2006, PostgreSQL Global Development Group
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/utils/adt/numeric.c,v 1.96 2006/10/04 00:29:59 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/utils/adt/numeric.c,v 1.97 2006/12/30 21:21:54 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -470,7 +470,7 @@ numeric_send(PG_FUNCTION_ARGS)
  *     scale of the attribute have to be applied on the value.
  */
 Datum
-numeric                (PG_FUNCTION_ARGS)
+numeric(PG_FUNCTION_ARGS)
 {
        Numeric         num = PG_GETARG_NUMERIC(0);
        int32           typmod = PG_GETARG_INT32(1);
@@ -537,6 +537,67 @@ numeric            (PG_FUNCTION_ARGS)
        PG_RETURN_NUMERIC(new);
 }
 
+Datum
+numerictypmodin(PG_FUNCTION_ARGS)
+{
+       ArrayType   *ta = PG_GETARG_ARRAYTYPE_P(0);
+       int32           *tl;
+       int                     n;
+       int32           typmod;
+
+       tl = ArrayGetTypmods(ta, &n);
+
+       if (n == 2)
+       {
+               if (tl[0] < 1 || tl[0] > NUMERIC_MAX_PRECISION)
+                       ereport(ERROR,
+                                       (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+                                        errmsg("NUMERIC precision %d must be between 1 and %d",
+                                                       tl[0], NUMERIC_MAX_PRECISION)));
+               if (tl[1] < 0 || tl[1] > tl[0])
+                       ereport(ERROR,
+                                       (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+                                        errmsg("NUMERIC scale %d must be between 0 and precision %d",
+                                                       tl[1], tl[0])));
+               typmod = ((tl[0] << 16) | tl[1]) + VARHDRSZ;
+       }
+       else if (n == 1)
+       {
+               if (tl[0] < 1 || tl[0] > NUMERIC_MAX_PRECISION)
+                       ereport(ERROR,
+                                       (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+                                        errmsg("NUMERIC precision %d must be between 1 and %d",
+                                                       tl[0], NUMERIC_MAX_PRECISION)));
+               /* scale defaults to zero */
+               typmod = (tl[0] << 16) + VARHDRSZ;
+       }
+       else
+       {
+               ereport(ERROR,
+                               (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+                                               errmsg("invalid NUMERIC type modifier")));
+               typmod = 0;                             /* keep compiler quiet */
+       }
+
+       PG_RETURN_INT32(typmod);
+}
+
+Datum
+numerictypmodout(PG_FUNCTION_ARGS)
+{
+       int32   typmod = PG_GETARG_INT32(0);
+       char   *res = (char *) palloc(64);
+
+       if (typmod >= 0)
+               snprintf(res, 64, "(%d,%d)",
+                                ((typmod - VARHDRSZ) >> 16) & 0xffff,
+                                (typmod - VARHDRSZ) & 0xffff);
+       else
+               *res = '\0';
+
+       PG_RETURN_CSTRING(res);
+}
+
 
 /* ----------------------------------------------------------------------
  *
index f94413e3f32cafb600e0418b4914c2600a8bebe5..f9b0bb2c9921c5e13bb3204234d67c6e1a8734a2 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/utils/adt/timestamp.c,v 1.169 2006/11/11 01:14:19 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/utils/adt/timestamp.c,v 1.170 2006/12/30 21:21:54 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -56,6 +56,60 @@ static void AdjustIntervalForTypmod(Interval *interval, int32 typmod);
 static TimestampTz timestamp2timestamptz(Timestamp timestamp);
 
 
+/* common code for timestamptypmodin and timestamptztypmodin */
+static int32
+anytimestamp_typmodin(bool istz, ArrayType *ta)
+{
+    int32    typmod;
+       int32    *tl;
+       int             n;
+
+       tl = ArrayGetTypmods(ta, &n);
+
+       /*
+        * we're not too tense about good error message here because grammar
+        * shouldn't allow wrong number of modifiers for TIMESTAMP
+        */
+       if (n != 1)
+               ereport(ERROR,
+                               (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+                                errmsg("invalid type modifier")));
+
+       if (*tl < 0)
+               ereport(ERROR,
+                               (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+                                errmsg("TIMESTAMP(%d)%s precision must not be negative",
+                                               *tl, (istz ? " WITH TIME ZONE" : ""))));
+       if (*tl > MAX_TIMESTAMP_PRECISION)
+       {
+               ereport(WARNING,
+                               (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+                                errmsg("TIMESTAMP(%d)%s precision reduced to maximum allowed, %d",
+                                               *tl, (istz ? " WITH TIME ZONE" : ""),
+                                               MAX_TIMESTAMP_PRECISION)));
+               typmod = MAX_TIMESTAMP_PRECISION;
+       } else
+               typmod = *tl;
+
+       return typmod;
+}
+
+/* common code for timestamptypmodout and timestamptztypmodout */
+static char *
+anytimestamp_typmodout(bool istz, int32 typmod)
+{
+       char    *res = (char *) palloc(64);
+       const char *tz = istz ? " with time zone" : " without time zone";
+
+       if (typmod >= 0)
+               snprintf(res, 64, "(%d)%s", (int) typmod, tz);
+       else
+               snprintf(res, 64, "%s", tz);
+
+       return res;
+}
+
+
 /*****************************************************************************
  *      USER I/O ROUTINES                                                                                                               *
  *****************************************************************************/
@@ -215,6 +269,22 @@ timestamp_send(PG_FUNCTION_ARGS)
        PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
 }
 
+Datum
+timestamptypmodin(PG_FUNCTION_ARGS)
+{
+       ArrayType    *ta = PG_GETARG_ARRAYTYPE_P(0);
+
+       PG_RETURN_INT32(anytimestamp_typmodin(false, ta));
+}
+
+Datum
+timestamptypmodout(PG_FUNCTION_ARGS)
+{
+       int32 typmod = PG_GETARG_INT32(0);
+
+       PG_RETURN_CSTRING(anytimestamp_typmodout(false, typmod));
+}
+
 
 /* timestamp_scale()
  * Adjust time type for specified scale factor.
@@ -461,6 +531,22 @@ timestamptz_send(PG_FUNCTION_ARGS)
        PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
 }
 
+Datum
+timestamptztypmodin(PG_FUNCTION_ARGS)
+{
+       ArrayType    *ta = PG_GETARG_ARRAYTYPE_P(0);
+
+       PG_RETURN_INT32(anytimestamp_typmodin(true, ta));
+}
+
+Datum
+timestamptztypmodout(PG_FUNCTION_ARGS)
+{
+       int32 typmod = PG_GETARG_INT32(0);
+
+       PG_RETURN_CSTRING(anytimestamp_typmodout(true, typmod));
+}
+
 
 /* timestamptz_scale()
  * Adjust time type for specified scale factor.
@@ -625,6 +711,162 @@ interval_send(PG_FUNCTION_ARGS)
        PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
 }
 
+Datum
+intervaltypmodin(PG_FUNCTION_ARGS)
+{
+       ArrayType       *ta = PG_GETARG_ARRAYTYPE_P(0);
+       int32           *tl;
+    int                n;
+       int32           typmod;
+
+       tl = ArrayGetTypmods(ta, &n);
+
+       /*
+        * tl[0] - opt_interval
+        * tl[1] - Iconst (optional)
+        *
+        * Note we must validate tl[0] even though it's normally guaranteed
+        * correct by the grammar --- consider SELECT 'foo'::"interval"(1000).
+        */
+       if (n > 0)
+       {
+               switch (tl[0])
+               {
+                       case INTERVAL_MASK(YEAR):
+                       case INTERVAL_MASK(MONTH):
+                       case INTERVAL_MASK(DAY):
+                       case INTERVAL_MASK(HOUR):
+                       case INTERVAL_MASK(MINUTE):
+                       case INTERVAL_MASK(SECOND):
+                       case INTERVAL_MASK(YEAR) | INTERVAL_MASK(MONTH):
+                       case INTERVAL_MASK(DAY) | INTERVAL_MASK(HOUR):
+                       case INTERVAL_MASK(DAY) | INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE):
+                       case INTERVAL_MASK(DAY) | INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE) | INTERVAL_MASK(SECOND):
+                       case INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE):
+                       case INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE) | INTERVAL_MASK(SECOND):
+                       case INTERVAL_MASK(MINUTE) | INTERVAL_MASK(SECOND):
+                       case INTERVAL_FULL_RANGE:
+                               /* all OK */
+                               break;
+                       default:
+                               ereport(ERROR,
+                                               (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+                                                errmsg("invalid INTERVAL type modifier")));
+               }
+       }
+
+       if (n == 1)
+       {
+               if (tl[0] != INTERVAL_FULL_RANGE)
+                       typmod = INTERVAL_TYPMOD(INTERVAL_FULL_PRECISION, tl[0]);
+               else
+                       typmod = -1;
+       }
+       else if (n == 2)
+       {
+               if (tl[1] < 0)
+                       ereport(ERROR,
+                                       (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+                                        errmsg("INTERVAL(%d) precision must not be negative",
+                                                        tl[1])));
+               if (tl[1] > MAX_INTERVAL_PRECISION)
+               {
+                       ereport(WARNING,
+                                       (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+                                       errmsg("INTERVAL(%d) precision reduced to maximum allowed, %d",
+                                       tl[1], MAX_INTERVAL_PRECISION)));
+                       typmod = INTERVAL_TYPMOD(MAX_INTERVAL_PRECISION, tl[0]);
+               }
+               else
+                       typmod = INTERVAL_TYPMOD(tl[1], tl[0]);
+       }
+       else
+       {
+               ereport(ERROR,
+                               (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+                                               errmsg("invalid INTERVAL type modifier")));
+               typmod = 0;                             /* keep compiler quiet */
+       }
+
+       PG_RETURN_INT32(typmod);
+}
+
+Datum
+intervaltypmodout(PG_FUNCTION_ARGS)
+{
+       int32 typmod = PG_GETARG_INT32(0);
+       char       *res = (char *) palloc(64);
+       int         fields;
+       int         precision;
+       const char *fieldstr;
+
+       if (typmod < 0)
+       {
+               *res = '\0';
+               PG_RETURN_CSTRING(res);
+       }
+
+       fields = INTERVAL_RANGE(typmod);
+       precision = INTERVAL_PRECISION(typmod);
+
+       switch (fields)
+       {
+               case INTERVAL_MASK(YEAR):
+                       fieldstr = " year";
+                       break;
+               case INTERVAL_MASK(MONTH):
+                       fieldstr = " month";
+                       break;
+               case INTERVAL_MASK(DAY):
+                       fieldstr = " day";
+                       break;
+               case INTERVAL_MASK(HOUR):
+                       fieldstr = " hour";
+                       break;
+               case INTERVAL_MASK(MINUTE):
+                       fieldstr = " minute";
+                       break;
+               case INTERVAL_MASK(SECOND):
+                       fieldstr = " second";
+                       break;
+               case INTERVAL_MASK(YEAR) | INTERVAL_MASK(MONTH):
+                       fieldstr = " year to month";
+                       break;
+               case INTERVAL_MASK(DAY) | INTERVAL_MASK(HOUR):
+                       fieldstr = " day to hour";
+                       break;
+               case INTERVAL_MASK(DAY) | INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE):
+                       fieldstr = " day to minute";
+                       break;
+               case INTERVAL_MASK(DAY) | INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE) | INTERVAL_MASK(SECOND):
+                       fieldstr = " day to second";
+                       break;
+               case INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE):
+                       fieldstr = " hour to minute";
+                       break;
+               case INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE) | INTERVAL_MASK(SECOND):
+                       fieldstr = " hour to second";
+                       break;
+               case INTERVAL_MASK(MINUTE) | INTERVAL_MASK(SECOND):
+                       fieldstr = " minute to second";
+                       break;
+               case INTERVAL_FULL_RANGE:
+                       fieldstr = "";
+                       break;
+               default:
+                       elog(ERROR, "invalid INTERVAL typmod: 0x%x", typmod);
+                       fieldstr = "";
+                       break;
+       }
+
+       if (precision != INTERVAL_FULL_PRECISION)
+               snprintf(res, 64, "(%d)%s", precision, fieldstr);
+       else
+               snprintf(res, 64, "%s", fieldstr);
+
+       PG_RETURN_CSTRING(res);
+}
+
 
 /* interval_scale()
  * Adjust interval type for specified fields.
index e0a67d340eff513306c30c1039aa03c9761f4881..4a810b955da37730d0453a845550819bdca824b0 100644 (file)
@@ -9,19 +9,71 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/utils/adt/varbit.c,v 1.50 2006/07/14 14:52:24 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/utils/adt/varbit.c,v 1.51 2006/12/30 21:21:54 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 
 #include "postgres.h"
 
+#include "access/htup.h"
 #include "libpq/pqformat.h"
+#include "utils/array.h"
 #include "utils/varbit.h"
 
 #define HEXDIG(z)       ((z)<10 ? ((z)+'0') : ((z)-10+'A'))
 
 
+/* common code for bittypmodin and varbittypmodin */
+static int32
+anybit_typmodin(ArrayType *ta, const char *typename)
+{
+       int32    typmod;
+       int32   *tl;
+       int             n;
+
+       tl = ArrayGetTypmods(ta, &n);
+
+       /*
+        * we're not too tense about good error message here because grammar
+        * shouldn't allow wrong number of modifiers for BIT
+        */
+       if (n != 1)
+               ereport(ERROR,
+                               (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+                                errmsg("invalid type modifier")));
+
+       if (*tl < 1)
+               ereport(ERROR,
+                               (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+                                errmsg("length for type %s must be at least 1",
+                                               typename)));
+       if (*tl > (MaxAttrSize * BITS_PER_BYTE))
+               ereport(ERROR,
+                               (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+                                errmsg("length for type %s cannot exceed %d",
+                                               typename, MaxAttrSize * BITS_PER_BYTE)));
+
+       typmod = *tl;
+
+       return typmod;
+}
+
+/* common code for bittypmodout and varbittypmodout */
+static char *
+anybit_typmodout(int32 typmod)
+{
+       char    *res = (char *) palloc(64);
+
+       if (typmod >= 0)
+               snprintf(res, 64, "(%d)", typmod);
+       else
+               *res = '\0';
+
+       return res;
+}
+
+
 /*----------
  *     attypmod -- contains the length of the bit string in bits, or for
  *                        varying bits the maximum length.
@@ -325,6 +377,23 @@ bit(PG_FUNCTION_ARGS)
        PG_RETURN_VARBIT_P(result);
 }
 
+Datum
+bittypmodin(PG_FUNCTION_ARGS)
+{
+       ArrayType    *ta = PG_GETARG_ARRAYTYPE_P(0);
+
+       PG_RETURN_INT32(anybit_typmodin(ta, "bit"));
+}
+
+Datum
+bittypmodout(PG_FUNCTION_ARGS)
+{
+       int32 typmod = PG_GETARG_INT32(0);
+
+       PG_RETURN_CSTRING(anybit_typmodout(typmod));
+}
+
+
 /*
  * varbit_in -
  *       converts a string to the internal representation of a bitstring.
@@ -603,6 +672,22 @@ varbit(PG_FUNCTION_ARGS)
        PG_RETURN_VARBIT_P(result);
 }
 
+Datum
+varbittypmodin(PG_FUNCTION_ARGS)
+{
+       ArrayType    *ta = PG_GETARG_ARRAYTYPE_P(0);
+
+       PG_RETURN_INT32(anybit_typmodin(ta, "varbit"));
+}
+
+Datum
+varbittypmodout(PG_FUNCTION_ARGS)
+{
+       int32 typmod = PG_GETARG_INT32(0);
+
+       PG_RETURN_CSTRING(anybit_typmodout(typmod));
+}
+
 
 /*
  * Comparison operators
index 937cf96ebef0d018756509a6a5edee0f77ab4d7d..9cc2f5e34e311bda6c267a6522d37450e2f0ab81 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/utils/adt/varchar.c,v 1.119 2006/10/04 00:30:00 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/utils/adt/varchar.c,v 1.120 2006/12/30 21:21:54 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 
 #include "access/hash.h"
 #include "libpq/pqformat.h"
+#include "utils/array.h"
 #include "utils/builtins.h"
 #include "mb/pg_wchar.h"
 
 
+/* common code for bpchartypmodin and varchartypmodin */
+static int32
+anychar_typmodin(ArrayType *ta, const char *typename)
+{
+       int32   typmod;
+       int32   *tl;
+       int             n;
+
+       tl = ArrayGetTypmods(ta, &n);
+
+       /*
+        * we're not too tense about good error message here because grammar
+        * shouldn't allow wrong number of modifiers for CHAR
+        */
+       if (n != 1)
+               ereport(ERROR,
+                               (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+                                errmsg("invalid type modifier")));
+
+       if (*tl < 1)
+               ereport(ERROR,
+                               (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+                                errmsg("length for type %s must be at least 1", typename)));
+       if (*tl > MaxAttrSize)
+               ereport(ERROR,
+                               (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+                                errmsg("length for type %s cannot exceed %d",
+                                               typename, MaxAttrSize)));
+
+       /*
+        * For largely historical reasons, the typmod is VARHDRSZ plus the
+        * number of characters; there is enough client-side code that knows
+        * about that that we'd better not change it.
+        */
+       typmod = VARHDRSZ + *tl;
+
+       return typmod;
+}
+
+/* common code for bpchartypmodout and varchartypmodout */
+static char *
+anychar_typmodout(int32 typmod)
+{
+       char    *res = (char *) palloc(64);
+
+       if (typmod > VARHDRSZ)
+               snprintf(res, 64, "(%d)", (int) (typmod - VARHDRSZ));
+       else
+               *res = '\0';
+
+       return res;
+}
+
+
 /*
  * CHAR() and VARCHAR() types are part of the ANSI SQL standard. CHAR()
  * is for blank-padded string whose length is specified in CREATE TABLE.
@@ -359,6 +414,22 @@ name_bpchar(PG_FUNCTION_ARGS)
        PG_RETURN_BPCHAR_P(result);
 }
 
+Datum
+bpchartypmodin(PG_FUNCTION_ARGS)
+{
+       ArrayType       *ta = PG_GETARG_ARRAYTYPE_P(0);
+
+       PG_RETURN_INT32(anychar_typmodin(ta, "char"));
+}
+
+Datum
+bpchartypmodout(PG_FUNCTION_ARGS)
+{
+       int32 typmod = PG_GETARG_INT32(0);
+
+       PG_RETURN_CSTRING(anychar_typmodout(typmod));
+}
+
 
 /*****************************************************************************
  *      varchar - varchar(n)
@@ -536,6 +607,22 @@ varchar(PG_FUNCTION_ARGS)
        PG_RETURN_VARCHAR_P(result);
 }
 
+Datum
+varchartypmodin(PG_FUNCTION_ARGS)
+{
+       ArrayType       *ta = PG_GETARG_ARRAYTYPE_P(0);
+
+       PG_RETURN_INT32(anychar_typmodin(ta, "varchar"));
+}
+
+Datum
+varchartypmodout(PG_FUNCTION_ARGS)
+{
+       int32 typmod = PG_GETARG_INT32(0);
+
+       PG_RETURN_CSTRING(anychar_typmodout(typmod));
+}
+
 
 /*****************************************************************************
  * Exported functions
index 824ef4a1efe9d2e2f7fef3d013286b3c9a4f1950..8c4cbef66cb375311dc63dec266a104f097a9ed7 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/utils/cache/lsyscache.c,v 1.139 2006/12/23 00:43:11 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/utils/cache/lsyscache.c,v 1.140 2006/12/30 21:21:54 tgl Exp $
  *
  * NOTES
  *       Eventually, the index information should go through here, too.
@@ -2016,6 +2016,60 @@ getTypeBinaryOutputInfo(Oid type, Oid *typSend, bool *typIsVarlena)
        ReleaseSysCache(typeTuple);
 }
 
+/*
+ * get_typmodin
+ *
+ *             Given the type OID, return the type's typmodin procedure, if any.
+ */
+Oid
+get_typmodin(Oid typid)
+{
+       HeapTuple       tp;
+
+       tp = SearchSysCache(TYPEOID,
+                                               ObjectIdGetDatum(typid),
+                                               0, 0, 0);
+       if (HeapTupleIsValid(tp))
+       {
+               Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
+               Oid                     result;
+
+               result = typtup->typmodin;
+               ReleaseSysCache(tp);
+               return result;
+       }
+       else
+               return InvalidOid;
+}
+
+#ifdef NOT_USED
+/*
+ * get_typmodout
+ *
+ *             Given the type OID, return the type's typmodout procedure, if any.
+ */
+Oid
+get_typmodout(Oid typid)
+{
+       HeapTuple       tp;
+
+       tp = SearchSysCache(TYPEOID,
+                                               ObjectIdGetDatum(typid),
+                                               0, 0, 0);
+       if (HeapTupleIsValid(tp))
+       {
+               Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
+               Oid                     result;
+
+               result = typtup->typmodout;
+               ReleaseSysCache(tp);
+               return result;
+       }
+       else
+               return InvalidOid;
+}
+#endif /* NOT_USED */
+
 
 /*                             ---------- STATISTICS CACHE ----------                                   */
 
index 6c6ff1fb5a36d7181d7a8826be8f6c8e711c032b..377c6d87c3a0381ec8c76a9f36a9bb5a0fd06e13 100644 (file)
@@ -10,7 +10,7 @@
  * Written by Peter Eisentraut <peter_e@gmx.net>.
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.363 2006/12/23 00:52:40 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.364 2006/12/30 21:21:54 tgl Exp $
  *
  *--------------------------------------------------------------------
  */
@@ -45,6 +45,7 @@
 #include "parser/gramparse.h"
 #include "parser/parse_expr.h"
 #include "parser/parse_relation.h"
+#include "parser/parse_type.h"
 #include "parser/scansup.h"
 #include "pgstat.h"
 #include "postmaster/autovacuum.h"
@@ -4523,14 +4524,17 @@ flatten_set_variable_args(const char *name, List *args)
                                         * to interval and back to normalize the value and account
                                         * for any typmod.
                                         */
+                                       int32           typmod;
                                        Datum           interval;
                                        char       *intervalout;
 
+                                       typmod = typenameTypeMod(NULL, arg->typename, INTERVALOID);
+
                                        interval =
                                                DirectFunctionCall3(interval_in,
                                                                                        CStringGetDatum(val),
                                                                                        ObjectIdGetDatum(InvalidOid),
-                                                                          Int32GetDatum(arg->typename->typmod));
+                                                                                       Int32GetDatum(typmod));
 
                                        intervalout =
                                                DatumGetCString(DirectFunctionCall1(interval_out,
index ae8d54936f18f47d2a9ba7e14d6a321026864f2d..637af90d91c8296d2900a9a9a0dab0d5d11fc62a 100644 (file)
@@ -12,7 +12,7 @@
  *     by PostgreSQL
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.454 2006/12/23 00:43:12 tgl Exp $
+ *       $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.455 2006/12/30 21:21:54 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -5007,11 +5007,15 @@ dumpBaseType(Archive *fout, TypeInfo *tinfo)
        char       *typoutput;
        char       *typreceive;
        char       *typsend;
+       char       *typmodin;
+       char       *typmodout;
        char       *typanalyze;
        Oid                     typinputoid;
        Oid                     typoutputoid;
        Oid                     typreceiveoid;
        Oid                     typsendoid;
+       Oid                     typmodinoid;
+       Oid                     typmodoutoid;
        Oid                     typanalyzeoid;
        char       *typdelim;
        char       *typbyval;
@@ -5024,15 +5028,35 @@ dumpBaseType(Archive *fout, TypeInfo *tinfo)
        selectSourceSchema(tinfo->dobj.namespace->dobj.name);
 
        /* Fetch type-specific details */
-       if (fout->remoteVersion >= 80000)
+       if (fout->remoteVersion >= 80300)
        {
                appendPQExpBuffer(query, "SELECT typlen, "
                                                  "typinput, typoutput, typreceive, typsend, "
+                                                 "typmodin, typmodout, typanalyze, "
+                                                 "typinput::pg_catalog.oid as typinputoid, "
+                                                 "typoutput::pg_catalog.oid as typoutputoid, "
+                                                 "typreceive::pg_catalog.oid as typreceiveoid, "
+                                                 "typsend::pg_catalog.oid as typsendoid, "
+                                                 "typmodin::pg_catalog.oid as typmodinoid, "
+                                                 "typmodout::pg_catalog.oid as typmodoutoid, "
+                                                 "typanalyze::pg_catalog.oid as typanalyzeoid, "
+                                                 "typdelim, typbyval, typalign, typstorage, "
+                                                 "pg_catalog.pg_get_expr(typdefaultbin, 'pg_catalog.pg_type'::pg_catalog.regclass) as typdefaultbin, typdefault "
+                                                 "FROM pg_catalog.pg_type "
+                                                 "WHERE oid = '%u'::pg_catalog.oid",
+                                                 tinfo->dobj.catId.oid);
+       }
+       else if (fout->remoteVersion >= 80000)
+       {
+               appendPQExpBuffer(query, "SELECT typlen, "
+                                                 "typinput, typoutput, typreceive, typsend, "
+                                                 "'-' as typmodin, '-' as typmodout, "
                                                  "typanalyze, "
                                                  "typinput::pg_catalog.oid as typinputoid, "
                                                  "typoutput::pg_catalog.oid as typoutputoid, "
                                                  "typreceive::pg_catalog.oid as typreceiveoid, "
                                                  "typsend::pg_catalog.oid as typsendoid, "
+                                                 "0 as typmodinoid, 0 as typmodoutoid, "
                                                  "typanalyze::pg_catalog.oid as typanalyzeoid, "
                                                  "typdelim, typbyval, typalign, typstorage, "
                                                  "pg_catalog.pg_get_expr(typdefaultbin, 'pg_catalog.pg_type'::pg_catalog.regclass) as typdefaultbin, typdefault "
@@ -5044,11 +5068,13 @@ dumpBaseType(Archive *fout, TypeInfo *tinfo)
        {
                appendPQExpBuffer(query, "SELECT typlen, "
                                                  "typinput, typoutput, typreceive, typsend, "
+                                                 "'-' as typmodin, '-' as typmodout, "
                                                  "'-' as typanalyze, "
                                                  "typinput::pg_catalog.oid as typinputoid, "
                                                  "typoutput::pg_catalog.oid as typoutputoid, "
                                                  "typreceive::pg_catalog.oid as typreceiveoid, "
                                                  "typsend::pg_catalog.oid as typsendoid, "
+                                                 "0 as typmodinoid, 0 as typmodoutoid, "
                                                  "0 as typanalyzeoid, "
                                                  "typdelim, typbyval, typalign, typstorage, "
                                                  "pg_catalog.pg_get_expr(typdefaultbin, 'pg_catalog.pg_type'::pg_catalog.regclass) as typdefaultbin, typdefault "
@@ -5061,10 +5087,12 @@ dumpBaseType(Archive *fout, TypeInfo *tinfo)
                appendPQExpBuffer(query, "SELECT typlen, "
                                                  "typinput, typoutput, "
                                                  "'-' as typreceive, '-' as typsend, "
+                                                 "'-' as typmodin, '-' as typmodout, "
                                                  "'-' as typanalyze, "
                                                  "typinput::pg_catalog.oid as typinputoid, "
                                                  "typoutput::pg_catalog.oid as typoutputoid, "
                                                  "0 as typreceiveoid, 0 as typsendoid, "
+                                                 "0 as typmodinoid, 0 as typmodoutoid, "
                                                  "0 as typanalyzeoid, "
                                                  "typdelim, typbyval, typalign, typstorage, "
                                                  "pg_catalog.pg_get_expr(typdefaultbin, 'pg_catalog.pg_type'::pg_catalog.regclass) as typdefaultbin, typdefault "
@@ -5081,10 +5109,12 @@ dumpBaseType(Archive *fout, TypeInfo *tinfo)
                appendPQExpBuffer(query, "SELECT typlen, "
                                                  "typinput, typoutput, "
                                                  "'-' as typreceive, '-' as typsend, "
+                                                 "'-' as typmodin, '-' as typmodout, "
                                                  "'-' as typanalyze, "
                                                  "typinput::oid as typinputoid, "
                                                  "typoutput::oid as typoutputoid, "
                                                  "0 as typreceiveoid, 0 as typsendoid, "
+                                                 "0 as typmodinoid, 0 as typmodoutoid, "
                                                  "0 as typanalyzeoid, "
                                                  "typdelim, typbyval, typalign, typstorage, "
                                                  "NULL as typdefaultbin, typdefault "
@@ -5101,10 +5131,12 @@ dumpBaseType(Archive *fout, TypeInfo *tinfo)
                appendPQExpBuffer(query, "SELECT typlen, "
                                                  "typinput, typoutput, "
                                                  "'-' as typreceive, '-' as typsend, "
+                                                 "'-' as typmodin, '-' as typmodout, "
                                                  "'-' as typanalyze, "
                                                  "typinput::oid as typinputoid, "
                                                  "typoutput::oid as typoutputoid, "
                                                  "0 as typreceiveoid, 0 as typsendoid, "
+                                                 "0 as typmodinoid, 0 as typmodoutoid, "
                                                  "0 as typanalyzeoid, "
                                                  "typdelim, typbyval, typalign, typstorage, "
                                                  "NULL as typdefaultbin, NULL as typdefault "
@@ -5117,10 +5149,12 @@ dumpBaseType(Archive *fout, TypeInfo *tinfo)
                appendPQExpBuffer(query, "SELECT typlen, "
                                                  "typinput, typoutput, "
                                                  "'-' as typreceive, '-' as typsend, "
+                                                 "'-' as typmodin, '-' as typmodout, "
                                                  "'-' as typanalyze, "
                                                  "typinput::oid as typinputoid, "
                                                  "typoutput::oid as typoutputoid, "
                                                  "0 as typreceiveoid, 0 as typsendoid, "
+                                                 "0 as typmodinoid, 0 as typmodoutoid, "
                                                  "0 as typanalyzeoid, "
                                                  "typdelim, typbyval, typalign, "
                                                  "'p'::char as typstorage, "
@@ -5147,11 +5181,15 @@ dumpBaseType(Archive *fout, TypeInfo *tinfo)
        typoutput = PQgetvalue(res, 0, PQfnumber(res, "typoutput"));
        typreceive = PQgetvalue(res, 0, PQfnumber(res, "typreceive"));
        typsend = PQgetvalue(res, 0, PQfnumber(res, "typsend"));
+       typmodin = PQgetvalue(res, 0, PQfnumber(res, "typmodin"));
+       typmodout = PQgetvalue(res, 0, PQfnumber(res, "typmodout"));
        typanalyze = PQgetvalue(res, 0, PQfnumber(res, "typanalyze"));
        typinputoid = atooid(PQgetvalue(res, 0, PQfnumber(res, "typinputoid")));
        typoutputoid = atooid(PQgetvalue(res, 0, PQfnumber(res, "typoutputoid")));
        typreceiveoid = atooid(PQgetvalue(res, 0, PQfnumber(res, "typreceiveoid")));
        typsendoid = atooid(PQgetvalue(res, 0, PQfnumber(res, "typsendoid")));
+       typmodinoid = atooid(PQgetvalue(res, 0, PQfnumber(res, "typmodinoid")));
+       typmodoutoid = atooid(PQgetvalue(res, 0, PQfnumber(res, "typmodoutoid")));
        typanalyzeoid = atooid(PQgetvalue(res, 0, PQfnumber(res, "typanalyzeoid")));
        typdelim = PQgetvalue(res, 0, PQfnumber(res, "typdelim"));
        typbyval = PQgetvalue(res, 0, PQfnumber(res, "typbyval"));
@@ -5193,6 +5231,10 @@ dumpBaseType(Archive *fout, TypeInfo *tinfo)
                        appendPQExpBuffer(q, ",\n    RECEIVE = %s", typreceive);
                if (OidIsValid(typsendoid))
                        appendPQExpBuffer(q, ",\n    SEND = %s", typsend);
+               if (OidIsValid(typmodinoid))
+                       appendPQExpBuffer(q, ",\n    TYPMOD_IN = %s", typmodin);
+               if (OidIsValid(typmodoutoid))
+                       appendPQExpBuffer(q, ",\n    TYPMOD_OUT = %s", typmodout);
                if (OidIsValid(typanalyzeoid))
                        appendPQExpBuffer(q, ",\n    ANALYZE = %s", typanalyze);
        }
@@ -5202,7 +5244,7 @@ dumpBaseType(Archive *fout, TypeInfo *tinfo)
                /* cannot combine these because fmtId uses static result area */
                appendPQExpBuffer(q, ",\n    INPUT = %s", fmtId(typinput));
                appendPQExpBuffer(q, ",\n    OUTPUT = %s", fmtId(typoutput));
-               /* no chance that receive/send/analyze need be printed */
+               /* receive/send/typmodin/typmodout/analyze need not be printed */
        }
 
        if (typdefault != NULL)
index 1b1e07bd719e44da90d216595a7e54bac46346da..1200af0c6e6871fca244ba714fbb28ae187b50db 100644 (file)
@@ -37,7 +37,7 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.367 2006/12/28 14:28:36 petere Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.368 2006/12/30 21:21:55 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -53,6 +53,6 @@
  */
 
 /*                                                     yyyymmddN */
-#define CATALOG_VERSION_NO     200612281
+#define CATALOG_VERSION_NO     200612291
 
 #endif
index 3fcc5ed67469ab9da61894b77fe94313b75f4b98..2c38c2b88f8b9babd1feb4be65ff6486b469ed89 100644 (file)
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/pg_attribute.h,v 1.126 2006/11/05 22:42:10 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_attribute.h,v 1.127 2006/12/30 21:21:55 tgl Exp $
  *
  * NOTES
  *       the genbki.sh script reads this file and generates .bki
@@ -236,15 +236,17 @@ typedef FormData_pg_attribute *Form_pg_attribute;
 { 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, {"typanalyze"},    24, -1,     4, 15, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
-{ 1247, {"typalign"},     18, -1,      1, 16, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
-{ 1247, {"typstorage"},    18, -1,     1, 17, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
-{ 1247, {"typnotnull"},    16, -1,     1, 18, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
-{ 1247, {"typbasetype"},   26, -1,     4, 19, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
-{ 1247, {"typtypmod"},    23, -1,      4, 20, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
-{ 1247, {"typndims"},     23, -1,      4, 21, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
-{ 1247, {"typdefaultbin"}, 25, -1, -1, 22, 0, -1, -1, false, 'x', 'i', false, false, false, true, 0 }, \
-{ 1247, {"typdefault"},    25, -1, -1, 23, 0, -1, -1, false, 'x', 'i', false, 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));
@@ -260,15 +262,17 @@ 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 typanalyze          24 -1 4  15 0 -1 -1 t p i t f f t 0));
-DATA(insert ( 1247 typalign                    18 -1 1  16 0 -1 -1 t p c t f f t 0));
-DATA(insert ( 1247 typstorage          18 -1 1  17 0 -1 -1 t p c t f f t 0));
-DATA(insert ( 1247 typnotnull          16 -1 1  18 0 -1 -1 t p c t f f t 0));
-DATA(insert ( 1247 typbasetype         26 -1 4  19 0 -1 -1 t p i t f f t 0));
-DATA(insert ( 1247 typtypmod           23 -1 4  20 0 -1 -1 t p i t f f t 0));
-DATA(insert ( 1247 typndims                    23 -1 4  21 0 -1 -1 t p i t f f t 0));
-DATA(insert ( 1247 typdefaultbin       25 -1 -1 22 0 -1 -1 f x i f f f t 0));
-DATA(insert ( 1247 typdefault          25 -1 -1 23 0 -1 -1 f x i f 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));
index 75aee92e51261acce0f6a69e6f3d05f00e9f390d..155b4c7bc32f7c52732fb865711f3542a31e337e 100644 (file)
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/pg_class.h,v 1.97 2006/11/05 22:42:10 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_class.h,v 1.98 2006/12/30 21:21:55 tgl Exp $
  *
  * NOTES
  *       the genbki.sh script reads this file and generates .bki
@@ -132,7 +132,7 @@ typedef FormData_pg_class *Form_pg_class;
  */
 
 /* 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 23 0 0 0 0 0 t f f f 3 _null_ _null_ ));
+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("");
index b591300709588807130d80acde96ff9e0921e1d8..f98717a978fa2a936d70387e656aa0157558d8d9 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.433 2006/12/28 14:28:36 petere Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.434 2006/12/30 21:21:55 tgl Exp $
  *
  * NOTES
  *       The script catalog/genbki.sh reads this file and generates .bki
@@ -1335,10 +1335,18 @@ DATA(insert OID = 1044 (  bpcharin                 PGNSP PGUID 12 f f t f i 3 1042 "2275 26
 DESCR("I/O");
 DATA(insert OID = 1045 (  bpcharout               PGNSP PGUID 12 f f t f i 1 2275 "1042" _null_ _null_ _null_  bpcharout - _null_ ));
 DESCR("I/O");
+DATA(insert OID = 2913 (  bpchartypmodin   PGNSP PGUID 12 f f t f i 1 23 "1007" _null_ _null_ _null_   bpchartypmodin - _null_ ));
+DESCR("I/O typmod");
+DATA(insert OID = 2914 (  bpchartypmodout  PGNSP PGUID 12 f f t f i 1 2275 "23" _null_ _null_ _null_   bpchartypmodout - _null_ ));
+DESCR("I/O typmod");
 DATA(insert OID = 1046 (  varcharin               PGNSP PGUID 12 f f t f i 3 1043 "2275 26 23" _null_ _null_ _null_ varcharin - _null_ ));
 DESCR("I/O");
 DATA(insert OID = 1047 (  varcharout      PGNSP PGUID 12 f f t f i 1 2275 "1043" _null_ _null_ _null_  varcharout - _null_ ));
 DESCR("I/O");
+DATA(insert OID = 2915 (  varchartypmodin  PGNSP PGUID 12 f f t f i 1 23 "1007" _null_ _null_ _null_   varchartypmodin - _null_ ));
+DESCR("I/O typmod");
+DATA(insert OID = 2916 (  varchartypmodout PGNSP PGUID 12 f f t f i 1 2275 "23" _null_ _null_ _null_   varchartypmodout - _null_ ));
+DESCR("I/O typmod");
 DATA(insert OID = 1048 (  bpchareq                PGNSP PGUID 12 f f t f i 2 16 "1042 1042" _null_ _null_ _null_ bpchareq - _null_ ));
 DESCR("equal");
 DATA(insert OID = 1049 (  bpcharlt                PGNSP PGUID 12 f f t f i 2 16 "1042 1042" _null_ _null_ _null_ bpcharlt - _null_ ));
@@ -1408,6 +1416,10 @@ DATA(insert OID = 1143 (  time_in                   PGNSP PGUID 12 f f t f s 3 1083 "2275 26 2
 DESCR("I/O");
 DATA(insert OID = 1144 (  time_out                PGNSP PGUID 12 f f t f i 1 2275 "1083" _null_ _null_ _null_  time_out - _null_ ));
 DESCR("I/O");
+DATA(insert OID = 2909 (  timetypmodin         PGNSP PGUID 12 f f t f i 1 23 "1007" _null_ _null_ _null_       timetypmodin - _null_ ));
+DESCR("I/O typmod");
+DATA(insert OID = 2910 (  timetypmodout        PGNSP PGUID 12 f f t f i 1 2275 "23" _null_ _null_ _null_       timetypmodout - _null_ ));
+DESCR("I/O typmod");
 DATA(insert OID = 1145 (  time_eq                 PGNSP PGUID 12 f f t f i 2 16 "1083 1083" _null_ _null_ _null_ time_eq - _null_ ));
 DESCR("equal");
 
@@ -1424,6 +1436,10 @@ DATA(insert OID = 1150 (  timestamptz_in   PGNSP PGUID 12 f f t f s 3 1184 "2275
 DESCR("I/O");
 DATA(insert OID = 1151 (  timestamptz_out  PGNSP PGUID 12 f f t f s 1 2275 "1184" _null_ _null_ _null_ timestamptz_out - _null_ ));
 DESCR("I/O");
+DATA(insert OID = 2907 (  timestamptztypmodin          PGNSP PGUID 12 f f t f i 1 23 "1007" _null_ _null_ _null_       timestamptztypmodin - _null_ ));
+DESCR("I/O typmod");
+DATA(insert OID = 2908 (  timestamptztypmodout         PGNSP PGUID 12 f f t f i 1 2275 "23" _null_ _null_ _null_       timestamptztypmodout - _null_ ));
+DESCR("I/O typmod");
 DATA(insert OID = 1152 (  timestamptz_eq   PGNSP PGUID 12 f f t f i 2 16 "1184 1184" _null_ _null_ _null_ timestamp_eq - _null_ ));
 DESCR("equal");
 DATA(insert OID = 1153 (  timestamptz_ne   PGNSP PGUID 12 f f t f i 2 16 "1184 1184" _null_ _null_ _null_ timestamp_ne - _null_ ));
@@ -1445,6 +1461,10 @@ DATA(insert OID = 1160 (  interval_in       PGNSP PGUID 12 f f t f s 3 1186 "2275 2
 DESCR("I/O");
 DATA(insert OID = 1161 (  interval_out    PGNSP PGUID 12 f f t f i 1 2275 "1186" _null_ _null_ _null_  interval_out - _null_ ));
 DESCR("I/O");
+DATA(insert OID = 2903 (  intervaltypmodin     PGNSP PGUID 12 f f t f i 1 23 "1007" _null_ _null_ _null_       intervaltypmodin - _null_ ));
+DESCR("I/O typmod");
+DATA(insert OID = 2904 (  intervaltypmodout    PGNSP PGUID 12 f f t f i 1 2275 "23" _null_ _null_ _null_       intervaltypmodout - _null_ ));
+DESCR("I/O typmod");
 DATA(insert OID = 1162 (  interval_eq     PGNSP PGUID 12 f f t f i 2 16 "1186 1186" _null_ _null_ _null_ interval_eq - _null_ ));
 DESCR("equal");
 DATA(insert OID = 1163 (  interval_ne     PGNSP PGUID 12 f f t f i 2 16 "1186 1186" _null_ _null_ _null_ interval_ne - _null_ ));
@@ -1668,6 +1688,10 @@ DATA(insert OID = 1312 (  timestamp_in            PGNSP PGUID 12 f f t f s 3 1114 "2275 2
 DESCR("I/O");
 DATA(insert OID = 1313 (  timestamp_out                 PGNSP PGUID 12 f f t f s 1 2275 "1114" _null_ _null_ _null_ timestamp_out - _null_ ));
 DESCR("I/O");
+DATA(insert OID = 2905 (  timestamptypmodin    PGNSP PGUID 12 f f t f i 1 23 "1007" _null_ _null_ _null_       timestamptypmodin - _null_ ));
+DESCR("I/O typmod");
+DATA(insert OID = 2906 (  timestamptypmodout   PGNSP PGUID 12 f f t f i 1 2275 "23" _null_ _null_ _null_       timestamptypmodout - _null_ ));
+DESCR("I/O typmod");
 DATA(insert OID = 1314 (  timestamptz_cmp       PGNSP PGUID 12 f f t f i 2 23 "1184 1184" _null_ _null_ _null_ timestamp_cmp - _null_ ));
 DESCR("less-equal-greater");
 DATA(insert OID = 1315 (  interval_cmp          PGNSP PGUID 12 f f t f i 2 23 "1186 1186" _null_ _null_ _null_ interval_cmp - _null_ ));
@@ -1721,6 +1745,10 @@ DATA(insert OID = 1350 (  timetz_in                 PGNSP PGUID 12 f f t f s 3 1266 "2275 26
 DESCR("I/O");
 DATA(insert OID = 1351 (  timetz_out      PGNSP PGUID 12 f f t f i 1 2275 "1266" _null_ _null_ _null_  timetz_out - _null_ ));
 DESCR("I/O");
+DATA(insert OID = 2911 (  timetztypmodin       PGNSP PGUID 12 f f t f i 1 23 "1007" _null_ _null_ _null_       timetztypmodin - _null_ ));
+DESCR("I/O typmod");
+DATA(insert OID = 2912 (  timetztypmodout      PGNSP PGUID 12 f f t f i 1 2275 "23" _null_ _null_ _null_       timetztypmodout - _null_ ));
+DESCR("I/O typmod");
 DATA(insert OID = 1352 (  timetz_eq               PGNSP PGUID 12 f f t f i 2 16 "1266 1266" _null_ _null_ _null_ timetz_eq - _null_ ));
 DESCR("equal");
 DATA(insert OID = 1353 (  timetz_ne               PGNSP PGUID 12 f f t f i 2 16 "1266 1266" _null_ _null_ _null_ timetz_ne - _null_ ));
@@ -2053,6 +2081,10 @@ DATA(insert OID = 1564 (  bit_in                 PGNSP PGUID 12 f f t f i 3 1560 "2275 26 23"
 DESCR("I/O");
 DATA(insert OID = 1565 (  bit_out                      PGNSP PGUID 12 f f t f i 1 2275 "1560" _null_ _null_ _null_ bit_out - _null_ ));
 DESCR("I/O");
+DATA(insert OID = 2919 (  bittypmodin          PGNSP PGUID 12 f f t f i 1 23 "1007" _null_ _null_ _null_       bittypmodin - _null_ ));
+DESCR("I/O typmod");
+DATA(insert OID = 2920 (  bittypmodout         PGNSP PGUID 12 f f t f i 1 2275 "23" _null_ _null_ _null_       bittypmodout - _null_ ));
+DESCR("I/O typmod");
 
 DATA(insert OID = 1569 (  like                         PGNSP PGUID 12 f f t f i 2 16 "25 25" _null_ _null_ _null_      textlike - _null_ ));
 DESCR("matches LIKE expression");
@@ -2078,6 +2110,10 @@ DATA(insert OID = 1579 (  varbit_in                      PGNSP PGUID 12 f f t f i 3 1562 "2275 26 2
 DESCR("I/O");
 DATA(insert OID = 1580 (  varbit_out           PGNSP PGUID 12 f f t f i 1 2275 "1562" _null_ _null_ _null_ varbit_out - _null_ ));
 DESCR("I/O");
+DATA(insert OID = 2902 (  varbittypmodin       PGNSP PGUID 12 f f t f i 1 23 "1007" _null_ _null_ _null_       varbittypmodin - _null_ ));
+DESCR("I/O typmod");
+DATA(insert OID = 2921 (  varbittypmodout      PGNSP PGUID 12 f f t f i 1 2275 "23" _null_ _null_ _null_       varbittypmodout - _null_ ));
+DESCR("I/O typmod");
 
 DATA(insert OID = 1581 (  biteq                                PGNSP PGUID 12 f f t f i 2 16 "1560 1560" _null_ _null_ _null_  biteq - _null_ ));
 DESCR("equal");
@@ -2498,6 +2534,10 @@ DATA(insert OID = 1701 ( numeric_in                              PGNSP PGUID 12 f f t f i 3 1700 "2275 26
 DESCR("I/O");
 DATA(insert OID = 1702 ( numeric_out                   PGNSP PGUID 12 f f t f i 1 2275 "1700" _null_ _null_ _null_ numeric_out - _null_ ));
 DESCR("I/O");
+DATA(insert OID = 2917 (  numerictypmodin      PGNSP PGUID 12 f f t f i 1 23 "1007" _null_ _null_ _null_       numerictypmodin - _null_ ));
+DESCR("I/O typmod");
+DATA(insert OID = 2918 (  numerictypmodout     PGNSP PGUID 12 f f t f i 1 2275 "23" _null_ _null_ _null_       numerictypmodout - _null_ ));
+DESCR("I/O typmod");
 DATA(insert OID = 1703 ( numeric                               PGNSP PGUID 12 f f t f i 2 1700 "1700 23" _null_ _null_ _null_  numeric - _null_ ));
 DESCR("adjust numeric to typmod precision/scale");
 DATA(insert OID = 1704 ( numeric_abs                   PGNSP PGUID 12 f f t f i 1 1700 "1700" _null_ _null_ _null_ numeric_abs - _null_ ));
index 9a95ef305ba74307f7e2ddcfd8704727ae22aaf2..65f8b9deea8399661bfb0cf38eb4c72adac525c8 100644 (file)
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/pg_type.h,v 1.175 2006/12/28 14:28:36 petere Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_type.h,v 1.176 2006/12/30 21:21:55 tgl Exp $
  *
  * NOTES
  *       the genbki.sh script reads this file and generates .bki
@@ -104,6 +104,12 @@ CATALOG(pg_type,1247) BKI_BOOTSTRAP
        regproc         typreceive;             /* binary format (optional) */
        regproc         typsend;
 
+       /*
+        * I/O functions for optional type modifiers.
+        */
+        regproc        typmodin;
+        regproc        typmodout;
+
        /*
         * Custom ANALYZE procedure for the datatype (0 selects the default).
         */
@@ -205,7 +211,7 @@ typedef FormData_pg_type *Form_pg_type;
  *             compiler constants for pg_type
  * ----------------
  */
-#define Natts_pg_type                                  23
+#define Natts_pg_type                                  25
 #define Anum_pg_type_typname                   1
 #define Anum_pg_type_typnamespace              2
 #define Anum_pg_type_typowner                  3
@@ -220,15 +226,17 @@ typedef FormData_pg_type *Form_pg_type;
 #define Anum_pg_type_typoutput                 12
 #define Anum_pg_type_typreceive                        13
 #define Anum_pg_type_typsend                   14
-#define Anum_pg_type_typanalyze                        15
-#define Anum_pg_type_typalign                  16
-#define Anum_pg_type_typstorage                        17
-#define Anum_pg_type_typnotnull                        18
-#define Anum_pg_type_typbasetype               19
-#define Anum_pg_type_typtypmod                 20
-#define Anum_pg_type_typndims                  21
-#define Anum_pg_type_typdefaultbin             22
-#define Anum_pg_type_typdefault                        23
+#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
 
 
 /* ----------------
@@ -244,86 +252,86 @@ typedef FormData_pg_type *Form_pg_type;
 */
 
 /* 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_ ));
+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 f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 17 ( bytea      PGNSP PGUID -1 f b t \054 0  0 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 charin charout charrecv charsend - c p f 0 -1 0 _null_ _null_ ));
+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 p f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 19 ( name       PGNSP PGUID NAMEDATALEN f b t \054 0 18 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 int8in int8out int8recv int8send - d p f 0 -1 0 _null_ _null_ ));
+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_ ));
+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_ ));
+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_ ));
+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_ ));
+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 -1 0 _null_ _null_ ));
+DATA(insert OID = 25 ( text       PGNSP PGUID -1 f b t \054 0  0 textin textout textrecv textsend - - - i x f 0 -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 oidin oidout oidrecv oidsend - i p f 0 -1 0 _null_ _null_ ));
+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_ ));
+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_ ));
+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_ ));
+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_ ));
+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_ ));
+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_ ));
+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_ ));
+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_ ));
+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_ ));
+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 f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 143 ( _xml      PGNSP PGUID -1 f b t \054 0 142 array_in array_out array_recv array_send - - - i x f 0 -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_ ));
+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 */
@@ -333,194 +341,194 @@ DESCR("storage manager");
 /* 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 p f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 600 (  point    PGNSP PGUID 16 f b t \054 0 701 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 lseg_in lseg_out lseg_recv lseg_send - d p f 0 -1 0 _null_ _null_ ));
+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 -1 0 _null_ _null_ ));
+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 -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 box_in box_out box_recv box_send - d p f 0 -1 0 _null_ _null_ ));
+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_ ));
+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_ ));
+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_ ));
+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 - i p f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 700 (  float4    PGNSP PGUID 4 f b t \054 0   0 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 float8in float8out float8recv float8send - d p f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 701 (  float8    PGNSP PGUID 8 f b t \054 0   0 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 abstimein abstimeout abstimerecv abstimesend - i p f 0 -1 0 _null_ _null_ ));
+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_ ));
+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_ ));
+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_ ));
+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_ ));
+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 - d x f 0 -1 0 _null_ _null_ ));
-DATA(insert OID = 790 (  money    PGNSP PGUID   4 f b t \054 0 0 cash_in cash_out cash_recv cash_send - i p f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 719 (  _circle   PGNSP PGUID -1 f b t \054 0  718 array_in array_out array_recv array_send - - - d x f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 790 (  money    PGNSP PGUID   4 f b t \054 0 0 cash_in cash_out cash_recv cash_send - - - i p 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 array_in array_out array_recv array_send - i x f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 791 (  _money    PGNSP PGUID -1 f b t \054 0  790 array_in array_out array_recv array_send - - - i x 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_ ));
+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 p f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 869 ( inet      PGNSP PGUID  -1 f b t \054 0 0 inet_in inet_out inet_recv inet_send - - - i p 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 p f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 650 ( cidr      PGNSP PGUID  -1 f b t \054 0 0 cidr_in cidr_out cidr_recv cidr_send - - - i p 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 - i x 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_ ));
+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 - - - i x 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 - i x 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 - 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 - 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 x f 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 - d x 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 - i x f 0 -1 0 _null_ _null_ ));
+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 - - - i x 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 bpchartypmodin bpchartypmodout - 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 varchartypmodin varchartypmodout - 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 x f 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 - - - d x 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 - - - 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 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 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 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 array_in array_out array_recv array_send - i x f 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 - d x 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_ ));
+DATA(insert OID = 1022 (  _float8       PGNSP PGUID -1 f b t \054 0 701 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 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 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 array_in array_out array_recv array_send - - - i x f 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 - - - d x 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 - i x 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 - i x f 0 -1 0 _null_ _null_ ));
-DATA(insert OID = 1042 ( bpchar                 PGNSP PGUID -1 f b t \054 0    0 bpcharin bpcharout bpcharrecv bpcharsend - i x f 0 -1 0 _null_ _null_ ));
+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 - - - i x 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 - - - i x f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 1042 ( bpchar                 PGNSP PGUID -1 f b t \054 0    0 bpcharin bpcharout bpcharrecv bpcharsend bpchartypmodin 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 varcharin varcharout varcharrecv varcharsend - i x f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 1043 ( varchar        PGNSP PGUID -1 f b t \054 0    0 varcharin varcharout varcharrecv varcharsend varchartypmodin 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 date_in date_out date_recv date_send - i p f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 1082 ( date           PGNSP PGUID    4 t b t \054 0  0 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 time_in time_out time_recv time_send - d p f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 1083 ( time           PGNSP PGUID    8 f b t \054 0  0 time_in time_out time_recv time_send timetypmodin timetypmodout - 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_send - d p f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 1114 ( timestamp      PGNSP PGUID    8 f b t \054 0  0 timestamp_in timestamp_out timestamp_recv timestamp_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 array_in array_out array_recv array_send - 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 - 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_recv timestamptz_send - d p f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 1115 ( _timestamp  PGNSP PGUID       -1 f b t \054 0 1114 array_in array_out array_recv array_send timestamptypmodin timestamptypmodout - 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 timetypmodin timetypmodout - 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_recv timestamptz_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 - 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_send - d p f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 1185 ( _timestamptz PGNSP PGUID -1 f b t \054 0      1184 array_in array_out array_recv array_send timestamptztypmodin timestamptztypmodout - 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_send intervaltypmodin 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 - d x f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 1187 ( _interval      PGNSP PGUID    -1 f b t \054 0 1186 array_in array_out array_recv array_send intervaltypmodin intervaltypmodout - 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 - 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 - d p f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 1231 (  _numeric      PGNSP PGUID -1 f b t \054 0    1700 array_in array_out array_recv array_send numerictypmodin numerictypmodout - 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 timetztypmodin 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 array_in array_out array_recv array_send - d x f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 1270 ( _timetz        PGNSP PGUID -1 f b t \054 0    1266 array_in array_out array_recv array_send timetztypmodin timetztypmodout - 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 - i x f 0 -1 0 _null_ _null_ ));
+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 - 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 - i x f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 1561 ( _bit           PGNSP PGUID -1 f b t \054 0    1560 array_in array_out array_recv array_send bittypmodin bittypmodout - 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 varbittypmodin 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 array_in array_out array_recv array_send - i x f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 1563 ( _varbit        PGNSP PGUID -1 f b t \054 0    1562 array_in array_out array_recv array_send varbittypmodin varbittypmodout - 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_send - i m f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 1700 ( numeric          PGNSP PGUID -1 f b t \054 0  0 numeric_in numeric_out numeric_recv numeric_send numerictypmodin 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 f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 1790 ( refcursor        PGNSP PGUID -1 f b t \054 0  0 textin textout textrecv textsend - - - i x 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 array_in array_out array_recv array_send - i x f 0 -1 0 _null_ _null_ ));
+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 regprocedurerecv regproceduresend - i p f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 2202 ( regprocedure  PGNSP PGUID     4 t b t \054 0   0 regprocedurein regprocedureout regprocedurerecv regproceduresend - - - 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_ ));
+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 regoperatorrecv regoperatorsend - i p f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 2204 ( regoperator   PGNSP PGUID     4 t b t \054 0   0 regoperatorin regoperatorout regoperatorrecv regoperatorsend - - - 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_ ));
+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_ ));
+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_ ));
+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
 
 /*
@@ -532,25 +540,25 @@ DATA(insert OID = 2211 ( _regtype    PGNSP PGUID -1 f b t \054 0 2206 array_in a
  * 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_ ));
+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_ ));
+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_ ));
+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_ ));
+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_ ));
+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_ ));
+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_ ));
+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_ ));
+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_ ));
+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_ ));
+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
 
 /*
@@ -569,6 +577,8 @@ extern Oid TypeCreate(const char *typeName,
                   Oid outputProcedure,
                   Oid receiveProcedure,
                   Oid sendProcedure,
+                  Oid typmodinProcedure,
+                  Oid typmodoutProcedure,
                   Oid analyzeProcedure,
                   Oid elementType,
                   Oid baseType,
@@ -590,6 +600,8 @@ extern void GenerateTypeDependencies(Oid typeNamespace,
                                                 Oid outputProcedure,
                                                 Oid receiveProcedure,
                                                 Oid sendProcedure,
+                                                Oid typmodinProcedure,
+                                                Oid typmodoutProcedure,
                                                 Oid analyzeProcedure,
                                                 Oid elementType,
                                                 Oid baseType,
index bc62c90f4dcef3f5e99dbcdfffa339eac0896cd0..5d7fa50673c39db5cebf0e5fb9cd2099d3d09010 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.335 2006/12/23 00:43:12 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.336 2006/12/30 21:21:55 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -167,6 +167,8 @@ typedef struct Query
  * For TypeName structures generated internally, it is often easier to
  * specify the type by OID than by name.  If "names" is NIL then the
  * actual type OID is given by typeid, otherwise typeid is unused.
+ * Similarly, if "typmods" is NIL then the actual typmod is expected to
+ * be prespecified in typemod, otherwise typemod is unused.
  *
  * If pct_type is TRUE, then names is actually a field name and we look up
  * the type of that field.     Otherwise (the normal case), names is a type
@@ -180,7 +182,8 @@ typedef struct TypeName
        bool            timezone;               /* timezone specified? */
        bool            setof;                  /* is a set? */
        bool            pct_type;               /* %TYPE specified? */
-       int32           typmod;                 /* type modifier */
+       List       *typmods;            /* type modifier expression(s) */
+       int32           typemod;                /* prespecified type modifier */
        List       *arrayBounds;        /* array bounds */
        int                     location;               /* token location, or -1 if unknown */
 } TypeName;
index 0d2cf087d15fa506a5d5eba2495c7b2b0bbf8d72..1e9e616d09c400dc809af5528d4c41d3fe00a59e 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/parser/parse_type.h,v 1.33 2006/09/25 15:17:34 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/parser/parse_type.h,v 1.34 2006/12/30 21:21:55 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -24,6 +24,8 @@ extern Oid    LookupTypeName(ParseState *pstate, const TypeName *typename);
 extern char *TypeNameToString(const TypeName *typename);
 extern char *TypeNameListToString(List *typenames);
 extern Oid     typenameTypeId(ParseState *pstate, const TypeName *typename);
+extern int32 typenameTypeMod(ParseState *pstate, const TypeName *typename,
+                                                        Oid typeId);
 extern Type typenameType(ParseState *pstate, const TypeName *typename);
 
 extern Type typeidType(Oid id);
index 791f6ebd9993825e2e0816bfa129a686dde1011a..9c9ff140873c38af47958e502ed062d80423111a 100644 (file)
@@ -49,7 +49,7 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/utils/array.h,v 1.60 2006/11/08 19:24:38 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/utils/array.h,v 1.61 2006/12/30 21:21:55 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -255,6 +255,7 @@ extern void mda_get_range(int n, int *span, const int *st, const int *endp);
 extern void mda_get_prod(int n, const int *range, int *prod);
 extern void mda_get_offset_values(int n, int *dist, const int *prod, const int *span);
 extern int     mda_next_tuple(int n, int *curr, const int *span);
+extern int32 *ArrayGetTypmods(ArrayType *arr, int *n);
 
 /*
  * prototypes for functions defined in array_userfuncs.c
index e1ed7b862b34f3992f95d3b05fbf7549d07f6755..56e63d7f73c0a38c86d594957ab14b9ba59d3bbf 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/utils/builtins.h,v 1.282 2006/09/18 22:40:40 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/utils/builtins.h,v 1.283 2006/12/30 21:21:55 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -565,6 +565,8 @@ extern Datum bpcharin(PG_FUNCTION_ARGS);
 extern Datum bpcharout(PG_FUNCTION_ARGS);
 extern Datum bpcharrecv(PG_FUNCTION_ARGS);
 extern Datum bpcharsend(PG_FUNCTION_ARGS);
+extern Datum bpchartypmodin(PG_FUNCTION_ARGS);
+extern Datum bpchartypmodout(PG_FUNCTION_ARGS);
 extern Datum bpchar(PG_FUNCTION_ARGS);
 extern Datum char_bpchar(PG_FUNCTION_ARGS);
 extern Datum name_bpchar(PG_FUNCTION_ARGS);
@@ -586,6 +588,8 @@ extern Datum varcharin(PG_FUNCTION_ARGS);
 extern Datum varcharout(PG_FUNCTION_ARGS);
 extern Datum varcharrecv(PG_FUNCTION_ARGS);
 extern Datum varcharsend(PG_FUNCTION_ARGS);
+extern Datum varchartypmodin(PG_FUNCTION_ARGS);
+extern Datum varchartypmodout(PG_FUNCTION_ARGS);
 extern Datum varchar(PG_FUNCTION_ARGS);
 
 /* varlena.c */
@@ -789,7 +793,9 @@ extern Datum numeric_in(PG_FUNCTION_ARGS);
 extern Datum numeric_out(PG_FUNCTION_ARGS);
 extern Datum numeric_recv(PG_FUNCTION_ARGS);
 extern Datum numeric_send(PG_FUNCTION_ARGS);
-extern Datum numeric (PG_FUNCTION_ARGS);
+extern Datum numerictypmodin(PG_FUNCTION_ARGS);
+extern Datum numerictypmodout(PG_FUNCTION_ARGS);
+extern Datum numeric(PG_FUNCTION_ARGS);
 extern Datum numeric_abs(PG_FUNCTION_ARGS);
 extern Datum numeric_uminus(PG_FUNCTION_ARGS);
 extern Datum numeric_uplus(PG_FUNCTION_ARGS);
index 44eb8e811438faecb18d1283c214fe4135cb9f08..48a6ae1cee1f5e710f55fffff5fc3ccefc1f78c1 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/utils/date.h,v 1.34 2006/07/13 16:49:20 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/utils/date.h,v 1.35 2006/12/30 21:21:56 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -140,6 +140,8 @@ extern Datum time_in(PG_FUNCTION_ARGS);
 extern Datum time_out(PG_FUNCTION_ARGS);
 extern Datum time_recv(PG_FUNCTION_ARGS);
 extern Datum time_send(PG_FUNCTION_ARGS);
+extern Datum timetypmodin(PG_FUNCTION_ARGS);
+extern Datum timetypmodout(PG_FUNCTION_ARGS);
 extern Datum time_scale(PG_FUNCTION_ARGS);
 extern Datum time_eq(PG_FUNCTION_ARGS);
 extern Datum time_ne(PG_FUNCTION_ARGS);
@@ -166,6 +168,8 @@ extern Datum timetz_in(PG_FUNCTION_ARGS);
 extern Datum timetz_out(PG_FUNCTION_ARGS);
 extern Datum timetz_recv(PG_FUNCTION_ARGS);
 extern Datum timetz_send(PG_FUNCTION_ARGS);
+extern Datum timetztypmodin(PG_FUNCTION_ARGS);
+extern Datum timetztypmodout(PG_FUNCTION_ARGS);
 extern Datum timetz_scale(PG_FUNCTION_ARGS);
 extern Datum timetz_eq(PG_FUNCTION_ARGS);
 extern Datum timetz_ne(PG_FUNCTION_ARGS);
index 272b321e6421a349b733313e42084074cfb55c66..e78236b2185b905a4a4961a6f90e6693fcda0739 100644 (file)
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/utils/lsyscache.h,v 1.108 2006/12/23 00:43:13 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/utils/lsyscache.h,v 1.109 2006/12/30 21:21:56 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -100,6 +100,7 @@ extern void getTypeInputInfo(Oid type, Oid *typInput, Oid *typIOParam);
 extern void getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena);
 extern void getTypeBinaryInputInfo(Oid type, Oid *typReceive, Oid *typIOParam);
 extern void getTypeBinaryOutputInfo(Oid type, Oid *typSend, bool *typIsVarlena);
+extern Oid     get_typmodin(Oid typid);
 extern Oid     getBaseType(Oid typid);
 extern Oid     getBaseTypeAndTypmod(Oid typid, int32 *typmod);
 extern int32 get_typavgwidth(Oid typid, int32 typmod);
index 0c6e59cc92fa5062193e758476409a6412f1bc0a..3bbd63ba456630dc4c571ed9544fce48eeda202a 100644 (file)
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/utils/timestamp.h,v 1.64 2006/10/04 00:30:11 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/utils/timestamp.h,v 1.65 2006/12/30 21:21:56 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -200,6 +200,8 @@ extern Datum timestamp_in(PG_FUNCTION_ARGS);
 extern Datum timestamp_out(PG_FUNCTION_ARGS);
 extern Datum timestamp_recv(PG_FUNCTION_ARGS);
 extern Datum timestamp_send(PG_FUNCTION_ARGS);
+extern Datum timestamptypmodin(PG_FUNCTION_ARGS);
+extern Datum timestamptypmodout(PG_FUNCTION_ARGS);
 extern Datum timestamp_scale(PG_FUNCTION_ARGS);
 extern Datum timestamp_eq(PG_FUNCTION_ARGS);
 extern Datum timestamp_ne(PG_FUNCTION_ARGS);
@@ -232,6 +234,8 @@ extern Datum interval_in(PG_FUNCTION_ARGS);
 extern Datum interval_out(PG_FUNCTION_ARGS);
 extern Datum interval_recv(PG_FUNCTION_ARGS);
 extern Datum interval_send(PG_FUNCTION_ARGS);
+extern Datum intervaltypmodin(PG_FUNCTION_ARGS);
+extern Datum intervaltypmodout(PG_FUNCTION_ARGS);
 extern Datum interval_scale(PG_FUNCTION_ARGS);
 extern Datum interval_eq(PG_FUNCTION_ARGS);
 extern Datum interval_ne(PG_FUNCTION_ARGS);
@@ -264,6 +268,8 @@ extern Datum timestamptz_in(PG_FUNCTION_ARGS);
 extern Datum timestamptz_out(PG_FUNCTION_ARGS);
 extern Datum timestamptz_recv(PG_FUNCTION_ARGS);
 extern Datum timestamptz_send(PG_FUNCTION_ARGS);
+extern Datum timestamptztypmodin(PG_FUNCTION_ARGS);
+extern Datum timestamptztypmodout(PG_FUNCTION_ARGS);
 extern Datum timestamptz_scale(PG_FUNCTION_ARGS);
 extern Datum timestamptz_timestamp(PG_FUNCTION_ARGS);
 extern Datum timestamptz_zone(PG_FUNCTION_ARGS);
index 793d28d38355db94509d495b14de75fb3d848fae..f0fb87e71e7665c5f491960afe43f5a775e2da18 100644 (file)
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/utils/varbit.h,v 1.23 2006/03/05 15:59:08 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/utils/varbit.h,v 1.24 2006/12/30 21:21:56 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -64,10 +64,14 @@ extern Datum bit_in(PG_FUNCTION_ARGS);
 extern Datum bit_out(PG_FUNCTION_ARGS);
 extern Datum bit_recv(PG_FUNCTION_ARGS);
 extern Datum bit_send(PG_FUNCTION_ARGS);
+extern Datum bittypmodin(PG_FUNCTION_ARGS);
+extern Datum bittypmodout(PG_FUNCTION_ARGS);
 extern Datum varbit_in(PG_FUNCTION_ARGS);
 extern Datum varbit_out(PG_FUNCTION_ARGS);
 extern Datum varbit_recv(PG_FUNCTION_ARGS);
 extern Datum varbit_send(PG_FUNCTION_ARGS);
+extern Datum varbittypmodin(PG_FUNCTION_ARGS);
+extern Datum varbittypmodout(PG_FUNCTION_ARGS);
 extern Datum bit(PG_FUNCTION_ARGS);
 extern Datum varbit(PG_FUNCTION_ARGS);
 extern Datum biteq(PG_FUNCTION_ARGS);
index 3e2edeb1e0b6ff20482a42a30b61f7a3c6380c57..133ad857ac1c0ab83b32eaf22d5a7a36ca465343 100644 (file)
@@ -10,6 +10,8 @@ CREATE TYPE widget (
    internallength = 24, 
    input = widget_in,
    output = widget_out,
+   typmod_in = numerictypmodin,
+   typmod_out = numerictypmodout,
    alignment = double
 );
 CREATE TYPE city_budget ( 
@@ -99,3 +101,15 @@ ERROR:  type "text_w_default" already exists
 DROP TYPE default_test_row CASCADE;
 NOTICE:  drop cascades to function get_default_test()
 DROP TABLE default_test;
+-- Check usage of typmod with a user-defined type
+-- (we have borrowed numeric's typmod functions)
+CREATE TEMP TABLE mytab (foo widget(42,13,7));     -- should fail
+ERROR:  invalid NUMERIC type modifier
+CREATE TEMP TABLE mytab (foo widget(42,13));
+SELECT format_type(atttypid,atttypmod) FROM pg_attribute
+WHERE attrelid = 'mytab'::regclass AND attnum > 0;
+  format_type  
+---------------
+ widget(42,13)
+(1 row)
+
index 3aa8e3714bfca3f49b3523cb451077b3e37d5fae..f8cc66492cefb78ebbb556ebf616036a20e4d8bf 100644 (file)
@@ -840,8 +840,12 @@ SELECT time '03:30' + interval '1 month 04:01' AS "07:31:00";
 
 SELECT CAST(time with time zone '01:02-08' AS interval) AS "+00:01";
 ERROR:  cannot cast type time with time zone to interval
+LINE 1: SELECT CAST(time with time zone '01:02-08' AS interval) AS "...
+                                                      ^
 SELECT CAST(interval '02:03' AS time with time zone) AS "02:03:00-08";
 ERROR:  cannot cast type interval to time with time zone
+LINE 1: SELECT CAST(interval '02:03' AS time with time zone) AS "02:...
+                                        ^
 SELECT time with time zone '01:30-08' - interval '02:01' AS "23:29:00-08";
  23:29:00-08 
 -------------
index cc82b12e027a9a34089918d31e547a9edb99a07c..5945753a1b3f530cfc9fb6a09d195db461838980 100644 (file)
@@ -753,6 +753,22 @@ WHERE      typsend != 0 AND
 ------+---------
 (0 rows)
 
+SELECT ctid, typmodin 
+FROM   pg_catalog.pg_type fk 
+WHERE  typmodin != 0 AND 
+       NOT EXISTS(SELECT 1 FROM pg_catalog.pg_proc pk WHERE pk.oid = fk.typmodin);
+ ctid | typmodin 
+------+----------
+(0 rows)
+
+SELECT ctid, typmodout 
+FROM   pg_catalog.pg_type fk 
+WHERE  typmodout != 0 AND 
+       NOT EXISTS(SELECT 1 FROM pg_catalog.pg_proc pk WHERE pk.oid = fk.typmodout);
+ ctid | typmodout 
+------+-----------
+(0 rows)
+
 SELECT ctid, typbasetype 
 FROM   pg_catalog.pg_type fk 
 WHERE  typbasetype != 0 AND 
index 73d51925c2ffaab57d4327dba2819f1fbf9f2d16..11c9298e9aed472b2c60fb1c1f5e40997047c2e7 100644 (file)
@@ -212,6 +212,48 @@ WHERE p1.typsend = p2.oid AND p1.typtype in ('b', 'p') AND NOT
 -----+---------+-----+---------
 (0 rows)
 
+-- Check for bogus typmodin routines
+SELECT p1.oid, p1.typname, p2.oid, p2.proname
+FROM pg_type AS p1, pg_proc AS p2
+WHERE p1.typmodin = p2.oid AND p1.typtype in ('b', 'p') AND NOT
+    (p2.pronargs = 1 AND
+     p2.proargtypes[0] = 'int4[]'::regtype AND
+     p2.prorettype = 'int4'::regtype AND NOT p2.proretset);
+ oid | typname | oid | proname 
+-----+---------+-----+---------
+(0 rows)
+
+-- Check for bogus typmodout routines
+SELECT p1.oid, p1.typname, p2.oid, p2.proname
+FROM pg_type AS p1, pg_proc AS p2
+WHERE p1.typmodout = p2.oid AND p1.typtype in ('b', 'p') AND NOT
+    (p2.pronargs = 1 AND
+     p2.proargtypes[0] = 'int4'::regtype AND
+     p2.prorettype = 'cstring'::regtype AND NOT p2.proretset);
+ oid | typname | oid | proname 
+-----+---------+-----+---------
+(0 rows)
+
+-- Array types should have same typmodin/out as their element types
+SELECT p1.oid, p1.typname, p2.oid, p2.typname
+FROM pg_type AS p1, pg_type AS p2
+WHERE p1.typelem = p2.oid AND NOT
+    (p1.typmodin = p2.typmodin AND p1.typmodout = p2.typmodout);
+ oid | typname | oid | typname 
+-----+---------+-----+---------
+(0 rows)
+
+-- Check for bogus typanalyze routines
+SELECT p1.oid, p1.typname, p2.oid, p2.proname
+FROM pg_type AS p1, pg_proc AS p2
+WHERE p1.typanalyze = p2.oid AND p1.typtype in ('b', 'p') AND NOT
+    (p2.pronargs = 1 AND
+     p2.proargtypes[0] = 'internal'::regtype AND
+     p2.prorettype = 'bool'::regtype AND NOT p2.proretset);
+ oid | typname | oid | proname 
+-----+---------+-----+---------
+(0 rows)
+
 -- **************** pg_class ****************
 -- Look for illegal values in pg_class fields
 SELECT p1.oid, p1.relname
index 097d51fc925685dd8590ee2d2deb2a998a7f0726..c6e391d810460a3859526a7af974e39284f77023 100644 (file)
@@ -11,6 +11,8 @@ CREATE TYPE widget (
    internallength = 24, 
    input = widget_in,
    output = widget_out,
+   typmod_in = numerictypmodin,
+   typmod_out = numerictypmodout,
    alignment = double
 );
 
@@ -98,3 +100,12 @@ CREATE TYPE text_w_default;         -- should fail
 DROP TYPE default_test_row CASCADE;
 
 DROP TABLE default_test;
+
+-- Check usage of typmod with a user-defined type
+-- (we have borrowed numeric's typmod functions)
+
+CREATE TEMP TABLE mytab (foo widget(42,13,7));     -- should fail
+CREATE TEMP TABLE mytab (foo widget(42,13));
+
+SELECT format_type(atttypid,atttypmod) FROM pg_attribute
+WHERE attrelid = 'mytab'::regclass AND attnum > 0;
index bf713e9fa7cf2f24e9a18ac79580acd9d211ac6e..5eb440f0f541bab854295d7524fc93bb1c25281f 100644 (file)
@@ -377,6 +377,14 @@ SELECT     ctid, typsend
 FROM   pg_catalog.pg_type fk 
 WHERE  typsend != 0 AND 
        NOT EXISTS(SELECT 1 FROM pg_catalog.pg_proc pk WHERE pk.oid = fk.typsend);
+SELECT ctid, typmodin 
+FROM   pg_catalog.pg_type fk 
+WHERE  typmodin != 0 AND 
+       NOT EXISTS(SELECT 1 FROM pg_catalog.pg_proc pk WHERE pk.oid = fk.typmodin);
+SELECT ctid, typmodout 
+FROM   pg_catalog.pg_type fk 
+WHERE  typmodout != 0 AND 
+       NOT EXISTS(SELECT 1 FROM pg_catalog.pg_proc pk WHERE pk.oid = fk.typmodout);
 SELECT ctid, typbasetype 
 FROM   pg_catalog.pg_type fk 
 WHERE  typbasetype != 0 AND 
index 3969b4cce2ef4808dcfeac26d294cf6a30d13f5a..3677b90ceb9835c230f0c0d1a4d91cb5864899c6 100644 (file)
@@ -163,6 +163,40 @@ FROM pg_type AS p1, pg_proc AS p2
 WHERE p1.typsend = p2.oid AND p1.typtype in ('b', 'p') AND NOT
     (p2.prorettype = 'bytea'::regtype AND NOT p2.proretset);
 
+-- Check for bogus typmodin routines
+
+SELECT p1.oid, p1.typname, p2.oid, p2.proname
+FROM pg_type AS p1, pg_proc AS p2
+WHERE p1.typmodin = p2.oid AND p1.typtype in ('b', 'p') AND NOT
+    (p2.pronargs = 1 AND
+     p2.proargtypes[0] = 'int4[]'::regtype AND
+     p2.prorettype = 'int4'::regtype AND NOT p2.proretset);
+
+-- Check for bogus typmodout routines
+
+SELECT p1.oid, p1.typname, p2.oid, p2.proname
+FROM pg_type AS p1, pg_proc AS p2
+WHERE p1.typmodout = p2.oid AND p1.typtype in ('b', 'p') AND NOT
+    (p2.pronargs = 1 AND
+     p2.proargtypes[0] = 'int4'::regtype AND
+     p2.prorettype = 'cstring'::regtype AND NOT p2.proretset);
+
+-- Array types should have same typmodin/out as their element types
+
+SELECT p1.oid, p1.typname, p2.oid, p2.typname
+FROM pg_type AS p1, pg_type AS p2
+WHERE p1.typelem = p2.oid AND NOT
+    (p1.typmodin = p2.typmodin AND p1.typmodout = p2.typmodout);
+
+-- Check for bogus typanalyze routines
+
+SELECT p1.oid, p1.typname, p2.oid, p2.proname
+FROM pg_type AS p1, pg_proc AS p2
+WHERE p1.typanalyze = p2.oid AND p1.typtype in ('b', 'p') AND NOT
+    (p2.pronargs = 1 AND
+     p2.proargtypes[0] = 'internal'::regtype AND
+     p2.prorettype = 'bool'::regtype AND NOT p2.proretset);
+
 -- **************** pg_class ****************
 
 -- Look for illegal values in pg_class fields
index aec8f1bd8dec7c2fdf6dcd3c1116d7fa4ddf60d2..598aab2bbd1e83f93fd0ffbf9c43d87108696342 100644 (file)
@@ -130,6 +130,8 @@ Join pg_catalog.pg_type.typinput => pg_catalog.pg_proc.oid
 Join pg_catalog.pg_type.typoutput => pg_catalog.pg_proc.oid
 Join pg_catalog.pg_type.typreceive => pg_catalog.pg_proc.oid
 Join pg_catalog.pg_type.typsend => pg_catalog.pg_proc.oid
+Join pg_catalog.pg_type.typmodin => pg_catalog.pg_proc.oid
+Join pg_catalog.pg_type.typmodout => pg_catalog.pg_proc.oid
 Join pg_catalog.pg_type.typbasetype => pg_catalog.pg_type.oid
 
 ---------------------------------------------------------------------------