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  (Teodor Sigaev <teodor@sigaev.ru>)
Re: User defined I/O conversion casts  (Tom Lane <tgl@sss.pgh.pa.us>)
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:

Previous
From: "D'Arcy J.M. Cain"
Date:
Subject: Re: Proposal: new border setting in psql
Next
From: Teodor Sigaev
Date:
Subject: Re: User defined I/O conversion casts