Tom Lane wrote:
Heikki Linnakangas <[EMAIL PROTECTED]> writes:
Yeah, a magical OID clearly has some issues. A new field in pg_cast is the obvious alternative. How about adding a "castmethod" char field, with values:
b = binary-compatible cast (CREATE CAST ... WITHOUT FUNCTION)
i = I/O coercion cast (the new beast, CREATE CAST ... WITH INOUT)
f = use cast function specified in castfunc field.
castfunc is 0 for methods b and i.

Seems sane to me.  If you do that, please add a check in the opr_sanity
regression test that castfunc is nonzero if and only if castmethod is f.

Here's a patch. It seems pretty straightforward, I'll apply this tomorrow, barring objections. Note to self: bump the catalog version.

BTW, it looks like we don't have any test cases for the CREATE CAST command. I think I'll add one.

--
  Heikki Linnakangas
  EnterpriseDB   http://www.enterprisedb.com
*** doc/src/sgml/catalogs.sgml
--- doc/src/sgml/catalogs.sgml
***************
*** 1415,1423 ****
     cannot be deduced from some generic rule.  For example, casting between a
     domain and its base type is not explicitly represented in
     <structname>pg_cast</structname>.  Another important exception is that
!    <quote>I/O conversion casts</>, those performed using a data type's own
!    I/O functions to convert to or from <type>text</> or other string types,
!    are not explicitly represented in <structname>pg_cast</structname>.
    </para>
  
    <table>
--- 1415,1424 ----
     cannot be deduced from some generic rule.  For example, casting between a
     domain and its base type is not explicitly represented in
     <structname>pg_cast</structname>.  Another important exception is that
!    <quote>automatic I/O conversion casts</>, those performed using a data
!    type's own I/O functions to convert to or from <type>text</> or other
!    string types, are not explicitly represented in
!    <structname>pg_cast</structname>.
    </para>
  
    <table>
***************
*** 1454,1461 ****
        <entry><literal><link linkend="catalog-pg-proc"><structname>pg_proc</structname></link>.oid</literal></entry>
        <entry>
         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)
        </entry>
       </row>
  
--- 1455,1461 ----
        <entry><literal><link linkend="catalog-pg-proc"><structname>pg_proc</structname></link>.oid</literal></entry>
        <entry>
         The OID of the function to use to perform this cast.  Zero is
!        stored if the cast method doesn't require a function.
        </entry>
       </row>
  
***************
*** 1473,1478 ****
--- 1473,1489 ----
         other cases
        </entry>
       </row>
+      <row>
+       <entry><structfield>castmethod</structfield></entry>
+       <entry><type>char</type></entry>
+       <entry></entry>
+       <entry>
+        Indicates how the cast is performed.
+        <literal>f</> means that the function specified in the <structfield>castfunc</> field is used.
+        <literal>i</> means that the input/output functions are used.
+        <literal>b</> means that the types are binary-coercible, thus no conversion is required
+       </entry>
+      </row>
      </tbody>
     </tgroup>
    </table>
*** doc/src/sgml/ref/create_cast.sgml
--- doc/src/sgml/ref/create_cast.sgml
***************
*** 24,29 **** CREATE CAST (<replaceable>sourcetype</replaceable> AS <replaceable>targettype</r
--- 24,33 ----
  CREATE CAST (<replaceable>sourcetype</replaceable> AS <replaceable>targettype</replaceable>)
      WITHOUT FUNCTION
      [ AS ASSIGNMENT | AS IMPLICIT ]
+ 
+ CREATE CAST (<replaceable>sourcetype</replaceable> AS <replaceable>targettype</replaceable>)
+     WITH INOUT
+     [ AS ASSIGNMENT | AS IMPLICIT ]
  </synopsis>
   </refsynopsisdiv>
  
***************
*** 59,64 **** SELECT CAST(42 AS float8);
--- 63,75 ----
    </para>
  
    <para>
+    You can define a cast as an <firstterm>I/O conversion cast</> using
+    the <literal>WITH INOUT</literal> 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.
+   </para>
+ 
+   <para>
     By default, a cast can be invoked only by an explicit cast request,
     that is an explicit <literal>CAST(<replaceable>x</> AS
     <replaceable>typename</>)</literal> or
***************
*** 200,205 **** SELECT CAST ( 2 AS numeric ) + 4.0;
--- 211,228 ----
      </varlistentry>
  
      <varlistentry>
+      <term><literal>WITH INOUT</literal></term>
+ 
+      <listitem>
+       <para>
+        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.
+       </para>
+      </listitem>
+     </varlistentry>
+ 
+     <varlistentry>
       <term><literal>AS ASSIGNMENT</literal></term>
  
       <listitem>
***************
*** 284,296 **** SELECT CAST ( 2 AS numeric ) + 4.0;
     It is normally not necessary to create casts between user-defined types
     and the standard string types (<type>text</>, <type>varchar</>, and
     <type>char(<replaceable>n</>)</type>, as well as user-defined types that
!    are defined to be in the string category).  <productname>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 <firstterm>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
     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
     do so is if you want the conversion to be more easily invokable than the
--- 307,316 ----
     It is normally not necessary to create casts between user-defined types
     and the standard string types (<type>text</>, <type>varchar</>, and
     <type>char(<replaceable>n</>)</type>, as well as user-defined types that
!    are defined to be in the string category).  <productname>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
     do so is if you want the conversion to be more easily invokable than the
*** src/backend/commands/functioncmds.c
--- src/backend/commands/functioncmds.c
***************
*** 1383,1388 **** CreateCast(CreateCastStmt *stmt)
--- 1383,1389 ----
  	Oid			funcid;
  	int			nargs;
  	char		castcontext;
+ 	char		castmethod;
  	Relation	relation;
  	HeapTuple	tuple;
  	Datum		values[Natts_pg_cast];
***************
*** 1415,1421 **** CreateCast(CreateCastStmt *stmt)
--- 1416,1430 ----
  						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;
  
***************
*** 1476,1481 **** CreateCast(CreateCastStmt *stmt)
--- 1485,1496 ----
  	}
  	else
  	{
+ 		funcid = InvalidOid;
+ 		nargs = 0;
+ 	}
+ 
+ 	if (castmethod == COERCION_METHOD_BINARY)
+ 	{
  		int16		typ1len;
  		int16		typ2len;
  		bool		typ1byval;
***************
*** 1483,1492 **** 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.
--- 1498,1503 ----
***************
*** 1562,1567 **** CreateCast(CreateCastStmt *stmt)
--- 1573,1579 ----
  	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);
  
*** src/backend/nodes/copyfuncs.c
--- src/backend/nodes/copyfuncs.c
***************
*** 3042,3047 **** _copyCreateCastStmt(CreateCastStmt *from)
--- 3042,3048 ----
  	COPY_NODE_FIELD(targettype);
  	COPY_NODE_FIELD(func);
  	COPY_SCALAR_FIELD(context);
+ 	COPY_SCALAR_FIELD(inout);
  
  	return newnode;
  }
*** src/backend/nodes/equalfuncs.c
--- src/backend/nodes/equalfuncs.c
***************
*** 1666,1671 **** _equalCreateCastStmt(CreateCastStmt *a, CreateCastStmt *b)
--- 1666,1672 ----
  	COMPARE_NODE_FIELD(targettype);
  	COMPARE_NODE_FIELD(func);
  	COMPARE_SCALAR_FIELD(context);
+ 	COMPARE_SCALAR_FIELD(inout);
  
  	return true;
  }
*** src/backend/parser/gram.y
--- src/backend/parser/gram.y
***************
*** 4590,4595 **** CreateCastStmt: CREATE CAST '(' Typename AS Typename ')'
--- 4590,4596 ----
  					n->targettype = $6;
  					n->func = $10;
  					n->context = (CoercionContext) $11;
+ 					n->inout = false;
  					$$ = (Node *)n;
  				}
  			| CREATE CAST '(' Typename AS Typename ')'
***************
*** 4600,4605 **** CreateCastStmt: CREATE CAST '(' Typename AS Typename ')'
--- 4601,4618 ----
  					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;
  				}
  		;
*** src/backend/parser/parse_coerce.c
--- src/backend/parser/parse_coerce.c
***************
*** 1909,1919 **** 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;
  		}
  
  		ReleaseSysCache(tuple);
--- 1909,1931 ----
  		/* Rely on ordering of enum for correct behavior here */
  		if (ccontext >= castcontext)
  		{
! 			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);
*** src/bin/pg_dump/pg_dump.c
--- src/bin/pg_dump/pg_dump.c
***************
*** 36,41 **** int			optreset;
--- 36,42 ----
  
  #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,4430 **** getCasts(int *numCasts)
  	int			i_casttarget;
  	int			i_castfunc;
  	int			i_castcontext;
  
  	/* Make sure we are in proper schema */
  	selectSourceSchema("pg_catalog");
  
! 	if (g_fout->remoteVersion >= 70300)
  	{
  		appendPQExpBuffer(query, "SELECT tableoid, oid, "
! 						  "castsource, casttarget, castfunc, castcontext "
  						  "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 "
  						  "FROM pg_type t1, pg_type t2, pg_proc p "
  						  "WHERE p.pronargs = 1 AND "
  						  "p.proargtypes[0] = t1.oid AND "
--- 4411,4441 ----
  	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 >= 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, "
! 						  "CASE WHEN castfunc = 0 THEN 'b' ELSE 'f' END "
  						  "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, "
! 						  "'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,4452 **** getCasts(int *numCasts)
--- 4458,4464 ----
  	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,4467 **** getCasts(int *numCasts)
--- 4474,4480 ----
  		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,7205 **** dumpCast(Archive *fout, CastInfo *cast)
  					  getFormattedTypeName(cast->castsource, zeroAsNone),
  					  getFormattedTypeName(cast->casttarget, zeroAsNone));
  
! 	if (!OidIsValid(cast->castfunc))
! 		appendPQExpBuffer(defqry, "WITHOUT FUNCTION");
! 	else
  	{
! 		/*
! 		 * 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));
  	}
  
  	if (cast->castcontext == 'a')
--- 7201,7226 ----
  					  getFormattedTypeName(cast->castsource, zeroAsNone),
  					  getFormattedTypeName(cast->casttarget, zeroAsNone));
  
! 	switch(cast->castmethod)
  	{
! 		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')
*** src/bin/pg_dump/pg_dump.h
--- src/bin/pg_dump/pg_dump.h
***************
*** 376,381 **** typedef struct _castInfo
--- 376,382 ----
  	Oid			casttarget;
  	Oid			castfunc;
  	char		castcontext;
+ 	char		castmethod;
  } CastInfo;
  
  /* InhInfo isn't a DumpableObject, just temporary state */
*** src/include/catalog/pg_cast.h
--- src/include/catalog/pg_cast.h
***************
*** 36,41 **** CATALOG(pg_cast,2605)
--- 36,42 ----
  	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,71 **** typedef enum CoercionCodes
  	COERCION_CODE_EXPLICIT = 'e'	/* explicit cast operation */
  } CoercionCodes;
  
  
  /* ----------------
   *		compiler constants for pg_cast
   * ----------------
   */
! #define Natts_pg_cast				4
  #define Anum_pg_cast_castsource		1
  #define Anum_pg_cast_casttarget		2
  #define Anum_pg_cast_castfunc		3
  #define Anum_pg_cast_castcontext	4
  
  /* ----------------
   *		initial contents of pg_cast
--- 57,85 ----
  	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				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,119 **** 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 ));
  
  /* Allow explicit coercions between int4 and bool */
! DATA(insert (	23	16	2557 e ));
! DATA(insert (	16	23	2558 e ));
  
  /*
   * OID category: allow implicit conversion from any integral type (including
--- 94,133 ----
   * int2->int4->int8->numeric->float4->float8, while casts in the
   * reverse direction are assignment-only.
   */
! DATA(insert (	20	 21  714 a f ));
! DATA(insert (	20	 23  480 a f ));
! DATA(insert (	20	700  652 i f ));
! DATA(insert (	20	701  482 i f ));
! DATA(insert (	20 1700 1781 i f ));
! DATA(insert (	21	 20  754 i f ));
! DATA(insert (	21	 23  313 i f ));
! DATA(insert (	21	700  236 i f ));
! DATA(insert (	21	701  235 i f ));
! DATA(insert (	21 1700 1782 i f ));
! DATA(insert (	23	 20  481 i f ));
! DATA(insert (	23	 21  314 a f ));
! DATA(insert (	23	700  318 i f ));
! DATA(insert (	23	701  316 i f ));
! DATA(insert (	23 1700 1740 i f ));
! DATA(insert (  700	 20  653 a f ));
! DATA(insert (  700	 21  238 a f ));
! DATA(insert (  700	 23  319 a f ));
! DATA(insert (  700	701  311 i f ));
! DATA(insert (  700 1700 1742 a f ));
! DATA(insert (  701	 20  483 a f ));
! DATA(insert (  701	 21  237 a f ));
! DATA(insert (  701	 23  317 a f ));
! DATA(insert (  701	700  312 a f ));
! DATA(insert (  701 1700 1743 a f ));
! DATA(insert ( 1700	 20 1779 a f ));
! DATA(insert ( 1700	 21 1783 a f ));
! DATA(insert ( 1700	 23 1744 a f ));
! DATA(insert ( 1700	700 1745 i f ));
! DATA(insert ( 1700	701 1746 i f ));
  
  /* Allow explicit coercions between int4 and bool */
! DATA(insert (	23	16	2557 e f ));
! DATA(insert (	16	23	2558 e f ));
  
  /*
   * OID category: allow implicit conversion from any integral type (including
***************
*** 125,288 **** 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 ));
  
  /*
   * 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 ));
  
  /* Allow explicit coercions between int4 and "char" */
! 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 ));
  /* 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 ));
  
  /*
   * 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 ));
  
  /*
   * INET category
   */
! 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 ));
  /* 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 ));
  
  /*
   * Cross-category casts to and from TEXT
--- 139,302 ----
   * 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 f ));
! DATA(insert (	21	 26  313 i f ));
! DATA(insert (	23	 26    0 i b ));
! DATA(insert (	26	 20 1288 a f ));
! DATA(insert (	26	 23    0 a b ));
! DATA(insert (	26	 24    0 i b ));
! DATA(insert (	24	 26    0 i b ));
! DATA(insert (	20	 24 1287 i f ));
! DATA(insert (	21	 24  313 i f ));
! DATA(insert (	23	 24    0 i b ));
! DATA(insert (	24	 20 1288 a f ));
! DATA(insert (	24	 23    0 a b ));
! DATA(insert (	24 2202    0 i b ));
! DATA(insert ( 2202	 24    0 i b ));
! DATA(insert (	26 2202    0 i b ));
! DATA(insert ( 2202	 26    0 i b ));
! DATA(insert (	20 2202 1287 i f ));
! DATA(insert (	21 2202  313 i f ));
! DATA(insert (	23 2202    0 i b ));
! DATA(insert ( 2202	 20 1288 a f ));
! DATA(insert ( 2202	 23    0 a b ));
! DATA(insert (	26 2203    0 i b ));
! DATA(insert ( 2203	 26    0 i b ));
! DATA(insert (	20 2203 1287 i f ));
! DATA(insert (	21 2203  313 i f ));
! DATA(insert (	23 2203    0 i b ));
! DATA(insert ( 2203	 20 1288 a f ));
! DATA(insert ( 2203	 23    0 a b ));
! DATA(insert ( 2203 2204    0 i b ));
! DATA(insert ( 2204 2203    0 i b ));
! DATA(insert (	26 2204    0 i b ));
! DATA(insert ( 2204	 26    0 i b ));
! DATA(insert (	20 2204 1287 i f ));
! DATA(insert (	21 2204  313 i f ));
! DATA(insert (	23 2204    0 i b ));
! DATA(insert ( 2204	 20 1288 a f ));
! DATA(insert ( 2204	 23    0 a b ));
! DATA(insert (	26 2205    0 i b ));
! DATA(insert ( 2205	 26    0 i b ));
! DATA(insert (	20 2205 1287 i f ));
! DATA(insert (	21 2205  313 i f ));
! DATA(insert (	23 2205    0 i b ));
! DATA(insert ( 2205	 20 1288 a f ));
! DATA(insert ( 2205	 23    0 a b ));
! DATA(insert (	26 2206    0 i b ));
! DATA(insert ( 2206	 26    0 i b ));
! DATA(insert (	20 2206 1287 i f ));
! DATA(insert (	21 2206  313 i f ));
! DATA(insert (	23 2206    0 i b ));
! DATA(insert ( 2206	 20 1288 a f ));
! DATA(insert ( 2206	 23    0 a b ));
! DATA(insert (	26 3734    0 i b ));
! DATA(insert ( 3734	 26    0 i b ));
! DATA(insert (	20 3734 1287 i f ));
! DATA(insert (	21 3734  313 i f ));
! DATA(insert (	23 3734    0 i b ));
! DATA(insert ( 3734	 20 1288 a f ));
! DATA(insert ( 3734	 23    0 a b ));
! DATA(insert (	26 3769    0 i b ));
! DATA(insert ( 3769	 26    0 i b ));
! DATA(insert (	20 3769 1287 i f ));
! DATA(insert (	21 3769  313 i f ));
! DATA(insert (	23 3769    0 i b ));
! DATA(insert ( 3769	 20 1288 a f ));
! DATA(insert ( 3769	 23    0 a b ));
! DATA(insert (	25 2205 1079 i f ));
! DATA(insert ( 1043 2205 1079 i f ));
  
  /*
   * String category
   */
! DATA(insert (	25 1042    0 i b ));
! DATA(insert (	25 1043    0 i b ));
! DATA(insert ( 1042	 25  401 i f ));
! DATA(insert ( 1042 1043  401 i f ));
! DATA(insert ( 1043	 25    0 i b ));
! DATA(insert ( 1043 1042    0 i b ));
! DATA(insert (	18	 25  946 i f ));
! DATA(insert (	18 1042  860 a f ));
! DATA(insert (	18 1043  946 a f ));
! DATA(insert (	19	 25  406 i f ));
! DATA(insert (	19 1042  408 a f ));
! DATA(insert (	19 1043 1401 a f ));
! DATA(insert (	25	 18  944 a f ));
! DATA(insert ( 1042	 18  944 a f ));
! DATA(insert ( 1043	 18  944 a f ));
! DATA(insert (	25	 19  407 i f ));
! DATA(insert ( 1042	 19  409 i f ));
! DATA(insert ( 1043	 19 1400 i f ));
  
  /* Allow explicit coercions between int4 and "char" */
! DATA(insert (	18	 23   77 e f ));
! DATA(insert (	23	 18   78 e f ));
  
  /*
   * Datetime category
   */
! DATA(insert (  702 1082 1179 a f ));
! DATA(insert (  702 1083 1364 a f ));
! DATA(insert (  702 1114 2023 i f ));
! DATA(insert (  702 1184 1173 i f ));
! DATA(insert (  703 1186 1177 i f ));
! DATA(insert ( 1082 1114 2024 i f ));
! DATA(insert ( 1082 1184 1174 i f ));
! DATA(insert ( 1083 1186 1370 i f ));
! DATA(insert ( 1083 1266 2047 i f ));
! DATA(insert ( 1114	702 2030 a f ));
! DATA(insert ( 1114 1082 2029 a f ));
! DATA(insert ( 1114 1083 1316 a f ));
! DATA(insert ( 1114 1184 2028 i f ));
! DATA(insert ( 1184	702 1180 a f ));
! DATA(insert ( 1184 1082 1178 a f ));
! DATA(insert ( 1184 1083 2019 a f ));
! DATA(insert ( 1184 1114 2027 a f ));
! DATA(insert ( 1184 1266 1388 a f ));
! DATA(insert ( 1186	703 1194 a f ));
! DATA(insert ( 1186 1083 1419 a f ));
! DATA(insert ( 1266 1083 2046 a f ));
  /* Cross-category casts between int4 and abstime, reltime */
! DATA(insert (	23	702    0 e b ));
! DATA(insert (  702	 23    0 e b ));
! DATA(insert (	23	703    0 e b ));
! DATA(insert (  703	 23    0 e b ));
  
  /*
   * Geometric category
   */
! DATA(insert (  601	600 1532 e f ));
! DATA(insert (  602	600 1533 e f ));
! DATA(insert (  602	604 1449 a f ));
! DATA(insert (  603	600 1534 e f ));
! DATA(insert (  603	601 1541 e f ));
! DATA(insert (  603	604 1448 a f ));
! DATA(insert (  603	718 1479 e f ));
! DATA(insert (  604	600 1540 e f ));
! DATA(insert (  604	602 1447 a f ));
! DATA(insert (  604	603 1446 e f ));
! DATA(insert (  604	718 1474 e f ));
! DATA(insert (  718	600 1416 e f ));
! DATA(insert (  718	603 1480 e f ));
! DATA(insert (  718	604 1544 e f ));
  
  /*
   * INET category
   */
! DATA(insert (  650	869    0 i b ));
! DATA(insert (  869	650 1715 a f ));
  
  /*
   * BitString category
   */
! DATA(insert ( 1560 1562    0 i b ));
! DATA(insert ( 1562 1560    0 i b ));
  /* Cross-category casts between bit and int4, int8 */
! DATA(insert (	20 1560 2075 e f ));
! DATA(insert (	23 1560 1683 e f ));
! DATA(insert ( 1560	 20 2076 e f ));
! DATA(insert ( 1560	 23 1684 e f ));
  
  /*
   * Cross-category casts to and from TEXT
***************
*** 296,341 **** 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 ));
  
  /*
   * 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 ));
  
  /*
   * 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 ));
  
  /*
   * 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 ));
  
  #endif   /* PG_CAST_H */
--- 310,355 ----
   * behavior will ensue when the automatic cast is applied instead of the
   * pg_cast entry!
   */
! DATA(insert (  650	 25  730 a f ));
! DATA(insert (  869	 25  730 a f ));
! DATA(insert (	16	 25 2971 a f ));
! DATA(insert (  142	 25    0 a b ));
! DATA(insert (	25	142 2896 e f ));
  
  /*
   * Cross-category casts to and from VARCHAR
   *
   * We support all the same casts as for TEXT.
   */
! DATA(insert (  650 1043  730 a f ));
! DATA(insert (  869 1043  730 a f ));
! DATA(insert (	16 1043 2971 a f ));
! DATA(insert (  142 1043    0 a b ));
! DATA(insert ( 1043	142 2896 e f ));
  
  /*
   * Cross-category casts to and from BPCHAR
   *
   * We support all the same casts as for TEXT.
   */
! DATA(insert (  650 1042  730 a f ));
! DATA(insert (  869 1042  730 a f ));
! DATA(insert (	16 1042 2971 a f ));
! DATA(insert (  142 1042    0 a b ));
! DATA(insert ( 1042	142 2896 e f ));
  
  /*
   * Length-coercion functions
   */
! DATA(insert ( 1042 1042  668 i f ));
! DATA(insert ( 1043 1043  669 i f ));
! DATA(insert ( 1083 1083 1968 i f ));
! DATA(insert ( 1114 1114 1961 i f ));
! DATA(insert ( 1184 1184 1967 i f ));
! DATA(insert ( 1186 1186 1200 i f ));
! DATA(insert ( 1266 1266 1969 i f ));
! DATA(insert ( 1560 1560 1685 i f ));
! DATA(insert ( 1562 1562 1687 i f ));
! DATA(insert ( 1700 1700 1703 i f ));
  
  #endif   /* PG_CAST_H */
*** src/include/nodes/parsenodes.h
--- src/include/nodes/parsenodes.h
***************
*** 2062,2067 **** typedef struct CreateCastStmt
--- 2062,2068 ----
  	TypeName   *targettype;
  	FuncWithArgs *func;
  	CoercionContext context;
+ 	bool		inout;
  } CreateCastStmt;
  
  /* ----------------------
*** src/test/regress/expected/opr_sanity.out
--- src/test/regress/expected/opr_sanity.out
***************
*** 22,28 **** 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
   ($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))
--- 22,28 ----
  SELECT ($1 = $2) OR
   EXISTS(select 1 from pg_catalog.pg_cast where
          castsource = $1 and casttarget = $2 and
!         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,39 **** 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
   ($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,39 ----
  SELECT ($1 = $2) OR
   EXISTS(select 1 from pg_catalog.pg_cast where
          castsource = $1 and casttarget = $2 and
!         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,270 **** 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 
! ------------+------------+----------+-------------
  (0 rows)
  
  -- Look for casts to/from the same type that aren't length coercion functions.
--- 262,281 ----
  -- oidjoins test).
  SELECT *
  FROM pg_cast c
! 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,287 **** 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 
! ------------+------------+----------+-------------
  (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 
! ------------+------------+----------+-------------
  (0 rows)
  
  -- Look for cast functions that don't have the right signature.  The
--- 284,298 ----
  SELECT *
  FROM pg_cast c
  WHERE castsource = casttarget AND castfunc = 0;
!  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 | castmethod 
! ------------+------------+----------+-------------+------------
  (0 rows)
  
  -- Look for cast functions that don't have the right signature.  The
***************
*** 299,306 **** 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 
! ------------+------------+----------+-------------
  (0 rows)
  
  SELECT c.*
--- 310,317 ----
               OR (c.castsource = 'character'::regtype AND
                   p.proargtypes[0] = 'text'::regtype))
       OR NOT binary_coercible(p.prorettype, c.casttarget));
!  castsource | casttarget | castfunc | castcontext | castmethod 
! ------------+------------+----------+-------------+------------
  (0 rows)
  
  SELECT c.*
***************
*** 308,315 **** 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 
! ------------+------------+----------+-------------
  (0 rows)
  
  -- Look for binary compatible casts that do not have the reverse
--- 319,326 ----
  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 | castmethod 
! ------------+------------+----------+-------------+------------
  (0 rows)
  
  -- Look for binary compatible casts that do not have the reverse
***************
*** 324,342 **** WHERE c.castfunc = p.oid AND
  -- texttoxml(), which does an XML syntax check.
  SELECT *
  FROM pg_cast c
! WHERE c.castfunc = 0 AND
      NOT EXISTS (SELECT 1 FROM pg_cast k
!                 WHERE k.castfunc = 0 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
  (6 rows)
  
  -- **************** pg_operator ****************
--- 335,353 ----
  -- texttoxml(), which does an XML syntax check.
  SELECT *
  FROM pg_cast c
! WHERE c.castmethod = 'b' AND
      NOT EXISTS (SELECT 1 FROM pg_cast k
!                 WHERE k.castmethod = 'b' AND
                      k.castsource = c.casttarget AND
                      k.casttarget = c.castsource);
!  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 ****************
*** src/test/regress/sql/opr_sanity.sql
--- src/test/regress/sql/opr_sanity.sql
***************
*** 25,31 **** 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
   ($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))
--- 25,31 ----
  SELECT ($1 = $2) OR
   EXISTS(select 1 from pg_catalog.pg_cast where
          castsource = $1 and casttarget = $2 and
!         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,43 **** 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
   ($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,43 ----
  SELECT ($1 = $2) OR
   EXISTS(select 1 from pg_catalog.pg_cast where
          castsource = $1 and casttarget = $2 and
!         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,220 **** 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');
  
  -- 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.)
--- 214,229 ----
  
  SELECT *
  FROM pg_cast c
! 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,275 **** WHERE c.castfunc = p.oid AND
  
  SELECT *
  FROM pg_cast c
! WHERE c.castfunc = 0 AND
      NOT EXISTS (SELECT 1 FROM pg_cast k
!                 WHERE k.castfunc = 0 AND
                      k.castsource = c.casttarget AND
                      k.casttarget = c.castsource);
  
--- 276,284 ----
  
  SELECT *
  FROM pg_cast c
! WHERE c.castmethod = 'b' AND
      NOT EXISTS (SELECT 1 FROM pg_cast k
!                 WHERE k.castmethod = 'b' AND
                      k.castsource = c.casttarget AND
                      k.casttarget = c.castsource);
  
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to