]> granicus.if.org Git - postgresql/commitdiff
Change typreceive function API so that receive functions get the same
authorTom Lane <tgl@sss.pgh.pa.us>
Sun, 10 Jul 2005 21:14:00 +0000 (21:14 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Sun, 10 Jul 2005 21:14:00 +0000 (21:14 +0000)
optional arguments as text input functions, ie, typioparam OID and
atttypmod.  Make all the datatypes that use typmod enforce it the same
way in typreceive as they do in typinput.  This fixes a problem with
failure to enforce length restrictions during COPY FROM BINARY.

18 files changed:
doc/src/sgml/ref/create_type.sgml
src/backend/commands/copy.c
src/backend/commands/typecmds.c
src/backend/tcop/fastpath.c
src/backend/tcop/postgres.c
src/backend/utils/adt/arrayfuncs.c
src/backend/utils/adt/date.c
src/backend/utils/adt/numeric.c
src/backend/utils/adt/rowtypes.c
src/backend/utils/adt/timestamp.c
src/backend/utils/adt/varbit.c
src/backend/utils/adt/varchar.c
src/backend/utils/adt/varlena.c
src/backend/utils/mb/mbutils.c
src/include/catalog/catversion.h
src/include/catalog/pg_proc.h
src/test/regress/expected/type_sanity.out
src/test/regress/sql/type_sanity.sql

index 69899d84f53d7b94ab45db3fa04077837d256433..4f002b65194974bbb4ee7e776ea937b0b5cf3e69 100644 (file)
@@ -1,5 +1,5 @@
 <!--
-$PostgreSQL: pgsql/doc/src/sgml/ref/create_type.sgml,v 1.55 2005/05/01 18:56:17 tgl Exp $
+$PostgreSQL: pgsql/doc/src/sgml/ref/create_type.sgml,v 1.56 2005/07/10 21:13:57 tgl Exp $
 PostgreSQL documentation
 -->
 
@@ -125,12 +125,13 @@ CREATE TYPE <replaceable class="parameter">name</replaceable> (
    function should perform adequate checking to ensure that the value is
    valid.
    The receive function may be declared as taking one argument of type
-   <type>internal</type>, or two arguments of types <type>internal</type>
-   and <type>oid</type>.  It must return a value of the data type itself.
-   (The first argument is a pointer to a <type>StringInfo</type> buffer
-   holding the received byte string; the optional second argument is the
-   element type OID in case this is an array type, or the type's own OID for a
-   composite type.)  Similarly, the optional
+   <type>internal</type>, or as taking three arguments of types
+   <type>internal</type>, <type>oid</type>, <type>integer</type>.
+   The first argument is a pointer to a <type>StringInfo</type> buffer
+   holding the received byte string; the optional arguments are the
+   same as for the text input function.
+   The receive function must return a value of the data type itself.
+   Similarly, the optional
    <replaceable class="parameter">send_function</replaceable> converts
    from the internal representation to the external binary representation.
    If this function is not supplied, the type cannot participate in binary
index 10e68684b8e6e62f3e141b6a05da72f4eb8e1637..d25189d0ac34174ef23f75a2cfa60e6eb7cd11cc 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/commands/copy.c,v 1.246 2005/06/28 05:08:53 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/commands/copy.c,v 1.247 2005/07/10 21:13:58 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -144,7 +144,7 @@ static char *CopyReadAttributeCSV(const char *delim, const char *null_print,
                                         char *quote, char *escape,
                                         CopyReadResult *result, bool *isnull);
 static Datum CopyReadBinaryAttribute(int column_no, FmgrInfo *flinfo,
-                                               Oid typioparam, bool *isnull);
+                                               Oid typioparam, int32 typmod, bool *isnull);
 static void CopyAttributeOut(char *string, char *delim);
 static void CopyAttributeOutCSV(char *string, char *delim, char *quote,
                                        char *escape, bool force_quote);
@@ -1843,8 +1843,9 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
                                copy_attname = "oid";
                                loaded_oid =
                                        DatumGetObjectId(CopyReadBinaryAttribute(0,
-                                                                                                               &oid_in_function,
-                                                                                                                 oid_typioparam,
+                                                                                                                        &oid_in_function,
+                                                                                                                        oid_typioparam,
+                                                                                                                        -1,
                                                                                                                         &isnull));
                                if (isnull || loaded_oid == InvalidOid)
                                        ereport(ERROR,
@@ -1864,6 +1865,7 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
                                values[m] = CopyReadBinaryAttribute(i,
                                                                                                        &in_functions[m],
                                                                                                        typioparams[m],
+                                                                                                       attr[m]->atttypmod,
                                                                                                        &isnull);
                                nulls[m] = isnull ? 'n' : ' ';
                                copy_attname = NULL;
@@ -2556,7 +2558,8 @@ CopyReadAttributeCSV(const char *delim, const char *null_print, char *quote,
  * Read a binary attribute
  */
 static Datum
-CopyReadBinaryAttribute(int column_no, FmgrInfo *flinfo, Oid typioparam,
+CopyReadBinaryAttribute(int column_no, FmgrInfo *flinfo,
+                                               Oid typioparam, int32 typmod,
                                                bool *isnull)
 {
        int32           fld_size;
@@ -2594,9 +2597,10 @@ CopyReadBinaryAttribute(int column_no, FmgrInfo *flinfo, Oid typioparam,
        attribute_buf.data[fld_size] = '\0';
 
        /* Call the column type's binary input converter */
-       result = FunctionCall2(flinfo,
+       result = FunctionCall3(flinfo,
                                                   PointerGetDatum(&attribute_buf),
-                                                  ObjectIdGetDatum(typioparam));
+                                                  ObjectIdGetDatum(typioparam),
+                                                  Int32GetDatum(typmod));
 
        /* Trouble if it didn't eat the whole buffer */
        if (attribute_buf.cursor != attribute_buf.len)
index e5f2a2f762bc7281827c5b51c58d023bd3752548..7406e15376abd7d76b4ff8e3e37df93d974a4d4e 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/commands/typecmds.c,v 1.74 2005/07/07 20:39:58 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/commands/typecmds.c,v 1.75 2005/07/10 21:13:58 tgl Exp $
  *
  * DESCRIPTION
  *       The "DefineFoo" routines take the parse tree and pick out the
@@ -859,7 +859,7 @@ findTypeInputFunction(List *procname, Oid typeOid)
 
        /*
         * Input functions can take a single argument of type CSTRING, or
-        * three arguments (string, element OID, typmod).
+        * three arguments (string, typioparam OID, typmod).
         *
         * For backwards compatibility we allow OPAQUE in place of CSTRING; if we
         * see this, we issue a warning and fix up the pg_proc entry.
@@ -973,12 +973,12 @@ findTypeOutputFunction(List *procname, Oid typeOid)
 static Oid
 findTypeReceiveFunction(List *procname, Oid typeOid)
 {
-       Oid                     argList[2];
+       Oid                     argList[3];
        Oid                     procOid;
 
        /*
         * Receive functions can take a single argument of type INTERNAL, or
-        * two arguments (internal, oid).
+        * three arguments (internal, typioparam OID, typmod).
         */
        argList[0] = INTERNALOID;
 
@@ -987,8 +987,9 @@ findTypeReceiveFunction(List *procname, Oid typeOid)
                return procOid;
 
        argList[1] = OIDOID;
+       argList[2] = INT4OID;
 
-       procOid = LookupFuncName(procname, 2, argList, true);
+       procOid = LookupFuncName(procname, 3, argList, true);
        if (OidIsValid(procOid))
                return procOid;
 
index bd9b490378592d113fcc90991b31d61aecd8727c..a870f2c9c883c59a6efa940b11f8292259f8b277 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/tcop/fastpath.c,v 1.80 2005/05/01 18:56:18 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/tcop/fastpath.c,v 1.81 2005/07/10 21:13:58 tgl Exp $
  *
  * NOTES
  *       This cruft is the server side of PQfn.
@@ -493,9 +493,10 @@ parse_fcall_arguments(StringInfo msgBuf, struct fp_info * fip,
                        /* Call the argument type's binary input converter */
                        getTypeBinaryInputInfo(fip->argtypes[i], &typreceive, &typioparam);
 
-                       fcinfo->arg[i] = OidFunctionCall2(typreceive,
+                       fcinfo->arg[i] = OidFunctionCall3(typreceive,
                                                                                          PointerGetDatum(&abuf),
-                                                                                  ObjectIdGetDatum(typioparam));
+                                                                                         ObjectIdGetDatum(typioparam),
+                                                                                         Int32GetDatum(-1));
 
                        /* Trouble if it didn't eat the whole buffer */
                        if (abuf.cursor != abuf.len)
@@ -579,9 +580,10 @@ parse_fcall_arguments_20(StringInfo msgBuf, struct fp_info * fip,
                /* Call the argument type's binary input converter */
                getTypeBinaryInputInfo(fip->argtypes[i], &typreceive, &typioparam);
 
-               fcinfo->arg[i] = OidFunctionCall2(typreceive,
+               fcinfo->arg[i] = OidFunctionCall3(typreceive,
                                                                                  PointerGetDatum(&abuf),
-                                                                                 ObjectIdGetDatum(typioparam));
+                                                                                 ObjectIdGetDatum(typioparam),
+                                                                                 Int32GetDatum(-1));
 
                /* Trouble if it didn't eat the whole buffer */
                if (abuf.cursor != abuf.len)
index 6973e9d3b3cb48fd566ead7ecbb23425b04de60c..038a482239f0c4a4dad63da2b60b7ee2bcd6bbb7 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.452 2005/07/04 04:51:49 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.453 2005/07/10 21:13:58 tgl Exp $
  *
  * NOTES
  *       this is the "main" module of the postgres backend and
@@ -1571,9 +1571,10 @@ exec_bind_message(StringInfo input_message)
                                                getTypeBinaryInputInfo(ptype, &typreceive, &typioparam);
 
                                                params[i].value =
-                                                       OidFunctionCall2(typreceive,
+                                                       OidFunctionCall3(typreceive,
                                                                                         PointerGetDatum(&pbuf),
-                                                                                  ObjectIdGetDatum(typioparam));
+                                                                                        ObjectIdGetDatum(typioparam),
+                                                                                        Int32GetDatum(-1));
 
                                                /* Trouble if it didn't eat the whole buffer */
                                                if (pbuf.cursor != pbuf.len)
index 794b95e22975d2be4b786789348ffcf1a0f8f76a..07edd7014da341c0233046af9342164624fc573b 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/utils/adt/arrayfuncs.c,v 1.120 2005/05/01 18:56:18 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/utils/adt/arrayfuncs.c,v 1.121 2005/07/10 21:13:58 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -81,7 +81,7 @@ static Datum *ReadArrayStr(char *arrayStr, const char *origStr,
                         int typlen, bool typbyval, char typalign,
                         int *nbytes);
 static Datum *ReadArrayBinary(StringInfo buf, int nitems,
-                               FmgrInfo *receiveproc, Oid typioparam,
+                               FmgrInfo *receiveproc, Oid typioparam, int32 typmod,
                                int typlen, bool typbyval, char typalign,
                                int *nbytes);
 static void CopyArrayEls(char *p, Datum *values, int nitems,
@@ -1121,6 +1121,8 @@ array_recv(PG_FUNCTION_ARGS)
        StringInfo      buf = (StringInfo) PG_GETARG_POINTER(0);
        Oid                     spec_element_type = PG_GETARG_OID(1);   /* type of an array
                                                                                                                 * element */
+       int32           typmod = PG_GETARG_INT32(2);    /* typmod for array
+                                                                                                * elements */
        Oid                     element_type;
        int                     typlen;
        bool            typbyval;
@@ -1215,7 +1217,8 @@ array_recv(PG_FUNCTION_ARGS)
        typalign = my_extra->typalign;
        typioparam = my_extra->typioparam;
 
-       dataPtr = ReadArrayBinary(buf, nitems, &my_extra->proc, typioparam,
+       dataPtr = ReadArrayBinary(buf, nitems, &my_extra->proc,
+                                                         typioparam, typmod,
                                                          typlen, typbyval, typalign,
                                                          &nbytes);
        nbytes += ARR_OVERHEAD(ndim);
@@ -1249,6 +1252,7 @@ ReadArrayBinary(StringInfo buf,
                                int nitems,
                                FmgrInfo *receiveproc,
                                Oid typioparam,
+                               int32 typmod,
                                int typlen,
                                bool typbyval,
                                char typalign,
@@ -1289,9 +1293,10 @@ ReadArrayBinary(StringInfo buf,
                buf->data[buf->cursor] = '\0';
 
                /* Now call the element's receiveproc */
-               values[i] = FunctionCall2(receiveproc,
+               values[i] = FunctionCall3(receiveproc,
                                                                  PointerGetDatum(&elem_buf),
-                                                                 ObjectIdGetDatum(typioparam));
+                                                                 ObjectIdGetDatum(typioparam),
+                                                                 Int32GetDatum(typmod));
 
                /* Trouble if it didn't eat the whole buffer */
                if (elem_buf.cursor != itemlen)
index abc6155594f137f242268fb8deff5d36c26da894..4f8f96075d92448683ce5a1f6c2feab61213039c 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/utils/adt/date.c,v 1.110 2005/06/15 00:34:08 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/utils/adt/date.c,v 1.111 2005/07/10 21:13:59 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -982,12 +982,21 @@ Datum
 time_recv(PG_FUNCTION_ARGS)
 {
        StringInfo      buf = (StringInfo) PG_GETARG_POINTER(0);
+#ifdef NOT_USED
+       Oid                     typelem = PG_GETARG_OID(1);
+#endif
+       int32           typmod = PG_GETARG_INT32(2);
+       TimeADT         result;
 
 #ifdef HAVE_INT64_TIMESTAMP
-       PG_RETURN_TIMEADT((TimeADT) pq_getmsgint64(buf));
+       result = pq_getmsgint64(buf);
 #else
-       PG_RETURN_TIMEADT((TimeADT) pq_getmsgfloat8(buf));
+       result = pq_getmsgfloat8(buf);
 #endif
+
+       AdjustTimeForTypmod(&result, typmod);
+
+       PG_RETURN_TIMEADT(result);
 }
 
 /*
@@ -1774,18 +1783,24 @@ Datum
 timetz_recv(PG_FUNCTION_ARGS)
 {
        StringInfo      buf = (StringInfo) PG_GETARG_POINTER(0);
-       TimeTzADT  *time;
+#ifdef NOT_USED
+       Oid                     typelem = PG_GETARG_OID(1);
+#endif
+       int32           typmod = PG_GETARG_INT32(2);
+       TimeTzADT  *result;
 
-       time = (TimeTzADT *) palloc(sizeof(TimeTzADT));
+       result = (TimeTzADT *) palloc(sizeof(TimeTzADT));
 
 #ifdef HAVE_INT64_TIMESTAMP
-       time->time = pq_getmsgint64(buf);
+       result->time = pq_getmsgint64(buf);
 #else
-       time->time = pq_getmsgfloat8(buf);
+       result->time = pq_getmsgfloat8(buf);
 #endif
-       time->zone = pq_getmsgint(buf, sizeof(time->zone));
+       result->zone = pq_getmsgint(buf, sizeof(result->zone));
+
+       AdjustTimeForTypmod(&(result->time), typmod);
 
-       PG_RETURN_TIMETZADT_P(time);
+       PG_RETURN_TIMETZADT_P(result);
 }
 
 /*
index 8b39bb4248cc97caf4ce421b8db9d8ee180e0041..4aa631ee5778df3b4726c804e3effd27e3ca12bf 100644 (file)
@@ -14,7 +14,7 @@
  * Copyright (c) 1998-2005, PostgreSQL Global Development Group
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/utils/adt/numeric.c,v 1.84 2005/06/04 14:12:50 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/utils/adt/numeric.c,v 1.85 2005/07/10 21:13:59 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -383,6 +383,10 @@ Datum
 numeric_recv(PG_FUNCTION_ARGS)
 {
        StringInfo      buf = (StringInfo) PG_GETARG_POINTER(0);
+#ifdef NOT_USED
+       Oid                     typelem = PG_GETARG_OID(1);
+#endif
+       int32           typmod = PG_GETARG_INT32(2);
        NumericVar      value;
        Numeric         res;
        int                     len,
@@ -419,6 +423,8 @@ numeric_recv(PG_FUNCTION_ARGS)
                value.digits[i] = d;
        }
 
+       apply_typmod(&value, typmod);
+
        res = make_result(&value);
        free_var(&value);
 
index d3a151a8ab14778f3184c21bfa6549e88c1614dc..07a5cf54eeaab3e93446104c37f5f8bee3e540cb 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/utils/adt/rowtypes.c,v 1.11 2005/05/01 18:56:18 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/utils/adt/rowtypes.c,v 1.12 2005/07/10 21:13:59 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -54,6 +54,9 @@ record_in(PG_FUNCTION_ARGS)
 {
        char       *string = PG_GETARG_CSTRING(0);
        Oid                     tupType = PG_GETARG_OID(1);
+#ifdef NOT_USED
+       int32           typmod = PG_GETARG_INT32(2);
+#endif
        HeapTupleHeader result;
        int32           tupTypmod;
        TupleDesc       tupdesc;
@@ -417,6 +420,9 @@ record_recv(PG_FUNCTION_ARGS)
 {
        StringInfo      buf = (StringInfo) PG_GETARG_POINTER(0);
        Oid                     tupType = PG_GETARG_OID(1);
+#ifdef NOT_USED
+       int32           typmod = PG_GETARG_INT32(2);
+#endif
        HeapTupleHeader result;
        int32           tupTypmod;
        TupleDesc       tupdesc;
@@ -560,10 +566,10 @@ record_recv(PG_FUNCTION_ARGS)
                                column_info->column_type = column_type;
                        }
 
-                       values[i] = FunctionCall2(&column_info->proc,
+                       values[i] = FunctionCall3(&column_info->proc,
                                                                          PointerGetDatum(&item_buf),
-                                                         ObjectIdGetDatum(column_info->typioparam));
-
+                                                                         ObjectIdGetDatum(column_info->typioparam),
+                                                                         Int32GetDatum(tupdesc->attrs[i]->atttypmod));
                        nulls[i] = ' ';
 
                        /* Trouble if it didn't eat the whole buffer */
index 8b64711e63548e9493bc82b5ca59a916fab1513b..0f928ef57494d7494d4c043bca20682467bb084c 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/utils/adt/timestamp.c,v 1.129 2005/07/04 14:38:31 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/utils/adt/timestamp.c,v 1.130 2005/07/10 21:13:59 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -170,6 +170,10 @@ Datum
 timestamp_recv(PG_FUNCTION_ARGS)
 {
        StringInfo      buf = (StringInfo) PG_GETARG_POINTER(0);
+#ifdef NOT_USED
+       Oid                     typelem = PG_GETARG_OID(1);
+#endif
+       int32           typmod = PG_GETARG_INT32(2);
        Timestamp timestamp;
        struct pg_tm tt,
                           *tm = &tt;
@@ -177,7 +181,6 @@ timestamp_recv(PG_FUNCTION_ARGS)
 
 #ifdef HAVE_INT64_TIMESTAMP
        timestamp = (Timestamp) pq_getmsgint64(buf);
-
 #else
        timestamp = (Timestamp) pq_getmsgfloat8(buf);
 #endif
@@ -185,11 +188,13 @@ timestamp_recv(PG_FUNCTION_ARGS)
        /* rangecheck: see if timestamp_out would like it */
        if (TIMESTAMP_NOT_FINITE(timestamp))
                 /* ok */ ;
-       else if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL) !=0)
+       else if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL) != 0)
                ereport(ERROR,
                                (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
                                 errmsg("timestamp out of range")));
 
+       AdjustTimestampForTypmod(&timestamp, typmod);
+
        PG_RETURN_TIMESTAMP(timestamp);
 }
 
@@ -409,6 +414,10 @@ Datum
 timestamptz_recv(PG_FUNCTION_ARGS)
 {
        StringInfo      buf = (StringInfo) PG_GETARG_POINTER(0);
+#ifdef NOT_USED
+       Oid                     typelem = PG_GETARG_OID(1);
+#endif
+       int32           typmod = PG_GETARG_INT32(2);
        TimestampTz timestamp;
        int                     tz;
        struct pg_tm tt,
@@ -418,7 +427,6 @@ timestamptz_recv(PG_FUNCTION_ARGS)
 
 #ifdef HAVE_INT64_TIMESTAMP
        timestamp = (TimestampTz) pq_getmsgint64(buf);
-
 #else
        timestamp = (TimestampTz) pq_getmsgfloat8(buf);
 #endif
@@ -431,6 +439,8 @@ timestamptz_recv(PG_FUNCTION_ARGS)
                                (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
                                 errmsg("timestamp out of range")));
 
+       AdjustTimestampForTypmod(&timestamp, typmod);
+
        PG_RETURN_TIMESTAMPTZ(timestamp);
 }
 
@@ -526,7 +536,6 @@ interval_in(PG_FUNCTION_ARGS)
                                ereport(ERROR,
                                                (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
                                                 errmsg("interval out of range")));
-                       AdjustIntervalForTypmod(result, typmod);
                        break;
 
                case DTK_INVALID:
@@ -540,6 +549,8 @@ interval_in(PG_FUNCTION_ARGS)
                                 dtype, str);
        }
 
+       AdjustIntervalForTypmod(result, typmod);
+
        PG_RETURN_INTERVAL_P(result);
 }
 
@@ -573,18 +584,23 @@ Datum
 interval_recv(PG_FUNCTION_ARGS)
 {
        StringInfo      buf = (StringInfo) PG_GETARG_POINTER(0);
+#ifdef NOT_USED
+       Oid                     typelem = PG_GETARG_OID(1);
+#endif
+       int32           typmod = PG_GETARG_INT32(2);
        Interval   *interval;
 
        interval = (Interval *) palloc(sizeof(Interval));
 
 #ifdef HAVE_INT64_TIMESTAMP
        interval->time = pq_getmsgint64(buf);
-
 #else
        interval->time = pq_getmsgfloat8(buf);
 #endif
        interval->month = pq_getmsgint(buf, sizeof(interval->month));
 
+       AdjustIntervalForTypmod(interval, typmod);
+
        PG_RETURN_INTERVAL_P(interval);
 }
 
index bdbf43c8993b3cd919278c2a06f9803ffc59c0af..1996638d28ea9f23503e4aaecbfcfcd8eb9eb616 100644 (file)
@@ -9,7 +9,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/utils/adt/varbit.c,v 1.44 2004/12/31 22:01:22 pgsql Exp $
+ *       $PostgreSQL: pgsql/src/backend/utils/adt/varbit.c,v 1.45 2005/07/10 21:13:59 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -221,8 +221,49 @@ bit_out(PG_FUNCTION_ARGS)
 Datum
 bit_recv(PG_FUNCTION_ARGS)
 {
-       /* Exactly the same as varbit_recv, so share code */
-       return varbit_recv(fcinfo);
+       StringInfo      buf = (StringInfo) PG_GETARG_POINTER(0);
+#ifdef NOT_USED
+       Oid                     typelem = PG_GETARG_OID(1);
+#endif
+       int32           atttypmod = PG_GETARG_INT32(2);
+       VarBit     *result;
+       int                     len,
+                               bitlen;
+       int                     ipad;
+       bits8           mask;
+
+       bitlen = pq_getmsgint(buf, sizeof(int32));
+       if (bitlen < 0)
+               ereport(ERROR,
+                               (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
+                                errmsg("invalid length in external bit string")));
+
+       /*
+        * Sometimes atttypmod is not supplied. If it is supplied we need to
+        * make sure that the bitstring fits.
+        */
+       if (atttypmod > 0 && bitlen != atttypmod)
+               ereport(ERROR,
+                               (errcode(ERRCODE_STRING_DATA_LENGTH_MISMATCH),
+                          errmsg("bit string length %d does not match type bit(%d)",
+                                         bitlen, atttypmod)));
+
+       len = VARBITTOTALLEN(bitlen);
+       result = (VarBit *) palloc(len);
+       VARATT_SIZEP(result) = len;
+       VARBITLEN(result) = bitlen;
+
+       pq_copymsgbytes(buf, (char *) VARBITS(result), VARBITBYTES(result));
+
+       /* Make sure last byte is zero-padded if needed */
+       ipad = VARBITPAD(result);
+       if (ipad > 0)
+       {
+               mask = BITMASK << ipad;
+               *(VARBITS(result) + VARBITBYTES(result) - 1) &= mask;
+       }
+
+       PG_RETURN_VARBIT_P(result);
 }
 
 /*
@@ -459,6 +500,10 @@ Datum
 varbit_recv(PG_FUNCTION_ARGS)
 {
        StringInfo      buf = (StringInfo) PG_GETARG_POINTER(0);
+#ifdef NOT_USED
+       Oid                     typelem = PG_GETARG_OID(1);
+#endif
+       int32           atttypmod = PG_GETARG_INT32(2);
        VarBit     *result;
        int                     len,
                                bitlen;
@@ -471,6 +516,16 @@ varbit_recv(PG_FUNCTION_ARGS)
                                (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
                                 errmsg("invalid length in external bit string")));
 
+       /*
+        * Sometimes atttypmod is not supplied. If it is supplied we need to
+        * make sure that the bitstring fits.
+        */
+       if (atttypmod > 0 && bitlen > atttypmod)
+               ereport(ERROR,
+                               (errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION),
+                                errmsg("bit string too long for type bit varying(%d)",
+                                               atttypmod)));
+
        len = VARBITTOTALLEN(bitlen);
        result = (VarBit *) palloc(len);
        VARATT_SIZEP(result) = len;
index 6d89b3df2f70b9ed488d080804ba7984623eaeea..5c5c1075c71a0a9d4fab6b7a3e64674ddb6dbf13 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/utils/adt/varchar.c,v 1.110 2005/05/29 20:15:59 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/utils/adt/varchar.c,v 1.111 2005/07/10 21:13:59 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -16,6 +16,8 @@
 
 #include "access/hash.h"
 #include "catalog/pg_type.h"
+#include "lib/stringinfo.h"
+#include "libpq/pqformat.h"
 #include "miscadmin.h"
 #include "utils/array.h"
 #include "utils/builtins.h"
  *****************************************************************************/
 
 /*
- * Convert a C string to CHARACTER internal representation.  atttypmod
- * is the declared length of the type plus VARHDRSZ.
+ * bpchar_input -- common guts of bpcharin and bpcharrecv
+ *
+ * s is the input text of length len (may not be null-terminated)
+ * atttypmod is the typmod value to apply
  *
- * If the C string is too long, raise an error, unless the extra
+ * Note that atttypmod is measured in characters, which
+ * is not necessarily the same as the number of bytes.
+ *
+ * If the input string is too long, raise an error, unless the extra
  * characters are spaces, in which case they're truncated.  (per SQL)
  */
-Datum
-bpcharin(PG_FUNCTION_ARGS)
+static BpChar *
+bpchar_input(const char *s, size_t len, int32 atttypmod)
 {
-       char       *s = PG_GETARG_CSTRING(0);
-
-#ifdef NOT_USED
-       Oid                     typelem = PG_GETARG_OID(1);
-#endif
-       int32           atttypmod = PG_GETARG_INT32(2);
        BpChar     *result;
        char       *r;
-       size_t          len,
-                               maxlen;
+       size_t          maxlen;
 
        /* verify encoding */
-       len = strlen(s);
        pg_verifymbstr(s, len, false);
 
        /* If typmod is -1 (or invalid), use the actual string length */
@@ -85,30 +84,32 @@ bpcharin(PG_FUNCTION_ARGS)
                size_t          charlen;                /* number of CHARACTERS in the input */
 
                maxlen = atttypmod - VARHDRSZ;
-               charlen = pg_mbstrlen(s);
+               charlen = pg_mbstrlen_with_len(s, len);
                if (charlen > maxlen)
                {
                        /* Verify that extra characters are spaces, and clip them off */
                        size_t          mbmaxlen = pg_mbcharcliplen(s, len, maxlen);
+                       size_t          j;
 
                        /*
                         * at this point, len is the actual BYTE length of the input
                         * string, maxlen is the max number of CHARACTERS allowed for this
-                        * bpchar type.
+                        * bpchar type, mbmaxlen is the length in BYTES of those chars.
                         */
-                       if (strspn(s + mbmaxlen, " ") == len - mbmaxlen)
-                               len = mbmaxlen;
-                       else
-                               ereport(ERROR,
-                                               (errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION),
-                                                errmsg("value too long for type character(%d)",
-                                                               (int) maxlen)));
+                       for (j = mbmaxlen; j < len; j++)
+                       {
+                               if (s[j] != ' ')
+                                       ereport(ERROR,
+                                                       (errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION),
+                                                        errmsg("value too long for type character(%d)",
+                                                                       (int) maxlen)));
+                       }
 
                        /*
                         * Now we set maxlen to the necessary byte length, not
                         * the number of CHARACTERS!
                         */
-                       maxlen = len;
+                       maxlen = len = mbmaxlen;
                }
                else
                {
@@ -120,7 +121,7 @@ bpcharin(PG_FUNCTION_ARGS)
                }
        }
 
-       result = palloc(maxlen + VARHDRSZ);
+       result = (BpChar *) palloc(maxlen + VARHDRSZ);
        VARATT_SIZEP(result) = maxlen + VARHDRSZ;
        r = VARDATA(result);
        memcpy(r, s, len);
@@ -129,6 +130,24 @@ bpcharin(PG_FUNCTION_ARGS)
        if (maxlen > len)
                memset(r + len, ' ', maxlen - len);
 
+       return result;
+}
+
+/*
+ * Convert a C string to CHARACTER internal representation.  atttypmod
+ * is the declared length of the type plus VARHDRSZ.
+ */
+Datum
+bpcharin(PG_FUNCTION_ARGS)
+{
+       char       *s = PG_GETARG_CSTRING(0);
+#ifdef NOT_USED
+       Oid                     typelem = PG_GETARG_OID(1);
+#endif
+       int32           atttypmod = PG_GETARG_INT32(2);
+       BpChar     *result;
+
+       result = bpchar_input(s, strlen(s), atttypmod);
        PG_RETURN_BPCHAR_P(result);
 }
 
@@ -158,8 +177,19 @@ bpcharout(PG_FUNCTION_ARGS)
 Datum
 bpcharrecv(PG_FUNCTION_ARGS)
 {
-       /* Exactly the same as textrecv, so share code */
-       return textrecv(fcinfo);
+       StringInfo      buf = (StringInfo) PG_GETARG_POINTER(0);
+#ifdef NOT_USED
+       Oid                     typelem = PG_GETARG_OID(1);
+#endif
+       int32           atttypmod = PG_GETARG_INT32(2);
+       BpChar     *result;
+       char       *str;
+       int                     nbytes;
+
+       str = pq_getmsgtext(buf, buf->len - buf->cursor, &nbytes);
+       result = bpchar_input(str, nbytes, atttypmod);
+       pfree(str);
+       PG_RETURN_BPCHAR_P(result);
 }
 
 /*
@@ -344,30 +374,24 @@ name_bpchar(PG_FUNCTION_ARGS)
  *****************************************************************************/
 
 /*
- * Convert a C string to VARCHAR internal representation.  atttypmod
- * is the declared length of the type plus VARHDRSZ.
+ * varchar_input -- common guts of varcharin and varcharrecv
+ *
+ * s is the input text of length len (may not be null-terminated)
+ * atttypmod is the typmod value to apply
  *
- * Note that atttypmod is regarded as the number of characters, which
+ * Note that atttypmod is measured in characters, which
  * is not necessarily the same as the number of bytes.
  *
- * If the C string is too long, raise an error, unless the extra characters
- * are spaces, in which case they're truncated.  (per SQL)
+ * If the input string is too long, raise an error, unless the extra
+ * characters are spaces, in which case they're truncated.  (per SQL)
  */
-Datum
-varcharin(PG_FUNCTION_ARGS)
+static VarChar *
+varchar_input(const char *s, size_t len, int32 atttypmod)
 {
-       char       *s = PG_GETARG_CSTRING(0);
-
-#ifdef NOT_USED
-       Oid                     typelem = PG_GETARG_OID(1);
-#endif
-       int32           atttypmod = PG_GETARG_INT32(2);
        VarChar    *result;
-       size_t          len,
-                               maxlen;
+       size_t          maxlen;
 
        /* verify encoding */
-       len = strlen(s);
        pg_verifymbstr(s, len, false);
 
        maxlen = atttypmod - VARHDRSZ;
@@ -376,20 +400,42 @@ varcharin(PG_FUNCTION_ARGS)
        {
                /* Verify that extra characters are spaces, and clip them off */
                size_t          mbmaxlen = pg_mbcharcliplen(s, len, maxlen);
+               size_t          j;
 
-               if (strspn(s + mbmaxlen, " ") == len - mbmaxlen)
-                       len = mbmaxlen;
-               else
-                       ereport(ERROR,
-                                       (errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION),
-                                 errmsg("value too long for type character varying(%d)",
-                                                (int) maxlen)));
+               for (j = mbmaxlen; j < len; j++)
+               {
+                       if (s[j] != ' ')
+                               ereport(ERROR,
+                                               (errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION),
+                                                errmsg("value too long for type character varying(%d)",
+                                                               (int) maxlen)));
+               }
+
+               len = mbmaxlen;
        }
 
-       result = palloc(len + VARHDRSZ);
+       result = (VarChar *) palloc(len + VARHDRSZ);
        VARATT_SIZEP(result) = len + VARHDRSZ;
        memcpy(VARDATA(result), s, len);
 
+       return result;
+}
+
+/*
+ * Convert a C string to VARCHAR internal representation.  atttypmod
+ * is the declared length of the type plus VARHDRSZ.
+ */
+Datum
+varcharin(PG_FUNCTION_ARGS)
+{
+       char       *s = PG_GETARG_CSTRING(0);
+#ifdef NOT_USED
+       Oid                     typelem = PG_GETARG_OID(1);
+#endif
+       int32           atttypmod = PG_GETARG_INT32(2);
+       VarChar    *result;
+
+       result = varchar_input(s, strlen(s), atttypmod);
        PG_RETURN_VARCHAR_P(result);
 }
 
@@ -419,8 +465,19 @@ varcharout(PG_FUNCTION_ARGS)
 Datum
 varcharrecv(PG_FUNCTION_ARGS)
 {
-       /* Exactly the same as textrecv, so share code */
-       return textrecv(fcinfo);
+       StringInfo      buf = (StringInfo) PG_GETARG_POINTER(0);
+#ifdef NOT_USED
+       Oid                     typelem = PG_GETARG_OID(1);
+#endif
+       int32           atttypmod = PG_GETARG_INT32(2);
+       VarChar    *result;
+       char       *str;
+       int                     nbytes;
+
+       str = pq_getmsgtext(buf, buf->len - buf->cursor, &nbytes);
+       result = varchar_input(str, nbytes, atttypmod);
+       pfree(str);
+       PG_RETURN_VARCHAR_P(result);
 }
 
 /*
index ba40747df41c4a0c3bbcaa6bbd1f0e73c9f06432..9b57a497a1d713169dbbe09ab356fb6f8c9777c2 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/utils/adt/varlena.c,v 1.127 2005/07/10 04:54:30 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/utils/adt/varlena.c,v 1.128 2005/07/10 21:13:59 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -299,6 +299,10 @@ textrecv(PG_FUNCTION_ARGS)
        int                     nbytes;
 
        str = pq_getmsgtext(buf, buf->len - buf->cursor, &nbytes);
+
+       /* verify encoding */
+       pg_verifymbstr(str, nbytes, false);
+
        result = (text *) palloc(nbytes + VARHDRSZ);
        VARATT_SIZEP(result) = nbytes + VARHDRSZ;
        memcpy(VARDATA(result), str, nbytes);
index 541f9c2a5d302a6e1611bca9c9aade540d63cc26..a670bcce624c975825b8806c2bd31d8de4dd5dc3 100644 (file)
@@ -4,7 +4,7 @@
  * (currently mule internal code (mic) is used)
  * Tatsuo Ishii
  *
- * $PostgreSQL: pgsql/src/backend/utils/mb/mbutils.c,v 1.49 2005/03/07 04:30:52 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/mb/mbutils.c,v 1.50 2005/07/10 21:13:59 tgl Exp $
  */
 #include "postgres.h"
 
@@ -489,16 +489,21 @@ pg_mbstrlen(const unsigned char *mbstr)
 }
 
 /* returns the length (counted as a wchar) of a multibyte string
-   (not necessarily  NULL terminated) */
+ * (not necessarily NULL terminated)
+ */
 int
 pg_mbstrlen_with_len(const unsigned char *mbstr, int limit)
 {
        int                     len = 0;
-       int                     l;
+
+       /* optimization for single byte encoding */
+       if (pg_database_encoding_max_length() == 1)
+               return limit;
 
        while (limit > 0 && *mbstr)
        {
-               l = pg_mblen(mbstr);
+               int             l = pg_mblen(mbstr);
+
                limit -= l;
                mbstr += l;
                len++;
index 3452b246d17537adfb02e56891ccd7ea5178d805..5ce6b4724e12f905e57a4f761f7671a07a4a385d 100644 (file)
@@ -37,7 +37,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.287 2005/07/10 04:54:31 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.288 2005/07/10 21:13:59 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -53,6 +53,6 @@
  */
 
 /*                                                     yyyymmddN */
-#define CATALOG_VERSION_NO     200507101
+#define CATALOG_VERSION_NO     200507102
 
 #endif
index 9ea413a6f541c3bf59e652c0015e594d1c241a8a..f0ecaa9d9baebeefbb1ff2d3a12f8fc2e092036c 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.375 2005/07/10 04:54:31 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.376 2005/07/10 21:13:59 tgl Exp $
  *
  * NOTES
  *       The script catalog/genbki.sh reads this file and generates .bki
@@ -3236,7 +3236,7 @@ DESCR("current user privilege on tablespace by tablespace name");
 DATA(insert OID = 2395 (  has_tablespace_privilege                PGNSP PGUID 12 f f t f s 2 16 "26 25" _null_ _null_ _null_ has_tablespace_privilege_id - _null_ ));
 DESCR("current user privilege on tablespace by tablespace oid");
 
-DATA(insert OID = 2290 (  record_in                    PGNSP PGUID 12 f f t f v 2 2249 "2275 26" _null_ _null_ _null_  record_in - _null_ ));
+DATA(insert OID = 2290 (  record_in                    PGNSP PGUID 12 f f t f v 3 2249 "2275 26 23" _null_ _null_ _null_       record_in - _null_ ));
 DESCR("I/O");
 DATA(insert OID = 2291 (  record_out           PGNSP PGUID 12 f f t f v 1 2275 "2249" _null_ _null_ _null_     record_out - _null_ ));
 DESCR("I/O");
@@ -3377,11 +3377,11 @@ DESCR("less-equal-greater");
 
 
 /* send/receive functions */
-DATA(insert OID = 2400 (  array_recv              PGNSP PGUID 12 f f t f s 2 2277 "2281 26" _null_ _null_ _null_  array_recv - _null_ ));
+DATA(insert OID = 2400 (  array_recv              PGNSP PGUID 12 f f t f s 3 2277 "2281 26 23" _null_ _null_ _null_  array_recv - _null_ ));
 DESCR("I/O");
 DATA(insert OID = 2401 (  array_send              PGNSP PGUID 12 f f t f s 1 17 "2277" _null_ _null_ _null_    array_send - _null_ ));
 DESCR("I/O");
-DATA(insert OID = 2402 (  record_recv             PGNSP PGUID 12 f f t f v 2 2249 "2281 26" _null_ _null_ _null_  record_recv - _null_ ));
+DATA(insert OID = 2402 (  record_recv             PGNSP PGUID 12 f f t f v 3 2249 "2281 26 23" _null_ _null_ _null_  record_recv - _null_ ));
 DESCR("I/O");
 DATA(insert OID = 2403 (  record_send             PGNSP PGUID 12 f f t f v 1 17 "2249" _null_ _null_ _null_  record_send - _null_ ));
 DESCR("I/O");
@@ -3437,11 +3437,11 @@ DATA(insert OID = 2428 (  point_recv               PGNSP PGUID 12 f f t f i 1 600 "2281" _
 DESCR("I/O");
 DATA(insert OID = 2429 (  point_send              PGNSP PGUID 12 f f t f i 1 17 "600" _null_ _null_ _null_     point_send - _null_ ));
 DESCR("I/O");
-DATA(insert OID = 2430 (  bpcharrecv              PGNSP PGUID 12 f f t f s 1 1042 "2281" _null_ _null_ _null_  bpcharrecv - _null_ ));
+DATA(insert OID = 2430 (  bpcharrecv              PGNSP PGUID 12 f f t f s 3 1042 "2281 26 23" _null_ _null_ _null_  bpcharrecv - _null_ ));
 DESCR("I/O");
 DATA(insert OID = 2431 (  bpcharsend              PGNSP PGUID 12 f f t f s 1 17 "1042" _null_ _null_ _null_    bpcharsend - _null_ ));
 DESCR("I/O");
-DATA(insert OID = 2432 (  varcharrecv             PGNSP PGUID 12 f f t f s 1 1043 "2281" _null_ _null_ _null_  varcharrecv - _null_ ));
+DATA(insert OID = 2432 (  varcharrecv             PGNSP PGUID 12 f f t f s 3 1043 "2281 26 23" _null_ _null_ _null_  varcharrecv - _null_ ));
 DESCR("I/O");
 DATA(insert OID = 2433 (  varcharsend             PGNSP PGUID 12 f f t f s 1 17 "1043" _null_ _null_ _null_    varcharsend - _null_ ));
 DESCR("I/O");
@@ -3489,15 +3489,15 @@ DATA(insert OID = 2454 (  regtyperecv              PGNSP PGUID 12 f f t f i 1 2206 "2281"
 DESCR("I/O");
 DATA(insert OID = 2455 (  regtypesend             PGNSP PGUID 12 f f t f i 1 17 "2206" _null_ _null_ _null_    regtypesend - _null_ ));
 DESCR("I/O");
-DATA(insert OID = 2456 (  bit_recv                        PGNSP PGUID 12 f f t f i 1 1560 "2281" _null_ _null_ _null_  bit_recv - _null_ ));
+DATA(insert OID = 2456 (  bit_recv                        PGNSP PGUID 12 f f t f i 3 1560 "2281 26 23" _null_ _null_ _null_  bit_recv - _null_ ));
 DESCR("I/O");
 DATA(insert OID = 2457 (  bit_send                        PGNSP PGUID 12 f f t f i 1 17 "1560" _null_ _null_ _null_    bit_send - _null_ ));
 DESCR("I/O");
-DATA(insert OID = 2458 (  varbit_recv             PGNSP PGUID 12 f f t f i 1 1562 "2281" _null_ _null_ _null_  varbit_recv - _null_ ));
+DATA(insert OID = 2458 (  varbit_recv             PGNSP PGUID 12 f f t f i 3 1562 "2281 26 23" _null_ _null_ _null_  varbit_recv - _null_ ));
 DESCR("I/O");
 DATA(insert OID = 2459 (  varbit_send             PGNSP PGUID 12 f f t f i 1 17 "1562" _null_ _null_ _null_    varbit_send - _null_ ));
 DESCR("I/O");
-DATA(insert OID = 2460 (  numeric_recv            PGNSP PGUID 12 f f t f i 1 1700 "2281" _null_ _null_ _null_  numeric_recv - _null_ ));
+DATA(insert OID = 2460 (  numeric_recv            PGNSP PGUID 12 f f t f i 3 1700 "2281 26 23" _null_ _null_ _null_  numeric_recv - _null_ ));
 DESCR("I/O");
 DATA(insert OID = 2461 (  numeric_send            PGNSP PGUID 12 f f t f i 1 17 "1700" _null_ _null_ _null_    numeric_send - _null_ ));
 DESCR("I/O");
@@ -3517,23 +3517,23 @@ DATA(insert OID = 2468 (  date_recv                        PGNSP PGUID 12 f f t f i 1 1082 "2281"
 DESCR("I/O");
 DATA(insert OID = 2469 (  date_send                       PGNSP PGUID 12 f f t f i 1 17 "1082" _null_ _null_ _null_    date_send - _null_ ));
 DESCR("I/O");
-DATA(insert OID = 2470 (  time_recv                       PGNSP PGUID 12 f f t f i 1 1083 "2281" _null_ _null_ _null_  time_recv - _null_ ));
+DATA(insert OID = 2470 (  time_recv                       PGNSP PGUID 12 f f t f i 3 1083 "2281 26 23" _null_ _null_ _null_  time_recv - _null_ ));
 DESCR("I/O");
 DATA(insert OID = 2471 (  time_send                       PGNSP PGUID 12 f f t f i 1 17 "1083" _null_ _null_ _null_    time_send - _null_ ));
 DESCR("I/O");
-DATA(insert OID = 2472 (  timetz_recv             PGNSP PGUID 12 f f t f i 1 1266 "2281" _null_ _null_ _null_  timetz_recv - _null_ ));
+DATA(insert OID = 2472 (  timetz_recv             PGNSP PGUID 12 f f t f i 3 1266 "2281 26 23" _null_ _null_ _null_  timetz_recv - _null_ ));
 DESCR("I/O");
 DATA(insert OID = 2473 (  timetz_send             PGNSP PGUID 12 f f t f i 1 17 "1266" _null_ _null_ _null_    timetz_send - _null_ ));
 DESCR("I/O");
-DATA(insert OID = 2474 (  timestamp_recv          PGNSP PGUID 12 f f t f i 1 1114 "2281" _null_ _null_ _null_  timestamp_recv - _null_ ));
+DATA(insert OID = 2474 (  timestamp_recv          PGNSP PGUID 12 f f t f i 3 1114 "2281 26 23" _null_ _null_ _null_  timestamp_recv - _null_ ));
 DESCR("I/O");
 DATA(insert OID = 2475 (  timestamp_send          PGNSP PGUID 12 f f t f i 1 17 "1114" _null_ _null_ _null_    timestamp_send - _null_ ));
 DESCR("I/O");
-DATA(insert OID = 2476 (  timestamptz_recv        PGNSP PGUID 12 f f t f i 1 1184 "2281" _null_ _null_ _null_  timestamptz_recv - _null_ ));
+DATA(insert OID = 2476 (  timestamptz_recv        PGNSP PGUID 12 f f t f i 3 1184 "2281 26 23" _null_ _null_ _null_  timestamptz_recv - _null_ ));
 DESCR("I/O");
 DATA(insert OID = 2477 (  timestamptz_send        PGNSP PGUID 12 f f t f i 1 17 "1184" _null_ _null_ _null_    timestamptz_send - _null_ ));
 DESCR("I/O");
-DATA(insert OID = 2478 (  interval_recv                   PGNSP PGUID 12 f f t f i 1 1186 "2281" _null_ _null_ _null_  interval_recv - _null_ ));
+DATA(insert OID = 2478 (  interval_recv                   PGNSP PGUID 12 f f t f i 3 1186 "2281 26 23" _null_ _null_ _null_  interval_recv - _null_ ));
 DESCR("I/O");
 DATA(insert OID = 2479 (  interval_send                   PGNSP PGUID 12 f f t f i 1 17 "1186" _null_ _null_ _null_    interval_send - _null_ ));
 DESCR("I/O");
index 0eb6bb8e9613c53af17562842b5f0609c86ba866..73d51925c2ffaab57d4327dba2819f1fbf9f2d16 100644 (file)
@@ -69,11 +69,10 @@ WHERE p1.typtype in ('b') AND p1.typname NOT LIKE E'\\_%' AND NOT EXISTS
  705 | unknown
 (2 rows)
 
--- Conversion routines must be provided except in 'c' entries.
+-- Text conversion routines must be provided.
 SELECT p1.oid, p1.typname
 FROM pg_type as p1
-WHERE p1.typtype != 'c' AND
-    (p1.typinput = 0 OR p1.typoutput = 0);
+WHERE (p1.typinput = 0 OR p1.typoutput = 0);
  oid | typname 
 -----+---------
 (0 rows)
@@ -83,8 +82,6 @@ SELECT p1.oid, p1.typname, p2.oid, p2.proname
 FROM pg_type AS p1, pg_proc AS p2
 WHERE p1.typinput = p2.oid AND p1.typtype in ('b', 'p') AND NOT
     ((p2.pronargs = 1 AND p2.proargtypes[0] = 'cstring'::regtype) OR
-     (p2.pronargs = 2 AND p2.proargtypes[0] = 'cstring'::regtype AND
-      p2.proargtypes[1] = 'oid'::regtype) OR
      (p2.pronargs = 3 AND p2.proargtypes[0] = 'cstring'::regtype AND
       p2.proargtypes[1] = 'oid'::regtype AND
       p2.proargtypes[2] = 'int4'::regtype));
@@ -148,8 +145,9 @@ SELECT p1.oid, p1.typname, p2.oid, p2.proname
 FROM pg_type AS p1, pg_proc AS p2
 WHERE p1.typreceive = p2.oid AND p1.typtype in ('b', 'p') AND NOT
     ((p2.pronargs = 1 AND p2.proargtypes[0] = 'internal'::regtype) OR
-     (p2.pronargs = 2 AND p2.proargtypes[0] = 'internal'::regtype AND
-      p2.proargtypes[1] = 'oid'::regtype));
+     (p2.pronargs = 3 AND p2.proargtypes[0] = 'internal'::regtype AND
+      p2.proargtypes[1] = 'oid'::regtype AND
+      p2.proargtypes[2] = 'int4'::regtype));
  oid | typname | oid | proname 
 -----+---------+-----+---------
 (0 rows)
@@ -181,6 +179,15 @@ ORDER BY 1;
   30 | oidvector  | 2420 | oidvectorrecv
 (2 rows)
 
+-- Suspicious if typreceive doesn't take same number of args as typinput
+SELECT p1.oid, p1.typname, p2.oid, p2.proname, p3.oid, p3.proname
+FROM pg_type AS p1, pg_proc AS p2, pg_proc AS p3
+WHERE p1.typinput = p2.oid AND p1.typreceive = p3.oid AND
+    p2.pronargs != p3.pronargs;
+ oid | typname | oid | proname | oid | proname 
+-----+---------+-----+---------+-----+---------
+(0 rows)
+
 -- Check for bogus typsend routines
 -- As of 7.4, this check finds refcursor, which is borrowing
 -- other types' I/O routines
index 20f6a75ffae9f5ad6af61a775cce828f0f0f104b..3969b4cce2ef4808dcfeac26d294cf6a30d13f5a 100644 (file)
@@ -59,12 +59,11 @@ WHERE p1.typtype in ('b') AND p1.typname NOT LIKE E'\\_%' AND NOT EXISTS
      WHERE p2.typname = ('_' || p1.typname)::name AND
            p2.typelem = p1.oid);
 
--- Conversion routines must be provided except in 'c' entries.
+-- Text conversion routines must be provided.
 
 SELECT p1.oid, p1.typname
 FROM pg_type as p1
-WHERE p1.typtype != 'c' AND
-    (p1.typinput = 0 OR p1.typoutput = 0);
+WHERE (p1.typinput = 0 OR p1.typoutput = 0);
 
 -- Check for bogus typinput routines
 
@@ -72,8 +71,6 @@ SELECT p1.oid, p1.typname, p2.oid, p2.proname
 FROM pg_type AS p1, pg_proc AS p2
 WHERE p1.typinput = p2.oid AND p1.typtype in ('b', 'p') AND NOT
     ((p2.pronargs = 1 AND p2.proargtypes[0] = 'cstring'::regtype) OR
-     (p2.pronargs = 2 AND p2.proargtypes[0] = 'cstring'::regtype AND
-      p2.proargtypes[1] = 'oid'::regtype) OR
      (p2.pronargs = 3 AND p2.proargtypes[0] = 'cstring'::regtype AND
       p2.proargtypes[1] = 'oid'::regtype AND
       p2.proargtypes[2] = 'int4'::regtype));
@@ -120,8 +117,9 @@ SELECT p1.oid, p1.typname, p2.oid, p2.proname
 FROM pg_type AS p1, pg_proc AS p2
 WHERE p1.typreceive = p2.oid AND p1.typtype in ('b', 'p') AND NOT
     ((p2.pronargs = 1 AND p2.proargtypes[0] = 'internal'::regtype) OR
-     (p2.pronargs = 2 AND p2.proargtypes[0] = 'internal'::regtype AND
-      p2.proargtypes[1] = 'oid'::regtype));
+     (p2.pronargs = 3 AND p2.proargtypes[0] = 'internal'::regtype AND
+      p2.proargtypes[1] = 'oid'::regtype AND
+      p2.proargtypes[2] = 'int4'::regtype));
 
 -- As of 7.4, this check finds refcursor, which is borrowing
 -- other types' I/O routines
@@ -141,6 +139,12 @@ WHERE p1.typreceive = p2.oid AND p1.typtype in ('b', 'p') AND
     (p2.oid = 'array_recv'::regproc)
 ORDER BY 1;
 
+-- Suspicious if typreceive doesn't take same number of args as typinput
+SELECT p1.oid, p1.typname, p2.oid, p2.proname, p3.oid, p3.proname
+FROM pg_type AS p1, pg_proc AS p2, pg_proc AS p3
+WHERE p1.typinput = p2.oid AND p1.typreceive = p3.oid AND
+    p2.pronargs != p3.pronargs;
+
 -- Check for bogus typsend routines
 
 -- As of 7.4, this check finds refcursor, which is borrowing