Add support for user-defined I/O conversion casts.
authorHeikki Linnakangas
Fri, 31 Oct 2008 08:39:22 +0000 (08:39 +0000)
committerHeikki Linnakangas
Fri, 31 Oct 2008 08:39:22 +0000 (08:39 +0000)
14 files changed:
doc/src/sgml/catalogs.sgml
doc/src/sgml/ref/create_cast.sgml
src/backend/commands/functioncmds.c
src/backend/nodes/copyfuncs.c
src/backend/nodes/equalfuncs.c
src/backend/parser/gram.y
src/backend/parser/parse_coerce.c
src/bin/pg_dump/pg_dump.c
src/bin/pg_dump/pg_dump.h
src/include/catalog/catversion.h
src/include/catalog/pg_cast.h
src/include/nodes/parsenodes.h
src/test/regress/expected/opr_sanity.out
src/test/regress/sql/opr_sanity.sql

index a68799334add93bb962b4d47d106f6871606ee0e..faee42ba1036d6e6faeec720946ce523ce6570f7 100644 (file)
@@ -1,4 +1,4 @@
-
+
 
    cannot be deduced from some generic rule.  For example, casting between a
    domain and its base type is not explicitly represented in
    pg_cast.  Another important exception is that
-   I/O conversion casts, those performed using a data type's own
-   I/O functions to convert to or from text or other string types,
-   are not explicitly represented in pg_cast.
+   automatic I/O conversion casts, those performed using a data
+   type's own I/O functions to convert to or from text or other
+   string types, are not explicitly represented in
+   pg_cast.
   
 
   
       pg_proc.oid
       
        The OID of the function to use to perform this cast.  Zero is
-       stored if the data types are binary coercible (that is, no
-       run-time operation is needed to perform the cast)
+       stored if the cast method doesn't require a function.
       
      
 
        other cases
       
      
+     
+      castmethod
+      char
+      
+      
+       Indicates how the cast is performed.
+       f means that the function specified in the castfunc field is used.
+       i means that the input/output functions are used.
+       b means that the types are binary-coercible, thus no conversion is required
+      
+     
     
    
   
index 080f31832d2e92d9d1cfbd731565dae95f7146b4..c771d22ad9480ef50cec04d8e489ad27dea894a3 100644 (file)
@@ -1,4 +1,4 @@
-
+
 
 
  
@@ -24,6 +24,10 @@ CREATE CAST (sourcetype AS targettype
 CREATE CAST (sourcetype AS targettype)
     WITHOUT FUNCTION
     [ AS ASSIGNMENT | AS IMPLICIT ]
+
+CREATE CAST (sourcetype AS targettype)
+    WITH INOUT
+    [ AS ASSIGNMENT | AS IMPLICIT ]
 
  
 
@@ -58,6 +62,13 @@ SELECT CAST(42 AS float8);
    binary compatible.)
   
 
+  
+   You can define a cast as an I/O conversion cast using
+   the WITH INOUT syntax. An I/O conversion cast is
+   performed by invoking the output function of the source data type, and
+   passing the result to the input function of the target data type.
+  
+
   
    By default, a cast can be invoked only by an explicit cast request,
    that is an explicit CAST(x AS
@@ -199,6 +210,18 @@ SELECT CAST ( 2 AS numeric ) + 4.0;
      
     
 
+    
+     WITH INOUT
+
+     
+      
+       Indicates that the cast is an I/O conversion cast, performed by
+       invoking the output function of the source data type, and passing the
+       result to the input function of the target data type.
+      
+     
+    
+
     
      AS ASSIGNMENT
 
@@ -284,15 +307,12 @@ SELECT CAST ( 2 AS numeric ) + 4.0;
    It is normally not necessary to create casts between user-defined types
    and the standard string types (text, varchar, and
    char(n), as well as user-defined types that
-   are defined to be in the string category).  PostgreSQL will
-   automatically handle a cast to a string type by invoking the other
-   type's output function, or conversely handle a cast from a string type
-   by invoking the other type's input function.  These
-   automatically-provided casts are known as I/O conversion
-   casts.  I/O conversion casts to string types are treated as
-   assignment casts, while I/O conversion casts from string types are
+   are defined to be in the string category).  PostgreSQL
+   provides automatic I/O conversion casts for that. The automatic casts to
+   string types are treated as assignment casts, while the automatic casts
+   from string types are
    explicit-only.  You can override this behavior by declaring your own
-   cast to replace an I/O conversion cast, but usually the only reason to
+   cast to replace an automatic cast, but usually the only reason to
    do so is if you want the conversion to be more easily invokable than the
    standard assignment-only or explicit-only setting.  Another possible
    reason is that you want the conversion to behave differently from the
index 12762b8aaabf56d9a9010904effaedbe462e9ada..80a57457ee506065824d278dbec918280b704c0c 100644 (file)
@@ -10,7 +10,7 @@
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/commands/functioncmds.c,v 1.99 2008/10/21 10:38:51 petere Exp $
+ *   $PostgreSQL: pgsql/src/backend/commands/functioncmds.c,v 1.100 2008/10/31 08:39:20 heikki Exp $
  *
  * DESCRIPTION
  *   These routines take the parse tree and pick out the
@@ -1383,6 +1383,7 @@ CreateCast(CreateCastStmt *stmt)
    Oid         funcid;
    int         nargs;
    char        castcontext;
+   char        castmethod;
    Relation    relation;
    HeapTuple   tuple;
    Datum       values[Natts_pg_cast];
@@ -1415,7 +1416,15 @@ CreateCast(CreateCastStmt *stmt)
                        format_type_be(sourcetypeid),
                        format_type_be(targettypeid))));
 
+   /* Detemine the cast method */
    if (stmt->func != NULL)
+       castmethod = COERCION_METHOD_FUNCTION;
+   else if(stmt->inout)
+       castmethod = COERCION_METHOD_INOUT;
+   else
+       castmethod = COERCION_METHOD_BINARY;
+
+   if (castmethod == COERCION_METHOD_FUNCTION)
    {
        Form_pg_proc procstruct;
 
@@ -1475,6 +1484,12 @@ CreateCast(CreateCastStmt *stmt)
        ReleaseSysCache(tuple);
    }
    else
+   {
+       funcid = InvalidOid;
+       nargs = 0;
+   }
+
+   if (castmethod == COERCION_METHOD_BINARY)
    {
        int16       typ1len;
        int16       typ2len;
@@ -1483,10 +1498,6 @@ CreateCast(CreateCastStmt *stmt)
        char        typ1align;
        char        typ2align;
 
-       /* indicates binary coercibility */
-       funcid = InvalidOid;
-       nargs = 0;
-
        /*
         * Must be superuser to create binary-compatible casts, since
         * erroneous casts can easily crash the backend.
@@ -1562,6 +1573,7 @@ CreateCast(CreateCastStmt *stmt)
    values[Anum_pg_cast_casttarget - 1] = ObjectIdGetDatum(targettypeid);
    values[Anum_pg_cast_castfunc - 1] = ObjectIdGetDatum(funcid);
    values[Anum_pg_cast_castcontext - 1] = CharGetDatum(castcontext);
+   values[Anum_pg_cast_castmethod - 1] = CharGetDatum(castmethod);
 
    MemSet(nulls, ' ', Natts_pg_cast);
 
index 2dce7bab18f28507d275154f829f2c9052e13d1a..d56075e6bbfab7090eebae52d1deb67214f03fcf 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.409 2008/10/21 20:42:52 tgl Exp $
+ *   $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.410 2008/10/31 08:39:20 heikki Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -3042,6 +3042,7 @@ _copyCreateCastStmt(CreateCastStmt *from)
    COPY_NODE_FIELD(targettype);
    COPY_NODE_FIELD(func);
    COPY_SCALAR_FIELD(context);
+   COPY_SCALAR_FIELD(inout);
 
    return newnode;
 }
index e0b8bdcecb1230ad8e75ca870ef10a5df6d1d10f..e17aff89228ce805856bb9784b9514619d79f502 100644 (file)
@@ -22,7 +22,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.334 2008/10/21 20:42:52 tgl Exp $
+ *   $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.335 2008/10/31 08:39:20 heikki Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1666,6 +1666,7 @@ _equalCreateCastStmt(CreateCastStmt *a, CreateCastStmt *b)
    COMPARE_NODE_FIELD(targettype);
    COMPARE_NODE_FIELD(func);
    COMPARE_SCALAR_FIELD(context);
+   COMPARE_SCALAR_FIELD(inout);
 
    return true;
 }
index 8b44e5b6ba4aebdd53b5b371a0aaf597585d9454..b78d5b302e38973471ae8f08689b58be094a4bf1 100644 (file)
@@ -11,7 +11,7 @@
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.632 2008/10/29 11:24:53 petere Exp $
+ *   $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.633 2008/10/31 08:39:20 heikki Exp $
  *
  * HISTORY
  *   AUTHOR            DATE            MAJOR EVENT
@@ -4590,6 +4590,7 @@ CreateCastStmt: CREATE CAST '(' Typename AS Typename ')'
                    n->targettype = $6;
                    n->func = $10;
                    n->context = (CoercionContext) $11;
+                   n->inout = false;
                    $$ = (Node *)n;
                }
            | CREATE CAST '(' Typename AS Typename ')'
@@ -4600,6 +4601,18 @@ CreateCastStmt: CREATE CAST '(' Typename AS Typename ')'
                    n->targettype = $6;
                    n->func = NULL;
                    n->context = (CoercionContext) $10;
+                   n->inout = false;
+                   $$ = (Node *)n;
+               }
+           | CREATE CAST '(' Typename AS Typename ')'
+                   WITH INOUT cast_context
+               {
+                   CreateCastStmt *n = makeNode(CreateCastStmt);
+                   n->sourcetype = $4;
+                   n->targettype = $6;
+                   n->func = NULL;
+                   n->context = (CoercionContext) $10;
+                   n->inout = true;
                    $$ = (Node *)n;
                }
        ;
index 6d703ae571884d9c5cba8252e99020ed7e5fd0a0..112a07beb581e5aed663924a22f1a48d5249a3f6 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/parser/parse_coerce.c,v 2.170 2008/10/25 17:19:09 tgl Exp $
+ *   $PostgreSQL: pgsql/src/backend/parser/parse_coerce.c,v 2.171 2008/10/31 08:39:21 heikki Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1909,11 +1909,23 @@ find_coercion_pathway(Oid targetTypeId, Oid sourceTypeId,
        /* Rely on ordering of enum for correct behavior here */
        if (ccontext >= castcontext)
        {
-           *funcid = castForm->castfunc;
-           if (OidIsValid(*funcid))
-               result = COERCION_PATH_FUNC;
-           else
-               result = COERCION_PATH_RELABELTYPE;
+           switch (castForm->castmethod)
+           {
+               case COERCION_METHOD_FUNCTION:
+                   result = COERCION_PATH_FUNC;
+                   *funcid = castForm->castfunc;
+                   break;
+               case COERCION_METHOD_INOUT:
+                   result = COERCION_PATH_COERCEVIAIO;
+                   break;
+               case COERCION_METHOD_BINARY:
+                   result = COERCION_PATH_RELABELTYPE;
+                   break;
+               default:
+                   elog(ERROR, "unrecognized castmethod: %d",
+                        (int) castForm->castmethod);
+                   break;
+           }
        }
 
        ReleaseSysCache(tuple);
index 074b647c338c43f07b9f75b927aac49e1d4096cd..ac05a4a5b70f2ec9ed7bd1aceb02abe7ffe1f3ff 100644 (file)
@@ -12,7 +12,7 @@
  * by PostgreSQL
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.502 2008/09/24 19:33:15 heikki Exp $
+ *   $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.503 2008/10/31 08:39:21 heikki Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -36,6 +36,7 @@ int           optreset;
 
 #include "access/attnum.h"
 #include "access/sysattr.h"
+#include "catalog/pg_cast.h"
 #include "catalog/pg_class.h"
 #include "catalog/pg_proc.h"
 #include "catalog/pg_trigger.h"
@@ -4410,21 +4411,31 @@ getCasts(int *numCasts)
    int         i_casttarget;
    int         i_castfunc;
    int         i_castcontext;
+   int         i_castmethod;
 
    /* Make sure we are in proper schema */
    selectSourceSchema("pg_catalog");
 
-   if (g_fout->remoteVersion >= 70300)
+   if (g_fout->remoteVersion >= 80400)
+   {
+       appendPQExpBuffer(query, "SELECT tableoid, oid, "
+                         "castsource, casttarget, castfunc, castcontext, "
+                         "castmethod "
+                         "FROM pg_cast ORDER BY 3,4");
+   }
+   else if (g_fout->remoteVersion >= 70300)
    {
        appendPQExpBuffer(query, "SELECT tableoid, oid, "
-                         "castsource, casttarget, castfunc, castcontext "
+                         "castsource, casttarget, castfunc, castcontext, "
+                         "CASE WHEN castfunc = 0 THEN 'b' ELSE 'f' END AS castmethod "
                          "FROM pg_cast ORDER BY 3,4");
    }
    else
    {
        appendPQExpBuffer(query, "SELECT 0 as tableoid, p.oid, "
                          "t1.oid as castsource, t2.oid as casttarget, "
-                         "p.oid as castfunc, 'e' as castcontext "
+                         "p.oid as castfunc, 'e' as castcontext, "
+                         "'f' as castmethod "
                          "FROM pg_type t1, pg_type t2, pg_proc p "
                          "WHERE p.pronargs = 1 AND "
                          "p.proargtypes[0] = t1.oid AND "
@@ -4447,6 +4458,7 @@ getCasts(int *numCasts)
    i_casttarget = PQfnumber(res, "casttarget");
    i_castfunc = PQfnumber(res, "castfunc");
    i_castcontext = PQfnumber(res, "castcontext");
+   i_castmethod = PQfnumber(res, "castmethod");
 
    for (i = 0; i < ntups; i++)
    {
@@ -4462,6 +4474,7 @@ getCasts(int *numCasts)
        castinfo[i].casttarget = atooid(PQgetvalue(res, i, i_casttarget));
        castinfo[i].castfunc = atooid(PQgetvalue(res, i, i_castfunc));
        castinfo[i].castcontext = *(PQgetvalue(res, i, i_castcontext));
+       castinfo[i].castmethod = *(PQgetvalue(res, i, i_castmethod));
 
        /*
         * Try to name cast as concatenation of typnames.  This is only used
@@ -7188,18 +7201,26 @@ dumpCast(Archive *fout, CastInfo *cast)
                      getFormattedTypeName(cast->castsource, zeroAsNone),
                      getFormattedTypeName(cast->casttarget, zeroAsNone));
 
-   if (!OidIsValid(cast->castfunc))
-       appendPQExpBuffer(defqry, "WITHOUT FUNCTION");
-   else
+   switch(cast->castmethod)
    {
-       /*
-        * Always qualify the function name, in case it is not in pg_catalog
-        * schema (format_function_signature won't qualify it).
-        */
-       appendPQExpBuffer(defqry, "WITH FUNCTION %s.",
-                         fmtId(funcInfo->dobj.namespace->dobj.name));
-       appendPQExpBuffer(defqry, "%s",
-                         format_function_signature(funcInfo, true));
+       case COERCION_METHOD_BINARY:
+           appendPQExpBuffer(defqry, "WITHOUT FUNCTION");
+           break;
+       case COERCION_METHOD_INOUT:
+           appendPQExpBuffer(defqry, "WITH INOUT");
+           break;
+       case COERCION_METHOD_FUNCTION:
+           /*
+            * Always qualify the function name, in case it is not in
+            * pg_catalog schema (format_function_signature won't qualify it).
+            */
+           appendPQExpBuffer(defqry, "WITH FUNCTION %s.",
+                             fmtId(funcInfo->dobj.namespace->dobj.name));
+           appendPQExpBuffer(defqry, "%s",
+                             format_function_signature(funcInfo, true));
+           break;
+       default:
+           write_msg(NULL, "WARNING: bogus value in pg_cast.castmethod field\n");
    }
 
    if (cast->castcontext == 'a')
index f443d9de590bffab4321bef37a82143225e3d50d..80f02efb2f12338dd205cea99a7bd1f02acbdef3 100644 (file)
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.h,v 1.141 2008/09/08 15:26:23 tgl Exp $
+ * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.h,v 1.142 2008/10/31 08:39:21 heikki Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -376,6 +376,7 @@ typedef struct _castInfo
    Oid         casttarget;
    Oid         castfunc;
    char        castcontext;
+   char        castmethod;
 } CastInfo;
 
 /* InhInfo isn't a DumpableObject, just temporary state */
index f242dcf469e813ca32897b9e335e734971beba01..3d0db7a461d172b6d4eae4218cb29355d2bd7e1d 100644 (file)
@@ -37,7 +37,7 @@
  * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.499 2008/10/17 22:10:30 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.500 2008/10/31 08:39:22 heikki Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -53,6 +53,6 @@
  */
 
 /*                         yyyymmddN */
-#define CATALOG_VERSION_NO 200810171
+#define CATALOG_VERSION_NO 200810311
 
 #endif
index 5ad101361c93410d55dcec1447d2960a59a98fe5..466815575fea0ae50f17f6a305ffffa23b60211d 100644 (file)
@@ -10,7 +10,7 @@
  *
  * Copyright (c) 2002-2008, PostgreSQL Global Development Group
  *
- * $PostgreSQL: pgsql/src/include/catalog/pg_cast.h,v 1.39 2008/03/27 03:57:34 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_cast.h,v 1.40 2008/10/31 08:39:22 heikki Exp $
  *
  * NOTES
  *   the genbki.sh script reads this file and generates .bki
@@ -36,6 +36,7 @@ CATALOG(pg_cast,2605)
    Oid         casttarget;     /* destination datatype for cast */
    Oid         castfunc;       /* cast function; 0 = binary coercible */
    char        castcontext;    /* contexts in which cast can be used */
+   char        castmethod;     /* cast method */
 } FormData_pg_cast;
 
 typedef FormData_pg_cast *Form_pg_cast;
@@ -56,16 +57,29 @@ typedef enum CoercionCodes
    COERCION_CODE_EXPLICIT = 'e'    /* explicit cast operation */
 } CoercionCodes;
 
+/*
+ * The allowable values for pg_cast.castmethod are specified by this enum.
+ * Since castcontext is stored as a "char", we use ASCII codes for human
+ * convenience in reading the table.
+ */
+typedef enum CoercionMethod
+{
+   COERCION_METHOD_FUNCTION = 'f',     /* use a function */
+   COERCION_METHOD_BINARY = 'b',       /* types are binary-compatible */
+   COERCION_METHOD_INOUT = 'i'         /* use input/output functions */
+} CoercionMethod;
+
 
 /* ----------------
  *     compiler constants for pg_cast
  * ----------------
  */
-#define Natts_pg_cast              4
+#define Natts_pg_cast              5
 #define Anum_pg_cast_castsource        1
 #define Anum_pg_cast_casttarget        2
 #define Anum_pg_cast_castfunc      3
 #define Anum_pg_cast_castcontext   4
+#define Anum_pg_cast_castmethod        5
 
 /* ----------------
  *     initial contents of pg_cast
@@ -80,40 +94,40 @@ typedef enum CoercionCodes
  * int2->int4->int8->numeric->float4->float8, while casts in the
  * reverse direction are assignment-only.
  */
-DATA(insert (  20   21  714 a ));
-DATA(insert (  20   23  480 a ));
-DATA(insert (  20  700  652 i ));
-DATA(insert (  20  701  482 i ));
-DATA(insert (  20 1700 1781 i ));
-DATA(insert (  21   20  754 i ));
-DATA(insert (  21   23  313 i ));
-DATA(insert (  21  700  236 i ));
-DATA(insert (  21  701  235 i ));
-DATA(insert (  21 1700 1782 i ));
-DATA(insert (  23   20  481 i ));
-DATA(insert (  23   21  314 a ));
-DATA(insert (  23  700  318 i ));
-DATA(insert (  23  701  316 i ));
-DATA(insert (  23 1700 1740 i ));
-DATA(insert (  700  20  653 a ));
-DATA(insert (  700  21  238 a ));
-DATA(insert (  700  23  319 a ));
-DATA(insert (  700 701  311 i ));
-DATA(insert (  700 1700 1742 a ));
-DATA(insert (  701  20  483 a ));
-DATA(insert (  701  21  237 a ));
-DATA(insert (  701  23  317 a ));
-DATA(insert (  701 700  312 a ));
-DATA(insert (  701 1700 1743 a ));
-DATA(insert ( 1700  20 1779 a ));
-DATA(insert ( 1700  21 1783 a ));
-DATA(insert ( 1700  23 1744 a ));
-DATA(insert ( 1700 700 1745 i ));
-DATA(insert ( 1700 701 1746 i ));
+DATA(insert (  20   21  714 a ));
+DATA(insert (  20   23  480 a ));
+DATA(insert (  20  700  652 i ));
+DATA(insert (  20  701  482 i ));
+DATA(insert (  20 1700 1781 i ));
+DATA(insert (  21   20  754 i ));
+DATA(insert (  21   23  313 i ));
+DATA(insert (  21  700  236 i ));
+DATA(insert (  21  701  235 i ));
+DATA(insert (  21 1700 1782 i ));
+DATA(insert (  23   20  481 i ));
+DATA(insert (  23   21  314 a ));
+DATA(insert (  23  700  318 i ));
+DATA(insert (  23  701  316 i ));
+DATA(insert (  23 1700 1740 i ));
+DATA(insert (  700  20  653 a ));
+DATA(insert (  700  21  238 a ));
+DATA(insert (  700  23  319 a ));
+DATA(insert (  700 701  311 i ));
+DATA(insert (  700 1700 1742 a ));
+DATA(insert (  701  20  483 a ));
+DATA(insert (  701  21  237 a ));
+DATA(insert (  701  23  317 a ));
+DATA(insert (  701 700  312 a ));
+DATA(insert (  701 1700 1743 a ));
+DATA(insert ( 1700  20 1779 a ));
+DATA(insert ( 1700  21 1783 a ));
+DATA(insert ( 1700  23 1744 a ));
+DATA(insert ( 1700 700 1745 i ));
+DATA(insert ( 1700 701 1746 i ));
 
 /* Allow explicit coercions between int4 and bool */
-DATA(insert (  23  16  2557 e ));
-DATA(insert (  16  23  2558 e ));
+DATA(insert (  23  16  2557 e ));
+DATA(insert (  16  23  2558 e ));
 
 /*
  * OID category: allow implicit conversion from any integral type (including
@@ -125,164 +139,164 @@ DATA(insert (   16  23  2558 e ));
  * casts from text and varchar to regclass, which exist mainly to support
  * legacy forms of nextval() and related functions.
  */
-DATA(insert (  20   26 1287 i ));
-DATA(insert (  21   26  313 i ));
-DATA(insert (  23   26    0 i ));
-DATA(insert (  26   20 1288 a ));
-DATA(insert (  26   23    0 a ));
-DATA(insert (  26   24    0 i ));
-DATA(insert (  24   26    0 i ));
-DATA(insert (  20   24 1287 i ));
-DATA(insert (  21   24  313 i ));
-DATA(insert (  23   24    0 i ));
-DATA(insert (  24   20 1288 a ));
-DATA(insert (  24   23    0 a ));
-DATA(insert (  24 2202    0 i ));
-DATA(insert ( 2202  24    0 i ));
-DATA(insert (  26 2202    0 i ));
-DATA(insert ( 2202  26    0 i ));
-DATA(insert (  20 2202 1287 i ));
-DATA(insert (  21 2202  313 i ));
-DATA(insert (  23 2202    0 i ));
-DATA(insert ( 2202  20 1288 a ));
-DATA(insert ( 2202  23    0 a ));
-DATA(insert (  26 2203    0 i ));
-DATA(insert ( 2203  26    0 i ));
-DATA(insert (  20 2203 1287 i ));
-DATA(insert (  21 2203  313 i ));
-DATA(insert (  23 2203    0 i ));
-DATA(insert ( 2203  20 1288 a ));
-DATA(insert ( 2203  23    0 a ));
-DATA(insert ( 2203 2204    0 i ));
-DATA(insert ( 2204 2203    0 i ));
-DATA(insert (  26 2204    0 i ));
-DATA(insert ( 2204  26    0 i ));
-DATA(insert (  20 2204 1287 i ));
-DATA(insert (  21 2204  313 i ));
-DATA(insert (  23 2204    0 i ));
-DATA(insert ( 2204  20 1288 a ));
-DATA(insert ( 2204  23    0 a ));
-DATA(insert (  26 2205    0 i ));
-DATA(insert ( 2205  26    0 i ));
-DATA(insert (  20 2205 1287 i ));
-DATA(insert (  21 2205  313 i ));
-DATA(insert (  23 2205    0 i ));
-DATA(insert ( 2205  20 1288 a ));
-DATA(insert ( 2205  23    0 a ));
-DATA(insert (  26 2206    0 i ));
-DATA(insert ( 2206  26    0 i ));
-DATA(insert (  20 2206 1287 i ));
-DATA(insert (  21 2206  313 i ));
-DATA(insert (  23 2206    0 i ));
-DATA(insert ( 2206  20 1288 a ));
-DATA(insert ( 2206  23    0 a ));
-DATA(insert (  26 3734    0 i ));
-DATA(insert ( 3734  26    0 i ));
-DATA(insert (  20 3734 1287 i ));
-DATA(insert (  21 3734  313 i ));
-DATA(insert (  23 3734    0 i ));
-DATA(insert ( 3734  20 1288 a ));
-DATA(insert ( 3734  23    0 a ));
-DATA(insert (  26 3769    0 i ));
-DATA(insert ( 3769  26    0 i ));
-DATA(insert (  20 3769 1287 i ));
-DATA(insert (  21 3769  313 i ));
-DATA(insert (  23 3769    0 i ));
-DATA(insert ( 3769  20 1288 a ));
-DATA(insert ( 3769  23    0 a ));
-DATA(insert (  25 2205 1079 i ));
-DATA(insert ( 1043 2205 1079 i ));
+DATA(insert (  20   26 1287 i ));
+DATA(insert (  21   26  313 i ));
+DATA(insert (  23   26    0 i ));
+DATA(insert (  26   20 1288 a ));
+DATA(insert (  26   23    0 a ));
+DATA(insert (  26   24    0 i ));
+DATA(insert (  24   26    0 i ));
+DATA(insert (  20   24 1287 i ));
+DATA(insert (  21   24  313 i ));
+DATA(insert (  23   24    0 i ));
+DATA(insert (  24   20 1288 a ));
+DATA(insert (  24   23    0 a ));
+DATA(insert (  24 2202    0 i ));
+DATA(insert ( 2202  24    0 i ));
+DATA(insert (  26 2202    0 i ));
+DATA(insert ( 2202  26    0 i ));
+DATA(insert (  20 2202 1287 i ));
+DATA(insert (  21 2202  313 i ));
+DATA(insert (  23 2202    0 i ));
+DATA(insert ( 2202  20 1288 a ));
+DATA(insert ( 2202  23    0 a ));
+DATA(insert (  26 2203    0 i ));
+DATA(insert ( 2203  26    0 i ));
+DATA(insert (  20 2203 1287 i ));
+DATA(insert (  21 2203  313 i ));
+DATA(insert (  23 2203    0 i ));
+DATA(insert ( 2203  20 1288 a ));
+DATA(insert ( 2203  23    0 a ));
+DATA(insert ( 2203 2204    0 i ));
+DATA(insert ( 2204 2203    0 i ));
+DATA(insert (  26 2204    0 i ));
+DATA(insert ( 2204  26    0 i ));
+DATA(insert (  20 2204 1287 i ));
+DATA(insert (  21 2204  313 i ));
+DATA(insert (  23 2204    0 i ));
+DATA(insert ( 2204  20 1288 a ));
+DATA(insert ( 2204  23    0 a ));
+DATA(insert (  26 2205    0 i ));
+DATA(insert ( 2205  26    0 i ));
+DATA(insert (  20 2205 1287 i ));
+DATA(insert (  21 2205  313 i ));
+DATA(insert (  23 2205    0 i ));
+DATA(insert ( 2205  20 1288 a ));
+DATA(insert ( 2205  23    0 a ));
+DATA(insert (  26 2206    0 i ));
+DATA(insert ( 2206  26    0 i ));
+DATA(insert (  20 2206 1287 i ));
+DATA(insert (  21 2206  313 i ));
+DATA(insert (  23 2206    0 i ));
+DATA(insert ( 2206  20 1288 a ));
+DATA(insert ( 2206  23    0 a ));
+DATA(insert (  26 3734    0 i ));
+DATA(insert ( 3734  26    0 i ));
+DATA(insert (  20 3734 1287 i ));
+DATA(insert (  21 3734  313 i ));
+DATA(insert (  23 3734    0 i ));
+DATA(insert ( 3734  20 1288 a ));
+DATA(insert ( 3734  23    0 a ));
+DATA(insert (  26 3769    0 i ));
+DATA(insert ( 3769  26    0 i ));
+DATA(insert (  20 3769 1287 i ));
+DATA(insert (  21 3769  313 i ));
+DATA(insert (  23 3769    0 i ));
+DATA(insert ( 3769  20 1288 a ));
+DATA(insert ( 3769  23    0 a ));
+DATA(insert (  25 2205 1079 i ));
+DATA(insert ( 1043 2205 1079 i ));
 
 /*
  * String category
  */
-DATA(insert (  25 1042    0 i ));
-DATA(insert (  25 1043    0 i ));
-DATA(insert ( 1042  25  401 i ));
-DATA(insert ( 1042 1043  401 i ));
-DATA(insert ( 1043  25    0 i ));
-DATA(insert ( 1043 1042    0 i ));
-DATA(insert (  18   25  946 i ));
-DATA(insert (  18 1042  860 a ));
-DATA(insert (  18 1043  946 a ));
-DATA(insert (  19   25  406 i ));
-DATA(insert (  19 1042  408 a ));
-DATA(insert (  19 1043 1401 a ));
-DATA(insert (  25   18  944 a ));
-DATA(insert ( 1042  18  944 a ));
-DATA(insert ( 1043  18  944 a ));
-DATA(insert (  25   19  407 i ));
-DATA(insert ( 1042  19  409 i ));
-DATA(insert ( 1043  19 1400 i ));
+DATA(insert (  25 1042    0 i ));
+DATA(insert (  25 1043    0 i ));
+DATA(insert ( 1042  25  401 i ));
+DATA(insert ( 1042 1043  401 i ));
+DATA(insert ( 1043  25    0 i ));
+DATA(insert ( 1043 1042    0 i ));
+DATA(insert (  18   25  946 i ));
+DATA(insert (  18 1042  860 a ));
+DATA(insert (  18 1043  946 a ));
+DATA(insert (  19   25  406 i ));
+DATA(insert (  19 1042  408 a ));
+DATA(insert (  19 1043 1401 a ));
+DATA(insert (  25   18  944 a ));
+DATA(insert ( 1042  18  944 a ));
+DATA(insert ( 1043  18  944 a ));
+DATA(insert (  25   19  407 i ));
+DATA(insert ( 1042  19  409 i ));
+DATA(insert ( 1043  19 1400 i ));
 
 /* Allow explicit coercions between int4 and "char" */
-DATA(insert (  18   23   77 e ));
-DATA(insert (  23   18   78 e ));
+DATA(insert (  18   23   77 e ));
+DATA(insert (  23   18   78 e ));
 
 /*
  * Datetime category
  */
-DATA(insert (  702 1082 1179 a ));
-DATA(insert (  702 1083 1364 a ));
-DATA(insert (  702 1114 2023 i ));
-DATA(insert (  702 1184 1173 i ));
-DATA(insert (  703 1186 1177 i ));
-DATA(insert ( 1082 1114 2024 i ));
-DATA(insert ( 1082 1184 1174 i ));
-DATA(insert ( 1083 1186 1370 i ));
-DATA(insert ( 1083 1266 2047 i ));
-DATA(insert ( 1114 702 2030 a ));
-DATA(insert ( 1114 1082 2029 a ));
-DATA(insert ( 1114 1083 1316 a ));
-DATA(insert ( 1114 1184 2028 i ));
-DATA(insert ( 1184 702 1180 a ));
-DATA(insert ( 1184 1082 1178 a ));
-DATA(insert ( 1184 1083 2019 a ));
-DATA(insert ( 1184 1114 2027 a ));
-DATA(insert ( 1184 1266 1388 a ));
-DATA(insert ( 1186 703 1194 a ));
-DATA(insert ( 1186 1083 1419 a ));
-DATA(insert ( 1266 1083 2046 a ));
+DATA(insert (  702 1082 1179 a ));
+DATA(insert (  702 1083 1364 a ));
+DATA(insert (  702 1114 2023 i ));
+DATA(insert (  702 1184 1173 i ));
+DATA(insert (  703 1186 1177 i ));
+DATA(insert ( 1082 1114 2024 i ));
+DATA(insert ( 1082 1184 1174 i ));
+DATA(insert ( 1083 1186 1370 i ));
+DATA(insert ( 1083 1266 2047 i ));
+DATA(insert ( 1114 702 2030 a ));
+DATA(insert ( 1114 1082 2029 a ));
+DATA(insert ( 1114 1083 1316 a ));
+DATA(insert ( 1114 1184 2028 i ));
+DATA(insert ( 1184 702 1180 a ));
+DATA(insert ( 1184 1082 1178 a ));
+DATA(insert ( 1184 1083 2019 a ));
+DATA(insert ( 1184 1114 2027 a ));
+DATA(insert ( 1184 1266 1388 a ));
+DATA(insert ( 1186 703 1194 a ));
+DATA(insert ( 1186 1083 1419 a ));
+DATA(insert ( 1266 1083 2046 a ));
 /* Cross-category casts between int4 and abstime, reltime */
-DATA(insert (  23  702    0 e ));
-DATA(insert (  702  23    0 e ));
-DATA(insert (  23  703    0 e ));
-DATA(insert (  703  23    0 e ));
+DATA(insert (  23  702    0 e ));
+DATA(insert (  702  23    0 e ));
+DATA(insert (  23  703    0 e ));
+DATA(insert (  703  23    0 e ));
 
 /*
  * Geometric category
  */
-DATA(insert (  601 600 1532 e ));
-DATA(insert (  602 600 1533 e ));
-DATA(insert (  602 604 1449 a ));
-DATA(insert (  603 600 1534 e ));
-DATA(insert (  603 601 1541 e ));
-DATA(insert (  603 604 1448 a ));
-DATA(insert (  603 718 1479 e ));
-DATA(insert (  604 600 1540 e ));
-DATA(insert (  604 602 1447 a ));
-DATA(insert (  604 603 1446 e ));
-DATA(insert (  604 718 1474 e ));
-DATA(insert (  718 600 1416 e ));
-DATA(insert (  718 603 1480 e ));
-DATA(insert (  718 604 1544 e ));
+DATA(insert (  601 600 1532 e ));
+DATA(insert (  602 600 1533 e ));
+DATA(insert (  602 604 1449 a ));
+DATA(insert (  603 600 1534 e ));
+DATA(insert (  603 601 1541 e ));
+DATA(insert (  603 604 1448 a ));
+DATA(insert (  603 718 1479 e ));
+DATA(insert (  604 600 1540 e ));
+DATA(insert (  604 602 1447 a ));
+DATA(insert (  604 603 1446 e ));
+DATA(insert (  604 718 1474 e ));
+DATA(insert (  718 600 1416 e ));
+DATA(insert (  718 603 1480 e ));
+DATA(insert (  718 604 1544 e ));
 
 /*
  * INET category
  */
-DATA(insert (  650 869    0 i ));
-DATA(insert (  869 650 1715 a ));
+DATA(insert (  650 869    0 i ));
+DATA(insert (  869 650 1715 a ));
 
 /*
  * BitString category
  */
-DATA(insert ( 1560 1562    0 i ));
-DATA(insert ( 1562 1560    0 i ));
+DATA(insert ( 1560 1562    0 i ));
+DATA(insert ( 1562 1560    0 i ));
 /* Cross-category casts between bit and int4, int8 */
-DATA(insert (  20 1560 2075 e ));
-DATA(insert (  23 1560 1683 e ));
-DATA(insert ( 1560  20 2076 e ));
-DATA(insert ( 1560  23 1684 e ));
+DATA(insert (  20 1560 2075 e ));
+DATA(insert (  23 1560 1683 e ));
+DATA(insert ( 1560  20 2076 e ));
+DATA(insert ( 1560  23 1684 e ));
 
 /*
  * Cross-category casts to and from TEXT
@@ -296,46 +310,46 @@ DATA(insert ( 1560     23 1684 e ));
  * behavior will ensue when the automatic cast is applied instead of the
  * pg_cast entry!
  */
-DATA(insert (  650  25  730 a ));
-DATA(insert (  869  25  730 a ));
-DATA(insert (  16   25 2971 a ));
-DATA(insert (  142  25    0 a ));
-DATA(insert (  25  142 2896 e ));
+DATA(insert (  650  25  730 a ));
+DATA(insert (  869  25  730 a ));
+DATA(insert (  16   25 2971 a ));
+DATA(insert (  142  25    0 a ));
+DATA(insert (  25  142 2896 e ));
 
 /*
  * Cross-category casts to and from VARCHAR
  *
  * We support all the same casts as for TEXT.
  */
-DATA(insert (  650 1043  730 a ));
-DATA(insert (  869 1043  730 a ));
-DATA(insert (  16 1043 2971 a ));
-DATA(insert (  142 1043    0 a ));
-DATA(insert ( 1043 142 2896 e ));
+DATA(insert (  650 1043  730 a ));
+DATA(insert (  869 1043  730 a ));
+DATA(insert (  16 1043 2971 a ));
+DATA(insert (  142 1043    0 a ));
+DATA(insert ( 1043 142 2896 e ));
 
 /*
  * Cross-category casts to and from BPCHAR
  *
  * We support all the same casts as for TEXT.
  */
-DATA(insert (  650 1042  730 a ));
-DATA(insert (  869 1042  730 a ));
-DATA(insert (  16 1042 2971 a ));
-DATA(insert (  142 1042    0 a ));
-DATA(insert ( 1042 142 2896 e ));
+DATA(insert (  650 1042  730 a ));
+DATA(insert (  869 1042  730 a ));
+DATA(insert (  16 1042 2971 a ));
+DATA(insert (  142 1042    0 a ));
+DATA(insert ( 1042 142 2896 e ));
 
 /*
  * Length-coercion functions
  */
-DATA(insert ( 1042 1042  668 i ));
-DATA(insert ( 1043 1043  669 i ));
-DATA(insert ( 1083 1083 1968 i ));
-DATA(insert ( 1114 1114 1961 i ));
-DATA(insert ( 1184 1184 1967 i ));
-DATA(insert ( 1186 1186 1200 i ));
-DATA(insert ( 1266 1266 1969 i ));
-DATA(insert ( 1560 1560 1685 i ));
-DATA(insert ( 1562 1562 1687 i ));
-DATA(insert ( 1700 1700 1703 i ));
+DATA(insert ( 1042 1042  668 i ));
+DATA(insert ( 1043 1043  669 i ));
+DATA(insert ( 1083 1083 1968 i ));
+DATA(insert ( 1114 1114 1961 i ));
+DATA(insert ( 1184 1184 1967 i ));
+DATA(insert ( 1186 1186 1200 i ));
+DATA(insert ( 1266 1266 1969 i ));
+DATA(insert ( 1560 1560 1685 i ));
+DATA(insert ( 1562 1562 1687 i ));
+DATA(insert ( 1700 1700 1703 i ));
 
 #endif   /* PG_CAST_H */
index 2660d7adb80c8f2e74e1211ce5b360d3e1da7fbe..5e112d178ba236eae84068341a096a338d4089c3 100644 (file)
@@ -13,7 +13,7 @@
  * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.376 2008/10/04 21:56:55 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.377 2008/10/31 08:39:22 heikki Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -2062,6 +2062,7 @@ typedef struct CreateCastStmt
    TypeName   *targettype;
    FuncWithArgs *func;
    CoercionContext context;
+   bool        inout;
 } CreateCastStmt;
 
 /* ----------------------
index a21c2ba3744250a84dbc4a175dcf8d095b979125..87464ec9cf4557a717f83e0d716afa5734cdfdff 100644 (file)
@@ -22,7 +22,7 @@ create function binary_coercible(oid, oid) returns bool as $$
 SELECT ($1 = $2) OR
  EXISTS(select 1 from pg_catalog.pg_cast where
         castsource = $1 and casttarget = $2 and
-        castfunc = 0 and castcontext = 'i') OR
+        castmethod = 'b' and castcontext = 'i') OR
  ($2 = 'pg_catalog.anyarray'::pg_catalog.regtype AND
   EXISTS(select 1 from pg_catalog.pg_type where
          oid = $1 and typelem != 0 and typlen = -1))
@@ -33,7 +33,7 @@ create function physically_coercible(oid, oid) returns bool as $$
 SELECT ($1 = $2) OR
  EXISTS(select 1 from pg_catalog.pg_cast where
         castsource = $1 and casttarget = $2 and
-        castfunc = 0) OR
+        castmethod = 'b') OR
  ($2 = 'pg_catalog.anyarray'::pg_catalog.regtype AND
   EXISTS(select 1 from pg_catalog.pg_type where
          oid = $1 and typelem != 0 and typlen = -1))
@@ -262,9 +262,20 @@ WHERE p1.prorettype = 'internal'::regtype AND NOT
 -- oidjoins test).
 SELECT *
 FROM pg_cast c
-WHERE castsource = 0 OR casttarget = 0 OR castcontext NOT IN ('e', 'a', 'i');
- castsource | casttarget | castfunc | castcontext 
-------------+------------+----------+-------------
+WHERE castsource = 0 OR casttarget = 0 OR castcontext NOT IN ('e', 'a', 'i')
+    OR castmethod NOT IN ('f', 'b' ,'i');
+ castsource | casttarget | castfunc | castcontext | castmethod 
+------------+------------+----------+-------------+------------
+(0 rows)
+
+-- Check that castfunc is nonzero only for cast methods that need a function,
+-- and zero otherwise
+SELECT *
+FROM pg_cast c
+WHERE (castmethod = 'f' AND castfunc = 0)
+   OR (castmethod IN ('b', 'i') AND castfunc <> 0);
+ castsource | casttarget | castfunc | castcontext | castmethod 
+------------+------------+----------+-------------+------------
 (0 rows)
 
 -- Look for casts to/from the same type that aren't length coercion functions.
@@ -273,15 +284,15 @@ WHERE castsource = 0 OR casttarget = 0 OR castcontext NOT IN ('e', 'a', 'i');
 SELECT *
 FROM pg_cast c
 WHERE castsource = casttarget AND castfunc = 0;
- castsource | casttarget | castfunc | castcontext 
-------------+------------+----------+-------------
+ castsource | casttarget | castfunc | castcontext | castmethod 
+------------+------------+----------+-------------+------------
 (0 rows)
 
 SELECT c.*
 FROM pg_cast c, pg_proc p
 WHERE c.castfunc = p.oid AND p.pronargs < 2 AND castsource = casttarget;
- castsource | casttarget | castfunc | castcontext 
-------------+------------+----------+-------------
+ castsource | casttarget | castfunc | castcontext | castmethod 
+------------+------------+----------+-------------+------------
 (0 rows)
 
 -- Look for cast functions that don't have the right signature.  The
@@ -299,8 +310,8 @@ WHERE c.castfunc = p.oid AND
              OR (c.castsource = 'character'::regtype AND
                  p.proargtypes[0] = 'text'::regtype))
      OR NOT binary_coercible(p.prorettype, c.casttarget));
- castsource | casttarget | castfunc | castcontext 
-------------+------------+----------+-------------
+ castsource | casttarget | castfunc | castcontext | castmethod 
+------------+------------+----------+-------------+------------
 (0 rows)
 
 SELECT c.*
@@ -308,8 +319,8 @@ FROM pg_cast c, pg_proc p
 WHERE c.castfunc = p.oid AND
     ((p.pronargs > 1 AND p.proargtypes[1] != 'int4'::regtype) OR
      (p.pronargs > 2 AND p.proargtypes[2] != 'bool'::regtype));
- castsource | casttarget | castfunc | castcontext 
-------------+------------+----------+-------------
+ castsource | casttarget | castfunc | castcontext | castmethod 
+------------+------------+----------+-------------+------------
 (0 rows)
 
 -- Look for binary compatible casts that do not have the reverse
@@ -324,19 +335,19 @@ WHERE c.castfunc = p.oid AND
 -- texttoxml(), which does an XML syntax check.
 SELECT *
 FROM pg_cast c
-WHERE c.castfunc = 0 AND
+WHERE c.castmethod = 'b' AND
     NOT EXISTS (SELECT 1 FROM pg_cast k
-                WHERE k.castfunc = 0 AND
+                WHERE k.castmethod = 'b' AND
                     k.castsource = c.casttarget AND
                     k.casttarget = c.castsource);
- castsource | casttarget | castfunc | castcontext 
-------------+------------+----------+-------------
-         25 |       1042 |        0 | i
-       1043 |       1042 |        0 | i
-        650 |        869 |        0 | i
-        142 |         25 |        0 | a
-        142 |       1043 |        0 | a
-        142 |       1042 |        0 | a
+ castsource | casttarget | castfunc | castcontext | castmethod 
+------------+------------+----------+-------------+------------
+         25 |       1042 |        0 | i           | b
+       1043 |       1042 |        0 | i           | b
+        650 |        869 |        0 | i           | b
+        142 |         25 |        0 | a           | b
+        142 |       1043 |        0 | a           | b
+        142 |       1042 |        0 | a           | b
 (6 rows)
 
 -- **************** pg_operator ****************
index 57c2cad95151649f0fe9c0ad2df14061749b27bb..c254a8b6cb0cca682402ec9b69c469b01b09e58b 100644 (file)
@@ -25,7 +25,7 @@ create function binary_coercible(oid, oid) returns bool as $$
 SELECT ($1 = $2) OR
  EXISTS(select 1 from pg_catalog.pg_cast where
         castsource = $1 and casttarget = $2 and
-        castfunc = 0 and castcontext = 'i') OR
+        castmethod = 'b' and castcontext = 'i') OR
  ($2 = 'pg_catalog.anyarray'::pg_catalog.regtype AND
   EXISTS(select 1 from pg_catalog.pg_type where
          oid = $1 and typelem != 0 and typlen = -1))
@@ -37,7 +37,7 @@ create function physically_coercible(oid, oid) returns bool as $$
 SELECT ($1 = $2) OR
  EXISTS(select 1 from pg_catalog.pg_cast where
         castsource = $1 and casttarget = $2 and
-        castfunc = 0) OR
+        castmethod = 'b') OR
  ($2 = 'pg_catalog.anyarray'::pg_catalog.regtype AND
   EXISTS(select 1 from pg_catalog.pg_type where
          oid = $1 and typelem != 0 and typlen = -1))
@@ -214,7 +214,16 @@ WHERE p1.prorettype = 'internal'::regtype AND NOT
 
 SELECT *
 FROM pg_cast c
-WHERE castsource = 0 OR casttarget = 0 OR castcontext NOT IN ('e', 'a', 'i');
+WHERE castsource = 0 OR casttarget = 0 OR castcontext NOT IN ('e', 'a', 'i')
+    OR castmethod NOT IN ('f', 'b' ,'i');
+
+-- Check that castfunc is nonzero only for cast methods that need a function,
+-- and zero otherwise
+
+SELECT *
+FROM pg_cast c
+WHERE (castmethod = 'f' AND castfunc = 0)
+   OR (castmethod IN ('b', 'i') AND castfunc <> 0);
 
 -- Look for casts to/from the same type that aren't length coercion functions.
 -- (We assume they are length coercions if they take multiple arguments.)
@@ -267,9 +276,9 @@ WHERE c.castfunc = p.oid AND
 
 SELECT *
 FROM pg_cast c
-WHERE c.castfunc = 0 AND
+WHERE c.castmethod = 'b' AND
     NOT EXISTS (SELECT 1 FROM pg_cast k
-                WHERE k.castfunc = 0 AND
+                WHERE k.castmethod = 'b' AND
                     k.castsource = c.casttarget AND
                     k.casttarget = c.castsource);