Commit e3afbb35 authored by Peter Eisentraut's avatar Peter Eisentraut

Allow binary-coercible types for cast function arguments and return types.

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".
parent 11014765
<!-- $PostgreSQL: pgsql/doc/src/sgml/catalogs.sgml,v 2.166 2008/05/09 23:32:03 tgl Exp $ --> <!-- $PostgreSQL: pgsql/doc/src/sgml/catalogs.sgml,v 2.167 2008/07/11 07:02:43 petere Exp $ -->
<!-- <!--
Documentation of the system catalogs, directed toward PostgreSQL developers Documentation of the system catalogs, directed toward PostgreSQL developers
--> -->
...@@ -1440,7 +1440,7 @@ ...@@ -1440,7 +1440,7 @@
<entry><literal><link linkend="catalog-pg-proc"><structname>pg_proc</structname></link>.oid</literal></entry> <entry><literal><link linkend="catalog-pg-proc"><structname>pg_proc</structname></link>.oid</literal></entry>
<entry> <entry>
The OID of the function to use to perform this cast. Zero is 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) run-time operation is needed to perform the cast)
</entry> </entry>
</row> </row>
......
<!-- $PostgreSQL: pgsql/doc/src/sgml/ref/create_cast.sgml,v 1.26 2007/06/05 21:31:04 tgl Exp $ --> <!-- $PostgreSQL: pgsql/doc/src/sgml/ref/create_cast.sgml,v 1.27 2008/07/11 07:02:43 petere Exp $ -->
<refentry id="SQL-CREATECAST"> <refentry id="SQL-CREATECAST">
<refmeta> <refmeta>
...@@ -44,12 +44,18 @@ SELECT CAST(42 AS float8); ...@@ -44,12 +44,18 @@ SELECT CAST(42 AS float8);
</para> </para>
<para> <para>
Two types can be <firstterm>binary compatible</firstterm>, which Two types can be <firstterm>binary coercible</firstterm>, which
means that they can be converted into one another <quote>for means that the conversion can be performed <quote>for free</quote>
free</quote> without invoking any function. This requires that without invoking any function. This requires that corresponding
corresponding values use the same internal representation. For values use the same internal representation. For instance, the
instance, the types <type>text</type> and <type>varchar</type> are types <type>text</type> and <type>varchar</type> are binary
binary compatible. 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>
<para> <para>
...@@ -127,8 +133,8 @@ SELECT CAST ( 2 AS numeric ) + 4.0; ...@@ -127,8 +133,8 @@ SELECT CAST ( 2 AS numeric ) + 4.0;
<para> <para>
To be able to create a cast, you must own the source or the target 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. data type. To create a binary-coercible cast, you must be superuser.
(This restriction is made because an erroneous binary-compatible cast (This restriction is made because an erroneous binary-coercible cast
conversion can easily crash the server.) conversion can easily crash the server.)
</para> </para>
</refsect1> </refsect1>
...@@ -176,7 +182,7 @@ SELECT CAST ( 2 AS numeric ) + 4.0; ...@@ -176,7 +182,7 @@ SELECT CAST ( 2 AS numeric ) + 4.0;
<listitem> <listitem>
<para> <para>
Indicates that the source type and the target type are binary 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> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
...@@ -205,8 +211,8 @@ SELECT CAST ( 2 AS numeric ) + 4.0; ...@@ -205,8 +211,8 @@ SELECT CAST ( 2 AS numeric ) + 4.0;
<para> <para>
Cast implementation functions can have one to three arguments. Cast implementation functions can have one to three arguments.
The first argument type must be identical to the cast's source type. The first argument type must be identical to or binary-coercible from
The second argument, the cast's source type. The second argument,
if present, must be type <type>integer</>; it receives the type if present, must be type <type>integer</>; it receives the type
modifier associated with the destination type, or <literal>-1</> modifier associated with the destination type, or <literal>-1</>
if there is none. The third argument, if there is none. The third argument,
...@@ -218,6 +224,11 @@ SELECT CAST ( 2 AS numeric ) + 4.0; ...@@ -218,6 +224,11 @@ SELECT CAST ( 2 AS numeric ) + 4.0;
your own data types so that this matters.) your own data types so that this matters.)
</para> </para>
<para>
The return type of a cast function must be identical to or
binary-coercible to the cast's target type.
</para>
<para> <para>
Ordinarily a cast must have different source and target data types. Ordinarily a cast must have different source and target data types.
However, it is allowed to declare a cast with identical source and However, it is allowed to declare a cast with identical source and
...@@ -311,10 +322,10 @@ SELECT CAST ( 2 AS numeric ) + 4.0; ...@@ -311,10 +322,10 @@ SELECT CAST ( 2 AS numeric ) + 4.0;
request without having matched it to an actual function. request without having matched it to an actual function.
If a function call <replaceable>name</>(<replaceable>x</>) does not If a function call <replaceable>name</>(<replaceable>x</>) does not
exactly match any existing function, but <replaceable>name</> is the name 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 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 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 though they lack any function. Likewise, if there is no
<structname>pg_cast</> entry but the cast would be to or from a string <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 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); ...@@ -345,7 +356,7 @@ CREATE CAST (bigint AS int4) WITH FUNCTION int4(bigint);
<para> <para>
The <command>CREATE CAST</command> command conforms to the The <command>CREATE CAST</command> command conforms to the
<acronym>SQL</acronym> standard, <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. types or extra arguments to implementation functions.
<literal>AS IMPLICIT</> is a <productname>PostgreSQL</productname> <literal>AS IMPLICIT</> is a <productname>PostgreSQL</productname>
extension, too. extension, too.
......
<!-- $PostgreSQL: pgsql/doc/src/sgml/typeconv.sgml,v 1.53 2007/11/26 16:46:50 tgl Exp $ --> <!-- $PostgreSQL: pgsql/doc/src/sgml/typeconv.sgml,v 1.54 2008/07/11 07:02:43 petere Exp $ -->
<chapter Id="typeconv"> <chapter Id="typeconv">
<title>Type Conversion</title> <title>Type Conversion</title>
...@@ -522,7 +522,7 @@ If no exact match is found, see whether the function call appears ...@@ -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 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) 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 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 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 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, 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 ...@@ -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> 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 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 char</>, the internal name of the <type>character</type> data type) to match the target
column type. (Since the types <type>text</type> and column type. (Since the conversion from <type>text</type> to
<type>bpchar</type> are binary-compatible, this conversion does <type>bpchar</type> is binary-coercible, this conversion does
not insert any real function call.) Finally, the sizing function not insert any real function call.) Finally, the sizing function
<literal>bpchar(bpchar, integer)</literal> is found in the system catalog <literal>bpchar(bpchar, integer)</literal> is found in the system catalog
and applied to the operator's result and the stored column length. This and applied to the operator's result and the stored column length. This
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/functioncmds.c,v 1.93 2008/06/19 00:46:04 alvherre Exp $ * $PostgreSQL: pgsql/src/backend/commands/functioncmds.c,v 1.94 2008/07/11 07:02:43 petere Exp $
* *
* DESCRIPTION * DESCRIPTION
* These routines take the parse tree and pick out the * These routines take the parse tree and pick out the
...@@ -48,6 +48,7 @@ ...@@ -48,6 +48,7 @@
#include "commands/defrem.h" #include "commands/defrem.h"
#include "commands/proclang.h" #include "commands/proclang.h"
#include "miscadmin.h" #include "miscadmin.h"
#include "parser/parse_coerce.h"
#include "parser/parse_func.h" #include "parser/parse_func.h"
#include "parser/parse_type.h" #include "parser/parse_type.h"
#include "utils/acl.h" #include "utils/acl.h"
...@@ -1403,10 +1404,10 @@ CreateCast(CreateCastStmt *stmt) ...@@ -1403,10 +1404,10 @@ CreateCast(CreateCastStmt *stmt)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION), (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
errmsg("cast function must take one to three arguments"))); errmsg("cast function must take one to three arguments")));
if (procstruct->proargtypes.values[0] != sourcetypeid) if (!IsBinaryCoercible(sourcetypeid, procstruct->proargtypes.values[0]))
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION), (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) if (nargs > 1 && procstruct->proargtypes.values[1] != INT4OID)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION), (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
...@@ -1415,10 +1416,10 @@ CreateCast(CreateCastStmt *stmt) ...@@ -1415,10 +1416,10 @@ CreateCast(CreateCastStmt *stmt)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION), (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
errmsg("third argument of cast function must be type boolean"))); errmsg("third argument of cast function must be type boolean")));
if (procstruct->prorettype != targettypeid) if (!IsBinaryCoercible(procstruct->prorettype, targettypeid))
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION), (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 * Restricting the volatility of a cast function may or may not be a
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment