Re: User defined I/O conversion casts
От | Heikki Linnakangas |
---|---|
Тема | Re: User defined I/O conversion casts |
Дата | |
Msg-id | 490A138E.80100@enterprisedb.com обсуждение исходный текст |
Ответ на | Re: User defined I/O conversion casts (Tom Lane <tgl@sss.pgh.pa.us>) |
Ответы |
Re: User defined I/O conversion casts
(Tom Lane <tgl@sss.pgh.pa.us>)
|
Список | pgsql-hackers |
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);
В списке pgsql-hackers по дате отправления: