User defined I/O conversion casts - Mailing list pgsql-hackers
From | Heikki Linnakangas |
---|---|
Subject | User defined I/O conversion casts |
Date | |
Msg-id | 48B7D675.4020601@enterprisedb.com Whole thread Raw |
Responses |
Re: User defined I/O conversion casts
Re: User defined I/O conversion casts |
List | pgsql-hackers |
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; /* ----------------------
pgsql-hackers by date: