Add support for user-defined I/O conversion casts.

This commit is contained in:
Heikki Linnakangas 2008-10-31 08:39:22 +00:00
parent 34e37d58ed
commit 092bc49653
14 changed files with 396 additions and 269 deletions

View File

@ -1,4 +1,4 @@
<!-- $PostgreSQL: pgsql/doc/src/sgml/catalogs.sgml,v 2.179 2008/10/17 22:10:29 tgl Exp $ --> <!-- $PostgreSQL: pgsql/doc/src/sgml/catalogs.sgml,v 2.180 2008/10/31 08:39:19 heikki Exp $ -->
<!-- <!--
Documentation of the system catalogs, directed toward PostgreSQL developers Documentation of the system catalogs, directed toward PostgreSQL developers
--> -->
@ -1415,9 +1415,10 @@
cannot be deduced from some generic rule. For example, casting between a cannot be deduced from some generic rule. For example, casting between a
domain and its base type is not explicitly represented in domain and its base type is not explicitly represented in
<structname>pg_cast</structname>. Another important exception is that <structname>pg_cast</structname>. Another important exception is that
<quote>I/O conversion casts</>, those performed using a data type's own <quote>automatic I/O conversion casts</>, those performed using a data
I/O functions to convert to or from <type>text</> or other string types, type's own I/O functions to convert to or from <type>text</> or other
are not explicitly represented in <structname>pg_cast</structname>. string types, are not explicitly represented in
<structname>pg_cast</structname>.
</para> </para>
<table> <table>
@ -1454,8 +1455,7 @@
<entry><literal><link linkend="catalog-pg-proc"><structname>pg_proc</structname></link>.oid</literal></entry> <entry><literal><link linkend="catalog-pg-proc"><structname>pg_proc</structname></link>.oid</literal></entry>
<entry> <entry>
The OID of the function to use to perform this cast. Zero is The OID of the function to use to perform this cast. Zero is
stored if the data types are binary coercible (that is, no stored if the cast method doesn't require a function.
run-time operation is needed to perform the cast)
</entry> </entry>
</row> </row>
@ -1473,6 +1473,17 @@
other cases other cases
</entry> </entry>
</row> </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> </tbody>
</tgroup> </tgroup>
</table> </table>

View File

@ -1,4 +1,4 @@
<!-- $PostgreSQL: pgsql/doc/src/sgml/ref/create_cast.sgml,v 1.29 2008/07/30 21:23:17 tgl Exp $ --> <!-- $PostgreSQL: pgsql/doc/src/sgml/ref/create_cast.sgml,v 1.30 2008/10/31 08:39:20 heikki Exp $ -->
<refentry id="SQL-CREATECAST"> <refentry id="SQL-CREATECAST">
<refmeta> <refmeta>
@ -24,6 +24,10 @@ CREATE CAST (<replaceable>sourcetype</replaceable> AS <replaceable>targettype</r
CREATE CAST (<replaceable>sourcetype</replaceable> AS <replaceable>targettype</replaceable>) CREATE CAST (<replaceable>sourcetype</replaceable> AS <replaceable>targettype</replaceable>)
WITHOUT FUNCTION WITHOUT FUNCTION
[ AS ASSIGNMENT | AS IMPLICIT ] [ AS ASSIGNMENT | AS IMPLICIT ]
CREATE CAST (<replaceable>sourcetype</replaceable> AS <replaceable>targettype</replaceable>)
WITH INOUT
[ AS ASSIGNMENT | AS IMPLICIT ]
</synopsis> </synopsis>
</refsynopsisdiv> </refsynopsisdiv>
@ -58,6 +62,13 @@ SELECT CAST(42 AS float8);
binary compatible.) binary compatible.)
</para> </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> <para>
By default, a cast can be invoked only by an explicit cast request, By default, a cast can be invoked only by an explicit cast request,
that is an explicit <literal>CAST(<replaceable>x</> AS that is an explicit <literal>CAST(<replaceable>x</> AS
@ -199,6 +210,18 @@ SELECT CAST ( 2 AS numeric ) + 4.0;
</listitem> </listitem>
</varlistentry> </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> <varlistentry>
<term><literal>AS ASSIGNMENT</literal></term> <term><literal>AS ASSIGNMENT</literal></term>
@ -284,15 +307,12 @@ SELECT CAST ( 2 AS numeric ) + 4.0;
It is normally not necessary to create casts between user-defined types It is normally not necessary to create casts between user-defined types
and the standard string types (<type>text</>, <type>varchar</>, and and the standard string types (<type>text</>, <type>varchar</>, and
<type>char(<replaceable>n</>)</type>, as well as user-defined types that <type>char(<replaceable>n</>)</type>, as well as user-defined types that
are defined to be in the string category). <productname>PostgreSQL</> will are defined to be in the string category). <productname>PostgreSQL</>
automatically handle a cast to a string type by invoking the other provides automatic I/O conversion casts for that. The automatic casts to
type's output function, or conversely handle a cast from a string type string types are treated as assignment casts, while the automatic casts
by invoking the other type's input function. These from string types are
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 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 do so is if you want the conversion to be more easily invokable than the
standard assignment-only or explicit-only setting. Another possible standard assignment-only or explicit-only setting. Another possible
reason is that you want the conversion to behave differently from the reason is that you want the conversion to behave differently from the

View File

@ -10,7 +10,7 @@
* *
* *
* IDENTIFICATION * 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 * DESCRIPTION
* These routines take the parse tree and pick out the * These routines take the parse tree and pick out the
@ -1383,6 +1383,7 @@ CreateCast(CreateCastStmt *stmt)
Oid funcid; Oid funcid;
int nargs; int nargs;
char castcontext; char castcontext;
char castmethod;
Relation relation; Relation relation;
HeapTuple tuple; HeapTuple tuple;
Datum values[Natts_pg_cast]; Datum values[Natts_pg_cast];
@ -1415,7 +1416,15 @@ CreateCast(CreateCastStmt *stmt)
format_type_be(sourcetypeid), format_type_be(sourcetypeid),
format_type_be(targettypeid)))); format_type_be(targettypeid))));
/* Detemine the cast method */
if (stmt->func != NULL) 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; Form_pg_proc procstruct;
@ -1475,6 +1484,12 @@ CreateCast(CreateCastStmt *stmt)
ReleaseSysCache(tuple); ReleaseSysCache(tuple);
} }
else else
{
funcid = InvalidOid;
nargs = 0;
}
if (castmethod == COERCION_METHOD_BINARY)
{ {
int16 typ1len; int16 typ1len;
int16 typ2len; int16 typ2len;
@ -1483,10 +1498,6 @@ CreateCast(CreateCastStmt *stmt)
char typ1align; char typ1align;
char typ2align; char typ2align;
/* indicates binary coercibility */
funcid = InvalidOid;
nargs = 0;
/* /*
* Must be superuser to create binary-compatible casts, since * Must be superuser to create binary-compatible casts, since
* erroneous casts can easily crash the backend. * 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_casttarget - 1] = ObjectIdGetDatum(targettypeid);
values[Anum_pg_cast_castfunc - 1] = ObjectIdGetDatum(funcid); values[Anum_pg_cast_castfunc - 1] = ObjectIdGetDatum(funcid);
values[Anum_pg_cast_castcontext - 1] = CharGetDatum(castcontext); values[Anum_pg_cast_castcontext - 1] = CharGetDatum(castcontext);
values[Anum_pg_cast_castmethod - 1] = CharGetDatum(castmethod);
MemSet(nulls, ' ', Natts_pg_cast); MemSet(nulls, ' ', Natts_pg_cast);

View File

@ -15,7 +15,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * 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(targettype);
COPY_NODE_FIELD(func); COPY_NODE_FIELD(func);
COPY_SCALAR_FIELD(context); COPY_SCALAR_FIELD(context);
COPY_SCALAR_FIELD(inout);
return newnode; return newnode;
} }

View File

@ -22,7 +22,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * 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(targettype);
COMPARE_NODE_FIELD(func); COMPARE_NODE_FIELD(func);
COMPARE_SCALAR_FIELD(context); COMPARE_SCALAR_FIELD(context);
COMPARE_SCALAR_FIELD(inout);
return true; return true;
} }

View File

@ -11,7 +11,7 @@
* *
* *
* IDENTIFICATION * 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 * HISTORY
* AUTHOR DATE MAJOR EVENT * AUTHOR DATE MAJOR EVENT
@ -4590,6 +4590,7 @@ CreateCastStmt: CREATE CAST '(' Typename AS Typename ')'
n->targettype = $6; n->targettype = $6;
n->func = $10; n->func = $10;
n->context = (CoercionContext) $11; n->context = (CoercionContext) $11;
n->inout = false;
$$ = (Node *)n; $$ = (Node *)n;
} }
| CREATE CAST '(' Typename AS Typename ')' | CREATE CAST '(' Typename AS Typename ')'
@ -4600,6 +4601,18 @@ CreateCastStmt: CREATE CAST '(' Typename AS Typename ')'
n->targettype = $6; n->targettype = $6;
n->func = NULL; n->func = NULL;
n->context = (CoercionContext) $10; 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; $$ = (Node *)n;
} }
; ;

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 */ /* Rely on ordering of enum for correct behavior here */
if (ccontext >= castcontext) if (ccontext >= castcontext)
{ {
*funcid = castForm->castfunc; switch (castForm->castmethod)
if (OidIsValid(*funcid)) {
case COERCION_METHOD_FUNCTION:
result = COERCION_PATH_FUNC; result = COERCION_PATH_FUNC;
else *funcid = castForm->castfunc;
break;
case COERCION_METHOD_INOUT:
result = COERCION_PATH_COERCEVIAIO;
break;
case COERCION_METHOD_BINARY:
result = COERCION_PATH_RELABELTYPE; result = COERCION_PATH_RELABELTYPE;
break;
default:
elog(ERROR, "unrecognized castmethod: %d",
(int) castForm->castmethod);
break;
}
} }
ReleaseSysCache(tuple); ReleaseSysCache(tuple);

View File

@ -12,7 +12,7 @@
* by PostgreSQL * by PostgreSQL
* *
* IDENTIFICATION * 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/attnum.h"
#include "access/sysattr.h" #include "access/sysattr.h"
#include "catalog/pg_cast.h"
#include "catalog/pg_class.h" #include "catalog/pg_class.h"
#include "catalog/pg_proc.h" #include "catalog/pg_proc.h"
#include "catalog/pg_trigger.h" #include "catalog/pg_trigger.h"
@ -4410,21 +4411,31 @@ getCasts(int *numCasts)
int i_casttarget; int i_casttarget;
int i_castfunc; int i_castfunc;
int i_castcontext; int i_castcontext;
int i_castmethod;
/* Make sure we are in proper schema */ /* Make sure we are in proper schema */
selectSourceSchema("pg_catalog"); selectSourceSchema("pg_catalog");
if (g_fout->remoteVersion >= 70300) if (g_fout->remoteVersion >= 80400)
{ {
appendPQExpBuffer(query, "SELECT tableoid, oid, " appendPQExpBuffer(query, "SELECT tableoid, oid, "
"castsource, casttarget, castfunc, castcontext " "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 AS castmethod "
"FROM pg_cast ORDER BY 3,4"); "FROM pg_cast ORDER BY 3,4");
} }
else else
{ {
appendPQExpBuffer(query, "SELECT 0 as tableoid, p.oid, " appendPQExpBuffer(query, "SELECT 0 as tableoid, p.oid, "
"t1.oid as castsource, t2.oid as casttarget, " "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 " "FROM pg_type t1, pg_type t2, pg_proc p "
"WHERE p.pronargs = 1 AND " "WHERE p.pronargs = 1 AND "
"p.proargtypes[0] = t1.oid AND " "p.proargtypes[0] = t1.oid AND "
@ -4447,6 +4458,7 @@ getCasts(int *numCasts)
i_casttarget = PQfnumber(res, "casttarget"); i_casttarget = PQfnumber(res, "casttarget");
i_castfunc = PQfnumber(res, "castfunc"); i_castfunc = PQfnumber(res, "castfunc");
i_castcontext = PQfnumber(res, "castcontext"); i_castcontext = PQfnumber(res, "castcontext");
i_castmethod = PQfnumber(res, "castmethod");
for (i = 0; i < ntups; i++) for (i = 0; i < ntups; i++)
{ {
@ -4462,6 +4474,7 @@ getCasts(int *numCasts)
castinfo[i].casttarget = atooid(PQgetvalue(res, i, i_casttarget)); castinfo[i].casttarget = atooid(PQgetvalue(res, i, i_casttarget));
castinfo[i].castfunc = atooid(PQgetvalue(res, i, i_castfunc)); castinfo[i].castfunc = atooid(PQgetvalue(res, i, i_castfunc));
castinfo[i].castcontext = *(PQgetvalue(res, i, i_castcontext)); 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 * 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->castsource, zeroAsNone),
getFormattedTypeName(cast->casttarget, zeroAsNone)); getFormattedTypeName(cast->casttarget, zeroAsNone));
if (!OidIsValid(cast->castfunc)) switch(cast->castmethod)
appendPQExpBuffer(defqry, "WITHOUT FUNCTION");
else
{ {
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 * Always qualify the function name, in case it is not in
* schema (format_function_signature won't qualify it). * pg_catalog schema (format_function_signature won't qualify it).
*/ */
appendPQExpBuffer(defqry, "WITH FUNCTION %s.", appendPQExpBuffer(defqry, "WITH FUNCTION %s.",
fmtId(funcInfo->dobj.namespace->dobj.name)); fmtId(funcInfo->dobj.namespace->dobj.name));
appendPQExpBuffer(defqry, "%s", appendPQExpBuffer(defqry, "%s",
format_function_signature(funcInfo, true)); format_function_signature(funcInfo, true));
break;
default:
write_msg(NULL, "WARNING: bogus value in pg_cast.castmethod field\n");
} }
if (cast->castcontext == 'a') if (cast->castcontext == 'a')

View File

@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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 casttarget;
Oid castfunc; Oid castfunc;
char castcontext; char castcontext;
char castmethod;
} CastInfo; } CastInfo;
/* InhInfo isn't a DumpableObject, just temporary state */ /* InhInfo isn't a DumpableObject, just temporary state */

View File

@ -37,7 +37,7 @@
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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 */ /* yyyymmddN */
#define CATALOG_VERSION_NO 200810171 #define CATALOG_VERSION_NO 200810311
#endif #endif

View File

@ -10,7 +10,7 @@
* *
* Copyright (c) 2002-2008, PostgreSQL Global Development Group * 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 * NOTES
* the genbki.sh script reads this file and generates .bki * 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 casttarget; /* destination datatype for cast */
Oid castfunc; /* cast function; 0 = binary coercible */ Oid castfunc; /* cast function; 0 = binary coercible */
char castcontext; /* contexts in which cast can be used */ char castcontext; /* contexts in which cast can be used */
char castmethod; /* cast method */
} FormData_pg_cast; } FormData_pg_cast;
typedef FormData_pg_cast *Form_pg_cast; typedef FormData_pg_cast *Form_pg_cast;
@ -56,16 +57,29 @@ typedef enum CoercionCodes
COERCION_CODE_EXPLICIT = 'e' /* explicit cast operation */ COERCION_CODE_EXPLICIT = 'e' /* explicit cast operation */
} CoercionCodes; } 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 * 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_castsource 1
#define Anum_pg_cast_casttarget 2 #define Anum_pg_cast_casttarget 2
#define Anum_pg_cast_castfunc 3 #define Anum_pg_cast_castfunc 3
#define Anum_pg_cast_castcontext 4 #define Anum_pg_cast_castcontext 4
#define Anum_pg_cast_castmethod 5
/* ---------------- /* ----------------
* initial contents of pg_cast * initial contents of pg_cast
@ -80,40 +94,40 @@ typedef enum CoercionCodes
* int2->int4->int8->numeric->float4->float8, while casts in the * int2->int4->int8->numeric->float4->float8, while casts in the
* reverse direction are assignment-only. * reverse direction are assignment-only.
*/ */
DATA(insert ( 20 21 714 a )); DATA(insert ( 20 21 714 a f ));
DATA(insert ( 20 23 480 a )); DATA(insert ( 20 23 480 a f ));
DATA(insert ( 20 700 652 i )); DATA(insert ( 20 700 652 i f ));
DATA(insert ( 20 701 482 i )); DATA(insert ( 20 701 482 i f ));
DATA(insert ( 20 1700 1781 i )); DATA(insert ( 20 1700 1781 i f ));
DATA(insert ( 21 20 754 i )); DATA(insert ( 21 20 754 i f ));
DATA(insert ( 21 23 313 i )); DATA(insert ( 21 23 313 i f ));
DATA(insert ( 21 700 236 i )); DATA(insert ( 21 700 236 i f ));
DATA(insert ( 21 701 235 i )); DATA(insert ( 21 701 235 i f ));
DATA(insert ( 21 1700 1782 i )); DATA(insert ( 21 1700 1782 i f ));
DATA(insert ( 23 20 481 i )); DATA(insert ( 23 20 481 i f ));
DATA(insert ( 23 21 314 a )); DATA(insert ( 23 21 314 a f ));
DATA(insert ( 23 700 318 i )); DATA(insert ( 23 700 318 i f ));
DATA(insert ( 23 701 316 i )); DATA(insert ( 23 701 316 i f ));
DATA(insert ( 23 1700 1740 i )); DATA(insert ( 23 1700 1740 i f ));
DATA(insert ( 700 20 653 a )); DATA(insert ( 700 20 653 a f ));
DATA(insert ( 700 21 238 a )); DATA(insert ( 700 21 238 a f ));
DATA(insert ( 700 23 319 a )); DATA(insert ( 700 23 319 a f ));
DATA(insert ( 700 701 311 i )); DATA(insert ( 700 701 311 i f ));
DATA(insert ( 700 1700 1742 a )); DATA(insert ( 700 1700 1742 a f ));
DATA(insert ( 701 20 483 a )); DATA(insert ( 701 20 483 a f ));
DATA(insert ( 701 21 237 a )); DATA(insert ( 701 21 237 a f ));
DATA(insert ( 701 23 317 a )); DATA(insert ( 701 23 317 a f ));
DATA(insert ( 701 700 312 a )); DATA(insert ( 701 700 312 a f ));
DATA(insert ( 701 1700 1743 a )); DATA(insert ( 701 1700 1743 a f ));
DATA(insert ( 1700 20 1779 a )); DATA(insert ( 1700 20 1779 a f ));
DATA(insert ( 1700 21 1783 a )); DATA(insert ( 1700 21 1783 a f ));
DATA(insert ( 1700 23 1744 a )); DATA(insert ( 1700 23 1744 a f ));
DATA(insert ( 1700 700 1745 i )); DATA(insert ( 1700 700 1745 i f ));
DATA(insert ( 1700 701 1746 i )); DATA(insert ( 1700 701 1746 i f ));
/* Allow explicit coercions between int4 and bool */ /* Allow explicit coercions between int4 and bool */
DATA(insert ( 23 16 2557 e )); DATA(insert ( 23 16 2557 e f ));
DATA(insert ( 16 23 2558 e )); DATA(insert ( 16 23 2558 e f ));
/* /*
* OID category: allow implicit conversion from any integral type (including * 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 * casts from text and varchar to regclass, which exist mainly to support
* legacy forms of nextval() and related functions. * legacy forms of nextval() and related functions.
*/ */
DATA(insert ( 20 26 1287 i )); DATA(insert ( 20 26 1287 i f ));
DATA(insert ( 21 26 313 i )); DATA(insert ( 21 26 313 i f ));
DATA(insert ( 23 26 0 i )); DATA(insert ( 23 26 0 i b ));
DATA(insert ( 26 20 1288 a )); DATA(insert ( 26 20 1288 a f ));
DATA(insert ( 26 23 0 a )); DATA(insert ( 26 23 0 a b ));
DATA(insert ( 26 24 0 i )); DATA(insert ( 26 24 0 i b ));
DATA(insert ( 24 26 0 i )); DATA(insert ( 24 26 0 i b ));
DATA(insert ( 20 24 1287 i )); DATA(insert ( 20 24 1287 i f ));
DATA(insert ( 21 24 313 i )); DATA(insert ( 21 24 313 i f ));
DATA(insert ( 23 24 0 i )); DATA(insert ( 23 24 0 i b ));
DATA(insert ( 24 20 1288 a )); DATA(insert ( 24 20 1288 a f ));
DATA(insert ( 24 23 0 a )); DATA(insert ( 24 23 0 a b ));
DATA(insert ( 24 2202 0 i )); DATA(insert ( 24 2202 0 i b ));
DATA(insert ( 2202 24 0 i )); DATA(insert ( 2202 24 0 i b ));
DATA(insert ( 26 2202 0 i )); DATA(insert ( 26 2202 0 i b ));
DATA(insert ( 2202 26 0 i )); DATA(insert ( 2202 26 0 i b ));
DATA(insert ( 20 2202 1287 i )); DATA(insert ( 20 2202 1287 i f ));
DATA(insert ( 21 2202 313 i )); DATA(insert ( 21 2202 313 i f ));
DATA(insert ( 23 2202 0 i )); DATA(insert ( 23 2202 0 i b ));
DATA(insert ( 2202 20 1288 a )); DATA(insert ( 2202 20 1288 a f ));
DATA(insert ( 2202 23 0 a )); DATA(insert ( 2202 23 0 a b ));
DATA(insert ( 26 2203 0 i )); DATA(insert ( 26 2203 0 i b ));
DATA(insert ( 2203 26 0 i )); DATA(insert ( 2203 26 0 i b ));
DATA(insert ( 20 2203 1287 i )); DATA(insert ( 20 2203 1287 i f ));
DATA(insert ( 21 2203 313 i )); DATA(insert ( 21 2203 313 i f ));
DATA(insert ( 23 2203 0 i )); DATA(insert ( 23 2203 0 i b ));
DATA(insert ( 2203 20 1288 a )); DATA(insert ( 2203 20 1288 a f ));
DATA(insert ( 2203 23 0 a )); DATA(insert ( 2203 23 0 a b ));
DATA(insert ( 2203 2204 0 i )); DATA(insert ( 2203 2204 0 i b ));
DATA(insert ( 2204 2203 0 i )); DATA(insert ( 2204 2203 0 i b ));
DATA(insert ( 26 2204 0 i )); DATA(insert ( 26 2204 0 i b ));
DATA(insert ( 2204 26 0 i )); DATA(insert ( 2204 26 0 i b ));
DATA(insert ( 20 2204 1287 i )); DATA(insert ( 20 2204 1287 i f ));
DATA(insert ( 21 2204 313 i )); DATA(insert ( 21 2204 313 i f ));
DATA(insert ( 23 2204 0 i )); DATA(insert ( 23 2204 0 i b ));
DATA(insert ( 2204 20 1288 a )); DATA(insert ( 2204 20 1288 a f ));
DATA(insert ( 2204 23 0 a )); DATA(insert ( 2204 23 0 a b ));
DATA(insert ( 26 2205 0 i )); DATA(insert ( 26 2205 0 i b ));
DATA(insert ( 2205 26 0 i )); DATA(insert ( 2205 26 0 i b ));
DATA(insert ( 20 2205 1287 i )); DATA(insert ( 20 2205 1287 i f ));
DATA(insert ( 21 2205 313 i )); DATA(insert ( 21 2205 313 i f ));
DATA(insert ( 23 2205 0 i )); DATA(insert ( 23 2205 0 i b ));
DATA(insert ( 2205 20 1288 a )); DATA(insert ( 2205 20 1288 a f ));
DATA(insert ( 2205 23 0 a )); DATA(insert ( 2205 23 0 a b ));
DATA(insert ( 26 2206 0 i )); DATA(insert ( 26 2206 0 i b ));
DATA(insert ( 2206 26 0 i )); DATA(insert ( 2206 26 0 i b ));
DATA(insert ( 20 2206 1287 i )); DATA(insert ( 20 2206 1287 i f ));
DATA(insert ( 21 2206 313 i )); DATA(insert ( 21 2206 313 i f ));
DATA(insert ( 23 2206 0 i )); DATA(insert ( 23 2206 0 i b ));
DATA(insert ( 2206 20 1288 a )); DATA(insert ( 2206 20 1288 a f ));
DATA(insert ( 2206 23 0 a )); DATA(insert ( 2206 23 0 a b ));
DATA(insert ( 26 3734 0 i )); DATA(insert ( 26 3734 0 i b ));
DATA(insert ( 3734 26 0 i )); DATA(insert ( 3734 26 0 i b ));
DATA(insert ( 20 3734 1287 i )); DATA(insert ( 20 3734 1287 i f ));
DATA(insert ( 21 3734 313 i )); DATA(insert ( 21 3734 313 i f ));
DATA(insert ( 23 3734 0 i )); DATA(insert ( 23 3734 0 i b ));
DATA(insert ( 3734 20 1288 a )); DATA(insert ( 3734 20 1288 a f ));
DATA(insert ( 3734 23 0 a )); DATA(insert ( 3734 23 0 a b ));
DATA(insert ( 26 3769 0 i )); DATA(insert ( 26 3769 0 i b ));
DATA(insert ( 3769 26 0 i )); DATA(insert ( 3769 26 0 i b ));
DATA(insert ( 20 3769 1287 i )); DATA(insert ( 20 3769 1287 i f ));
DATA(insert ( 21 3769 313 i )); DATA(insert ( 21 3769 313 i f ));
DATA(insert ( 23 3769 0 i )); DATA(insert ( 23 3769 0 i b ));
DATA(insert ( 3769 20 1288 a )); DATA(insert ( 3769 20 1288 a f ));
DATA(insert ( 3769 23 0 a )); DATA(insert ( 3769 23 0 a b ));
DATA(insert ( 25 2205 1079 i )); DATA(insert ( 25 2205 1079 i f ));
DATA(insert ( 1043 2205 1079 i )); DATA(insert ( 1043 2205 1079 i f ));
/* /*
* String category * String category
*/ */
DATA(insert ( 25 1042 0 i )); DATA(insert ( 25 1042 0 i b ));
DATA(insert ( 25 1043 0 i )); DATA(insert ( 25 1043 0 i b ));
DATA(insert ( 1042 25 401 i )); DATA(insert ( 1042 25 401 i f ));
DATA(insert ( 1042 1043 401 i )); DATA(insert ( 1042 1043 401 i f ));
DATA(insert ( 1043 25 0 i )); DATA(insert ( 1043 25 0 i b ));
DATA(insert ( 1043 1042 0 i )); DATA(insert ( 1043 1042 0 i b ));
DATA(insert ( 18 25 946 i )); DATA(insert ( 18 25 946 i f ));
DATA(insert ( 18 1042 860 a )); DATA(insert ( 18 1042 860 a f ));
DATA(insert ( 18 1043 946 a )); DATA(insert ( 18 1043 946 a f ));
DATA(insert ( 19 25 406 i )); DATA(insert ( 19 25 406 i f ));
DATA(insert ( 19 1042 408 a )); DATA(insert ( 19 1042 408 a f ));
DATA(insert ( 19 1043 1401 a )); DATA(insert ( 19 1043 1401 a f ));
DATA(insert ( 25 18 944 a )); DATA(insert ( 25 18 944 a f ));
DATA(insert ( 1042 18 944 a )); DATA(insert ( 1042 18 944 a f ));
DATA(insert ( 1043 18 944 a )); DATA(insert ( 1043 18 944 a f ));
DATA(insert ( 25 19 407 i )); DATA(insert ( 25 19 407 i f ));
DATA(insert ( 1042 19 409 i )); DATA(insert ( 1042 19 409 i f ));
DATA(insert ( 1043 19 1400 i )); DATA(insert ( 1043 19 1400 i f ));
/* Allow explicit coercions between int4 and "char" */ /* Allow explicit coercions between int4 and "char" */
DATA(insert ( 18 23 77 e )); DATA(insert ( 18 23 77 e f ));
DATA(insert ( 23 18 78 e )); DATA(insert ( 23 18 78 e f ));
/* /*
* Datetime category * Datetime category
*/ */
DATA(insert ( 702 1082 1179 a )); DATA(insert ( 702 1082 1179 a f ));
DATA(insert ( 702 1083 1364 a )); DATA(insert ( 702 1083 1364 a f ));
DATA(insert ( 702 1114 2023 i )); DATA(insert ( 702 1114 2023 i f ));
DATA(insert ( 702 1184 1173 i )); DATA(insert ( 702 1184 1173 i f ));
DATA(insert ( 703 1186 1177 i )); DATA(insert ( 703 1186 1177 i f ));
DATA(insert ( 1082 1114 2024 i )); DATA(insert ( 1082 1114 2024 i f ));
DATA(insert ( 1082 1184 1174 i )); DATA(insert ( 1082 1184 1174 i f ));
DATA(insert ( 1083 1186 1370 i )); DATA(insert ( 1083 1186 1370 i f ));
DATA(insert ( 1083 1266 2047 i )); DATA(insert ( 1083 1266 2047 i f ));
DATA(insert ( 1114 702 2030 a )); DATA(insert ( 1114 702 2030 a f ));
DATA(insert ( 1114 1082 2029 a )); DATA(insert ( 1114 1082 2029 a f ));
DATA(insert ( 1114 1083 1316 a )); DATA(insert ( 1114 1083 1316 a f ));
DATA(insert ( 1114 1184 2028 i )); DATA(insert ( 1114 1184 2028 i f ));
DATA(insert ( 1184 702 1180 a )); DATA(insert ( 1184 702 1180 a f ));
DATA(insert ( 1184 1082 1178 a )); DATA(insert ( 1184 1082 1178 a f ));
DATA(insert ( 1184 1083 2019 a )); DATA(insert ( 1184 1083 2019 a f ));
DATA(insert ( 1184 1114 2027 a )); DATA(insert ( 1184 1114 2027 a f ));
DATA(insert ( 1184 1266 1388 a )); DATA(insert ( 1184 1266 1388 a f ));
DATA(insert ( 1186 703 1194 a )); DATA(insert ( 1186 703 1194 a f ));
DATA(insert ( 1186 1083 1419 a )); DATA(insert ( 1186 1083 1419 a f ));
DATA(insert ( 1266 1083 2046 a )); DATA(insert ( 1266 1083 2046 a f ));
/* Cross-category casts between int4 and abstime, reltime */ /* Cross-category casts between int4 and abstime, reltime */
DATA(insert ( 23 702 0 e )); DATA(insert ( 23 702 0 e b ));
DATA(insert ( 702 23 0 e )); DATA(insert ( 702 23 0 e b ));
DATA(insert ( 23 703 0 e )); DATA(insert ( 23 703 0 e b ));
DATA(insert ( 703 23 0 e )); DATA(insert ( 703 23 0 e b ));
/* /*
* Geometric category * Geometric category
*/ */
DATA(insert ( 601 600 1532 e )); DATA(insert ( 601 600 1532 e f ));
DATA(insert ( 602 600 1533 e )); DATA(insert ( 602 600 1533 e f ));
DATA(insert ( 602 604 1449 a )); DATA(insert ( 602 604 1449 a f ));
DATA(insert ( 603 600 1534 e )); DATA(insert ( 603 600 1534 e f ));
DATA(insert ( 603 601 1541 e )); DATA(insert ( 603 601 1541 e f ));
DATA(insert ( 603 604 1448 a )); DATA(insert ( 603 604 1448 a f ));
DATA(insert ( 603 718 1479 e )); DATA(insert ( 603 718 1479 e f ));
DATA(insert ( 604 600 1540 e )); DATA(insert ( 604 600 1540 e f ));
DATA(insert ( 604 602 1447 a )); DATA(insert ( 604 602 1447 a f ));
DATA(insert ( 604 603 1446 e )); DATA(insert ( 604 603 1446 e f ));
DATA(insert ( 604 718 1474 e )); DATA(insert ( 604 718 1474 e f ));
DATA(insert ( 718 600 1416 e )); DATA(insert ( 718 600 1416 e f ));
DATA(insert ( 718 603 1480 e )); DATA(insert ( 718 603 1480 e f ));
DATA(insert ( 718 604 1544 e )); DATA(insert ( 718 604 1544 e f ));
/* /*
* INET category * INET category
*/ */
DATA(insert ( 650 869 0 i )); DATA(insert ( 650 869 0 i b ));
DATA(insert ( 869 650 1715 a )); DATA(insert ( 869 650 1715 a f ));
/* /*
* BitString category * BitString category
*/ */
DATA(insert ( 1560 1562 0 i )); DATA(insert ( 1560 1562 0 i b ));
DATA(insert ( 1562 1560 0 i )); DATA(insert ( 1562 1560 0 i b ));
/* Cross-category casts between bit and int4, int8 */ /* Cross-category casts between bit and int4, int8 */
DATA(insert ( 20 1560 2075 e )); DATA(insert ( 20 1560 2075 e f ));
DATA(insert ( 23 1560 1683 e )); DATA(insert ( 23 1560 1683 e f ));
DATA(insert ( 1560 20 2076 e )); DATA(insert ( 1560 20 2076 e f ));
DATA(insert ( 1560 23 1684 e )); DATA(insert ( 1560 23 1684 e f ));
/* /*
* Cross-category casts to and from TEXT * 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 * behavior will ensue when the automatic cast is applied instead of the
* pg_cast entry! * pg_cast entry!
*/ */
DATA(insert ( 650 25 730 a )); DATA(insert ( 650 25 730 a f ));
DATA(insert ( 869 25 730 a )); DATA(insert ( 869 25 730 a f ));
DATA(insert ( 16 25 2971 a )); DATA(insert ( 16 25 2971 a f ));
DATA(insert ( 142 25 0 a )); DATA(insert ( 142 25 0 a b ));
DATA(insert ( 25 142 2896 e )); DATA(insert ( 25 142 2896 e f ));
/* /*
* Cross-category casts to and from VARCHAR * Cross-category casts to and from VARCHAR
* *
* We support all the same casts as for TEXT. * We support all the same casts as for TEXT.
*/ */
DATA(insert ( 650 1043 730 a )); DATA(insert ( 650 1043 730 a f ));
DATA(insert ( 869 1043 730 a )); DATA(insert ( 869 1043 730 a f ));
DATA(insert ( 16 1043 2971 a )); DATA(insert ( 16 1043 2971 a f ));
DATA(insert ( 142 1043 0 a )); DATA(insert ( 142 1043 0 a b ));
DATA(insert ( 1043 142 2896 e )); DATA(insert ( 1043 142 2896 e f ));
/* /*
* Cross-category casts to and from BPCHAR * Cross-category casts to and from BPCHAR
* *
* We support all the same casts as for TEXT. * We support all the same casts as for TEXT.
*/ */
DATA(insert ( 650 1042 730 a )); DATA(insert ( 650 1042 730 a f ));
DATA(insert ( 869 1042 730 a )); DATA(insert ( 869 1042 730 a f ));
DATA(insert ( 16 1042 2971 a )); DATA(insert ( 16 1042 2971 a f ));
DATA(insert ( 142 1042 0 a )); DATA(insert ( 142 1042 0 a b ));
DATA(insert ( 1042 142 2896 e )); DATA(insert ( 1042 142 2896 e f ));
/* /*
* Length-coercion functions * Length-coercion functions
*/ */
DATA(insert ( 1042 1042 668 i )); DATA(insert ( 1042 1042 668 i f ));
DATA(insert ( 1043 1043 669 i )); DATA(insert ( 1043 1043 669 i f ));
DATA(insert ( 1083 1083 1968 i )); DATA(insert ( 1083 1083 1968 i f ));
DATA(insert ( 1114 1114 1961 i )); DATA(insert ( 1114 1114 1961 i f ));
DATA(insert ( 1184 1184 1967 i )); DATA(insert ( 1184 1184 1967 i f ));
DATA(insert ( 1186 1186 1200 i )); DATA(insert ( 1186 1186 1200 i f ));
DATA(insert ( 1266 1266 1969 i )); DATA(insert ( 1266 1266 1969 i f ));
DATA(insert ( 1560 1560 1685 i )); DATA(insert ( 1560 1560 1685 i f ));
DATA(insert ( 1562 1562 1687 i )); DATA(insert ( 1562 1562 1687 i f ));
DATA(insert ( 1700 1700 1703 i )); DATA(insert ( 1700 1700 1703 i f ));
#endif /* PG_CAST_H */ #endif /* PG_CAST_H */

View File

@ -13,7 +13,7 @@
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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; TypeName *targettype;
FuncWithArgs *func; FuncWithArgs *func;
CoercionContext context; CoercionContext context;
bool inout;
} CreateCastStmt; } CreateCastStmt;
/* ---------------------- /* ----------------------

View File

@ -22,7 +22,7 @@ create function binary_coercible(oid, oid) returns bool as $$
SELECT ($1 = $2) OR SELECT ($1 = $2) OR
EXISTS(select 1 from pg_catalog.pg_cast where EXISTS(select 1 from pg_catalog.pg_cast where
castsource = $1 and casttarget = $2 and 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 ($2 = 'pg_catalog.anyarray'::pg_catalog.regtype AND
EXISTS(select 1 from pg_catalog.pg_type where EXISTS(select 1 from pg_catalog.pg_type where
oid = $1 and typelem != 0 and typlen = -1)) 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 SELECT ($1 = $2) OR
EXISTS(select 1 from pg_catalog.pg_cast where EXISTS(select 1 from pg_catalog.pg_cast where
castsource = $1 and casttarget = $2 and castsource = $1 and casttarget = $2 and
castfunc = 0) OR castmethod = 'b') OR
($2 = 'pg_catalog.anyarray'::pg_catalog.regtype AND ($2 = 'pg_catalog.anyarray'::pg_catalog.regtype AND
EXISTS(select 1 from pg_catalog.pg_type where EXISTS(select 1 from pg_catalog.pg_type where
oid = $1 and typelem != 0 and typlen = -1)) oid = $1 and typelem != 0 and typlen = -1))
@ -262,9 +262,20 @@ WHERE p1.prorettype = 'internal'::regtype AND NOT
-- oidjoins test). -- oidjoins test).
SELECT * SELECT *
FROM pg_cast c 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')
castsource | casttarget | castfunc | castcontext 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) (0 rows)
-- Look for casts to/from the same type that aren't length coercion functions. -- 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 * SELECT *
FROM pg_cast c FROM pg_cast c
WHERE castsource = casttarget AND castfunc = 0; WHERE castsource = casttarget AND castfunc = 0;
castsource | casttarget | castfunc | castcontext castsource | casttarget | castfunc | castcontext | castmethod
------------+------------+----------+------------- ------------+------------+----------+-------------+------------
(0 rows) (0 rows)
SELECT c.* SELECT c.*
FROM pg_cast c, pg_proc p FROM pg_cast c, pg_proc p
WHERE c.castfunc = p.oid AND p.pronargs < 2 AND castsource = casttarget; WHERE c.castfunc = p.oid AND p.pronargs < 2 AND castsource = casttarget;
castsource | casttarget | castfunc | castcontext castsource | casttarget | castfunc | castcontext | castmethod
------------+------------+----------+------------- ------------+------------+----------+-------------+------------
(0 rows) (0 rows)
-- Look for cast functions that don't have the right signature. The -- 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 OR (c.castsource = 'character'::regtype AND
p.proargtypes[0] = 'text'::regtype)) p.proargtypes[0] = 'text'::regtype))
OR NOT binary_coercible(p.prorettype, c.casttarget)); OR NOT binary_coercible(p.prorettype, c.casttarget));
castsource | casttarget | castfunc | castcontext castsource | casttarget | castfunc | castcontext | castmethod
------------+------------+----------+------------- ------------+------------+----------+-------------+------------
(0 rows) (0 rows)
SELECT c.* SELECT c.*
@ -308,8 +319,8 @@ FROM pg_cast c, pg_proc p
WHERE c.castfunc = p.oid AND WHERE c.castfunc = p.oid AND
((p.pronargs > 1 AND p.proargtypes[1] != 'int4'::regtype) OR ((p.pronargs > 1 AND p.proargtypes[1] != 'int4'::regtype) OR
(p.pronargs > 2 AND p.proargtypes[2] != 'bool'::regtype)); (p.pronargs > 2 AND p.proargtypes[2] != 'bool'::regtype));
castsource | casttarget | castfunc | castcontext castsource | casttarget | castfunc | castcontext | castmethod
------------+------------+----------+------------- ------------+------------+----------+-------------+------------
(0 rows) (0 rows)
-- Look for binary compatible casts that do not have the reverse -- 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. -- texttoxml(), which does an XML syntax check.
SELECT * SELECT *
FROM pg_cast c FROM pg_cast c
WHERE c.castfunc = 0 AND WHERE c.castmethod = 'b' AND
NOT EXISTS (SELECT 1 FROM pg_cast k NOT EXISTS (SELECT 1 FROM pg_cast k
WHERE k.castfunc = 0 AND WHERE k.castmethod = 'b' AND
k.castsource = c.casttarget AND k.castsource = c.casttarget AND
k.casttarget = c.castsource); k.casttarget = c.castsource);
castsource | casttarget | castfunc | castcontext castsource | casttarget | castfunc | castcontext | castmethod
------------+------------+----------+------------- ------------+------------+----------+-------------+------------
25 | 1042 | 0 | i 25 | 1042 | 0 | i | b
1043 | 1042 | 0 | i 1043 | 1042 | 0 | i | b
650 | 869 | 0 | i 650 | 869 | 0 | i | b
142 | 25 | 0 | a 142 | 25 | 0 | a | b
142 | 1043 | 0 | a 142 | 1043 | 0 | a | b
142 | 1042 | 0 | a 142 | 1042 | 0 | a | b
(6 rows) (6 rows)
-- **************** pg_operator **************** -- **************** pg_operator ****************

View File

@ -25,7 +25,7 @@ create function binary_coercible(oid, oid) returns bool as $$
SELECT ($1 = $2) OR SELECT ($1 = $2) OR
EXISTS(select 1 from pg_catalog.pg_cast where EXISTS(select 1 from pg_catalog.pg_cast where
castsource = $1 and casttarget = $2 and 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 ($2 = 'pg_catalog.anyarray'::pg_catalog.regtype AND
EXISTS(select 1 from pg_catalog.pg_type where EXISTS(select 1 from pg_catalog.pg_type where
oid = $1 and typelem != 0 and typlen = -1)) 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 SELECT ($1 = $2) OR
EXISTS(select 1 from pg_catalog.pg_cast where EXISTS(select 1 from pg_catalog.pg_cast where
castsource = $1 and casttarget = $2 and castsource = $1 and casttarget = $2 and
castfunc = 0) OR castmethod = 'b') OR
($2 = 'pg_catalog.anyarray'::pg_catalog.regtype AND ($2 = 'pg_catalog.anyarray'::pg_catalog.regtype AND
EXISTS(select 1 from pg_catalog.pg_type where EXISTS(select 1 from pg_catalog.pg_type where
oid = $1 and typelem != 0 and typlen = -1)) oid = $1 and typelem != 0 and typlen = -1))
@ -214,7 +214,16 @@ WHERE p1.prorettype = 'internal'::regtype AND NOT
SELECT * SELECT *
FROM pg_cast c 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. -- 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.) -- (We assume they are length coercions if they take multiple arguments.)
@ -267,9 +276,9 @@ WHERE c.castfunc = p.oid AND
SELECT * SELECT *
FROM pg_cast c FROM pg_cast c
WHERE c.castfunc = 0 AND WHERE c.castmethod = 'b' AND
NOT EXISTS (SELECT 1 FROM pg_cast k NOT EXISTS (SELECT 1 FROM pg_cast k
WHERE k.castfunc = 0 AND WHERE k.castmethod = 'b' AND
k.castsource = c.casttarget AND k.castsource = c.casttarget AND
k.casttarget = c.castsource); k.casttarget = c.castsource);