mirror of
https://github.com/postgres/postgres.git
synced 2025-06-22 02:52:08 +03:00
Represent type-specific length coercion functions as pg_cast entries,
eliminating the former hard-wired convention about their names. Allow pg_cast entries to represent both type coercion and length coercion in a single step --- this is represented by a function that takes an extra typmod argument, just like a length coercion function. This nicely merges the type and length coercion mechanisms into something at least a little cleaner than we had before. Make use of the single- coercion-step behavior to fix integer-to-bit coercion so that coercing to bit(n) yields the rightmost n bits of the integer instead of the leftmost n bits. This should fix recurrent complaints about the odd behavior of this coercion. Clean up the documentation of the bit string functions, and try to put it where people might actually find it. Also, get rid of the unreliable heuristics in ruleutils.c about whether to display nested coercion steps; instead require parse_coerce.c to label them properly in the first place.
This commit is contained in:
@ -1,6 +1,6 @@
|
||||
<!--
|
||||
Documentation of the system catalogs, directed toward PostgreSQL developers
|
||||
$PostgreSQL: pgsql/doc/src/sgml/catalogs.sgml,v 2.86 2004/06/07 04:04:47 tgl Exp $
|
||||
$PostgreSQL: pgsql/doc/src/sgml/catalogs.sgml,v 2.87 2004/06/16 01:26:33 tgl Exp $
|
||||
-->
|
||||
|
||||
<chapter id="catalogs">
|
||||
@ -934,7 +934,7 @@
|
||||
<entry>
|
||||
Indicates what contexts the cast may be invoked in.
|
||||
<literal>e</> means only as an explicit cast (using
|
||||
<literal>CAST</>, <literal>::</>, or function-call syntax).
|
||||
<literal>CAST</> or <literal>::</> syntax).
|
||||
<literal>a</> means implicitly in assignment
|
||||
to a target column, as well as explicitly.
|
||||
<literal>i</> means implicitly in expressions, as well as the
|
||||
@ -944,6 +944,39 @@
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</table>
|
||||
|
||||
<para>
|
||||
The cast functions listed in <structname>pg_cast</structname> must
|
||||
always take the cast source type as their first argument type, and
|
||||
return the cast destination type as their result type. A cast
|
||||
function can have up to three arguments. 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,
|
||||
if present, must be type <type>boolean</>; it receives <literal>true</>
|
||||
if the cast is an explicit cast, <literal>false</> otherwise.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
It is legitimate to create a <structname>pg_cast</structname> entry
|
||||
in which the source and target types are the same, if the associated
|
||||
function takes more than one argument. Such entries represent
|
||||
<quote>length coercion functions</> that coerce values of the type
|
||||
to be legal for a particular type modifier value. Note however that
|
||||
at present there is no support for associating non-default type
|
||||
modifiers with user-created data types, and so this facility is only
|
||||
of use for the small number of built-in types that have type modifier
|
||||
syntax built into the grammar.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
When a <structname>pg_cast</structname> entry has different source and
|
||||
target types and a function that takes more than one argument, it
|
||||
represents 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 steps, one to
|
||||
convert between datatypes and a second to apply the modifier.
|
||||
</para>
|
||||
</sect1>
|
||||
|
||||
<sect1 id="catalog-pg-class">
|
||||
|
@ -1,5 +1,5 @@
|
||||
<!--
|
||||
$PostgreSQL: pgsql/doc/src/sgml/datatype.sgml,v 1.145 2004/06/07 04:04:47 tgl Exp $
|
||||
$PostgreSQL: pgsql/doc/src/sgml/datatype.sgml,v 1.146 2004/06/16 01:26:35 tgl Exp $
|
||||
-->
|
||||
|
||||
<chapter id="datatype">
|
||||
@ -2851,7 +2851,7 @@ SELECT * FROM test1 WHERE a;
|
||||
linkend="sql-syntax-bit-strings"> for information about the syntax
|
||||
of bit string constants. Bit-logical operators and string
|
||||
manipulation functions are available; see <xref
|
||||
linkend="functions">.
|
||||
linkend="functions-bitstring">.
|
||||
</para>
|
||||
|
||||
<example>
|
||||
|
@ -1,5 +1,5 @@
|
||||
<!--
|
||||
$PostgreSQL: pgsql/doc/src/sgml/func.sgml,v 1.208 2004/06/14 19:01:09 tgl Exp $
|
||||
$PostgreSQL: pgsql/doc/src/sgml/func.sgml,v 1.209 2004/06/16 01:26:36 tgl Exp $
|
||||
PostgreSQL documentation
|
||||
-->
|
||||
|
||||
@ -488,55 +488,13 @@ PostgreSQL documentation
|
||||
</table>
|
||||
|
||||
<para>
|
||||
The bitwise operators are also available for the bit
|
||||
The bitwise operators work only on integral data types, whereas
|
||||
the others are available for all numeric data types. The bitwise
|
||||
operators are also available for the bit
|
||||
string types <type>bit</type> and <type>bit varying</type>, as
|
||||
shown in <xref linkend="functions-math-bit-table">.
|
||||
Bit string operands of <literal>&</literal>, <literal>|</literal>,
|
||||
and <literal>#</literal> must be of equal length. When bit
|
||||
shifting, the original length of the string is preserved, as shown
|
||||
in the table.
|
||||
shown in <xref linkend="functions-bit-string-op-table">.
|
||||
</para>
|
||||
|
||||
<table id="functions-math-bit-table">
|
||||
<title>Bit String Bitwise Operators</title>
|
||||
|
||||
<tgroup cols="2">
|
||||
<thead>
|
||||
<row>
|
||||
<entry>Example</entry>
|
||||
<entry>Result</entry>
|
||||
</row>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
<row>
|
||||
<entry><literal>B'10001' & B'01101'</literal></entry>
|
||||
<entry><literal>00001</literal></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><literal>B'10001' | B'01101'</literal></entry>
|
||||
<entry><literal>11101</literal></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><literal>B'10001' # B'01101'</literal></entry>
|
||||
<entry><literal>11110</literal></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><literal>~ B'10001'</literal></entry>
|
||||
<entry><literal>01110</literal></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><literal>B'10001' << 3</literal></entry>
|
||||
<entry><literal>01000</literal></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><literal>B'10001' >> 2</literal></entry>
|
||||
<entry><literal>00100</literal></entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</table>
|
||||
|
||||
<para>
|
||||
<xref linkend="functions-math-func-table"> shows the available
|
||||
mathematical functions. In the table, <literal>dp</literal>
|
||||
@ -2337,6 +2295,130 @@ PostgreSQL documentation
|
||||
</sect1>
|
||||
|
||||
|
||||
<sect1 id="functions-bitstring">
|
||||
<title>Bit String Functions and Operators</title>
|
||||
|
||||
<indexterm zone="functions-bitstring">
|
||||
<primary>bit strings</primary>
|
||||
<secondary>functions</secondary>
|
||||
</indexterm>
|
||||
|
||||
<para>
|
||||
This section describes functions and operators for examining and
|
||||
manipulating bit strings, that is values of the types
|
||||
<type>bit</type> and <type>bit varying</type>. Aside from the
|
||||
usual comparison operators, the operators
|
||||
shown in <xref linkend="functions-bit-string-op-table"> can be used.
|
||||
Bit string operands of <literal>&</literal>, <literal>|</literal>,
|
||||
and <literal>#</literal> must be of equal length. When bit
|
||||
shifting, the original length of the string is preserved, as shown
|
||||
in the examples.
|
||||
</para>
|
||||
|
||||
<table id="functions-bit-string-op-table">
|
||||
<title>Bit String Operators</title>
|
||||
|
||||
<tgroup cols="4">
|
||||
<thead>
|
||||
<row>
|
||||
<entry>Operator</entry>
|
||||
<entry>Description</entry>
|
||||
<entry>Example</entry>
|
||||
<entry>Result</entry>
|
||||
</row>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
<row>
|
||||
<entry> <literal>||</literal> </entry>
|
||||
<entry>concatenation</entry>
|
||||
<entry><literal>B'10001' || B'011'</literal></entry>
|
||||
<entry><literal>10001011</literal></entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry> <literal>&</literal> </entry>
|
||||
<entry>bitwise AND</entry>
|
||||
<entry><literal>B'10001' & B'01101'</literal></entry>
|
||||
<entry><literal>00001</literal></entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry> <literal>|</literal> </entry>
|
||||
<entry>bitwise OR</entry>
|
||||
<entry><literal>B'10001' | B'01101'</literal></entry>
|
||||
<entry><literal>11101</literal></entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry> <literal>#</literal> </entry>
|
||||
<entry>bitwise XOR</entry>
|
||||
<entry><literal>B'10001' # B'01101'</literal></entry>
|
||||
<entry><literal>11100</literal></entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry> <literal>~</literal> </entry>
|
||||
<entry>bitwise NOT</entry>
|
||||
<entry><literal>~ B'10001'</literal></entry>
|
||||
<entry><literal>01110</literal></entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry> <literal><<</literal> </entry>
|
||||
<entry>bitwise shift left</entry>
|
||||
<entry><literal>B'10001' << 3</literal></entry>
|
||||
<entry><literal>01000</literal></entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry> <literal>>></literal> </entry>
|
||||
<entry>bitwise shift right</entry>
|
||||
<entry><literal>B'10001' >> 2</literal></entry>
|
||||
<entry><literal>00100</literal></entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</table>
|
||||
|
||||
<para>
|
||||
The following <acronym>SQL</acronym>-standard functions work on bit
|
||||
strings as well as character strings:
|
||||
<literal><function>length</function></literal>,
|
||||
<literal><function>bit_length</function></literal>,
|
||||
<literal><function>octet_length</function></literal>,
|
||||
<literal><function>position</function></literal>,
|
||||
<literal><function>substring</function></literal>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
In addition, it is possible to cast integral values to and from type
|
||||
<type>bit</>.
|
||||
Some examples:
|
||||
<programlisting>
|
||||
44::bit(10) <lineannotation>0000101100</lineannotation>
|
||||
44::bit(3) <lineannotation>100</lineannotation>
|
||||
cast(-44 as bit(12)) <lineannotation>111111010100</lineannotation>
|
||||
'1110'::bit(4)::integer <lineannotation>14</lineannotation>
|
||||
</programlisting>
|
||||
Note that casting to just <quote>bit</> means casting to
|
||||
<literal>bit(1)</>, and so it will deliver only the least significant
|
||||
bit of the integer.
|
||||
</para>
|
||||
|
||||
<note>
|
||||
<para>
|
||||
Prior to <productname>PostgreSQL</productname> 7.5, casting an
|
||||
integer to <type>bit(n)</> would copy the leftmost <literal>n</>
|
||||
bits of the integer, whereas now it copies the rightmost <literal>n</>
|
||||
bits. Also, casting an integer to a bit string width wider than
|
||||
the integer itself will sign-extend on the left.
|
||||
</para>
|
||||
</note>
|
||||
|
||||
</sect1>
|
||||
|
||||
|
||||
<sect1 id="functions-matching">
|
||||
<title>Pattern Matching</title>
|
||||
|
||||
@ -7628,14 +7710,13 @@ SELECT pg_type_is_visible('myschema.widget'::regtype);
|
||||
<function>bit_and(<replaceable class="parameter">expression</replaceable>)</function>
|
||||
</entry>
|
||||
<entry>
|
||||
<type>smallint</type>, <type>integer</type>, <type>bigint</type> or
|
||||
<type>bit</type>,
|
||||
<type>smallint</type>, <type>integer</type>, <type>bigint</type>, or
|
||||
<type>bit</type>
|
||||
</entry>
|
||||
<entry>
|
||||
same as argument data type.
|
||||
</entry>
|
||||
<entry>the bitwise-and of all non-null input values, or null if empty
|
||||
same as argument data type
|
||||
</entry>
|
||||
<entry>the bitwise AND of all non-null input values, or null if none</entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
@ -7646,14 +7727,13 @@ SELECT pg_type_is_visible('myschema.widget'::regtype);
|
||||
<function>bit_or(<replaceable class="parameter">expression</replaceable>)</function>
|
||||
</entry>
|
||||
<entry>
|
||||
<type>smallint</type>, <type>integer</type>, <type>bigint</type> or
|
||||
<type>bit</type>,
|
||||
<type>smallint</type>, <type>integer</type>, <type>bigint</type>, or
|
||||
<type>bit</type>
|
||||
</entry>
|
||||
<entry>
|
||||
same as argument data type.
|
||||
</entry>
|
||||
<entry>the bitwise-or of all non-null input values, or null if empty.
|
||||
same as argument data type
|
||||
</entry>
|
||||
<entry>the bitwise OR of all non-null input values, or null if none</entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
@ -7669,9 +7749,7 @@ SELECT pg_type_is_visible('myschema.widget'::regtype);
|
||||
<entry>
|
||||
<type>bool</type>
|
||||
</entry>
|
||||
<entry>true if all input values are true, otherwise false.
|
||||
Also known as <function>bool_and</function>.
|
||||
</entry>
|
||||
<entry>true if all input values are true, otherwise false</entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
@ -7720,9 +7798,7 @@ SELECT pg_type_is_visible('myschema.widget'::regtype);
|
||||
<entry>
|
||||
<type>bool</type>
|
||||
</entry>
|
||||
<entry>true if all input values are true, otherwise false.
|
||||
Also known as <function>bool_and</function>.
|
||||
</entry>
|
||||
<entry>equivalent to <function>bool_and</function></entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
|
@ -1,4 +1,4 @@
|
||||
<!-- $PostgreSQL: pgsql/doc/src/sgml/ref/create_cast.sgml,v 1.16 2004/02/15 06:27:37 neilc Exp $ -->
|
||||
<!-- $PostgreSQL: pgsql/doc/src/sgml/ref/create_cast.sgml,v 1.17 2004/06/16 01:26:40 tgl Exp $ -->
|
||||
|
||||
<refentry id="SQL-CREATECAST">
|
||||
<refmeta>
|
||||
@ -18,7 +18,7 @@
|
||||
<refsynopsisdiv>
|
||||
<synopsis>
|
||||
CREATE CAST (<replaceable>sourcetype</replaceable> AS <replaceable>targettype</replaceable>)
|
||||
WITH FUNCTION <replaceable>funcname</replaceable> (<replaceable>argtype</replaceable>)
|
||||
WITH FUNCTION <replaceable>funcname</replaceable> (<replaceable>argtypes</replaceable>)
|
||||
[ AS ASSIGNMENT | AS IMPLICIT ]
|
||||
|
||||
CREATE CAST (<replaceable>sourcetype</replaceable> AS <replaceable>targettype</replaceable>)
|
||||
@ -55,9 +55,9 @@ SELECT CAST(42 AS text);
|
||||
<para>
|
||||
By default, a cast can be invoked only by an explicit cast request,
|
||||
that is an explicit <literal>CAST(<replaceable>x</> AS
|
||||
<replaceable>typename</>)</literal>,
|
||||
<replaceable>x</><literal>::</><replaceable>typename</>, or
|
||||
<replaceable>typename</>(<replaceable>x</>) construct.
|
||||
<replaceable>typename</>)</literal> or
|
||||
<replaceable>x</><literal>::</><replaceable>typename</>
|
||||
construct.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
@ -141,15 +141,14 @@ SELECT 'The time is ' || CAST(now() AS text);
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><replaceable>funcname</replaceable>(<replaceable>argtype</replaceable>)</term>
|
||||
<term><replaceable>funcname</replaceable>(<replaceable>argtypes</replaceable>)</term>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
The function used to perform the cast. The function name may
|
||||
be schema-qualified. If it is not, the function will be looked
|
||||
up in the schema search path. The argument type must be
|
||||
identical to the source type and the result data type must
|
||||
match the target type of the cast.
|
||||
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.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
@ -187,6 +186,42 @@ SELECT 'The time is ' || CAST(now() AS text);
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
|
||||
<para>
|
||||
Cast implementation functions may have one to three arguments.
|
||||
The first argument type must be identical to 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,
|
||||
if present, must be type <type>boolean</>; it receives <literal>true</>
|
||||
if the cast is an explicit cast, <literal>false</> otherwise.
|
||||
(Bizarrely, the SQL spec 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 datatypes so that this matters.)
|
||||
</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. (Since the grammar presently permits only certain
|
||||
built-in data types to have type modifiers, this feature is of no
|
||||
use for user-defined target types, but we mention it for completeness.)
|
||||
</para>
|
||||
|
||||
<para>
|
||||
When a cast has different source and
|
||||
target types and a function that takes more than one argument, it
|
||||
represents 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 steps, one to
|
||||
convert between datatypes and a second to apply the modifier.
|
||||
</para>
|
||||
|
||||
</refsect1>
|
||||
|
||||
<refsect1 id="sql-createcast-notes">
|
||||
@ -207,10 +242,40 @@ SELECT 'The time is ' || CAST(now() AS text);
|
||||
argument of a different type was automatically a cast function.
|
||||
This convention has been abandoned in face of the introduction of
|
||||
schemas and to be able to represent binary compatible casts in the
|
||||
system catalogs. (The built-in cast functions still follow this naming
|
||||
scheme, but they have to be shown as casts in the system catalog <literal>pg_cast</>
|
||||
now.)
|
||||
system catalogs. The built-in cast functions still follow this naming
|
||||
scheme, but they have to be shown as casts in the system catalog
|
||||
<structname>pg_cast</> as well.
|
||||
</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 datatypes using a
|
||||
function-style notation, that is
|
||||
<replaceable>typename</>(<replaceable>x</>). 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</> 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>
|
||||
There is one small lie in the preceding paragraph: there is still one
|
||||
case in which <structname>pg_cast</> will be used to resolve the
|
||||
meaning of an apparent function call. If a
|
||||
function call <replaceable>name</>(<replaceable>x</>) matches no
|
||||
actual function, but <replaceable>name</> is the name of a data type
|
||||
and <structname>pg_cast</> shows a binary-compatible cast to this
|
||||
type from the type of <replaceable>x</>, then the call will be construed
|
||||
as an explicit cast. This exception is made so that binary-compatible
|
||||
casts can be invoked using functional syntax, even though they lack
|
||||
any function.
|
||||
</para>
|
||||
</note>
|
||||
</refsect1>
|
||||
|
||||
|
||||
@ -234,7 +299,8 @@ CREATE CAST (text AS int4) WITH FUNCTION int4(text);
|
||||
<para>
|
||||
The <command>CREATE CAST</command> command conforms to SQL99,
|
||||
except that SQL99 does not make provisions for binary-compatible
|
||||
types. <literal>AS IMPLICIT</> is a <productname>PostgreSQL</productname>
|
||||
types or extra arguments to implementation functions.
|
||||
<literal>AS IMPLICIT</> is a <productname>PostgreSQL</productname>
|
||||
extension, too.
|
||||
</para>
|
||||
</refsect1>
|
||||
|
@ -1,5 +1,5 @@
|
||||
<!--
|
||||
$PostgreSQL: pgsql/doc/src/sgml/syntax.sgml,v 1.93 2004/06/07 04:04:47 tgl Exp $
|
||||
$PostgreSQL: pgsql/doc/src/sgml/syntax.sgml,v 1.94 2004/06/16 01:26:38 tgl Exp $
|
||||
-->
|
||||
|
||||
<chapter id="sql-syntax">
|
||||
@ -1319,7 +1319,7 @@ CAST ( <replaceable>expression</replaceable> AS <replaceable>type</replaceable>
|
||||
<para>
|
||||
When a cast is applied to a value expression of a known type, it
|
||||
represents a run-time type conversion. The cast will succeed only
|
||||
if a suitable type conversion function is available. Notice that this
|
||||
if a suitable type conversion operation has been defined. Notice that this
|
||||
is subtly different from the use of casts with constants, as shown in
|
||||
<xref linkend="sql-syntax-constants-generic">. A cast applied to an
|
||||
unadorned string literal represents the initial assignment of a type
|
||||
|
Reference in New Issue
Block a user