diff options
Diffstat (limited to 'doc/src/sgml/ref/create_cast.sgml')
-rw-r--r-- | doc/src/sgml/ref/create_cast.sgml | 424 |
1 files changed, 424 insertions, 0 deletions
diff --git a/doc/src/sgml/ref/create_cast.sgml b/doc/src/sgml/ref/create_cast.sgml new file mode 100644 index 0000000..bad75bc --- /dev/null +++ b/doc/src/sgml/ref/create_cast.sgml @@ -0,0 +1,424 @@ +<!-- +doc/src/sgml/ref/create_cast.sgml +PostgreSQL documentation +--> + +<refentry id="sql-createcast"> + <indexterm zone="sql-createcast"> + <primary>CREATE CAST</primary> + </indexterm> + + <refmeta> + <refentrytitle>CREATE CAST</refentrytitle> + <manvolnum>7</manvolnum> + <refmiscinfo>SQL - Language Statements</refmiscinfo> + </refmeta> + + <refnamediv> + <refname>CREATE CAST</refname> + <refpurpose>define a new cast</refpurpose> + </refnamediv> + + <refsynopsisdiv> +<synopsis> +CREATE CAST (<replaceable>source_type</replaceable> AS <replaceable>target_type</replaceable>) + WITH FUNCTION <replaceable>function_name</replaceable> [ (<replaceable>argument_type</replaceable> [, ...]) ] + [ AS ASSIGNMENT | AS IMPLICIT ] + +CREATE CAST (<replaceable>source_type</replaceable> AS <replaceable>target_type</replaceable>) + WITHOUT FUNCTION + [ AS ASSIGNMENT | AS IMPLICIT ] + +CREATE CAST (<replaceable>source_type</replaceable> AS <replaceable>target_type</replaceable>) + WITH INOUT + [ AS ASSIGNMENT | AS IMPLICIT ] +</synopsis> + </refsynopsisdiv> + + <refsect1 id="sql-createcast-description"> + <title>Description</title> + + <para> + <command>CREATE CAST</command> defines a new cast. A cast + specifies how to perform a conversion between + two data types. For example, +<programlisting> +SELECT CAST(42 AS float8); +</programlisting> + converts the integer constant 42 to type <type>float8</type> by + invoking a previously specified function, in this case + <literal>float8(int4)</literal>. (If no suitable cast has been defined, the + conversion fails.) + </para> + + <para> + 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> + You can define a cast as an <firstterm>I/O conversion cast</firstterm> by using + the <literal>WITH INOUT</literal> syntax. An I/O conversion cast is + performed by invoking the output function of the source data type, and + passing the resulting string to the input function of the target data type. + In many common cases, this feature avoids the need to write a separate + cast function for conversion. An I/O conversion cast acts the same as + a regular function-based cast; only the implementation is different. + </para> + + <para> + By default, a cast can be invoked only by an explicit cast request, + that is an explicit <literal>CAST(<replaceable>x</replaceable> AS + <replaceable>typename</replaceable>)</literal> or + <replaceable>x</replaceable><literal>::</literal><replaceable>typename</replaceable> + construct. + </para> + + <para> + If the cast is marked <literal>AS ASSIGNMENT</literal> then it can be invoked + implicitly when assigning a value to a column of the target data type. + For example, supposing that <literal>foo.f1</literal> is a column of + type <type>text</type>, then: +<programlisting> +INSERT INTO foo (f1) VALUES (42); +</programlisting> + will be allowed if the cast from type <type>integer</type> to type + <type>text</type> is marked <literal>AS ASSIGNMENT</literal>, otherwise not. + (We generally use the term <firstterm>assignment + cast</firstterm> to describe this kind of cast.) + </para> + + <para> + If the cast is marked <literal>AS IMPLICIT</literal> then it can be invoked + implicitly in any context, whether assignment or internally in an + expression. (We generally use the term <firstterm>implicit + cast</firstterm> to describe this kind of cast.) + For example, consider this query: +<programlisting> +SELECT 2 + 4.0; +</programlisting> + The parser initially marks the constants as being of type <type>integer</type> + and <type>numeric</type> respectively. There is no <type>integer</type> + <literal>+</literal> <type>numeric</type> operator in the system catalogs, + but there is a <type>numeric</type> <literal>+</literal> <type>numeric</type> operator. + The query will therefore succeed if a cast from <type>integer</type> to + <type>numeric</type> is available and is marked <literal>AS IMPLICIT</literal> — + which in fact it is. The parser will apply the implicit cast and resolve + the query as if it had been written +<programlisting> +SELECT CAST ( 2 AS numeric ) + 4.0; +</programlisting> + </para> + + <para> + Now, the catalogs also provide a cast from <type>numeric</type> to + <type>integer</type>. If that cast were marked <literal>AS IMPLICIT</literal> — + which it is not — then the parser would be faced with choosing + between the above interpretation and the alternative of casting the + <type>numeric</type> constant to <type>integer</type> and applying the + <type>integer</type> <literal>+</literal> <type>integer</type> operator. Lacking any + knowledge of which choice to prefer, it would give up and declare the + query ambiguous. The fact that only one of the two casts is + implicit is the way in which we teach the parser to prefer resolution + of a mixed <type>numeric</type>-and-<type>integer</type> expression as + <type>numeric</type>; there is no built-in knowledge about that. + </para> + + <para> + It is wise to be conservative about marking casts as implicit. An + overabundance of implicit casting paths can cause + <productname>PostgreSQL</productname> to choose surprising + interpretations of commands, or to be unable to resolve commands at + all because there are multiple possible interpretations. A good + rule of thumb is to make a cast implicitly invokable only for + information-preserving transformations between types in the same + general type category. For example, the cast from <type>int2</type> to + <type>int4</type> can reasonably be implicit, but the cast from + <type>float8</type> to <type>int4</type> should probably be + assignment-only. Cross-type-category casts, such as <type>text</type> + to <type>int4</type>, are best made explicit-only. + </para> + + <note> + <para> + Sometimes it is necessary for usability or standards-compliance reasons + to provide multiple implicit casts among a set of types, resulting in + ambiguity that cannot be avoided as above. The parser has a fallback + heuristic based on <firstterm>type categories</firstterm> and <firstterm>preferred + types</firstterm> that can help to provide desired behavior in such cases. See + <xref linkend="sql-createtype"/> for + more information. + </para> + </note> + + <para> + To be able to create a cast, you must own the source or the target data type + and have <literal>USAGE</literal> privilege on the other 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> + + <refsect1> + <title>Parameters</title> + + <variablelist> + <varlistentry> + <term><replaceable>source_type</replaceable></term> + + <listitem> + <para> + The name of the source data type of the cast. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><replaceable>target_type</replaceable></term> + + <listitem> + <para> + The name of the target data type of the cast. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal><replaceable>function_name</replaceable>[(<replaceable>argument_type</replaceable> [, ...])]</literal></term> + + <listitem> + <para> + The function used to perform the cast. The function name can + be schema-qualified. If it is not, the function will be looked + up in the schema search path. The function's result data type must + match the target type of the cast. Its arguments are discussed below. + If no argument list is specified, the function name must be unique in + its schema. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>WITHOUT FUNCTION</literal></term> + + <listitem> + <para> + Indicates that the source type is binary-coercible to the target type, + so no function is required to perform the cast. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>WITH INOUT</literal></term> + + <listitem> + <para> + Indicates that the cast is an I/O conversion cast, performed by + invoking the output function of the source data type, and passing the + resulting string to the input function of the target data type. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>AS ASSIGNMENT</literal></term> + + <listitem> + <para> + Indicates that the cast can be invoked implicitly in assignment + contexts. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>AS IMPLICIT</literal></term> + + <listitem> + <para> + Indicates that the cast can be invoked implicitly in any context. + </para> + </listitem> + </varlistentry> + </variablelist> + + <para> + Cast implementation functions can have one to three arguments. + 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</type>; it receives the type + modifier associated with the destination type, or <literal>-1</literal> + if there is none. The third argument, + if present, must be type <type>boolean</type>; it receives <literal>true</literal> + if the cast is an explicit cast, <literal>false</literal> otherwise. + (Bizarrely, the SQL standard demands different behaviors for explicit and + implicit casts in some cases. This argument is supplied for functions + that must implement such casts. It is not recommended that you design + 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 + target types if it has a cast implementation function with more than one + argument. This is used to represent type-specific length coercion + functions in the system catalogs. The named function is used to + coerce a value of the type to the type modifier value given by its + second argument. + </para> + + <para> + When a cast has different source and + target types and a function that takes more than one argument, it + supports converting from one type to another and applying a length + coercion in a single step. When no such entry is available, coercion + to a type that uses a type modifier involves two cast steps, one to + convert between data types and a second to apply the modifier. + </para> + + <para> + A cast to or from a domain type currently has no effect. Casting + to or from a domain uses the casts associated with its underlying type. + </para> + + </refsect1> + + <refsect1 id="sql-createcast-notes"> + <title>Notes</title> + + <para> + Use <link linkend="sql-dropcast"><command>DROP CAST</command></link> to remove user-defined casts. + </para> + + <para> + Remember that if you want to be able to convert types both ways you + need to declare casts both ways explicitly. + </para> + + <indexterm zone="sql-createcast"> + <primary>cast</primary> + <secondary>I/O conversion</secondary> + </indexterm> + + <para> + It is normally not necessary to create casts between user-defined types + and the standard string types (<type>text</type>, <type>varchar</type>, and + <type>char(<replaceable>n</replaceable>)</type>, as well as user-defined types that + are defined to be in the string category). <productname>PostgreSQL</productname> + provides automatic I/O conversion casts for that. The automatic casts to + string types are treated as assignment casts, while the automatic casts + from string types are + explicit-only. You can override this behavior by declaring your own + cast to replace an automatic cast, but usually the only reason to + do so is if you want the conversion to be more easily invokable than the + standard assignment-only or explicit-only setting. Another possible + reason is that you want the conversion to behave differently from the + type's I/O function; but that is sufficiently surprising that you + should think twice about whether it's a good idea. (A small number of + the built-in types do indeed have different behaviors for conversions, + mostly because of requirements of the SQL standard.) + </para> + + <para> + While not required, it is recommended that you continue to follow this old + convention of naming cast implementation functions after the target data + type. Many users are used to being able to cast data types using a + function-style notation, that is + <replaceable>typename</replaceable>(<replaceable>x</replaceable>). This notation is in fact + nothing more nor less than a call of the cast implementation function; it + is not specially treated as a cast. If your conversion functions are not + named to support this convention then you will have surprised users. + Since <productname>PostgreSQL</productname> allows overloading of the same function + name with different argument types, there is no difficulty in having + multiple conversion functions from different types that all use the + target type's name. + </para> + + <note> + <para> + Actually the preceding paragraph is an oversimplification: there are + two cases in which a function-call construct will be treated as a cast + request without having matched it to an actual function. + If a function call <replaceable>name</replaceable>(<replaceable>x</replaceable>) does not + exactly match any existing function, but <replaceable>name</replaceable> is the name + of a data type and <structname>pg_cast</structname> provides a binary-coercible cast + to this type from the type of <replaceable>x</replaceable>, then the call will be + construed as a binary-coercible cast. This exception is made so that + binary-coercible casts can be invoked using functional syntax, even + though they lack any function. Likewise, if there is no + <structname>pg_cast</structname> entry but the cast would be to or from a string + type, the call will be construed as an I/O conversion cast. This + exception allows I/O conversion casts to be invoked using functional + syntax. + </para> + </note> + + <note> + <para> + There is also an exception to the exception: I/O conversion casts from + composite types to string types cannot be invoked using functional + syntax, but must be written in explicit cast syntax (either + <literal>CAST</literal> or <literal>::</literal> notation). This exception was added + because after the introduction of automatically-provided I/O conversion + casts, it was found too easy to accidentally invoke such a cast when + a function or column reference was intended. + </para> + </note> + </refsect1> + + + <refsect1 id="sql-createcast-examples"> + <title>Examples</title> + + <para> + To create an assignment cast from type <type>bigint</type> to type + <type>int4</type> using the function <literal>int4(bigint)</literal>: +<programlisting> +CREATE CAST (bigint AS int4) WITH FUNCTION int4(bigint) AS ASSIGNMENT; +</programlisting> + (This cast is already predefined in the system.) + </para> + </refsect1> + + <refsect1 id="sql-createcast-compat"> + <title>Compatibility</title> + + <para> + The <command>CREATE CAST</command> command conforms to the + <acronym>SQL</acronym> standard, + except that SQL does not make provisions for binary-coercible + types or extra arguments to implementation functions. + <literal>AS IMPLICIT</literal> is a <productname>PostgreSQL</productname> + extension, too. + </para> + </refsect1> + + + <refsect1 id="sql-createcast-seealso"> + <title>See Also</title> + + <para> + <xref linkend="sql-createfunction"/>, + <xref linkend="sql-createtype"/>, + <xref linkend="sql-dropcast"/> + </para> + </refsect1> + +</refentry> |