Allow binary-coercible types for cast function arguments and return types.
authorPeter Eisentraut <peter_e@gmx.net>
Fri, 11 Jul 2008 07:02:43 +0000 (07:02 +0000)
committerPeter Eisentraut <peter_e@gmx.net>
Fri, 11 Jul 2008 07:02:43 +0000 (07:02 +0000)
Document return type of cast functions.

Also change documentation to prefer the term "binary coercible" in its
present sense instead of the previous term "binary compatible".

doc/src/sgml/catalogs.sgml
doc/src/sgml/ref/create_cast.sgml
doc/src/sgml/typeconv.sgml
src/backend/commands/functioncmds.c

index 853af42bc13704e90c9e4516b3768a62eb416919..e76804e97a4be1f6f95032e6aaefc717274445b0 100644 (file)
       <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 compatible (that is, no
+       stored if the data types are binary coercible (that is, no
        run-time operation is needed to perform the cast)
       </entry>
      </row>
index 5ed179017766d11a687de707ddaff8e590c62c9e..67210d5dd74d1234215be5d8d9682c69d1b75da6 100644 (file)
@@ -44,12 +44,18 @@ SELECT CAST(42 AS float8);
   </para>
 
   <para>
-   Two types can be <firstterm>binary compatible</firstterm>, which
-   means that they can be converted into one another <quote>for
-   free</quote> without invoking any function.  This requires that
-   corresponding values use the same internal representation.  For
-   instance, the types <type>text</type> and <type>varchar</type> are
-   binary compatible.
+   Two types can be <firstterm>binary coercible</firstterm>, which
+   means that the conversion can be performed <quote>for free</quote>
+   without invoking any function.  This requires that corresponding
+   values use the same internal representation.  For instance, the
+   types <type>text</type> and <type>varchar</type> are binary
+   coercible both ways.  Binary coercibility is not necessarily a
+   symmetric relationship.  For example, the cast
+   from <type>xml</type> to <type>text</type> can be performed for
+   free in the present implementation, but the reverse direction
+   requires a function that performs at least a syntax check.  (Two
+   types that are binary coercible both ways are also referred to as
+   binary compatible.)
   </para>
 
   <para>
@@ -127,8 +133,8 @@ SELECT CAST ( 2 AS numeric ) + 4.0;
 
   <para>
    To be able to create a cast, you must own the source or the target
-   data type.  To create a binary-compatible cast, you must be superuser.
-   (This restriction is made because an erroneous binary-compatible cast
+   data type.  To create a binary-coercible cast, you must be superuser.
+   (This restriction is made because an erroneous binary-coercible cast
    conversion can easily crash the server.)
   </para>
  </refsect1>
@@ -176,7 +182,7 @@ SELECT CAST ( 2 AS numeric ) + 4.0;
      <listitem>
       <para>
        Indicates that the source type and the target type are binary
-       compatible, so no function is required to perform the cast.
+       coercible, so no function is required to perform the cast.
       </para>
      </listitem>
     </varlistentry>
@@ -205,8 +211,8 @@ SELECT CAST ( 2 AS numeric ) + 4.0;
 
   <para>
    Cast implementation functions can have one to three arguments.
-   The first argument type must be identical to the cast's source type.
-   The second argument,
+   The first argument type must be identical to or binary-coercible from
+   the cast's source type.  The second argument,
    if present, must be type <type>integer</>; it receives the type
    modifier associated with the destination type, or <literal>-1</>
    if there is none.  The third argument,
@@ -218,6 +224,11 @@ SELECT CAST ( 2 AS numeric ) + 4.0;
    your own data types so that this matters.)
   </para>
 
+  <para>
+   The return type of a cast function must be identical to or
+   binary-coercible to the cast's target type.
+  </para>
+
   <para>
    Ordinarily a cast must have different source and target data types.
    However, it is allowed to declare a cast with identical source and
@@ -311,10 +322,10 @@ SELECT CAST ( 2 AS numeric ) + 4.0;
     request without having matched it to an actual function.
     If a function call <replaceable>name</>(<replaceable>x</>) does not
     exactly match any existing function, but <replaceable>name</> is the name
-    of a data type and <structname>pg_cast</> provides a binary-compatible cast
+    of a data type and <structname>pg_cast</> provides a binary-coercible cast
     to this type from the type of <replaceable>x</>, then the call will be
     construed as a binary-compatible cast.  This exception is made so that
-    binary-compatible casts can be invoked using functional syntax, even
+    binary-coercible casts can be invoked using functional syntax, even
     though they lack any function.  Likewise, if there is no
     <structname>pg_cast</> entry but the cast would be to or from a string
     type, the call will be construed as an I/O conversion cast.  This
@@ -345,7 +356,7 @@ CREATE CAST (bigint AS int4) WITH FUNCTION int4(bigint);
   <para>
    The <command>CREATE CAST</command> command conforms to the
    <acronym>SQL</acronym> standard,
-   except that SQL does not make provisions for binary-compatible
+   except that SQL does not make provisions for binary-coercible
    types or extra arguments to implementation functions.
    <literal>AS IMPLICIT</> is a <productname>PostgreSQL</productname> 
    extension, too.
index 334c22660cd626d73313a06e4986abad98b96a07..4add6f801387278c08cd6c4278c2874861f8a706 100644 (file)
@@ -522,7 +522,7 @@ If no exact match is found, see whether the function call appears
 to be a special type conversion request.  This happens if the function call
 has just one argument and the function name is the same as the (internal)
 name of some data type.  Furthermore, the function argument must be either
-an unknown-type literal, or a type that is binary-compatible with the named
+an unknown-type literal, or a type that is binary-coercible to the named
 data type, or a type that could be converted to the named data type by
 applying that type's I/O functions (that is, the conversion is either to or
 from one of the standard string types).  When these conditions are met,
@@ -783,8 +783,8 @@ to <type>text</type> by default, allowing the <literal>||</literal> operator
 to be resolved as <type>text</type> concatenation.  Then the <type>text</type>
 result of the operator is converted to <type>bpchar</type> (<quote>blank-padded
 char</>, the internal name of the <type>character</type> data type) to match the target
-column type.  (Since the types <type>text</type> and
-<type>bpchar</type> are binary-compatible, this conversion does
+column type.  (Since the conversion from <type>text</type> to
+<type>bpchar</type> is binary-coercible, this conversion does
 not insert any real function call.)  Finally, the sizing function
 <literal>bpchar(bpchar, integer)</literal> is found in the system catalog
 and applied to the operator's result and the stored column length.  This
index 4cb17fc4bfb61b2792af635e5e330c6217b3f4a8..3357f389799154551c757427ffffc5d36ea9366a 100644 (file)
@@ -48,6 +48,7 @@
 #include "commands/defrem.h"
 #include "commands/proclang.h"
 #include "miscadmin.h"
+#include "parser/parse_coerce.h"
 #include "parser/parse_func.h"
 #include "parser/parse_type.h"
 #include "utils/acl.h"
@@ -1403,10 +1404,10 @@ CreateCast(CreateCastStmt *stmt)
                        ereport(ERROR,
                                        (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
                                  errmsg("cast function must take one to three arguments")));
-               if (procstruct->proargtypes.values[0] != sourcetypeid)
+               if (!IsBinaryCoercible(sourcetypeid, procstruct->proargtypes.values[0]))
                        ereport(ERROR,
                                        (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
-                       errmsg("argument of cast function must match source data type")));
+                       errmsg("argument of cast function must match or be binary-compatible with source data type")));
                if (nargs > 1 && procstruct->proargtypes.values[1] != INT4OID)
                        ereport(ERROR,
                                        (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
@@ -1415,10 +1416,10 @@ CreateCast(CreateCastStmt *stmt)
                        ereport(ERROR,
                                        (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
                        errmsg("third argument of cast function must be type boolean")));
-               if (procstruct->prorettype != targettypeid)
+               if (!IsBinaryCoercible(procstruct->prorettype, targettypeid))
                        ereport(ERROR,
                                        (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
-                                        errmsg("return data type of cast function must match target data type")));
+                                        errmsg("return data type of cast function must match or be binary-compatible with target data type")));
 
                /*
                 * Restricting the volatility of a cast function may or may not be a