Tom Lane wrote:
> Heikki Linnakangas <heikki.linnakangas@enterprisedb.com> 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);