Since 8.3, the system provides automatic I/O conversion casts between
the built-in string types and other types, but there's currently no way
for a user to declare additional casts using the I/O functions. You can
always create a simple SQL function to do that, but it seems like we
should provide a direct interface for that. I propose the syntax:
CREATE CAST (<source> AS <target>) WITH INOUT [AS IMPLICIT | AS ASSIGNMENT]
Conveniently, INOUT is already a col_name_keyword, so this works without
any conflicts or new keywords.
This would be very useful for those who want relax some built-in
automatic assignment casts to implicit casts, 8.2 style, as well as
anyone creating a user-defined data type with casts that can be
implemented with the I/O functions.
Patch attached. I'm using a magic OID "1" in pg_cast.castfunc field to
mark these extra I/O conversion casts. Perhaps we want to have a
separate field for that or something, but that was a quick way to get
started.
Anyone else think this is a good idea? Thoughts on the implementation?
--
Heikki Linnakangas
EnterpriseDB http://www.enterprisedb.com
Index: src/backend/commands/functioncmds.c
===================================================================
RCS file: /home/hlinnaka/pgcvsrepository/pgsql/src/backend/commands/functioncmds.c,v
retrieving revision 1.98
diff -c -r1.98 functioncmds.c
*** src/backend/commands/functioncmds.c 18 Jul 2008 03:32:52 -0000 1.98
--- src/backend/commands/functioncmds.c 29 Aug 2008 10:56:49 -0000
***************
*** 1474,1479 ****
--- 1474,1481 ----
ReleaseSysCache(tuple);
}
+ else if (stmt->coerceviaio)
+ funcid = IOCOERCE_FUNCOID;
else
{
int16 typ1len;
***************
*** 1589,1595 ****
recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
/* dependency on function */
! if (OidIsValid(funcid))
{
referenced.classId = ProcedureRelationId;
referenced.objectId = funcid;
--- 1591,1597 ----
recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
/* dependency on function */
! if (OidIsValid(funcid) && funcid != IOCOERCE_FUNCOID)
{
referenced.classId = ProcedureRelationId;
referenced.objectId = funcid;
Index: src/backend/parser/gram.y
===================================================================
RCS file: /home/hlinnaka/pgcvsrepository/pgsql/src/backend/parser/gram.y,v
retrieving revision 2.618
diff -c -r2.618 gram.y
*** src/backend/parser/gram.y 18 Jul 2008 03:32:52 -0000 2.618
--- src/backend/parser/gram.y 29 Aug 2008 09:29:22 -0000
***************
*** 4534,4539 ****
--- 4534,4550 ----
n->context = (CoercionContext) $10;
$$ = (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->coerceviaio = true;
+ n->context = (CoercionContext) $10;
+ $$ = (Node *)n;
+ }
;
cast_context: AS IMPLICIT_P { $$ = COERCION_IMPLICIT; }
Index: src/backend/parser/parse_coerce.c
===================================================================
RCS file: /home/hlinnaka/pgcvsrepository/pgsql/src/backend/parser/parse_coerce.c,v
retrieving revision 2.163
diff -c -r2.163 parse_coerce.c
*** src/backend/parser/parse_coerce.c 30 Jul 2008 21:23:17 -0000 2.163
--- src/backend/parser/parse_coerce.c 29 Aug 2008 09:38:51 -0000
***************
*** 1745,1751 ****
if (ccontext >= castcontext)
{
*funcid = castForm->castfunc;
! if (OidIsValid(*funcid))
result = COERCION_PATH_FUNC;
else
result = COERCION_PATH_RELABELTYPE;
--- 1745,1756 ----
if (ccontext >= castcontext)
{
*funcid = castForm->castfunc;
! if (*funcid == IOCOERCE_FUNCOID)
! {
! result = COERCION_PATH_COERCEVIAIO;
! *funcid = InvalidOid;
! }
! else if (OidIsValid(*funcid))
result = COERCION_PATH_FUNC;
else
result = COERCION_PATH_RELABELTYPE;
Index: src/include/catalog/pg_cast.h
===================================================================
RCS file: /home/hlinnaka/pgcvsrepository/pgsql/src/include/catalog/pg_cast.h,v
retrieving revision 1.39
diff -c -r1.39 pg_cast.h
*** src/include/catalog/pg_cast.h 27 Mar 2008 03:57:34 -0000 1.39
--- src/include/catalog/pg_cast.h 29 Aug 2008 09:14:15 -0000
***************
*** 56,61 ****
--- 56,63 ----
COERCION_CODE_EXPLICIT = 'e' /* explicit cast operation */
} CoercionCodes;
+ #define IOCOERCE_FUNCOID 1
+
/* ----------------
* compiler constants for pg_cast
Index: src/include/nodes/parsenodes.h
===================================================================
RCS file: /home/hlinnaka/pgcvsrepository/pgsql/src/include/nodes/parsenodes.h,v
retrieving revision 1.371
diff -c -r1.371 parsenodes.h
*** src/include/nodes/parsenodes.h 7 Aug 2008 01:11:51 -0000 1.371
--- src/include/nodes/parsenodes.h 29 Aug 2008 09:21:08 -0000
***************
*** 1989,1994 ****
--- 1989,1995 ----
TypeName *targettype;
FuncWithArgs *func;
CoercionContext context;
+ bool coerceviaio;
} CreateCastStmt;
/* ----------------------
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers