Downgrade implicit casts to text to be assignment-only, except for the ones

from the other string-category types; this eliminates a lot of surprising
interpretations that the parser could formerly make when there was no directly
applicable operator.

Create a general mechanism that supports casts to and from the standard string
types (text,varchar,bpchar) for *every* datatype, by invoking the datatype's
I/O functions.  These new casts are assignment-only in the to-string direction,
explicit-only in the other, and therefore should create no surprising behavior.
Remove a bunch of thereby-obsoleted datatype-specific casting functions.

The "general mechanism" is a new expression node type CoerceViaIO that can
actually convert between *any* two datatypes if their external text
representations are compatible.  This is more general than needed for the
immediate feature, but might be useful in plpgsql or other places in future.

This commit does nothing about the issue that applying the concatenation
operator || to non-text types will now fail, often with strange error messages
due to misinterpreting the operator as array concatenation.  Since it often
(not always) worked before, we should either make it succeed or at least give
a more user-friendly error; but details are still under debate.

Peter Eisentraut and Tom Lane
This commit is contained in:
Tom Lane 2007-06-05 21:31:09 +00:00
parent 1120b99445
commit 31edbadf4a
60 changed files with 850 additions and 1612 deletions

View File

@ -236,10 +236,6 @@ cube_distance(cube, cube) returns double
cube_distance returns the distance between two cubes. If both cubes are
points, this is the normal distance function.
cube(text) returns cube
cube takes text input and returns a cube. This is useful for making cubes
from computed strings.
cube(float8) returns cube
This makes a one dimensional cube with both coordinates the same.
If the type of the argument is a numeric type other than float8 an

View File

@ -1,5 +1,5 @@
/******************************************************************************
$PostgreSQL: pgsql/contrib/cube/cube.c,v 1.32 2007/03/07 21:21:11 teodor Exp $
$PostgreSQL: pgsql/contrib/cube/cube.c,v 1.33 2007/06/05 21:31:03 tgl Exp $
This file contains routines that can be bound to a Postgres backend and
called by the backend in the process of processing queries. The calling
@ -173,18 +173,6 @@ cube_in(PG_FUNCTION_ARGS)
PG_RETURN_NDBOX(result);
}
/* Allow conversion from text to cube to allow input of computed strings */
/* There may be issues with toasted data here. I don't know enough to be sure.*/
Datum
cube(PG_FUNCTION_ARGS)
{
char *cstring;
cstring = DatumGetCString(DirectFunctionCall1(textout, PointerGetDatum(PG_GETARG_TEXT_P(0))));
PG_RETURN_DATUM(DirectFunctionCall1(cube_in, PointerGetDatum(cstring)));
}
/*
** Allows the construction of a cube from 2 float[]'s

View File

@ -31,16 +31,6 @@ CREATE TYPE cube (
COMMENT ON TYPE cube IS 'multi-dimensional cube ''(FLOAT-1, FLOAT-2, ..., FLOAT-N), (FLOAT-1, FLOAT-2, ..., FLOAT-N)''';
-- Convert from text to cube
CREATE OR REPLACE FUNCTION cube(text) RETURNS cube
AS 'MODULE_PATHNAME'
LANGUAGE C IMMUTABLE STRICT;
COMMENT ON FUNCTION cube(text) IS 'convert text to cube';
CREATE CAST (text AS cube) WITH FUNCTION cube(text) AS ASSIGNMENT;
--
-- External C-functions for R-tree methods
--

View File

@ -826,7 +826,7 @@ SELECT cube_distance('(0)'::cube,'(.3,.4)'::cube);
-- Test of cube function (text to cube)
--
SELECT cube('('||1||','||1.2||')');
SELECT cube('(1,1.2)'::text);
cube
----------
(1, 1.2)

View File

@ -826,7 +826,7 @@ SELECT cube_distance('(0)'::cube,'(.3,.4)'::cube);
-- Test of cube function (text to cube)
--
SELECT cube('('||1||','||1.2||')');
SELECT cube('(1,1.2)'::text);
cube
----------
(1, 1.2)

View File

@ -826,7 +826,7 @@ SELECT cube_distance('(0)'::cube,'(.3,.4)'::cube);
-- Test of cube function (text to cube)
--
SELECT cube('('||1||','||1.2||')');
SELECT cube('(1,1.2)'::text);
cube
----------
(1, 1.2)

View File

@ -223,7 +223,7 @@ SELECT cube_distance('(0)'::cube,'(.3,.4)'::cube);
-- Test of cube function (text to cube)
--
SELECT cube('('||1||','||1.2||')');
SELECT cube('(1,1.2)'::text);
SELECT cube(NULL);
-- Test of cube_dim function (dimensions stored in cube)

View File

@ -92,8 +92,4 @@ DROP FUNCTION cube_ne(cube, cube);
DROP FUNCTION cube_eq(cube, cube);
DROP CAST (text AS cube);
DROP FUNCTION cube(text);
DROP TYPE cube CASCADE;

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
*
* IDENTIFICATION
* $PostgreSQL: pgsql/contrib/isn/isn.c,v 1.5 2007/01/05 22:19:18 momjian Exp $
* $PostgreSQL: pgsql/contrib/isn/isn.c,v 1.6 2007/06/05 21:31:03 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -39,10 +39,6 @@ static const char *isn_names[] = {"EAN13/UPC/ISxN", "EAN13/UPC/ISxN", "EAN13", "
static bool g_weak = false;
static bool g_initialized = false;
/* Macros for converting TEXT to and from c-string */
#define GET_TEXT(cstrp) DatumGetTextP(DirectFunctionCall1(textin, CStringGetDatum(cstrp)))
#define GET_STR(textp) DatumGetCString(DirectFunctionCall1(textout, PointerGetDatum(textp)))
/***********************************************************************
**
@ -1042,30 +1038,6 @@ upc_in(PG_FUNCTION_ARGS)
/* casting functions
*/
PG_FUNCTION_INFO_V1(ean13_cast_to_text);
Datum
ean13_cast_to_text(PG_FUNCTION_ARGS)
{
ean13 val = PG_GETARG_EAN13(0);
char buf[MAXEAN13LEN + 1];
(void) ean2string(val, false, buf, false);
PG_RETURN_TEXT_P(GET_TEXT(buf));
}
PG_FUNCTION_INFO_V1(isn_cast_to_text);
Datum
isn_cast_to_text(PG_FUNCTION_ARGS)
{
ean13 val = PG_GETARG_EAN13(0);
char buf[MAXEAN13LEN + 1];
(void) ean2string(val, false, buf, true);
PG_RETURN_TEXT_P(GET_TEXT(buf));
}
PG_FUNCTION_INFO_V1(isbn_cast_from_ean13);
Datum
isbn_cast_from_ean13(PG_FUNCTION_ARGS)
@ -1115,61 +1087,6 @@ upc_cast_from_ean13(PG_FUNCTION_ARGS)
}
PG_FUNCTION_INFO_V1(ean13_cast_from_text);
Datum
ean13_cast_from_text(PG_FUNCTION_ARGS)
{
const char *str = GET_STR(PG_GETARG_TEXT_P(0));
ean13 result;
(void) string2ean(str, false, &result, EAN13);
PG_RETURN_EAN13(result);
}
PG_FUNCTION_INFO_V1(isbn_cast_from_text);
Datum
isbn_cast_from_text(PG_FUNCTION_ARGS)
{
const char *str = GET_STR(PG_GETARG_TEXT_P(0));
ean13 result;
(void) string2ean(str, false, &result, ISBN);
PG_RETURN_EAN13(result);
}
PG_FUNCTION_INFO_V1(ismn_cast_from_text);
Datum
ismn_cast_from_text(PG_FUNCTION_ARGS)
{
const char *str = GET_STR(PG_GETARG_TEXT_P(0));
ean13 result;
(void) string2ean(str, false, &result, ISMN);
PG_RETURN_EAN13(result);
}
PG_FUNCTION_INFO_V1(issn_cast_from_text);
Datum
issn_cast_from_text(PG_FUNCTION_ARGS)
{
const char *str = GET_STR(PG_GETARG_TEXT_P(0));
ean13 result;
(void) string2ean(str, false, &result, ISSN);
PG_RETURN_EAN13(result);
}
PG_FUNCTION_INFO_V1(upc_cast_from_text);
Datum
upc_cast_from_text(PG_FUNCTION_ARGS)
{
const char *str = GET_STR(PG_GETARG_TEXT_P(0));
ean13 result;
(void) string2ean(str, false, &result, UPC);
PG_RETURN_EAN13(result);
}
/* is_valid - returns false if the "invalid-check-digit-on-input" is set
*/
PG_FUNCTION_INFO_V1(is_valid);

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
*
* IDENTIFICATION
* $PostgreSQL: pgsql/contrib/isn/isn.h,v 1.3 2007/01/05 22:19:18 momjian Exp $
* $PostgreSQL: pgsql/contrib/isn/isn.h,v 1.4 2007/06/05 21:31:03 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -38,13 +38,6 @@ extern Datum ismn_in(PG_FUNCTION_ARGS);
extern Datum issn_in(PG_FUNCTION_ARGS);
extern Datum upc_in(PG_FUNCTION_ARGS);
extern Datum ean13_cast_to_text(PG_FUNCTION_ARGS);
extern Datum isn_cast_to_text(PG_FUNCTION_ARGS);
extern Datum ean13_cast_from_text(PG_FUNCTION_ARGS);
extern Datum isbn_cast_from_text(PG_FUNCTION_ARGS);
extern Datum ismn_cast_from_text(PG_FUNCTION_ARGS);
extern Datum issn_cast_from_text(PG_FUNCTION_ARGS);
extern Datum upc_cast_from_text(PG_FUNCTION_ARGS);
extern Datum isbn_cast_from_ean13(PG_FUNCTION_ARGS);
extern Datum ismn_cast_from_ean13(PG_FUNCTION_ARGS);
extern Datum issn_cast_from_ean13(PG_FUNCTION_ARGS);

View File

@ -2,7 +2,7 @@
-- PostgreSQL code for ISNs (ISBN, ISMN, ISSN, EAN13, UPC)
-- Copyright (c) 2004-2006, German Mendez Bravo (Kronuz)
--
-- $PostgreSQL: pgsql/contrib/isn/isn.sql.in,v 1.4 2006/11/24 18:44:37 tgl Exp $
-- $PostgreSQL: pgsql/contrib/isn/isn.sql.in,v 1.5 2007/06/05 21:31:03 tgl Exp $
--
-- Example:
-- create table test ( id isbn );
@ -2966,73 +2966,6 @@ AS 'MODULE_PATHNAME', 'upc_cast_from_ean13'
LANGUAGE 'C' IMMUTABLE STRICT;
CREATE FUNCTION ean13(text)
RETURNS ean13
AS 'MODULE_PATHNAME', 'ean13_cast_from_text'
LANGUAGE 'C' IMMUTABLE STRICT;
CREATE FUNCTION isbn13(text)
RETURNS isbn13
AS 'MODULE_PATHNAME', 'isbn_cast_from_text'
LANGUAGE 'C' IMMUTABLE STRICT;
CREATE FUNCTION ismn13(text)
RETURNS ismn13
AS 'MODULE_PATHNAME', 'ismn_cast_from_text'
LANGUAGE 'C' IMMUTABLE STRICT;
CREATE FUNCTION issn13(text)
RETURNS issn13
AS 'MODULE_PATHNAME', 'issn_cast_from_text'
LANGUAGE 'C' IMMUTABLE STRICT;
CREATE FUNCTION isbn(text)
RETURNS isbn
AS 'MODULE_PATHNAME', 'isbn_cast_from_text'
LANGUAGE 'C' IMMUTABLE STRICT;
CREATE FUNCTION ismn(text)
RETURNS ismn
AS 'MODULE_PATHNAME', 'ismn_cast_from_text'
LANGUAGE 'C' IMMUTABLE STRICT;
CREATE FUNCTION issn(text)
RETURNS issn
AS 'MODULE_PATHNAME', 'issn_cast_from_text'
LANGUAGE 'C' IMMUTABLE STRICT;
CREATE FUNCTION upc(text)
RETURNS upc
AS 'MODULE_PATHNAME', 'upc_cast_from_text'
LANGUAGE 'C' IMMUTABLE STRICT;
CREATE FUNCTION text(ean13)
RETURNS text
AS 'MODULE_PATHNAME', 'ean13_cast_to_text'
LANGUAGE 'C' IMMUTABLE STRICT;
CREATE FUNCTION text(isbn13)
RETURNS text
AS 'MODULE_PATHNAME', 'ean13_cast_to_text'
LANGUAGE 'C' IMMUTABLE STRICT;
CREATE FUNCTION text(ismn13)
RETURNS text
AS 'MODULE_PATHNAME', 'ean13_cast_to_text'
LANGUAGE 'C' IMMUTABLE STRICT;
CREATE FUNCTION text(issn13)
RETURNS text
AS 'MODULE_PATHNAME', 'ean13_cast_to_text'
LANGUAGE 'C' IMMUTABLE STRICT;
CREATE FUNCTION text(isbn)
RETURNS text
AS 'MODULE_PATHNAME', 'isn_cast_to_text'
LANGUAGE 'C' IMMUTABLE STRICT;
CREATE FUNCTION text(ismn)
RETURNS text
AS 'MODULE_PATHNAME', 'isn_cast_to_text'
LANGUAGE 'C' IMMUTABLE STRICT;
CREATE FUNCTION text(issn)
RETURNS text
AS 'MODULE_PATHNAME', 'isn_cast_to_text'
LANGUAGE 'C' IMMUTABLE STRICT;
CREATE FUNCTION text(upc)
RETURNS text
AS 'MODULE_PATHNAME', 'isn_cast_to_text'
LANGUAGE 'C' IMMUTABLE STRICT;
CREATE CAST (ean13 AS isbn13) WITH FUNCTION isbn13(ean13);
CREATE CAST (ean13 AS isbn) WITH FUNCTION isbn(ean13);
CREATE CAST (ean13 AS ismn13) WITH FUNCTION ismn13(ean13);
@ -3056,24 +2989,6 @@ CREATE CAST (ismn13 AS ismn) WITHOUT FUNCTION AS ASSIGNMENT;
CREATE CAST (issn AS issn13) WITHOUT FUNCTION AS ASSIGNMENT;
CREATE CAST (issn13 AS issn) WITHOUT FUNCTION AS ASSIGNMENT;
CREATE CAST (text AS ean13) WITH FUNCTION ean13(text);
CREATE CAST (text AS isbn13) WITH FUNCTION isbn13(text);
CREATE CAST (text AS ismn13) WITH FUNCTION ismn13(text);
CREATE CAST (text AS issn13) WITH FUNCTION issn13(text);
CREATE CAST (text AS isbn) WITH FUNCTION isbn(text);
CREATE CAST (text AS ismn) WITH FUNCTION ismn(text);
CREATE CAST (text AS issn) WITH FUNCTION issn(text);
CREATE CAST (text AS upc) WITH FUNCTION upc(text);
CREATE CAST (ean13 AS text) WITH FUNCTION text(ean13);
CREATE CAST (isbn13 AS text) WITH FUNCTION text(isbn13);
CREATE CAST (ismn13 AS text) WITH FUNCTION text(ismn13);
CREATE CAST (issn13 AS text) WITH FUNCTION text(issn13);
CREATE CAST (isbn AS text) WITH FUNCTION text(isbn);
CREATE CAST (ismn AS text) WITH FUNCTION text(ismn);
CREATE CAST (issn AS text) WITH FUNCTION text(issn);
CREATE CAST (upc AS text) WITH FUNCTION text(upc);
--
-- Validation stuff for lose types:
--

View File

@ -1,4 +1,4 @@
<!-- $PostgreSQL: pgsql/doc/src/sgml/catalogs.sgml,v 2.152 2007/05/15 19:13:54 neilc Exp $ -->
<!-- $PostgreSQL: pgsql/doc/src/sgml/catalogs.sgml,v 2.153 2007/06/05 21:31:03 tgl Exp $ -->
<!--
Documentation of the system catalogs, directed toward PostgreSQL developers
-->
@ -1358,11 +1358,22 @@
</indexterm>
<para>
The catalog <structname>pg_cast</structname> stores data type conversion paths,
both built-in paths and those defined with
The catalog <structname>pg_cast</structname> stores data type conversion
paths, both built-in paths and those defined with
<xref linkend="sql-createcast" endterm="sql-createcast-title">.
</para>
<para>
It should be noted that <structname>pg_cast</structname> does not represent
every type conversion that the system knows how to perform; only those that
cannot be deduced from some generic rule. For example, casting between a
domain and its base type is not explicitly represented in
<structname>pg_cast</structname>. Another important exception is that
<quote>I/O conversion casts</>, those performed using a data type's own
I/O functions to convert to or from <type>text</> or other string types,
are not explicitly represented in <structname>pg_cast</structname>.
</para>
<table>
<title><structfield>pg_cast</> Columns</title>

View File

@ -1,4 +1,4 @@
<!-- $PostgreSQL: pgsql/doc/src/sgml/ref/create_cast.sgml,v 1.25 2007/02/01 00:28:18 momjian Exp $ -->
<!-- $PostgreSQL: pgsql/doc/src/sgml/ref/create_cast.sgml,v 1.26 2007/06/05 21:31:04 tgl Exp $ -->
<refentry id="SQL-CREATECAST">
<refmeta>
@ -35,11 +35,11 @@ CREATE CAST (<replaceable>sourcetype</replaceable> AS <replaceable>targettype</r
specifies how to perform a conversion between
two data types. For example:
<programlisting>
SELECT CAST(42 AS text);
SELECT CAST(42 AS float8);
</programlisting>
converts the integer constant 42 to type <type>text</type> by
converts the integer constant 42 to type <type>float8</type> by
invoking a previously specified function, in this case
<literal>text(int4)</>. (If no suitable cast has been defined, the
<literal>float8(int4)</>. (If no suitable cast has been defined, the
conversion fails.)
</para>
@ -69,8 +69,7 @@ SELECT CAST(42 AS text);
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</>, otherwise
not.
<type>text</type> is marked <literal>AS ASSIGNMENT</>, otherwise not.
(We generally use the term <firstterm>assignment
cast</firstterm> to describe this kind of cast.)
</para>
@ -78,19 +77,37 @@ INSERT INTO foo (f1) VALUES (42);
<para>
If the cast is marked <literal>AS IMPLICIT</> then it can be invoked
implicitly in any context, whether assignment or internally in an
expression. For example, since <literal>||</> takes <type>text</>
operands,
<programlisting>
SELECT 'The time is ' || now();
</programlisting>
will be allowed only if the cast from type <type>timestamp</> to
<type>text</type> is marked <literal>AS IMPLICIT</>. Otherwise it
will be necessary to write the cast explicitly, for example:
<programlisting>
SELECT 'The time is ' || CAST(now() AS text);
</programlisting>
(We generally use the term <firstterm>implicit
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</>
and <type>numeric</> respectively. There is no <type>integer</>
<literal>+</> <type>numeric</> operator in the system catalogs,
but there is a <type>numeric</> <literal>+</> <type>numeric</> operator.
The query will therefore succeed if a cast from <type>integer</> to
<type>numeric</> is available and is marked <literal>AS IMPLICIT</> &mdash;
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</> to
<type>integer</>. If that cast were marked <literal>AS IMPLICIT</> &mdash;
which it is not &mdash; then the parser would be faced with choosing
between the above interpretation and the alternative of casting the
<type>numeric</> constant to <type>integer</> and applying the
<type>integer</> <literal>+</> <type>integer</> 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</>-and-<type>integer</> expression as
<type>numeric</>; there is no built-in knowledge about that.
</para>
<para>
@ -208,9 +225,7 @@ SELECT 'The time is ' || CAST(now() AS text);
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.)
second argument.
</para>
<para>
@ -237,6 +252,32 @@ SELECT 'The time is ' || CAST(now() AS text);
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>varchar</>, and
<type>char(<replaceable>n</>)</type>). <productname>PostgreSQL</> will
automatically handle a cast to a string type by invoking the other
type's output function, or conversely handle a cast from a string type
by invoking the other type's input function. These
automatically-provided casts are known as <firstterm>I/O conversion
casts</>. I/O conversion casts to string types are treated as
assignment casts, while I/O conversion casts from string types are
explicit-only. You can override this behavior by declaring your own
cast to replace an I/O conversion 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>
Prior to <productname>PostgreSQL</> 7.3, every function that had
the same name as a data type, returned that data type, and took one
@ -265,16 +306,20 @@ SELECT 'The time is ' || CAST(now() AS text);
<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.
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>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
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
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
exception allows I/O conversion casts to be invoked using functional
syntax.
</para>
</note>
</refsect1>
@ -284,10 +329,10 @@ SELECT 'The time is ' || CAST(now() AS text);
<title>Examples</title>
<para>
To create a cast from type <type>text</type> to type
<type>int4</type> using the function <literal>int4(text)</literal>:
To create a cast from type <type>bigint</type> to type
<type>int4</type> using the function <literal>int4(bigint)</literal>:
<programlisting>
CREATE CAST (text AS int4) WITH FUNCTION int4(text);
CREATE CAST (bigint AS int4) WITH FUNCTION int4(bigint);
</programlisting>
(This cast is already predefined in the system.)
</para>

View File

@ -1,4 +1,4 @@
<!-- $PostgreSQL: pgsql/doc/src/sgml/syntax.sgml,v 1.118 2007/05/11 17:57:11 tgl Exp $ -->
<!-- $PostgreSQL: pgsql/doc/src/sgml/syntax.sgml,v 1.119 2007/06/05 21:31:04 tgl Exp $ -->
<chapter id="sql-syntax">
<title>SQL Syntax</title>
@ -561,18 +561,18 @@ CAST ( '<replaceable>string</replaceable>' AS <replaceable>type</replaceable> )
The <literal>::</literal>, <literal>CAST()</literal>, and
function-call syntaxes can also be used to specify run-time type
conversions of arbitrary expressions, as discussed in <xref
linkend="sql-syntax-type-casts">. But the form
<literal><replaceable>type</replaceable> '<replaceable>string</replaceable>'</literal>
can only be used to specify the type of a literal constant.
Another restriction on
<literal><replaceable>type</replaceable> '<replaceable>string</replaceable>'</literal>
is that it does not work for array types; use <literal>::</literal>
linkend="sql-syntax-type-casts">. To avoid syntactic ambiguity, the
<literal><replaceable>type</> '<replaceable>string</>'</literal>
syntax can only be used to specify the type of a simple literal constant.
Another restriction on the
<literal><replaceable>type</> '<replaceable>string</>'</literal>
syntax is that it does not work for array types; use <literal>::</literal>
or <literal>CAST()</literal> to specify the type of an array constant.
</para>
<para>
The <literal>CAST()</> syntax conforms to SQL. The
<literal><replaceable>type</replaceable> '<replaceable>string</replaceable>'</literal>
<literal><replaceable>type</> '<replaceable>string</>'</literal>
syntax is a generalization of the standard: SQL specifies this syntax only
for a few data types, but <productname>PostgreSQL</productname> allows it
for all types. The syntax with
@ -1431,16 +1431,21 @@ CAST ( <replaceable>expression</replaceable> AS <replaceable>type</replaceable>
double-quoted, because of syntactic conflicts. Therefore, the use of
the function-like cast syntax leads to inconsistencies and should
probably be avoided in new applications.
(The function-like syntax is in fact just a function call. When
one of the two standard cast syntaxes is used to do a run-time
conversion, it will internally invoke a registered function to
perform the conversion. By convention, these conversion functions
have the same name as their output type, and thus the <quote>function-like
syntax</> is nothing more than a direct invocation of the underlying
conversion function. Obviously, this is not something that a portable
application should rely on.)
</para>
<note>
<para>
The function-like syntax is in fact just a function call. When
one of the two standard cast syntaxes is used to do a run-time
conversion, it will internally invoke a registered function to
perform the conversion. By convention, these conversion functions
have the same name as their output type, and thus the <quote>function-like
syntax</> is nothing more than a direct invocation of the underlying
conversion function. Obviously, this is not something that a portable
application should rely on. For further details see
<xref linkend="sql-createcast" endterm="sql-createcast-title">.
</para>
</note>
</sect2>
<sect2 id="sql-syntax-scalar-subqueries">

View File

@ -1,4 +1,4 @@
<!-- $PostgreSQL: pgsql/doc/src/sgml/typeconv.sgml,v 1.51 2007/02/01 19:10:24 momjian Exp $ -->
<!-- $PostgreSQL: pgsql/doc/src/sgml/typeconv.sgml,v 1.52 2007/06/05 21:31:04 tgl Exp $ -->
<chapter Id="typeconv">
<title>Type Conversion</title>
@ -139,7 +139,8 @@ and for the <function>GREATEST</> and <function>LEAST</> functions.
The system catalogs store information about which conversions, called
<firstterm>casts</firstterm>, between data types are valid, and how to
perform those conversions. Additional casts can be added by the user
with the <command>CREATE CAST</command> command. (This is usually
with the <xref linkend="sql-createcast" endterm="sql-createcast-title">
command. (This is usually
done in conjunction with defining new data types. The set of casts
between the built-in types has been carefully crafted and is best not
altered.)
@ -336,28 +337,28 @@ Some examples follow.
</para>
<example>
<title>Exponentiation Operator Type Resolution</title>
<title>Factorial Operator Type Resolution</title>
<para>
There is only one exponentiation
operator defined in the catalog, and it takes arguments of type
<type>double precision</type>.
The scanner assigns an initial type of <type>integer</type> to both arguments
of this query expression:
There is only one factorial operator (postfix <literal>!</>)
defined in the standard catalog, and it takes an argument of type
<type>bigint</type>.
The scanner assigns an initial type of <type>integer</type> to the argument
in this query expression:
<screen>
SELECT 2 ^ 3 AS "exp";
SELECT 40 ! AS "40 factorial";
exp
-----
8
40 factorial
--------------------------------------------------
815915283247897734345611269596115894272000000000
(1 row)
</screen>
So the parser does a type conversion on both operands and the query
So the parser does a type conversion on the operand and the query
is equivalent to
<screen>
SELECT CAST(2 AS double precision) ^ CAST(3 AS double precision) AS "exp";
SELECT CAST(40 AS bigint) ! AS "40 factorial";
</screen>
</para>
</example>
@ -421,7 +422,7 @@ entries for the prefix operator <literal>@</>, all of which implement
absolute-value operations for various numeric data types. One of these
entries is for type <type>float8</type>, which is the preferred type in
the numeric category. Therefore, <productname>PostgreSQL</productname>
will use that entry when faced with a non-numeric input:
will use that entry when faced with an <type>unknown</> input:
<screen>
SELECT @ '-4.5' AS "abs";
abs
@ -429,9 +430,9 @@ SELECT @ '-4.5' AS "abs";
4.5
(1 row)
</screen>
Here the system has performed an implicit conversion from <type>text</type> to <type>float8</type>
before applying the chosen operator. We can verify that <type>float8</type> and
not some other type was used:
Here the system has implicitly resolved the unknown-type literal as type
<type>float8</type> before applying the chosen operator. We can verify that
<type>float8</type> and not some other type was used:
<screen>
SELECT @ '-4.5e500' AS "abs";
@ -447,8 +448,8 @@ try a similar case with <literal>~</>, we get:
SELECT ~ '20' AS "negation";
ERROR: operator is not unique: ~ "unknown"
HINT: Could not choose a best candidate operator. You might need to add explicit
type casts.
HINT: Could not choose a best candidate operator. You might need to add
explicit type casts.
</screen>
This happens because the system cannot decide which of the several
possible <literal>~</> operators should be preferred. We can help
@ -518,12 +519,24 @@ this step.)
<step performance="required">
<para>
If no exact match is found, see whether the function call appears
to be a trivial 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)
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
data type. When these conditions are met, the function argument is converted
to the named data type without any actual function call.
an unknown-type literal, or a type that is binary-compatible with 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,
the function call is treated as a form of <literal>CAST</> specification.
<footnote>
<para>
The reason for this step is to support function-style cast specifications
in cases where there is not an actual cast function. If there is a cast
function, it is conventionally named after its output type, and so there
is no need to have a special case. See
<xref linkend="sql-createcast" endterm="sql-createcast-title">
for additional commentary.
</para>
</footnote>
</para>
</step>
<step performance="required">
@ -670,30 +683,31 @@ The parser learns from the <structname>pg_cast</> catalog that
<type>text</type> and <type>varchar</type>
are binary-compatible, meaning that one can be passed to a function that
accepts the other without doing any physical conversion. Therefore, no
explicit type conversion call is really inserted in this case.
type conversion call is really inserted in this case.
</para>
</note>
</para>
<para>
And, if the function is called with an argument of type <type>integer</type>, the parser will
try to convert that to <type>text</type>:
And, if the function is called with an argument of type <type>integer</type>,
the parser will try to convert that to <type>text</type>:
<screen>
SELECT substr(1234, 3);
ERROR: function substr(integer, integer) does not exist
HINT: No function matches the given name and argument types. You might need
to add explicit type casts.
</screen>
This does not work because <type>integer</> does not have an implicit cast
to <type>text</>. An explicit cast will work, however:
<screen>
SELECT substr(CAST (1234 AS text), 3);
substr
--------
34
(1 row)
</screen>
This actually executes as
<screen>
SELECT substr(CAST (1234 AS text), 3);
</screen>
This automatic transformation can succeed because there is an
implicitly invocable cast from <type>integer</type> to
<type>text</type>.
</para>
</example>

View File

@ -8,7 +8,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/catalog/dependency.c,v 1.65 2007/03/27 23:21:08 tgl Exp $
* $PostgreSQL: pgsql/src/backend/catalog/dependency.c,v 1.66 2007/06/05 21:31:04 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -1315,6 +1315,14 @@ find_expr_references_walker(Node *node,
add_object_address(OCLASS_TYPE, relab->resulttype, 0,
context->addrs);
}
if (IsA(node, CoerceViaIO))
{
CoerceViaIO *iocoerce = (CoerceViaIO *) node;
/* since there is no exposed function, need to depend on type */
add_object_address(OCLASS_TYPE, iocoerce->resulttype, 0,
context->addrs);
}
if (IsA(node, ArrayCoerceExpr))
{
ArrayCoerceExpr *acoerce = (ArrayCoerceExpr *) node;

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.217 2007/04/06 04:21:42 tgl Exp $
* $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.218 2007/06/05 21:31:04 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -145,6 +145,9 @@ static Datum ExecEvalFieldStore(FieldStoreState *fstate,
static Datum ExecEvalRelabelType(GenericExprState *exprstate,
ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone);
static Datum ExecEvalCoerceViaIO(CoerceViaIOState *iostate,
ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone);
static Datum ExecEvalArrayCoerceExpr(ArrayCoerceExprState *astate,
ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone);
@ -3504,6 +3507,40 @@ ExecEvalRelabelType(GenericExprState *exprstate,
return ExecEvalExpr(exprstate->arg, econtext, isNull, isDone);
}
/* ----------------------------------------------------------------
* ExecEvalCoerceViaIO
*
* Evaluate a CoerceViaIO node.
* ----------------------------------------------------------------
*/
static Datum
ExecEvalCoerceViaIO(CoerceViaIOState *iostate,
ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone)
{
Datum result;
Datum inputval;
char *string;
inputval = ExecEvalExpr(iostate->arg, econtext, isNull, isDone);
if (isDone && *isDone == ExprEndResult)
return inputval; /* nothing to do */
if (*isNull)
string = NULL; /* output functions are not called on nulls */
else
string = OutputFunctionCall(&iostate->outfunc, inputval);
result = InputFunctionCall(&iostate->infunc,
string,
iostate->intypioparam,
-1);
/* The input function cannot change the null/not-null status */
return result;
}
/* ----------------------------------------------------------------
* ExecEvalArrayCoerceExpr
*
@ -3850,6 +3887,26 @@ ExecInitExpr(Expr *node, PlanState *parent)
state = (ExprState *) gstate;
}
break;
case T_CoerceViaIO:
{
CoerceViaIO *iocoerce = (CoerceViaIO *) node;
CoerceViaIOState *iostate = makeNode(CoerceViaIOState);
Oid iofunc;
bool typisvarlena;
iostate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalCoerceViaIO;
iostate->arg = ExecInitExpr(iocoerce->arg, parent);
/* lookup the result type's input function */
getTypeInputInfo(iocoerce->resulttype, &iofunc,
&iostate->intypioparam);
fmgr_info(iofunc, &iostate->infunc);
/* lookup the input type's output function */
getTypeOutputInfo(exprType((Node *) iocoerce->arg),
&iofunc, &typisvarlena);
fmgr_info(iofunc, &iostate->outfunc);
state = (ExprState *) iostate;
}
break;
case T_ArrayCoerceExpr:
{
ArrayCoerceExpr *acoerce = (ArrayCoerceExpr *) node;

View File

@ -15,7 +15,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.376 2007/05/22 23:23:55 tgl Exp $
* $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.377 2007/06/05 21:31:04 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -1021,6 +1021,21 @@ _copyRelabelType(RelabelType *from)
return newnode;
}
/*
* _copyCoerceViaIO
*/
static CoerceViaIO *
_copyCoerceViaIO(CoerceViaIO *from)
{
CoerceViaIO *newnode = makeNode(CoerceViaIO);
COPY_NODE_FIELD(arg);
COPY_SCALAR_FIELD(resulttype);
COPY_SCALAR_FIELD(coerceformat);
return newnode;
}
/*
* _copyArrayCoerceExpr
*/
@ -3108,6 +3123,9 @@ copyObject(void *from)
case T_RelabelType:
retval = _copyRelabelType(from);
break;
case T_CoerceViaIO:
retval = _copyCoerceViaIO(from);
break;
case T_ArrayCoerceExpr:
retval = _copyArrayCoerceExpr(from);
break;

View File

@ -18,7 +18,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.307 2007/05/22 23:23:56 tgl Exp $
* $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.308 2007/06/05 21:31:04 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -359,6 +359,24 @@ _equalRelabelType(RelabelType *a, RelabelType *b)
return true;
}
static bool
_equalCoerceViaIO(CoerceViaIO *a, CoerceViaIO *b)
{
COMPARE_NODE_FIELD(arg);
COMPARE_SCALAR_FIELD(resulttype);
/*
* Special-case COERCE_DONTCARE, so that planner can build coercion nodes
* that are equal() to both explicit and implicit coercions.
*/
if (a->coerceformat != b->coerceformat &&
a->coerceformat != COERCE_DONTCARE &&
b->coerceformat != COERCE_DONTCARE)
return false;
return true;
}
static bool
_equalArrayCoerceExpr(ArrayCoerceExpr *a, ArrayCoerceExpr *b)
{
@ -2052,6 +2070,9 @@ equal(void *a, void *b)
case T_RelabelType:
retval = _equalRelabelType(a, b);
break;
case T_CoerceViaIO:
retval = _equalCoerceViaIO(a, b);
break;
case T_ArrayCoerceExpr:
retval = _equalArrayCoerceExpr(a, b);
break;

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.308 2007/05/22 23:23:56 tgl Exp $
* $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.309 2007/06/05 21:31:04 tgl Exp $
*
* NOTES
* Every node type that can appear in stored rules' parsetrees *must*
@ -870,6 +870,16 @@ _outRelabelType(StringInfo str, RelabelType *node)
WRITE_ENUM_FIELD(relabelformat, CoercionForm);
}
static void
_outCoerceViaIO(StringInfo str, CoerceViaIO *node)
{
WRITE_NODE_TYPE("COERCEVIAIO");
WRITE_NODE_FIELD(arg);
WRITE_OID_FIELD(resulttype);
WRITE_ENUM_FIELD(coerceformat, CoercionForm);
}
static void
_outArrayCoerceExpr(StringInfo str, ArrayCoerceExpr *node)
{
@ -2165,6 +2175,9 @@ _outNode(StringInfo str, void *obj)
case T_RelabelType:
_outRelabelType(str, obj);
break;
case T_CoerceViaIO:
_outCoerceViaIO(str, obj);
break;
case T_ArrayCoerceExpr:
_outArrayCoerceExpr(str, obj);
break;

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/nodes/readfuncs.c,v 1.206 2007/04/27 22:05:47 tgl Exp $
* $PostgreSQL: pgsql/src/backend/nodes/readfuncs.c,v 1.207 2007/06/05 21:31:04 tgl Exp $
*
* NOTES
* Path and Plan nodes do not have any readfuncs support, because we
@ -584,6 +584,21 @@ _readRelabelType(void)
READ_DONE();
}
/*
* _readCoerceViaIO
*/
static CoerceViaIO *
_readCoerceViaIO(void)
{
READ_LOCALS(CoerceViaIO);
READ_NODE_FIELD(arg);
READ_OID_FIELD(resulttype);
READ_ENUM_FIELD(coerceformat, CoercionForm);
READ_DONE();
}
/*
* _readArrayCoerceExpr
*/
@ -1042,6 +1057,8 @@ parseNodeString(void)
return_value = _readFieldStore();
else if (MATCH("RELABELTYPE", 11))
return_value = _readRelabelType();
else if (MATCH("COERCEVIAIO", 11))
return_value = _readCoerceViaIO();
else if (MATCH("ARRAYCOERCEEXPR", 15))
return_value = _readArrayCoerceExpr();
else if (MATCH("CONVERTROWTYPEEXPR", 18))

View File

@ -54,7 +54,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/optimizer/path/costsize.c,v 1.183 2007/05/21 17:57:33 tgl Exp $
* $PostgreSQL: pgsql/src/backend/optimizer/path/costsize.c,v 1.184 2007/06/05 21:31:05 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -70,6 +70,7 @@
#include "optimizer/pathnode.h"
#include "optimizer/planmain.h"
#include "parser/parsetree.h"
#include "parser/parse_expr.h"
#include "utils/lsyscache.h"
#include "utils/selfuncs.h"
#include "utils/tuplesort.h"
@ -1951,6 +1952,22 @@ cost_qual_eval_walker(Node *node, cost_qual_eval_context *context)
context->total.per_tuple += get_func_cost(saop->opfuncid) *
cpu_operator_cost * estimate_array_length(arraynode) * 0.5;
}
else if (IsA(node, CoerceViaIO))
{
CoerceViaIO *iocoerce = (CoerceViaIO *) node;
Oid iofunc;
Oid typioparam;
bool typisvarlena;
/* check the result type's input function */
getTypeInputInfo(iocoerce->resulttype,
&iofunc, &typioparam);
context->total.per_tuple += get_func_cost(iofunc) * cpu_operator_cost;
/* check the input type's output function */
getTypeOutputInfo(exprType((Node *) iocoerce->arg),
&iofunc, &typisvarlena);
context->total.per_tuple += get_func_cost(iofunc) * cpu_operator_cost;
}
else if (IsA(node, ArrayCoerceExpr))
{
ArrayCoerceExpr *acoerce = (ArrayCoerceExpr *) node;

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.244 2007/05/01 18:53:51 tgl Exp $
* $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.245 2007/06/05 21:31:05 tgl Exp $
*
* HISTORY
* AUTHOR DATE MAJOR EVENT
@ -734,6 +734,25 @@ contain_mutable_functions_walker(Node *node, void *context)
return true;
/* else fall through to check args */
}
else if (IsA(node, CoerceViaIO))
{
CoerceViaIO *expr = (CoerceViaIO *) node;
Oid iofunc;
Oid typioparam;
bool typisvarlena;
/* check the result type's input function */
getTypeInputInfo(expr->resulttype,
&iofunc, &typioparam);
if (func_volatile(iofunc) != PROVOLATILE_IMMUTABLE)
return true;
/* check the input type's output function */
getTypeOutputInfo(exprType((Node *) expr->arg),
&iofunc, &typisvarlena);
if (func_volatile(iofunc) != PROVOLATILE_IMMUTABLE)
return true;
/* else fall through to check args */
}
else if (IsA(node, ArrayCoerceExpr))
{
ArrayCoerceExpr *expr = (ArrayCoerceExpr *) node;
@ -826,6 +845,25 @@ contain_volatile_functions_walker(Node *node, void *context)
return true;
/* else fall through to check args */
}
else if (IsA(node, CoerceViaIO))
{
CoerceViaIO *expr = (CoerceViaIO *) node;
Oid iofunc;
Oid typioparam;
bool typisvarlena;
/* check the result type's input function */
getTypeInputInfo(expr->resulttype,
&iofunc, &typioparam);
if (func_volatile(iofunc) == PROVOLATILE_VOLATILE)
return true;
/* check the input type's output function */
getTypeOutputInfo(exprType((Node *) expr->arg),
&iofunc, &typisvarlena);
if (func_volatile(iofunc) == PROVOLATILE_VOLATILE)
return true;
/* else fall through to check args */
}
else if (IsA(node, ArrayCoerceExpr))
{
ArrayCoerceExpr *expr = (ArrayCoerceExpr *) node;
@ -1124,6 +1162,13 @@ find_nonnullable_rels_walker(Node *node, bool top_level)
result = find_nonnullable_rels_walker((Node *) expr->arg, top_level);
}
else if (IsA(node, CoerceViaIO))
{
/* not clear this is useful, but it can't hurt */
CoerceViaIO *expr = (CoerceViaIO *) node;
result = find_nonnullable_rels_walker((Node *) expr->arg, top_level);
}
else if (IsA(node, ArrayCoerceExpr))
{
/* ArrayCoerceExpr is strict at the array level */
@ -1486,6 +1531,13 @@ strip_implicit_coercions(Node *node)
if (r->relabelformat == COERCE_IMPLICIT_CAST)
return strip_implicit_coercions((Node *) r->arg);
}
else if (IsA(node, CoerceViaIO))
{
CoerceViaIO *c = (CoerceViaIO *) node;
if (c->coerceformat == COERCE_IMPLICIT_CAST)
return strip_implicit_coercions((Node *) c->arg);
}
else if (IsA(node, ArrayCoerceExpr))
{
ArrayCoerceExpr *c = (ArrayCoerceExpr *) node;
@ -1537,6 +1589,8 @@ set_coercionform_dontcare_walker(Node *node, void *context)
((FuncExpr *) node)->funcformat = COERCE_DONTCARE;
else if (IsA(node, RelabelType))
((RelabelType *) node)->relabelformat = COERCE_DONTCARE;
else if (IsA(node, CoerceViaIO))
((CoerceViaIO *) node)->coerceformat = COERCE_DONTCARE;
else if (IsA(node, ArrayCoerceExpr))
((ArrayCoerceExpr *) node)->coerceformat = COERCE_DONTCARE;
else if (IsA(node, ConvertRowtypeExpr))
@ -3471,6 +3525,8 @@ expression_tree_walker(Node *node,
break;
case T_RelabelType:
return walker(((RelabelType *) node)->arg, context);
case T_CoerceViaIO:
return walker(((CoerceViaIO *) node)->arg, context);
case T_ArrayCoerceExpr:
return walker(((ArrayCoerceExpr *) node)->arg, context);
case T_ConvertRowtypeExpr:
@ -3959,6 +4015,16 @@ expression_tree_mutator(Node *node,
return (Node *) newnode;
}
break;
case T_CoerceViaIO:
{
CoerceViaIO *iocoerce = (CoerceViaIO *) node;
CoerceViaIO *newnode;
FLATCOPY(newnode, iocoerce, CoerceViaIO);
MUTATE(newnode->arg, iocoerce->arg, Expr *);
return (Node *) newnode;
}
break;
case T_ArrayCoerceExpr:
{
ArrayCoerceExpr *acoerce = (ArrayCoerceExpr *) node;

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/parser/parse_coerce.c,v 2.153 2007/04/02 03:49:38 tgl Exp $
* $PostgreSQL: pgsql/src/backend/parser/parse_coerce.c,v 2.154 2007/06/05 21:31:05 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -37,9 +37,10 @@ static Node *coerce_type_typmod(Node *node,
bool hideInputCoercion);
static void hide_coercion_node(Node *node);
static Node *build_coercion_expression(Node *node,
Oid funcId, bool arrayCoerce,
Oid targetTypeId, int32 targetTypMod,
CoercionForm cformat, bool isExplicit);
CoercionPathType pathtype,
Oid funcId,
Oid targetTypeId, int32 targetTypMod,
CoercionForm cformat, bool isExplicit);
static Node *coerce_record_to_complex(ParseState *pstate, Node *node,
Oid targetTypeId,
CoercionContext ccontext,
@ -121,8 +122,8 @@ coerce_type(ParseState *pstate, Node *node,
CoercionContext ccontext, CoercionForm cformat)
{
Node *result;
CoercionPathType pathtype;
Oid funcId;
bool arrayCoerce;
if (targetTypeId == inputTypeId ||
node == NULL)
@ -280,10 +281,11 @@ coerce_type(ParseState *pstate, Node *node,
return (Node *) param;
}
if (find_coercion_pathway(targetTypeId, inputTypeId, ccontext,
&funcId, &arrayCoerce))
pathtype = find_coercion_pathway(targetTypeId, inputTypeId, ccontext,
&funcId);
if (pathtype != COERCION_PATH_NONE)
{
if (OidIsValid(funcId) || arrayCoerce)
if (pathtype != COERCION_PATH_RELABELTYPE)
{
/*
* Generate an expression tree representing run-time application
@ -298,7 +300,7 @@ coerce_type(ParseState *pstate, Node *node,
baseTypeMod = targetTypeMod;
baseTypeId = getBaseTypeAndTypmod(targetTypeId, &baseTypeMod);
result = build_coercion_expression(node, funcId, arrayCoerce,
result = build_coercion_expression(node, pathtype, funcId,
baseTypeId, baseTypeMod,
cformat,
(cformat != COERCE_IMPLICIT_CAST));
@ -397,8 +399,8 @@ can_coerce_type(int nargs, Oid *input_typeids, Oid *target_typeids,
{
Oid inputTypeId = input_typeids[i];
Oid targetTypeId = target_typeids[i];
CoercionPathType pathtype;
Oid funcId;
bool arrayCoerce;
/* no problem if same type */
if (inputTypeId == targetTypeId)
@ -426,8 +428,9 @@ can_coerce_type(int nargs, Oid *input_typeids, Oid *target_typeids,
* If pg_cast shows that we can coerce, accept. This test now covers
* both binary-compatible and coercion-function cases.
*/
if (find_coercion_pathway(targetTypeId, inputTypeId, ccontext,
&funcId, &arrayCoerce))
pathtype = find_coercion_pathway(targetTypeId, inputTypeId, ccontext,
&funcId);
if (pathtype != COERCION_PATH_NONE)
continue;
/*
@ -567,8 +570,8 @@ coerce_type_typmod(Node *node, Oid targetTypeId, int32 targetTypMod,
CoercionForm cformat, bool isExplicit,
bool hideInputCoercion)
{
CoercionPathType pathtype;
Oid funcId;
bool arrayCoerce;
/*
* A negative typmod is assumed to mean that no coercion is wanted. Also,
@ -577,14 +580,15 @@ coerce_type_typmod(Node *node, Oid targetTypeId, int32 targetTypMod,
if (targetTypMod < 0 || targetTypMod == exprTypmod(node))
return node;
if (find_typmod_coercion_function(targetTypeId,
&funcId, &arrayCoerce))
pathtype = find_typmod_coercion_function(targetTypeId, &funcId);
if (pathtype != COERCION_PATH_NONE)
{
/* Suppress display of nested coercion steps */
if (hideInputCoercion)
hide_coercion_node(node);
node = build_coercion_expression(node, funcId, arrayCoerce,
node = build_coercion_expression(node, pathtype, funcId,
targetTypeId, targetTypMod,
cformat, isExplicit);
}
@ -609,6 +613,8 @@ hide_coercion_node(Node *node)
((FuncExpr *) node)->funcformat = COERCE_IMPLICIT_CAST;
else if (IsA(node, RelabelType))
((RelabelType *) node)->relabelformat = COERCE_IMPLICIT_CAST;
else if (IsA(node, CoerceViaIO))
((CoerceViaIO *) node)->coerceformat = COERCE_IMPLICIT_CAST;
else if (IsA(node, ArrayCoerceExpr))
((ArrayCoerceExpr *) node)->coerceformat = COERCE_IMPLICIT_CAST;
else if (IsA(node, ConvertRowtypeExpr))
@ -630,7 +636,8 @@ hide_coercion_node(Node *node)
*/
static Node *
build_coercion_expression(Node *node,
Oid funcId, bool arrayCoerce,
CoercionPathType pathtype,
Oid funcId,
Oid targetTypeId, int32 targetTypMod,
CoercionForm cformat, bool isExplicit)
{
@ -651,7 +658,7 @@ build_coercion_expression(Node *node,
/*
* These Asserts essentially check that function is a legal coercion
* function. We can't make the seemingly obvious tests on prorettype
* and proargtypes[0], even in the non-arrayCoerce case, because of
* and proargtypes[0], even in the COERCION_PATH_FUNC case, because of
* various binary-compatibility cases.
*/
/* Assert(targetTypeId == procstruct->prorettype); */
@ -666,26 +673,7 @@ build_coercion_expression(Node *node,
ReleaseSysCache(tp);
}
if (arrayCoerce)
{
/* We need to build an ArrayCoerceExpr */
ArrayCoerceExpr *acoerce = makeNode(ArrayCoerceExpr);
acoerce->arg = (Expr *) node;
acoerce->elemfuncid = funcId;
acoerce->resulttype = targetTypeId;
/*
* Label the output as having a particular typmod only if we are
* really invoking a length-coercion function, ie one with more
* than one argument.
*/
acoerce->resulttypmod = (nargs >= 2) ? targetTypMod : -1;
acoerce->isExplicit = isExplicit;
acoerce->coerceformat = cformat;
return (Node *) acoerce;
}
else
if (pathtype == COERCION_PATH_FUNC)
{
/* We build an ordinary FuncExpr with special arguments */
List *args;
@ -723,6 +711,44 @@ build_coercion_expression(Node *node,
return (Node *) makeFuncExpr(funcId, targetTypeId, args, cformat);
}
else if (pathtype == COERCION_PATH_ARRAYCOERCE)
{
/* We need to build an ArrayCoerceExpr */
ArrayCoerceExpr *acoerce = makeNode(ArrayCoerceExpr);
acoerce->arg = (Expr *) node;
acoerce->elemfuncid = funcId;
acoerce->resulttype = targetTypeId;
/*
* Label the output as having a particular typmod only if we are
* really invoking a length-coercion function, ie one with more
* than one argument.
*/
acoerce->resulttypmod = (nargs >= 2) ? targetTypMod : -1;
acoerce->isExplicit = isExplicit;
acoerce->coerceformat = cformat;
return (Node *) acoerce;
}
else if (pathtype == COERCION_PATH_COERCEVIAIO)
{
/* We need to build a CoerceViaIO node */
CoerceViaIO *iocoerce = makeNode(CoerceViaIO);
Assert(!OidIsValid(funcId));
iocoerce->arg = (Expr *) node;
iocoerce->resulttype = targetTypeId;
iocoerce->coerceformat = cformat;
return (Node *) iocoerce;
}
else
{
elog(ERROR, "unsupported pathtype %d in build_coercion_expression",
(int) pathtype);
return NULL; /* keep compiler quiet */
}
}
@ -1711,29 +1737,38 @@ IsBinaryCoercible(Oid srctype, Oid targettype)
* find_coercion_pathway
* Look for a coercion pathway between two types.
*
* Currently, this deals only with scalar-type cases; it does not consider
* polymorphic types nor casts between composite types. (Perhaps fold
* those in someday?)
*
* ccontext determines the set of available casts.
*
* If we find a suitable entry in pg_cast, return TRUE, and set *funcid
* to the castfunc value, which may be InvalidOid for a binary-compatible
* coercion. Also, arrayCoerce is set to indicate whether this is a plain
* or array coercion (if true, funcid actually shows how to coerce the
* array elements).
* The possible result codes are:
* COERCION_PATH_NONE: failed to find any coercion pathway
* *funcid is set to InvalidOid
* COERCION_PATH_FUNC: apply the coercion function returned in *funcid
* COERCION_PATH_RELABELTYPE: binary-compatible cast, no function needed
* *funcid is set to InvalidOid
* COERCION_PATH_ARRAYCOERCE: need an ArrayCoerceExpr node
* *funcid is set to the element cast function, or InvalidOid
* if the array elements are binary-compatible
* COERCION_PATH_COERCEVIAIO: need a CoerceViaIO node
* *funcid is set to InvalidOid
*
* NOTE: *funcid == InvalidOid does not necessarily mean that no work is
* Note: COERCION_PATH_RELABELTYPE does not necessarily mean that no work is
* needed to do the coercion; if the target is a domain then we may need to
* apply domain constraint checking. If you want to check for a zero-effort
* conversion then use IsBinaryCoercible().
*/
bool
CoercionPathType
find_coercion_pathway(Oid targetTypeId, Oid sourceTypeId,
CoercionContext ccontext,
Oid *funcid, bool *arrayCoerce)
Oid *funcid)
{
bool result = false;
CoercionPathType result = COERCION_PATH_NONE;
HeapTuple tuple;
*funcid = InvalidOid;
*arrayCoerce = false;
/* Perhaps the types are domains; if so, look at their base types */
if (OidIsValid(sourceTypeId))
@ -1743,7 +1778,7 @@ find_coercion_pathway(Oid targetTypeId, Oid sourceTypeId,
/* Domains are always coercible to and from their base type */
if (sourceTypeId == targetTypeId)
return true;
return COERCION_PATH_RELABELTYPE;
/* Look in pg_cast */
tuple = SearchSysCache(CASTSOURCETARGET,
@ -1779,7 +1814,10 @@ find_coercion_pathway(Oid targetTypeId, Oid sourceTypeId,
if (ccontext >= castcontext)
{
*funcid = castForm->castfunc;
result = true;
if (OidIsValid(*funcid))
result = COERCION_PATH_FUNC;
else
result = COERCION_PATH_RELABELTYPE;
}
ReleaseSysCache(tuple);
@ -1789,7 +1827,7 @@ find_coercion_pathway(Oid targetTypeId, Oid sourceTypeId,
/*
* If there's no pg_cast entry, perhaps we are dealing with a pair of
* array types. If so, and if the element types have a suitable cast,
* report that with arrayCoerce = true.
* report that we can coerce with an ArrayCoerceExpr.
*
* Hack: disallow coercions to oidvector and int2vector, which
* otherwise tend to capture coercions that should go to "real" array
@ -1798,25 +1836,30 @@ find_coercion_pathway(Oid targetTypeId, Oid sourceTypeId,
* guaranteed to produce an output that meets the restrictions of
* these datatypes, such as being 1-dimensional.)
*/
Oid targetElemType;
Oid sourceElemType;
Oid elemfuncid;
bool elemarraycoerce;
if (targetTypeId == OIDVECTOROID || targetTypeId == INT2VECTOROID)
return false;
if ((targetElemType = get_element_type(targetTypeId)) != InvalidOid &&
(sourceElemType = get_element_type(sourceTypeId)) != InvalidOid)
if (targetTypeId != OIDVECTOROID && targetTypeId != INT2VECTOROID)
{
if (find_coercion_pathway(targetElemType, sourceElemType,
ccontext,
&elemfuncid, &elemarraycoerce) &&
!elemarraycoerce)
Oid targetElem;
Oid sourceElem;
if ((targetElem = get_element_type(targetTypeId)) != InvalidOid &&
(sourceElem = get_element_type(sourceTypeId)) != InvalidOid)
{
*funcid = elemfuncid;
*arrayCoerce = true;
result = true;
CoercionPathType elempathtype;
Oid elemfuncid;
elempathtype = find_coercion_pathway(targetElem,
sourceElem,
ccontext,
&elemfuncid);
if (elempathtype != COERCION_PATH_NONE &&
elempathtype != COERCION_PATH_ARRAYCOERCE)
{
*funcid = elemfuncid;
if (elempathtype == COERCION_PATH_COERCEVIAIO)
result = COERCION_PATH_COERCEVIAIO;
else
result = COERCION_PATH_ARRAYCOERCE;
}
}
}
@ -1826,14 +1869,39 @@ find_coercion_pathway(Oid targetTypeId, Oid sourceTypeId,
* mistakenly conclude that ANYENUM-to-some-enum-type is a
* trivial cast.
*/
if (!result)
if (result == COERCION_PATH_NONE)
{
if (type_is_enum(sourceTypeId))
result = find_coercion_pathway(targetTypeId, ANYENUMOID,
ccontext, funcid, arrayCoerce);
ccontext, funcid);
else if (sourceTypeId != ANYENUMOID && type_is_enum(targetTypeId))
result = find_coercion_pathway(ANYENUMOID, sourceTypeId,
ccontext, funcid, arrayCoerce);
ccontext, funcid);
}
/*
* If we still haven't found a possibility, consider automatic casting
* using I/O functions. We allow assignment casts to textual types
* and explicit casts from textual types to be handled this way.
* (The CoerceViaIO mechanism is a lot more general than that, but
* this is all we want to allow in the absence of a pg_cast entry.)
* It would probably be better to insist on explicit casts in both
* directions, but this is a compromise to preserve something of the
* pre-8.3 behavior that many types had implicit (yipes!) casts to
* text.
*/
if (result == COERCION_PATH_NONE)
{
if (ccontext >= COERCION_ASSIGNMENT &&
(targetTypeId == TEXTOID ||
targetTypeId == VARCHAROID ||
targetTypeId == BPCHAROID))
result = COERCION_PATH_COERCEVIAIO;
else if (ccontext >= COERCION_EXPLICIT &&
(sourceTypeId == TEXTOID ||
sourceTypeId == VARCHAROID ||
sourceTypeId == BPCHAROID))
result = COERCION_PATH_COERCEVIAIO;
}
}
@ -1851,19 +1919,26 @@ find_coercion_pathway(Oid targetTypeId, Oid sourceTypeId,
*
* If the given type is a varlena array type, we do not look for a coercion
* function associated directly with the array type, but instead look for
* one associated with the element type. If one exists, we report it with
* *arrayCoerce set to true.
* one associated with the element type. An ArrayCoerceExpr node must be
* used to apply such a function.
*
* We use the same result enum as find_coercion_pathway, but the only possible
* result codes are:
* COERCION_PATH_NONE: no length coercion needed
* COERCION_PATH_FUNC: apply the function returned in *funcid
* COERCION_PATH_ARRAYCOERCE: apply the function using ArrayCoerceExpr
*/
bool
CoercionPathType
find_typmod_coercion_function(Oid typeId,
Oid *funcid, bool *arrayCoerce)
Oid *funcid)
{
CoercionPathType result;
Type targetType;
Form_pg_type typeForm;
HeapTuple tuple;
*funcid = InvalidOid;
*arrayCoerce = false;
result = COERCION_PATH_FUNC;
targetType = typeidType(typeId);
typeForm = (Form_pg_type) GETSTRUCT(targetType);
@ -1875,7 +1950,7 @@ find_typmod_coercion_function(Oid typeId,
{
/* Yes, switch our attention to the element type */
typeId = typeForm->typelem;
*arrayCoerce = true;
result = COERCION_PATH_ARRAYCOERCE;
}
ReleaseSysCache(targetType);
@ -1893,5 +1968,8 @@ find_typmod_coercion_function(Oid typeId,
ReleaseSysCache(tuple);
}
return OidIsValid(*funcid);
if (!OidIsValid(*funcid))
result = COERCION_PATH_NONE;
return result;
}

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/parser/parse_expr.c,v 1.217 2007/04/27 22:05:48 tgl Exp $
* $PostgreSQL: pgsql/src/backend/parser/parse_expr.c,v 1.218 2007/06/05 21:31:05 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -265,6 +265,7 @@ transformExpr(ParseState *pstate, Node *expr)
case T_FieldSelect:
case T_FieldStore:
case T_RelabelType:
case T_CoerceViaIO:
case T_ArrayCoerceExpr:
case T_ConvertRowtypeExpr:
case T_CaseTestExpr:
@ -1806,6 +1807,9 @@ exprType(Node *expr)
case T_RelabelType:
type = ((RelabelType *) expr)->resulttype;
break;
case T_CoerceViaIO:
type = ((CoerceViaIO *) expr)->resulttype;
break;
case T_ArrayCoerceExpr:
type = ((ArrayCoerceExpr *) expr)->resulttype;
break;

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/parser/parse_func.c,v 1.195 2007/03/27 23:21:10 tgl Exp $
* $PostgreSQL: pgsql/src/backend/parser/parse_func.c,v 1.196 2007/06/05 21:31:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -160,7 +160,7 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
if (fdresult == FUNCDETAIL_COERCION)
{
/*
* We can do it as a trivial coercion. coerce_type can handle these
* We interpreted it as a type coercion. coerce_type can handle these
* cases, so why duplicate code...
*/
return coerce_type(pstate, linitial(fargs),
@ -669,7 +669,7 @@ func_select_candidate(int nargs,
* (exact match) is as quick as possible.
*
* If an exact match isn't found:
* 1) check for possible interpretation as a trivial type coercion
* 1) check for possible interpretation as a type coercion request
* 2) get a vector of all possible input arg type arrays constructed
* from the superclasses of the original input arg types
* 3) get a list of all possible argument type arrays to the function
@ -720,29 +720,35 @@ func_get_detail(List *funcname,
* If we didn't find an exact match, next consider the possibility
* that this is really a type-coercion request: a single-argument
* function call where the function name is a type name. If so, and
* if we can do the coercion trivially (no run-time function call
* needed), then go ahead and treat the "function call" as a coercion.
* if the coercion path is RELABELTYPE or COERCEVIAIO, then go ahead
* and treat the "function call" as a coercion.
*
* This interpretation needs to be given higher priority than
* interpretations involving a type coercion followed by a function
* call, otherwise we can produce surprising results. For example, we
* want "text(varchar)" to be interpreted as a trivial coercion, not
* want "text(varchar)" to be interpreted as a simple coercion, not
* as "text(name(varchar))" which the code below this point is
* entirely capable of selecting.
*
* "Trivial" coercions are ones that involve binary-compatible types
* and ones that are coercing a previously-unknown-type literal
* constant to a specific type.
* We also treat a coercion of a previously-unknown-type literal
* constant to a specific type this way.
*
* The reason we can restrict our check to binary-compatible coercions
* here is that we expect non-binary-compatible coercions to have an
* implementation function named after the target type. That function
* will be found by normal lookup if appropriate.
* The reason we reject COERCION_PATH_FUNC here is that we expect the
* cast implementation function to be named after the target type.
* Thus the function will be found by normal lookup if appropriate.
*
* NB: it's important that this code stays in sync with what
* coerce_type can do, because the caller will try to apply
* coerce_type if we return FUNCDETAIL_COERCION. If we return that
* result for something coerce_type can't handle, we'll cause infinite
* recursion between this module and coerce_type!
* The reason we reject COERCION_PATH_ARRAYCOERCE is mainly that
* you can't write "foo[] (something)" as a function call. In theory
* someone might want to invoke it as "_foo (something)" but we have
* never supported that historically, so we can insist that people
* write it as a normal cast instead. Lack of historical support is
* also the reason for not considering composite-type casts here.
*
* NB: it's important that this code does not exceed what coerce_type
* can do, because the caller will try to apply coerce_type if we
* return FUNCDETAIL_COERCION. If we return that result for something
* coerce_type can't handle, we'll cause infinite recursion between
* this module and coerce_type!
*/
if (nargs == 1 && fargs != NIL)
{
@ -755,16 +761,28 @@ func_get_detail(List *funcname,
{
Oid sourceType = argtypes[0];
Node *arg1 = linitial(fargs);
Oid cfuncid;
bool arrayCoerce;
bool iscoercion;
if ((sourceType == UNKNOWNOID && IsA(arg1, Const)) ||
(find_coercion_pathway(targetType, sourceType,
COERCION_EXPLICIT,
&cfuncid, &arrayCoerce) &&
cfuncid == InvalidOid && !arrayCoerce))
if (sourceType == UNKNOWNOID && IsA(arg1, Const))
{
/* Yup, it's a trivial type coercion */
/* always treat typename('literal') as coercion */
iscoercion = true;
}
else
{
CoercionPathType cpathtype;
Oid cfuncid;
cpathtype = find_coercion_pathway(targetType, sourceType,
COERCION_EXPLICIT,
&cfuncid);
iscoercion = (cpathtype == COERCION_PATH_RELABELTYPE ||
cpathtype == COERCION_PATH_COERCEVIAIO);
}
if (iscoercion)
{
/* Treat it as a type coercion */
*funcid = InvalidOid;
*rettype = targetType;
*retset = false;

View File

@ -9,7 +9,7 @@
#
#
# IDENTIFICATION
# $PostgreSQL: pgsql/src/backend/utils/Gen_fmgrtab.sh,v 1.35 2007/01/22 01:35:21 tgl Exp $
# $PostgreSQL: pgsql/src/backend/utils/Gen_fmgrtab.sh,v 1.36 2007/06/05 21:31:06 tgl Exp $
#
#-------------------------------------------------------------------------
@ -127,7 +127,7 @@ cat > "$$-$OIDSFILE" <<FuNkYfMgRsTuFf
* NOTE: macros are named after the prosrc value, ie the actual C name
* of the implementing function, not the proname which may be overloaded.
* For example, we want to be able to assign different macro names to both
* char_text() and int4_text() even though these both appear with proname
* char_text() and name_text() even though these both appear with proname
* 'text'. If the same C function appears in more than one pg_proc entry,
* its equivalent macro will be defined with the lowest OID among those
* entries.

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/adt/bool.c,v 1.39 2007/06/01 23:40:18 neilc Exp $
* $PostgreSQL: pgsql/src/backend/utils/adt/bool.c,v 1.40 2007/06/05 21:31:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -142,22 +142,11 @@ boolsend(PG_FUNCTION_ARGS)
PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
}
/*
* textbool - cast function for text => bool
*/
Datum
textbool(PG_FUNCTION_ARGS)
{
Datum in_text = PG_GETARG_DATUM(0);
char *str;
str = DatumGetCString(DirectFunctionCall1(textout, in_text));
PG_RETURN_DATUM(DirectFunctionCall1(boolin, CStringGetDatum(str)));
}
/*
* booltext - cast function for bool => text
*
* We need this because it's different from the behavior of boolout();
* this function follows the SQL-spec result (except for producing lower case)
*/
Datum
booltext(PG_FUNCTION_ARGS)

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/adt/date.c,v 1.131 2007/06/02 16:41:09 tgl Exp $
* $PostgreSQL: pgsql/src/backend/utils/adt/date.c,v 1.132 2007/06/05 21:31:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -873,65 +873,6 @@ abstime_date(PG_FUNCTION_ARGS)
}
/* date_text()
* Convert date to text data type.
*/
Datum
date_text(PG_FUNCTION_ARGS)
{
/* Input is a Date, but may as well leave it in Datum form */
Datum date = PG_GETARG_DATUM(0);
text *result;
char *str;
int len;
str = DatumGetCString(DirectFunctionCall1(date_out, date));
len = strlen(str) + VARHDRSZ;
result = palloc(len);
SET_VARSIZE(result, len);
memcpy(VARDATA(result), str, (len - VARHDRSZ));
pfree(str);
PG_RETURN_TEXT_P(result);
}
/* text_date()
* Convert text string to date.
* Text type is not null terminated, so use temporary string
* then call the standard input routine.
*/
Datum
text_date(PG_FUNCTION_ARGS)
{
text *str = PG_GETARG_TEXT_P(0);
int i;
char *sp,
*dp,
dstr[MAXDATELEN + 1];
if (VARSIZE(str) - VARHDRSZ > MAXDATELEN)
ereport(ERROR,
(errcode(ERRCODE_INVALID_DATETIME_FORMAT),
errmsg("invalid input syntax for type date: \"%s\"",
DatumGetCString(DirectFunctionCall1(textout,
PointerGetDatum(str))))));
sp = VARDATA(str);
dp = dstr;
for (i = 0; i < (VARSIZE(str) - VARHDRSZ); i++)
*dp++ = *sp++;
*dp = '\0';
return DirectFunctionCall1(date_in,
CStringGetDatum(dstr));
}
/*****************************************************************************
* Time ADT
*****************************************************************************/
@ -1617,62 +1558,6 @@ time_mi_interval(PG_FUNCTION_ARGS)
}
/* time_text()
* Convert time to text data type.
*/
Datum
time_text(PG_FUNCTION_ARGS)
{
/* Input is a Time, but may as well leave it in Datum form */
Datum time = PG_GETARG_DATUM(0);
text *result;
char *str;
int len;
str = DatumGetCString(DirectFunctionCall1(time_out, time));
len = strlen(str) + VARHDRSZ;
result = palloc(len);
SET_VARSIZE(result, len);
memcpy(VARDATA(result), str, len - VARHDRSZ);
pfree(str);
PG_RETURN_TEXT_P(result);
}
/* text_time()
* Convert text string to time.
* Text type is not null terminated, so use temporary string
* then call the standard input routine.
*/
Datum
text_time(PG_FUNCTION_ARGS)
{
text *str = PG_GETARG_TEXT_P(0);
char dstr[MAXDATELEN + 1];
size_t len;
if (VARSIZE(str) - VARHDRSZ > MAXDATELEN)
ereport(ERROR,
(errcode(ERRCODE_INVALID_DATETIME_FORMAT),
errmsg("invalid input syntax for type time: \"%s\"",
DatumGetCString(DirectFunctionCall1(textout,
PointerGetDatum(str))))));
len = VARSIZE(str) - VARHDRSZ;
memcpy(dstr, VARDATA(str), len);
dstr[len] = '\0';
return DirectFunctionCall3(time_in,
CStringGetDatum(dstr),
ObjectIdGetDatum(InvalidOid),
Int32GetDatum(-1));
}
/* time_part()
* Extract specified field from time type.
*/
@ -2400,66 +2285,6 @@ datetimetz_timestamptz(PG_FUNCTION_ARGS)
}
/* timetz_text()
* Convert timetz to text data type.
*/
Datum
timetz_text(PG_FUNCTION_ARGS)
{
/* Input is a Timetz, but may as well leave it in Datum form */
Datum timetz = PG_GETARG_DATUM(0);
text *result;
char *str;
int len;
str = DatumGetCString(DirectFunctionCall1(timetz_out, timetz));
len = strlen(str) + VARHDRSZ;
result = palloc(len);
SET_VARSIZE(result, len);
memcpy(VARDATA(result), str, (len - VARHDRSZ));
pfree(str);
PG_RETURN_TEXT_P(result);
}
/* text_timetz()
* Convert text string to timetz.
* Text type is not null terminated, so use temporary string
* then call the standard input routine.
*/
Datum
text_timetz(PG_FUNCTION_ARGS)
{
text *str = PG_GETARG_TEXT_P(0);
int i;
char *sp,
*dp,
dstr[MAXDATELEN + 1];
if (VARSIZE(str) - VARHDRSZ > MAXDATELEN)
ereport(ERROR,
(errcode(ERRCODE_INVALID_DATETIME_FORMAT),
errmsg("invalid input syntax for type time with time zone: \"%s\"",
DatumGetCString(DirectFunctionCall1(textout,
PointerGetDatum(str))))));
sp = VARDATA(str);
dp = dstr;
for (i = 0; i < (VARSIZE(str) - VARHDRSZ); i++)
*dp++ = *sp++;
*dp = '\0';
return DirectFunctionCall3(timetz_in,
CStringGetDatum(dstr),
ObjectIdGetDatum(InvalidOid),
Int32GetDatum(-1));
}
/* timetz_part()
* Extract specified field from time type.
*/

View File

@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/adt/enum.c,v 1.2 2007/04/02 22:14:17 adunstan Exp $
* $PostgreSQL: pgsql/src/backend/utils/adt/enum.c,v 1.3 2007/06/05 21:31:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -21,8 +21,6 @@
#include "utils/syscache.h"
static Oid cstring_enum(char *name, Oid enumtypoid);
static char *enum_cstring(Oid enumval);
static ArrayType *enum_range_internal(Oid enumtypoid, Oid lower, Oid upper);
static int enum_elem_cmp(const void *left, const void *right);
@ -32,75 +30,60 @@ static int enum_elem_cmp(const void *left, const void *right);
Datum
enum_in(PG_FUNCTION_ARGS)
{
char *name = PG_GETARG_CSTRING(0);
Oid enumtypoid = PG_GETARG_OID(1);
PG_RETURN_OID(cstring_enum(name, enumtypoid));
}
/* guts of enum_in and text-to-enum */
static Oid
cstring_enum(char *name, Oid enumtypoid)
{
HeapTuple tup;
char *name = PG_GETARG_CSTRING(0);
Oid enumtypoid = PG_GETARG_OID(1);
Oid enumoid;
HeapTuple tup;
/* must check length to prevent Assert failure within SearchSysCache */
if (strlen(name) >= NAMEDATALEN)
ereport(ERROR,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("invalid input value for enum %s: \"%s\"",
ereport(ERROR,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("invalid input value for enum %s: \"%s\"",
format_type_be(enumtypoid),
name)));
name)));
tup = SearchSysCache(ENUMTYPOIDNAME,
ObjectIdGetDatum(enumtypoid),
CStringGetDatum(name),
0, 0);
if (tup == NULL)
ereport(ERROR,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("invalid input value for enum %s: \"%s\"",
if (!HeapTupleIsValid(tup))
ereport(ERROR,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("invalid input value for enum %s: \"%s\"",
format_type_be(enumtypoid),
name)));
name)));
enumoid = HeapTupleGetOid(tup);
ReleaseSysCache(tup);
return enumoid;
PG_RETURN_OID(enumoid);
}
Datum
enum_out(PG_FUNCTION_ARGS)
{
Oid enumoid = PG_GETARG_OID(0);
PG_RETURN_CSTRING(enum_cstring(enumoid));
}
/* guts of enum_out and enum-to-text */
static char *
enum_cstring(Oid enumval)
{
Oid enumval = PG_GETARG_OID(0);
char *result;
HeapTuple tup;
Form_pg_enum en;
char *label;
tup = SearchSysCache(ENUMOID,
ObjectIdGetDatum(enumval),
0, 0, 0);
if (tup == NULL)
ereport(ERROR,
(errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
errmsg("invalid internal value for enum: %u",
enumval)));
if (!HeapTupleIsValid(tup))
ereport(ERROR,
(errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
errmsg("invalid internal value for enum: %u",
enumval)));
en = (Form_pg_enum) GETSTRUCT(tup);
label = pstrdup(NameStr(en->enumlabel));
result = pstrdup(NameStr(en->enumlabel));
ReleaseSysCache(tup);
return label;
PG_RETURN_CSTRING(result);
}
/* Comparison functions and related */
@ -191,47 +174,6 @@ enum_cmp(PG_FUNCTION_ARGS)
PG_RETURN_INT32(-1);
}
/* Casts between text and enum */
Datum
enum_text(PG_FUNCTION_ARGS)
{
Oid enumval = PG_GETARG_OID(0);
text *result;
char *cstr;
int len;
cstr = enum_cstring(enumval);
len = strlen(cstr);
result = (text *) palloc(VARHDRSZ + len);
SET_VARSIZE(result, VARHDRSZ + len);
memcpy(VARDATA(result), cstr, len);
pfree(cstr);
PG_RETURN_TEXT_P(result);
}
Datum
text_enum(PG_FUNCTION_ARGS)
{
text *textval = PG_GETARG_TEXT_P(0);
Oid enumtypoid;
char *str;
/*
* We rely on being able to get the specific enum type from the calling
* expression tree.
*/
enumtypoid = get_fn_expr_rettype(fcinfo->flinfo);
if (enumtypoid == InvalidOid)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("could not determine actual enum type")));
str = DatumGetCString(DirectFunctionCall1(textout,
PointerGetDatum(textval)));
PG_RETURN_OID(cstring_enum(str, enumtypoid));
}
/* Enum programming support functions */
Datum
@ -266,7 +208,7 @@ enum_first(PG_FUNCTION_ARGS)
ReleaseCatCacheList(list);
if (!OidIsValid(min)) /* should not happen */
if (!OidIsValid(min)) /* should not happen */
elog(ERROR, "no values found for enum %s",
format_type_be(enumtypoid));
@ -276,10 +218,10 @@ enum_first(PG_FUNCTION_ARGS)
Datum
enum_last(PG_FUNCTION_ARGS)
{
Oid enumtypoid;
Oid max = InvalidOid;
CatCList *list;
int num, i;
Oid enumtypoid;
Oid max = InvalidOid;
CatCList *list;
int num, i;
/*
* We rely on being able to get the specific enum type from the calling
@ -292,24 +234,24 @@ enum_last(PG_FUNCTION_ARGS)
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("could not determine actual enum type")));
list = SearchSysCacheList(ENUMTYPOIDNAME, 1,
ObjectIdGetDatum(enumtypoid),
list = SearchSysCacheList(ENUMTYPOIDNAME, 1,
ObjectIdGetDatum(enumtypoid),
0, 0, 0);
num = list->n_members;
for (i = 0; i < num; i++)
{
num = list->n_members;
for (i = 0; i < num; i++)
{
Oid valoid = HeapTupleHeaderGetOid(list->members[i]->tuple.t_data);
if(!OidIsValid(max) || valoid > max)
max = valoid;
}
if (!OidIsValid(max) || valoid > max)
max = valoid;
}
ReleaseCatCacheList(list);
if (!OidIsValid(max)) /* should not happen */
if (!OidIsValid(max)) /* should not happen */
elog(ERROR, "no values found for enum %s",
format_type_be(enumtypoid));
PG_RETURN_OID(max);
PG_RETURN_OID(max);
}
/* 2-argument variant of enum_range */
@ -368,26 +310,26 @@ static ArrayType *
enum_range_internal(Oid enumtypoid, Oid lower, Oid upper)
{
ArrayType *result;
CatCList *list;
int total, i, j;
Datum *elems;
CatCList *list;
int total, i, j;
Datum *elems;
list = SearchSysCacheList(ENUMTYPOIDNAME, 1,
ObjectIdGetDatum(enumtypoid),
ObjectIdGetDatum(enumtypoid),
0, 0, 0);
total = list->n_members;
elems = (Datum *) palloc(total * sizeof(Datum));
j = 0;
for (i = 0; i < total; i++)
{
for (i = 0; i < total; i++)
{
Oid val = HeapTupleGetOid(&(list->members[i]->tuple));
if ((!OidIsValid(lower) || lower <= val) &&
(!OidIsValid(upper) || val <= upper))
elems[j++] = ObjectIdGetDatum(val);
}
elems[j++] = ObjectIdGetDatum(val);
}
/* shouldn't need the cache anymore */
ReleaseCatCacheList(list);

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/adt/float.c,v 1.149 2007/02/27 23:48:08 tgl Exp $
* $PostgreSQL: pgsql/src/backend/utils/adt/float.c,v 1.150 2007/06/05 21:31:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -1196,108 +1196,6 @@ i2tof(PG_FUNCTION_ARGS)
}
/*
* float8_text - converts a float8 number to a text string
*/
Datum
float8_text(PG_FUNCTION_ARGS)
{
float8 num = PG_GETARG_FLOAT8(0);
text *result;
int len;
char *str;
str = DatumGetCString(DirectFunctionCall1(float8out,
Float8GetDatum(num)));
len = strlen(str) + VARHDRSZ;
result = (text *) palloc(len);
SET_VARSIZE(result, len);
memcpy(VARDATA(result), str, (len - VARHDRSZ));
pfree(str);
PG_RETURN_TEXT_P(result);
}
/*
* text_float8 - converts a text string to a float8 number
*/
Datum
text_float8(PG_FUNCTION_ARGS)
{
text *string = PG_GETARG_TEXT_P(0);
Datum result;
int len;
char *str;
len = (VARSIZE(string) - VARHDRSZ);
str = palloc(len + 1);
memcpy(str, VARDATA(string), len);
*(str + len) = '\0';
result = DirectFunctionCall1(float8in, CStringGetDatum(str));
pfree(str);
PG_RETURN_DATUM(result);
}
/*
* float4_text - converts a float4 number to a text string
*/
Datum
float4_text(PG_FUNCTION_ARGS)
{
float4 num = PG_GETARG_FLOAT4(0);
text *result;
int len;
char *str;
str = DatumGetCString(DirectFunctionCall1(float4out,
Float4GetDatum(num)));
len = strlen(str) + VARHDRSZ;
result = (text *) palloc(len);
SET_VARSIZE(result, len);
memcpy(VARDATA(result), str, (len - VARHDRSZ));
pfree(str);
PG_RETURN_TEXT_P(result);
}
/*
* text_float4 - converts a text string to a float4 number
*/
Datum
text_float4(PG_FUNCTION_ARGS)
{
text *string = PG_GETARG_TEXT_P(0);
Datum result;
int len;
char *str;
len = (VARSIZE(string) - VARHDRSZ);
str = palloc(len + 1);
memcpy(str, VARDATA(string), len);
*(str + len) = '\0';
result = DirectFunctionCall1(float4in, CStringGetDatum(str));
pfree(str);
PG_RETURN_DATUM(result);
}
/*
* =======================
* RANDOM FLOAT8 OPERATORS

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/adt/int.c,v 1.79 2007/02/27 23:48:08 tgl Exp $
* $PostgreSQL: pgsql/src/backend/utils/adt/int.c,v 1.80 2007/06/05 21:31:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -18,8 +18,6 @@
* int2in, int2out, int2recv, int2send
* int4in, int4out, int4recv, int4send
* int2vectorin, int2vectorout, int2vectorrecv, int2vectorsend
* Conversion routines:
* itoi, int2_text, int4_text
* Boolean operators:
* inteq, intne, intlt, intle, intgt, intge
* Arithmetic operators:
@ -343,68 +341,6 @@ i4toi2(PG_FUNCTION_ARGS)
PG_RETURN_INT16((int16) arg1);
}
Datum
int2_text(PG_FUNCTION_ARGS)
{
int16 arg1 = PG_GETARG_INT16(0);
text *result = (text *) palloc(7 + VARHDRSZ); /* sign,5 digits, '\0' */
pg_itoa(arg1, VARDATA(result));
SET_VARSIZE(result, strlen(VARDATA(result)) + VARHDRSZ);
PG_RETURN_TEXT_P(result);
}
Datum
text_int2(PG_FUNCTION_ARGS)
{
text *string = PG_GETARG_TEXT_P(0);
Datum result;
int len;
char *str;
len = VARSIZE(string) - VARHDRSZ;
str = palloc(len + 1);
memcpy(str, VARDATA(string), len);
*(str + len) = '\0';
result = DirectFunctionCall1(int2in, CStringGetDatum(str));
pfree(str);
return result;
}
Datum
int4_text(PG_FUNCTION_ARGS)
{
int32 arg1 = PG_GETARG_INT32(0);
text *result = (text *) palloc(12 + VARHDRSZ); /* sign,10 digits,'\0' */
pg_ltoa(arg1, VARDATA(result));
SET_VARSIZE(result, strlen(VARDATA(result)) + VARHDRSZ);
PG_RETURN_TEXT_P(result);
}
Datum
text_int4(PG_FUNCTION_ARGS)
{
text *string = PG_GETARG_TEXT_P(0);
Datum result;
int len;
char *str;
len = VARSIZE(string) - VARHDRSZ;
str = palloc(len + 1);
memcpy(str, VARDATA(string), len);
*(str + len) = '\0';
result = DirectFunctionCall1(int4in, CStringGetDatum(str));
pfree(str);
return result;
}
/* Cast int4 -> bool */
Datum
int4_bool(PG_FUNCTION_ARGS)

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/adt/int8.c,v 1.65 2007/02/27 23:48:08 tgl Exp $
* $PostgreSQL: pgsql/src/backend/utils/adt/int8.c,v 1.66 2007/06/05 21:31:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -1137,48 +1137,6 @@ oidtoi8(PG_FUNCTION_ARGS)
PG_RETURN_INT64((int64) arg);
}
Datum
text_int8(PG_FUNCTION_ARGS)
{
text *str = PG_GETARG_TEXT_P(0);
int len;
char *s;
Datum result;
len = (VARSIZE(str) - VARHDRSZ);
s = palloc(len + 1);
memcpy(s, VARDATA(str), len);
*(s + len) = '\0';
result = DirectFunctionCall1(int8in, CStringGetDatum(s));
pfree(s);
return result;
}
Datum
int8_text(PG_FUNCTION_ARGS)
{
/* arg is int64, but easier to leave it as Datum */
Datum arg = PG_GETARG_DATUM(0);
char *s;
int len;
text *result;
s = DatumGetCString(DirectFunctionCall1(int8out, arg));
len = strlen(s);
result = (text *) palloc(VARHDRSZ + len);
SET_VARSIZE(result, VARHDRSZ + len);
memcpy(VARDATA(result), s, len);
pfree(s);
PG_RETURN_TEXT_P(result);
}
/*
* non-persistent numeric series generator
*/

View File

@ -1,7 +1,7 @@
/*
* PostgreSQL type definitions for MAC addresses.
*
* $PostgreSQL: pgsql/src/backend/utils/adt/mac.c,v 1.37 2007/02/27 23:48:08 tgl Exp $
* $PostgreSQL: pgsql/src/backend/utils/adt/mac.c,v 1.38 2007/06/05 21:31:06 tgl Exp $
*/
#include "postgres.h"
@ -144,59 +144,6 @@ macaddr_send(PG_FUNCTION_ARGS)
}
/*
* Convert macaddr to text data type.
*/
Datum
macaddr_text(PG_FUNCTION_ARGS)
{
/* Input is a macaddr, but may as well leave it in Datum form */
Datum addr = PG_GETARG_DATUM(0);
text *result;
char *str;
int len;
str = DatumGetCString(DirectFunctionCall1(macaddr_out, addr));
len = (strlen(str) + VARHDRSZ);
result = palloc(len);
SET_VARSIZE(result, len);
memcpy(VARDATA(result), str, (len - VARHDRSZ));
pfree(str);
PG_RETURN_TEXT_P(result);
}
/*
* Convert text to macaddr data type.
*/
Datum
text_macaddr(PG_FUNCTION_ARGS)
{
text *addr = PG_GETARG_TEXT_P(0);
Datum result;
char str[100];
int len;
len = (VARSIZE(addr) - VARHDRSZ);
if (len >= sizeof(str))
ereport(ERROR,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("text too long to convert to MAC address")));
memcpy(str, VARDATA(addr), len);
*(str + len) = '\0';
result = DirectFunctionCall1(macaddr_in, CStringGetDatum(str));
return result;
}
/*
* Comparison function for sorting:
*/

View File

@ -1,7 +1,7 @@
/*
* PostgreSQL type definitions for the INET and CIDR types.
*
* $PostgreSQL: pgsql/src/backend/utils/adt/network.c,v 1.70 2007/05/17 23:31:49 tgl Exp $
* $PostgreSQL: pgsql/src/backend/utils/adt/network.c,v 1.71 2007/06/05 21:31:06 tgl Exp $
*
* Jon Postel RIP 16 Oct 1998
*/
@ -22,7 +22,6 @@
#include "utils/inet.h"
static inet *text_network(text *src, bool is_cidr);
static int32 network_cmp_internal(inet *a1, inet *a2);
static int bitncmp(void *l, void *r, int n);
static bool addressOK(unsigned char *a, int bits, int family);
@ -314,35 +313,6 @@ cidr_send(PG_FUNCTION_ARGS)
}
static inet *
text_network(text *src, bool is_cidr)
{
int len = VARSIZE(src) - VARHDRSZ;
char *str = palloc(len + 1);
memcpy(str, VARDATA(src), len);
str[len] = '\0';
return network_in(str, is_cidr);
}
Datum
text_inet(PG_FUNCTION_ARGS)
{
text *src = PG_GETARG_TEXT_P(0);
PG_RETURN_INET_P(text_network(src, false));
}
Datum
text_cidr(PG_FUNCTION_ARGS)
{
text *src = PG_GETARG_TEXT_P(0);
PG_RETURN_INET_P(text_network(src, true));
}
Datum
inet_to_cidr(PG_FUNCTION_ARGS)
{
@ -655,6 +625,11 @@ network_host(PG_FUNCTION_ARGS)
PG_RETURN_TEXT_P(ret);
}
/*
* network_show implements the inet and cidr casts to text. This is not
* quite the same behavior as network_out, hence we can't drop it in favor
* of CoerceViaIO.
*/
Datum
network_show(PG_FUNCTION_ARGS)
{

View File

@ -14,7 +14,7 @@
* Copyright (c) 1998-2007, PostgreSQL Global Development Group
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/adt/numeric.c,v 1.102 2007/05/08 18:56:47 neilc Exp $
* $PostgreSQL: pgsql/src/backend/utils/adt/numeric.c,v 1.103 2007/06/05 21:31:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -2146,50 +2146,6 @@ numeric_float4(PG_FUNCTION_ARGS)
}
Datum
text_numeric(PG_FUNCTION_ARGS)
{
text *str = PG_GETARG_TEXT_P(0);
int len;
char *s;
Datum result;
len = (VARSIZE(str) - VARHDRSZ);
s = palloc(len + 1);
memcpy(s, VARDATA(str), len);
*(s + len) = '\0';
result = DirectFunctionCall3(numeric_in, CStringGetDatum(s),
ObjectIdGetDatum(0), Int32GetDatum(-1));
pfree(s);
return result;
}
Datum
numeric_text(PG_FUNCTION_ARGS)
{
/* val is numeric, but easier to leave it as Datum */
Datum val = PG_GETARG_DATUM(0);
char *s;
int len;
text *result;
s = DatumGetCString(DirectFunctionCall1(numeric_out, val));
len = strlen(s);
result = (text *) palloc(VARHDRSZ + len);
SET_VARSIZE(result, VARHDRSZ + len);
memcpy(VARDATA(result), s, len);
pfree(s);
PG_RETURN_TEXT_P(result);
}
/* ----------------------------------------------------------------------
*
* Aggregate functions

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/adt/oid.c,v 1.71 2007/02/27 23:48:08 tgl Exp $
* $PostgreSQL: pgsql/src/backend/utils/adt/oid.c,v 1.72 2007/06/05 21:31:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -31,7 +31,7 @@
*****************************************************************************/
static Oid
oidin_subr(const char *funcname, const char *s, char **endloc)
oidin_subr(const char *s, char **endloc)
{
unsigned long cvt;
char *endptr;
@ -116,7 +116,7 @@ oidin(PG_FUNCTION_ARGS)
char *s = PG_GETARG_CSTRING(0);
Oid result;
result = oidin_subr("oidin", s, NULL);
result = oidin_subr(s, NULL);
PG_RETURN_OID(result);
}
@ -202,7 +202,7 @@ oidvectorin(PG_FUNCTION_ARGS)
oidString++;
if (*oidString == '\0')
break;
result->values[n] = oidin_subr("oidvectorin", oidString, &oidString);
result->values[n] = oidin_subr(oidString, &oidString);
}
while (*oidString && isspace((unsigned char) *oidString))
oidString++;
@ -419,45 +419,3 @@ oidvectorgt(PG_FUNCTION_ARGS)
PG_RETURN_BOOL(cmp > 0);
}
Datum
oid_text(PG_FUNCTION_ARGS)
{
Oid oid = PG_GETARG_OID(0);
text *result;
int len;
char *str;
str = DatumGetCString(DirectFunctionCall1(oidout,
ObjectIdGetDatum(oid)));
len = strlen(str) + VARHDRSZ;
result = (text *) palloc(len);
SET_VARSIZE(result, len);
memcpy(VARDATA(result), str, (len - VARHDRSZ));
pfree(str);
PG_RETURN_TEXT_P(result);
}
Datum
text_oid(PG_FUNCTION_ARGS)
{
text *string = PG_GETARG_TEXT_P(0);
Oid result;
int len;
char *str;
len = (VARSIZE(string) - VARHDRSZ);
str = palloc(len + 1);
memcpy(str, VARDATA(string), len);
*(str + len) = '\0';
result = oidin_subr("text_oid", str, NULL);
pfree(str);
PG_RETURN_OID(result);
}

View File

@ -13,7 +13,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/adt/regproc.c,v 1.100 2007/01/05 22:19:41 momjian Exp $
* $PostgreSQL: pgsql/src/backend/utils/adt/regproc.c,v 1.101 2007/06/05 21:31:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -1070,6 +1070,10 @@ regtypesend(PG_FUNCTION_ARGS)
/*
* text_regclass: convert text to regclass
*
* This could be replaced by CoerceViaIO, except that we need to treat
* text-to-regclass as an implicit cast to support legacy forms of nextval()
* and related functions.
*/
Datum
text_regclass(PG_FUNCTION_ARGS)

View File

@ -15,7 +15,7 @@
*
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
*
* $PostgreSQL: pgsql/src/backend/utils/adt/ri_triggers.c,v 1.94 2007/03/27 23:21:10 tgl Exp $
* $PostgreSQL: pgsql/src/backend/utils/adt/ri_triggers.c,v 1.95 2007/06/05 21:31:06 tgl Exp $
*
* ----------
*/
@ -3871,7 +3871,7 @@ ri_HashCompareOp(Oid eq_opr, Oid typeid)
Oid lefttype,
righttype,
castfunc;
bool arrayCoerce;
CoercionPathType pathtype;
/* We always need to know how to call the equality operator */
fmgr_info_cxt(get_opcode(eq_opr), &entry->eq_opr_finfo,
@ -3885,20 +3885,28 @@ ri_HashCompareOp(Oid eq_opr, Oid typeid)
* here and in ri_AttributesEqual(). At the moment there is no
* point because cases involving nonidentical array types will
* be rejected at constraint creation time.
*
* XXX perhaps also consider supporting CoerceViaIO? No need at the
* moment since that will never be generated for implicit coercions.
*/
op_input_types(eq_opr, &lefttype, &righttype);
Assert(lefttype == righttype);
if (typeid == lefttype)
castfunc = InvalidOid; /* simplest case */
else if (!find_coercion_pathway(lefttype, typeid, COERCION_IMPLICIT,
&castfunc, &arrayCoerce)
|| arrayCoerce) /* XXX fixme */
else
{
/* If target is ANYARRAY, assume it's OK, else punt. */
if (lefttype != ANYARRAYOID)
elog(ERROR, "no conversion function from %s to %s",
format_type_be(typeid),
format_type_be(lefttype));
pathtype = find_coercion_pathway(lefttype, typeid,
COERCION_IMPLICIT,
&castfunc);
if (pathtype != COERCION_PATH_FUNC &&
pathtype != COERCION_PATH_RELABELTYPE)
{
/* If target is ANYARRAY, assume it's OK, else punt. */
if (lefttype != ANYARRAYOID)
elog(ERROR, "no conversion function from %s to %s",
format_type_be(typeid),
format_type_be(lefttype));
}
}
if (OidIsValid(castfunc))
fmgr_info_cxt(castfunc, &entry->cast_func_finfo,

View File

@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.258 2007/05/24 18:58:42 tgl Exp $
* $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.259 2007/06/05 21:31:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -3127,6 +3127,9 @@ isSimpleNode(Node *node, Node *parentNode, int prettyFlags)
case T_RelabelType:
return isSimpleNode((Node *) ((RelabelType *) node)->arg,
node, prettyFlags);
case T_CoerceViaIO:
return isSimpleNode((Node *) ((CoerceViaIO *) node)->arg,
node, prettyFlags);
case T_ArrayCoerceExpr:
return isSimpleNode((Node *) ((ArrayCoerceExpr *) node)->arg,
node, prettyFlags);
@ -3595,6 +3598,27 @@ get_rule_expr(Node *node, deparse_context *context,
}
break;
case T_CoerceViaIO:
{
CoerceViaIO *iocoerce = (CoerceViaIO *) node;
Node *arg = (Node *) iocoerce->arg;
if (iocoerce->coerceformat == COERCE_IMPLICIT_CAST &&
!showimplicit)
{
/* don't show the implicit cast */
get_rule_expr_paren(arg, context, false, node);
}
else
{
get_coercion_expr(arg, context,
iocoerce->resulttype,
-1,
node);
}
}
break;
case T_ArrayCoerceExpr:
{
ArrayCoerceExpr *acoerce = (ArrayCoerceExpr *) node;

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/adt/timestamp.c,v 1.176 2007/04/30 21:01:52 tgl Exp $
* $PostgreSQL: pgsql/src/backend/utils/adt/timestamp.c,v 1.177 2007/06/05 21:31:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -3229,187 +3229,6 @@ timestamptz_age(PG_FUNCTION_ARGS)
*---------------------------------------------------------*/
/* timestamp_text()
* Convert timestamp to text data type.
*/
Datum
timestamp_text(PG_FUNCTION_ARGS)
{
/* Input is a Timestamp, but may as well leave it in Datum form */
Datum timestamp = PG_GETARG_DATUM(0);
text *result;
char *str;
int len;
str = DatumGetCString(DirectFunctionCall1(timestamp_out, timestamp));
len = (strlen(str) + VARHDRSZ);
result = palloc(len);
SET_VARSIZE(result, len);
memcpy(VARDATA(result), str, len - VARHDRSZ);
pfree(str);
PG_RETURN_TEXT_P(result);
}
/* text_timestamp()
* Convert text string to timestamp.
* Text type is not null terminated, so use temporary string
* then call the standard input routine.
*/
Datum
text_timestamp(PG_FUNCTION_ARGS)
{
text *str = PG_GETARG_TEXT_P(0);
int i;
char *sp,
*dp,
dstr[MAXDATELEN + 1];
if (VARSIZE(str) - VARHDRSZ > MAXDATELEN)
ereport(ERROR,
(errcode(ERRCODE_INVALID_DATETIME_FORMAT),
errmsg("invalid input syntax for type timestamp: \"%s\"",
DatumGetCString(DirectFunctionCall1(textout,
PointerGetDatum(str))))));
sp = VARDATA(str);
dp = dstr;
for (i = 0; i < VARSIZE(str) - VARHDRSZ; i++)
*dp++ = *sp++;
*dp = '\0';
return DirectFunctionCall3(timestamp_in,
CStringGetDatum(dstr),
ObjectIdGetDatum(InvalidOid),
Int32GetDatum(-1));
}
/* timestamptz_text()
* Convert timestamp with time zone to text data type.
*/
Datum
timestamptz_text(PG_FUNCTION_ARGS)
{
/* Input is a Timestamp, but may as well leave it in Datum form */
Datum timestamp = PG_GETARG_DATUM(0);
text *result;
char *str;
int len;
str = DatumGetCString(DirectFunctionCall1(timestamptz_out, timestamp));
len = strlen(str) + VARHDRSZ;
result = palloc(len);
SET_VARSIZE(result, len);
memcpy(VARDATA(result), str, len - VARHDRSZ);
pfree(str);
PG_RETURN_TEXT_P(result);
}
/* text_timestamptz()
* Convert text string to timestamp with time zone.
* Text type is not null terminated, so use temporary string
* then call the standard input routine.
*/
Datum
text_timestamptz(PG_FUNCTION_ARGS)
{
text *str = PG_GETARG_TEXT_P(0);
int i;
char *sp,
*dp,
dstr[MAXDATELEN + 1];
if (VARSIZE(str) - VARHDRSZ > MAXDATELEN)
ereport(ERROR,
(errcode(ERRCODE_INVALID_DATETIME_FORMAT),
errmsg("invalid input syntax for type timestamp with time zone: \"%s\"",
DatumGetCString(DirectFunctionCall1(textout,
PointerGetDatum(str))))));
sp = VARDATA(str);
dp = dstr;
for (i = 0; i < VARSIZE(str) - VARHDRSZ; i++)
*dp++ = *sp++;
*dp = '\0';
return DirectFunctionCall3(timestamptz_in,
CStringGetDatum(dstr),
ObjectIdGetDatum(InvalidOid),
Int32GetDatum(-1));
}
/* interval_text()
* Convert interval to text data type.
*/
Datum
interval_text(PG_FUNCTION_ARGS)
{
Interval *interval = PG_GETARG_INTERVAL_P(0);
text *result;
char *str;
int len;
str = DatumGetCString(DirectFunctionCall1(interval_out,
IntervalPGetDatum(interval)));
len = strlen(str) + VARHDRSZ;
result = palloc(len);
SET_VARSIZE(result, len);
memcpy(VARDATA(result), str, len - VARHDRSZ);
pfree(str);
PG_RETURN_TEXT_P(result);
}
/* text_interval()
* Convert text string to interval.
* Text type may not be null terminated, so copy to temporary string
* then call the standard input routine.
*/
Datum
text_interval(PG_FUNCTION_ARGS)
{
text *str = PG_GETARG_TEXT_P(0);
int i;
char *sp,
*dp,
dstr[MAXDATELEN + 1];
if (VARSIZE(str) - VARHDRSZ > MAXDATELEN)
ereport(ERROR,
(errcode(ERRCODE_INVALID_DATETIME_FORMAT),
errmsg("invalid input syntax for type interval: \"%s\"",
DatumGetCString(DirectFunctionCall1(textout,
PointerGetDatum(str))))));
sp = VARDATA(str);
dp = dstr;
for (i = 0; i < (VARSIZE(str) - VARHDRSZ); i++)
*dp++ = *sp++;
*dp = '\0';
return DirectFunctionCall3(interval_in,
CStringGetDatum(dstr),
ObjectIdGetDatum(InvalidOid),
Int32GetDatum(-1));
}
/* timestamp_trunc()
* Truncate timestamp to specified units.
*/

View File

@ -6,7 +6,7 @@
* Copyright (c) 2007, PostgreSQL Global Development Group
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/adt/uuid.c,v 1.3 2007/01/31 19:33:54 neilc Exp $
* $PostgreSQL: pgsql/src/backend/utils/adt/uuid.c,v 1.4 2007/06/05 21:31:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -238,32 +238,3 @@ uuid_hash(PG_FUNCTION_ARGS)
pg_uuid_t *key = PG_GETARG_UUID_P(0);
return hash_any(key->data, UUID_LEN);
}
/* cast text to uuid */
Datum
text_uuid(PG_FUNCTION_ARGS)
{
text *input = PG_GETARG_TEXT_P(0);
int length;
char *str;
Datum result;
length = VARSIZE(input) - VARHDRSZ;
str = palloc(length + 1);
memcpy(str, VARDATA(input), length);
*(str + length) = '\0';
result = DirectFunctionCall1(uuid_in, CStringGetDatum(str));
pfree(str);
PG_RETURN_DATUM(result);
}
/* cast uuid to text */
Datum
uuid_text(PG_FUNCTION_ARGS)
{
pg_uuid_t *uuid = PG_GETARG_UUID_P(0);
Datum uuid_str = DirectFunctionCall1(uuid_out, UUIDPGetDatum(uuid));
PG_RETURN_DATUM(DirectFunctionCall1(textin, uuid_str));
}

View File

@ -37,7 +37,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.409 2007/06/01 23:40:18 neilc Exp $
* $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.410 2007/06/05 21:31:07 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -53,6 +53,6 @@
*/
/* yyyymmddN */
#define CATALOG_VERSION_NO 200706012
#define CATALOG_VERSION_NO 200706051
#endif

View File

@ -10,7 +10,7 @@
*
* Copyright (c) 2002-2007, PostgreSQL Global Development Group
*
* $PostgreSQL: pgsql/src/include/catalog/pg_cast.h,v 1.33 2007/06/01 23:40:18 neilc Exp $
* $PostgreSQL: pgsql/src/include/catalog/pg_cast.h,v 1.34 2007/06/05 21:31:07 tgl Exp $
*
* NOTES
* the genbki.sh script reads this file and generates .bki
@ -173,7 +173,7 @@ DATA(insert ( 25 2205 1079 i ));
DATA(insert ( 1043 2205 1079 i ));
/*
* String category: this needs to be tightened up
* String category
*/
DATA(insert ( 25 1042 0 i ));
DATA(insert ( 25 1043 0 i ));
@ -193,7 +193,8 @@ DATA(insert ( 1043 18 944 a ));
DATA(insert ( 25 19 407 i ));
DATA(insert ( 1042 19 409 i ));
DATA(insert ( 1043 19 1400 i ));
/* Cross-category casts between int4 and "char" */
/* Allow explicit coercions between int4 and "char" */
DATA(insert ( 18 23 77 e ));
DATA(insert ( 23 18 78 e ));
@ -265,127 +266,42 @@ DATA(insert ( 1560 23 1684 e ));
/*
* Cross-category casts to and from TEXT
*
* For historical reasons, most casts to TEXT are implicit. This is BAD
* and should be reined in.
* We need entries here only for a few specialized cases where the behavior
* of the cast function differs from the datatype's I/O functions. Otherwise,
* parse_coerce.c will generate CoerceViaIO operations without any prompting.
*
* Note that the castcontext values specified here should be no stronger than
* parse_coerce.c's automatic casts ('a' to text, 'e' from text) else odd
* behavior will ensue when the automatic cast is applied instead of the
* pg_cast entry!
*/
DATA(insert ( 20 25 1289 i ));
DATA(insert ( 25 20 1290 e ));
DATA(insert ( 21 25 113 i ));
DATA(insert ( 25 21 818 e ));
DATA(insert ( 23 25 112 i ));
DATA(insert ( 25 23 819 e ));
DATA(insert ( 26 25 114 i ));
DATA(insert ( 25 26 817 e ));
DATA(insert ( 25 650 1714 e ));
DATA(insert ( 700 25 841 i ));
DATA(insert ( 25 700 839 e ));
DATA(insert ( 701 25 840 i ));
DATA(insert ( 25 701 838 e ));
DATA(insert ( 829 25 752 e ));
DATA(insert ( 25 829 767 e ));
DATA(insert ( 650 25 730 e ));
DATA(insert ( 869 25 730 e ));
DATA(insert ( 25 869 1713 e ));
DATA(insert ( 1082 25 749 i ));
DATA(insert ( 25 1082 748 e ));
DATA(insert ( 1083 25 948 i ));
DATA(insert ( 25 1083 837 e ));
DATA(insert ( 1114 25 2034 i ));
DATA(insert ( 25 1114 2022 e ));
DATA(insert ( 1184 25 1192 i ));
DATA(insert ( 25 1184 1191 e ));
DATA(insert ( 1186 25 1193 i ));
DATA(insert ( 25 1186 1263 e ));
DATA(insert ( 1266 25 939 i ));
DATA(insert ( 25 1266 938 e ));
DATA(insert ( 1700 25 1688 i ));
DATA(insert ( 25 1700 1686 e ));
DATA(insert ( 142 25 2922 e ));
DATA(insert ( 650 25 730 a ));
DATA(insert ( 869 25 730 a ));
DATA(insert ( 16 25 2971 a ));
DATA(insert ( 142 25 2922 a ));
DATA(insert ( 25 142 2896 e ));
DATA(insert ( 16 25 2971 e ));
DATA(insert ( 25 16 2970 e ));
/*
* Cross-category casts to and from VARCHAR
*
* We support all the same casts as for TEXT, but none are implicit.
* We support all the same casts as for TEXT.
*/
DATA(insert ( 20 1043 1289 a ));
DATA(insert ( 1043 20 1290 e ));
DATA(insert ( 21 1043 113 a ));
DATA(insert ( 1043 21 818 e ));
DATA(insert ( 23 1043 112 a ));
DATA(insert ( 1043 23 819 e ));
DATA(insert ( 26 1043 114 a ));
DATA(insert ( 1043 26 817 e ));
DATA(insert ( 1043 650 1714 e ));
DATA(insert ( 700 1043 841 a ));
DATA(insert ( 1043 700 839 e ));
DATA(insert ( 701 1043 840 a ));
DATA(insert ( 1043 701 838 e ));
DATA(insert ( 829 1043 752 e ));
DATA(insert ( 1043 829 767 e ));
DATA(insert ( 650 1043 730 e ));
DATA(insert ( 869 1043 730 e ));
DATA(insert ( 1043 869 1713 e ));
DATA(insert ( 1082 1043 749 a ));
DATA(insert ( 1043 1082 748 e ));
DATA(insert ( 1083 1043 948 a ));
DATA(insert ( 1043 1083 837 e ));
DATA(insert ( 1114 1043 2034 a ));
DATA(insert ( 1043 1114 2022 e ));
DATA(insert ( 1184 1043 1192 a ));
DATA(insert ( 1043 1184 1191 e ));
DATA(insert ( 1186 1043 1193 a ));
DATA(insert ( 1043 1186 1263 e ));
DATA(insert ( 1266 1043 939 a ));
DATA(insert ( 1043 1266 938 e ));
DATA(insert ( 1700 1043 1688 a ));
DATA(insert ( 1043 1700 1686 e ));
DATA(insert ( 142 1043 2922 e ));
DATA(insert ( 650 1043 730 a ));
DATA(insert ( 869 1043 730 a ));
DATA(insert ( 16 1043 2971 a ));
DATA(insert ( 142 1043 2922 a ));
DATA(insert ( 1043 142 2896 e ));
DATA(insert ( 16 1043 2971 e ));
DATA(insert ( 1043 16 2970 e ));
/*
* Cross-category casts to and from BPCHAR
*
* A function supporting cast to TEXT/VARCHAR can be used for cast to BPCHAR,
* but the other direction is okay only if the function treats trailing
* blanks as insignificant. So this is a subset of the VARCHAR list.
* (Arguably the holdouts should be fixed, but I'm not doing that now...)
* We support all the same casts as for TEXT.
*/
DATA(insert ( 20 1042 1289 a ));
DATA(insert ( 1042 20 1290 e ));
DATA(insert ( 21 1042 113 a ));
DATA(insert ( 1042 21 818 e ));
DATA(insert ( 23 1042 112 a ));
DATA(insert ( 1042 23 819 e ));
DATA(insert ( 26 1042 114 a ));
DATA(insert ( 1042 26 817 e ));
DATA(insert ( 700 1042 841 a ));
DATA(insert ( 1042 700 839 e ));
DATA(insert ( 701 1042 840 a ));
DATA(insert ( 1042 701 838 e ));
DATA(insert ( 829 1042 752 e ));
DATA(insert ( 1042 829 767 e ));
DATA(insert ( 650 1042 730 e ));
DATA(insert ( 869 1042 730 e ));
DATA(insert ( 1082 1042 749 a ));
DATA(insert ( 1042 1082 748 e ));
DATA(insert ( 1083 1042 948 a ));
DATA(insert ( 1042 1083 837 e ));
DATA(insert ( 1114 1042 2034 a ));
DATA(insert ( 1042 1114 2022 e ));
DATA(insert ( 1184 1042 1192 a ));
DATA(insert ( 1042 1184 1191 e ));
DATA(insert ( 1186 1042 1193 a ));
DATA(insert ( 1042 1186 1263 e ));
DATA(insert ( 1266 1042 939 a ));
DATA(insert ( 1042 1266 938 e ));
DATA(insert ( 1700 1042 1688 a ));
DATA(insert ( 1042 1700 1686 e ));
DATA(insert ( 142 1042 2922 e ));
DATA(insert ( 650 1042 730 a ));
DATA(insert ( 869 1042 730 a ));
DATA(insert ( 16 1042 2971 a ));
DATA(insert ( 142 1042 2922 a ));
DATA(insert ( 1042 142 2896 e ));
/*
* Length-coercion functions
@ -401,16 +317,4 @@ DATA(insert ( 1560 1560 1685 i ));
DATA(insert ( 1562 1562 1687 i ));
DATA(insert ( 1700 1700 1703 i ));
/* casts to and from uuid */
DATA(insert ( 25 2950 2964 a ));
DATA(insert ( 2950 25 2965 a ));
DATA(insert ( 1043 2950 2964 a ));
DATA(insert ( 2950 1043 2965 a ));
/*
* enums
*/
DATA(insert ( 3500 25 3532 e ));
DATA(insert ( 25 3500 3533 e ));
#endif /* PG_CAST_H */

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.457 2007/06/01 23:40:18 neilc Exp $
* $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.458 2007/06/05 21:31:07 tgl Exp $
*
* NOTES
* The script catalog/genbki.sh reads this file and generates .bki
@ -238,12 +238,6 @@ DESCR("I/O");
DATA(insert OID = 110 ( unknownout PGNSP PGUID 12 1 0 f f t f i 1 2275 "705" _null_ _null_ _null_ unknownout - _null_ ));
DESCR("I/O");
DATA(insert OID = 111 ( numeric_fac PGNSP PGUID 12 1 0 f f t f i 1 1700 "20" _null_ _null_ _null_ numeric_fac - _null_ ));
DATA(insert OID = 112 ( text PGNSP PGUID 12 1 0 f f t f i 1 25 "23" _null_ _null_ _null_ int4_text - _null_ ));
DESCR("convert int4 to text");
DATA(insert OID = 113 ( text PGNSP PGUID 12 1 0 f f t f i 1 25 "21" _null_ _null_ _null_ int2_text - _null_ ));
DESCR("convert int2 to text");
DATA(insert OID = 114 ( text PGNSP PGUID 12 1 0 f f t f i 1 25 "26" _null_ _null_ _null_ oid_text - _null_ ));
DESCR("convert oid to text");
DATA(insert OID = 115 ( box_above_eq PGNSP PGUID 12 1 0 f f t f i 2 16 "603 603" _null_ _null_ _null_ box_above_eq - _null_ ));
DESCR("is above (allows touching)");
@ -513,7 +507,7 @@ DESCR("abstime in tinterval");
DATA(insert OID = 249 ( tintervalrel PGNSP PGUID 12 1 0 f f t f i 1 703 "704" _null_ _null_ _null_ tintervalrel - _null_ ));
DESCR("tinterval to reltime");
DATA(insert OID = 250 ( timenow PGNSP PGUID 12 1 0 f f t f s 0 702 "" _null_ _null_ _null_ timenow - _null_ ));
DESCR("Current date and time (abstime)");
DESCR("current date and time (abstime)");
DATA(insert OID = 251 ( abstimeeq PGNSP PGUID 12 1 0 f f t f i 2 16 "702 702" _null_ _null_ _null_ abstimeeq - _null_ ));
DESCR("equal");
DATA(insert OID = 252 ( abstimene PGNSP PGUID 12 1 0 f f t f i 2 16 "702 702" _null_ _null_ _null_ abstimene - _null_ ));
@ -561,7 +555,7 @@ DESCR("start of interval");
DATA(insert OID = 273 ( tintervalend PGNSP PGUID 12 1 0 f f t f i 1 702 "704" _null_ _null_ _null_ tintervalend - _null_ ));
DESCR("end of interval");
DATA(insert OID = 274 ( timeofday PGNSP PGUID 12 1 0 f f t f v 0 25 "" _null_ _null_ _null_ timeofday - _null_ ));
DESCR("Current date and time - increments during transactions");
DESCR("current date and time - increments during transactions");
DATA(insert OID = 275 ( isfinite PGNSP PGUID 12 1 0 f f t f i 1 16 "702" _null_ _null_ _null_ abstime_finite - _null_ ));
DESCR("finite abstime?");
@ -1091,22 +1085,6 @@ DESCR("greater-than-or-equal");
/* OIDS 800 - 899 */
DATA(insert OID = 817 ( oid PGNSP PGUID 12 1 0 f f t f i 1 26 "25" _null_ _null_ _null_ text_oid - _null_ ));
DESCR("convert text to oid");
DATA(insert OID = 818 ( int2 PGNSP PGUID 12 1 0 f f t f i 1 21 "25" _null_ _null_ _null_ text_int2 - _null_ ));
DESCR("convert text to int2");
DATA(insert OID = 819 ( int4 PGNSP PGUID 12 1 0 f f t f i 1 23 "25" _null_ _null_ _null_ text_int4 - _null_ ));
DESCR("convert text to int4");
DATA(insert OID = 838 ( float8 PGNSP PGUID 12 1 0 f f t f i 1 701 "25" _null_ _null_ _null_ text_float8 - _null_ ));
DESCR("convert text to float8");
DATA(insert OID = 839 ( float4 PGNSP PGUID 12 1 0 f f t f i 1 700 "25" _null_ _null_ _null_ text_float4 - _null_ ));
DESCR("convert text to float4");
DATA(insert OID = 840 ( text PGNSP PGUID 12 1 0 f f t f i 1 25 "701" _null_ _null_ _null_ float8_text - _null_ ));
DESCR("convert float8 to text");
DATA(insert OID = 841 ( text PGNSP PGUID 12 1 0 f f t f i 1 25 "700" _null_ _null_ _null_ float4_text - _null_ ));
DESCR("convert float4 to text");
DATA(insert OID = 846 ( cash_mul_flt4 PGNSP PGUID 12 1 0 f f t f i 2 790 "790 700" _null_ _null_ _null_ cash_mul_flt4 - _null_ ));
DESCR("multiply");
DATA(insert OID = 847 ( cash_div_flt4 PGNSP PGUID 12 1 0 f f t f i 2 790 "790 700" _null_ _null_ _null_ cash_div_flt4 - _null_ ));
@ -1303,19 +1281,6 @@ DESCR("horizontal?");
DATA(insert OID = 999 ( lseg_eq PGNSP PGUID 12 1 0 f f t f i 2 16 "601 601" _null_ _null_ _null_ lseg_eq - _null_ ));
DESCR("equal");
DATA(insert OID = 748 ( date PGNSP PGUID 12 1 0 f f t f s 1 1082 "25" _null_ _null_ _null_ text_date - _null_ ));
DESCR("convert text to date");
DATA(insert OID = 749 ( text PGNSP PGUID 12 1 0 f f t f s 1 25 "1082" _null_ _null_ _null_ date_text - _null_ ));
DESCR("convert date to text");
DATA(insert OID = 837 ( time PGNSP PGUID 12 1 0 f f t f s 1 1083 "25" _null_ _null_ _null_ text_time - _null_ ));
DESCR("convert text to time");
DATA(insert OID = 948 ( text PGNSP PGUID 12 1 0 f f t f i 1 25 "1083" _null_ _null_ _null_ time_text - _null_ ));
DESCR("convert time to text");
DATA(insert OID = 938 ( timetz PGNSP PGUID 12 1 0 f f t f s 1 1266 "25" _null_ _null_ _null_ text_timetz - _null_ ));
DESCR("convert text to timetz");
DATA(insert OID = 939 ( text PGNSP PGUID 12 1 0 f f t f i 1 25 "1266" _null_ _null_ _null_ timetz_text - _null_ ));
DESCR("convert timetz to text");
/* OIDS 1000 - 1999 */
DATA(insert OID = 1026 ( timezone PGNSP PGUID 12 1 0 f f t f i 2 1114 "1186 1184" _null_ _null_ _null_ timestamptz_izone - _null_ ));
@ -1524,12 +1489,6 @@ DATA(insert OID = 1189 ( timestamptz_pl_interval PGNSP PGUID 12 1 0 f f t f s 2
DESCR("plus");
DATA(insert OID = 1190 ( timestamptz_mi_interval PGNSP PGUID 12 1 0 f f t f s 2 1184 "1184 1186" _null_ _null_ _null_ timestamptz_mi_interval - _null_ ));
DESCR("minus");
DATA(insert OID = 1191 ( timestamptz PGNSP PGUID 12 1 0 f f t f s 1 1184 "25" _null_ _null_ _null_ text_timestamptz - _null_ ));
DESCR("convert text to timestamp with time zone");
DATA(insert OID = 1192 ( text PGNSP PGUID 12 1 0 f f t f s 1 25 "1184" _null_ _null_ _null_ timestamptz_text - _null_ ));
DESCR("convert timestamp with time zone to text");
DATA(insert OID = 1193 ( text PGNSP PGUID 12 1 0 f f t f i 1 25 "1186" _null_ _null_ _null_ interval_text - _null_ ));
DESCR("convert interval to text");
DATA(insert OID = 1194 ( reltime PGNSP PGUID 12 1 0 f f t f i 1 703 "1186" _null_ _null_ _null_ interval_reltime - _null_ ));
DESCR("convert interval to reltime");
DATA(insert OID = 1195 ( timestamptz_smaller PGNSP PGUID 12 1 0 f f t f i 2 1184 "1184 1184" _null_ _null_ _null_ timestamp_smaller - _null_ ));
@ -1586,9 +1545,6 @@ DESCR("absolute value");
DATA(insert OID = 1253 ( int2abs PGNSP PGUID 12 1 0 f f t f i 1 21 "21" _null_ _null_ _null_ int2abs - _null_ ));
DESCR("absolute value");
DATA(insert OID = 1263 ( interval PGNSP PGUID 12 1 0 f f t f s 1 1186 "25" _null_ _null_ _null_ text_interval - _null_ ));
DESCR("convert text to interval");
DATA(insert OID = 1271 ( overlaps PGNSP PGUID 12 1 0 f f f f i 4 16 "1266 1266 1266 1266" _null_ _null_ _null_ overlaps_timetz - _null_ ));
DESCR("SQL92 interval comparison");
DATA(insert OID = 1272 ( datetime_pl PGNSP PGUID 12 1 0 f f t f i 2 1114 "1082 1083" _null_ _null_ _null_ datetime_timestamp - _null_ ));
@ -1617,11 +1573,6 @@ DESCR("convert int8 to oid");
DATA(insert OID = 1288 ( int8 PGNSP PGUID 12 1 0 f f t f i 1 20 "26" _null_ _null_ _null_ oidtoi8 - _null_ ));
DESCR("convert oid to int8");
DATA(insert OID = 1289 ( text PGNSP PGUID 12 1 0 f f t f i 1 25 "20" _null_ _null_ _null_ int8_text - _null_ ));
DESCR("convert int8 to text");
DATA(insert OID = 1290 ( int8 PGNSP PGUID 12 1 0 f f t f i 1 20 "25" _null_ _null_ _null_ text_int8 - _null_ ));
DESCR("convert text to int8");
DATA(insert OID = 1292 ( tideq PGNSP PGUID 12 1 0 f f t f i 2 16 "27 27" _null_ _null_ _null_ tideq - _null_ ));
DESCR("equal");
DATA(insert OID = 1293 ( currtid PGNSP PGUID 12 1 0 f f t f v 2 27 "26 27" _null_ _null_ _null_ currtid_byreloid - _null_ ));
@ -2407,12 +2358,8 @@ DESCR("I/O");
DATA(insert OID = 437 ( macaddr_out PGNSP PGUID 12 1 0 f f t f i 1 2275 "829" _null_ _null_ _null_ macaddr_out - _null_ ));
DESCR("I/O");
DATA(insert OID = 752 ( text PGNSP PGUID 12 1 0 f f t f i 1 25 "829" _null_ _null_ _null_ macaddr_text - _null_ ));
DESCR("MAC address to text");
DATA(insert OID = 753 ( trunc PGNSP PGUID 12 1 0 f f t f i 1 829 "829" _null_ _null_ _null_ macaddr_trunc - _null_ ));
DESCR("MAC manufacturer fields");
DATA(insert OID = 767 ( macaddr PGNSP PGUID 12 1 0 f f t f i 1 829 "25" _null_ _null_ _null_ text_macaddr - _null_ ));
DESCR("text to MAC address");
DATA(insert OID = 830 ( macaddr_eq PGNSP PGUID 12 1 0 f f t f i 2 16 "829 829" _null_ _null_ _null_ macaddr_eq - _null_ ));
DESCR("equal");
@ -2490,10 +2437,6 @@ DATA(insert OID = 730 ( text PGNSP PGUID 12 1 0 f f t f i 1 25 "869" _null_
DESCR("show all parts of inet/cidr value");
DATA(insert OID = 1362 ( hostmask PGNSP PGUID 12 1 0 f f t f i 1 869 "869" _null_ _null_ _null_ network_hostmask - _null_ ));
DESCR("hostmask of address");
DATA(insert OID = 1713 ( inet PGNSP PGUID 12 1 0 f f t f i 1 869 "25" _null_ _null_ _null_ text_inet - _null_ ));
DESCR("text to inet");
DATA(insert OID = 1714 ( cidr PGNSP PGUID 12 1 0 f f t f i 1 650 "25" _null_ _null_ _null_ text_cidr - _null_ ));
DESCR("text to cidr");
DATA(insert OID = 1715 ( cidr PGNSP PGUID 12 1 0 f f t f i 1 650 "869" _null_ _null_ _null_ inet_to_cidr - _null_ ));
DESCR("coerce inet to cidr");
@ -2521,11 +2464,6 @@ DESCR("subtract integer from inet value");
DATA(insert OID = 2633 ( inetmi PGNSP PGUID 12 1 0 f f t f i 2 20 "869 869" _null_ _null_ _null_ inetmi - _null_ ));
DESCR("subtract inet values");
DATA(insert OID = 1686 ( numeric PGNSP PGUID 12 1 0 f f t f i 1 1700 "25" _null_ _null_ _null_ text_numeric - _null_ ));
DESCR("(internal)");
DATA(insert OID = 1688 ( text PGNSP PGUID 12 1 0 f f t f i 1 25 "1700" _null_ _null_ _null_ numeric_text - _null_ ));
DESCR("(internal)");
DATA(insert OID = 1690 ( time_mi_time PGNSP PGUID 12 1 0 f f t f i 2 1186 "1083 1083" _null_ _null_ _null_ time_mi_time - _null_ ));
DESCR("minus");
@ -3009,9 +2947,9 @@ DATA(insert OID = 2274 ( pg_stat_reset PGNSP PGUID 12 1 0 f f f f v 0 2278
DESCR("Statistics: Reset collected statistics for current database");
DATA(insert OID = 1946 ( encode PGNSP PGUID 12 1 0 f f t f i 2 25 "17 25" _null_ _null_ _null_ binary_encode - _null_ ));
DESCR("Convert bytea value into some ascii-only text string");
DESCR("convert bytea value into some ascii-only text string");
DATA(insert OID = 1947 ( decode PGNSP PGUID 12 1 0 f f t f i 2 17 "25 25" _null_ _null_ _null_ binary_decode - _null_ ));
DESCR("Convert ascii-encoded text string into bytea value");
DESCR("convert ascii-encoded text string into bytea value");
DATA(insert OID = 1948 ( byteaeq PGNSP PGUID 12 1 0 f f t f i 2 16 "17 17" _null_ _null_ _null_ byteaeq - _null_ ));
DESCR("equal");
@ -3076,8 +3014,6 @@ DATA(insert OID = 2020 ( date_trunc PGNSP PGUID 12 1 0 f f t f i 2 1114 "25 11
DESCR("truncate timestamp to specified units");
DATA(insert OID = 2021 ( date_part PGNSP PGUID 12 1 0 f f t f i 2 701 "25 1114" _null_ _null_ _null_ timestamp_part - _null_ ));
DESCR("extract field from timestamp");
DATA(insert OID = 2022 ( timestamp PGNSP PGUID 12 1 0 f f t f s 1 1114 "25" _null_ _null_ _null_ text_timestamp - _null_ ));
DESCR("convert text to timestamp");
DATA(insert OID = 2023 ( timestamp PGNSP PGUID 12 1 0 f f t f s 1 1114 "702" _null_ _null_ _null_ abstime_timestamp - _null_ ));
DESCR("convert abstime to timestamp");
DATA(insert OID = 2024 ( timestamp PGNSP PGUID 12 1 0 f f t f i 1 1114 "1082" _null_ _null_ _null_ date_timestamp - _null_ ));
@ -3098,8 +3034,6 @@ DATA(insert OID = 2032 ( timestamp_pl_interval PGNSP PGUID 12 1 0 f f t f i 2 1
DESCR("plus");
DATA(insert OID = 2033 ( timestamp_mi_interval PGNSP PGUID 12 1 0 f f t f i 2 1114 "1114 1186" _null_ _null_ _null_ timestamp_mi_interval - _null_ ));
DESCR("minus");
DATA(insert OID = 2034 ( text PGNSP PGUID 12 1 0 f f t f s 1 25 "1114" _null_ _null_ _null_ timestamp_text - _null_ ));
DESCR("convert timestamp to text");
DATA(insert OID = 2035 ( timestamp_smaller PGNSP PGUID 12 1 0 f f t f i 2 1114 "1114 1114" _null_ _null_ _null_ timestamp_smaller - _null_ ));
DESCR("smaller of two");
DATA(insert OID = 2036 ( timestamp_larger PGNSP PGUID 12 1 0 f f t f i 2 1114 "1114 1114" _null_ _null_ _null_ timestamp_larger - _null_ ));
@ -3191,13 +3125,13 @@ DATA(insert OID = 2855 ( pg_is_other_temp_schema PGNSP PGUID 12 1 0 f f t f s 1
DESCR("is schema another session's temp schema?");
DATA(insert OID = 2171 ( pg_cancel_backend PGNSP PGUID 12 1 0 f f t f v 1 16 "23" _null_ _null_ _null_ pg_cancel_backend - _null_ ));
DESCR("Cancel a server process' current query");
DESCR("cancel a server process' current query");
DATA(insert OID = 2172 ( pg_start_backup PGNSP PGUID 12 1 0 f f t f v 1 25 "25" _null_ _null_ _null_ pg_start_backup - _null_ ));
DESCR("Prepare for taking an online backup");
DESCR("prepare for taking an online backup");
DATA(insert OID = 2173 ( pg_stop_backup PGNSP PGUID 12 1 0 f f t f v 0 25 "" _null_ _null_ _null_ pg_stop_backup - _null_ ));
DESCR("Finish taking an online backup");
DESCR("finish taking an online backup");
DATA(insert OID = 2848 ( pg_switch_xlog PGNSP PGUID 12 1 0 f f t f v 0 25 "" _null_ _null_ _null_ pg_switch_xlog - _null_ ));
DESCR("Switch to new xlog file");
DESCR("switch to new xlog file");
DATA(insert OID = 2849 ( pg_current_xlog_location PGNSP PGUID 12 1 0 f f t f v 0 25 "" _null_ _null_ _null_ pg_current_xlog_location - _null_ ));
DESCR("current xlog write location");
DATA(insert OID = 2852 ( pg_current_xlog_insert_location PGNSP PGUID 12 1 0 f f t f v 0 25 "" _null_ _null_ _null_ pg_current_xlog_insert_location - _null_ ));
@ -3208,23 +3142,21 @@ DATA(insert OID = 2851 ( pg_xlogfile_name PGNSP PGUID 12 1 0 f f t f i 1 25 "2
DESCR("xlog filename, given an xlog location");
DATA(insert OID = 2621 ( pg_reload_conf PGNSP PGUID 12 1 0 f f t f v 0 16 "" _null_ _null_ _null_ pg_reload_conf - _null_ ));
DESCR("Reload configuration files");
DESCR("reload configuration files");
DATA(insert OID = 2622 ( pg_rotate_logfile PGNSP PGUID 12 1 0 f f t f v 0 16 "" _null_ _null_ _null_ pg_rotate_logfile - _null_ ));
DESCR("Rotate log file");
DESCR("rotate log file");
DATA(insert OID = 2623 ( pg_stat_file PGNSP PGUID 12 1 0 f f t f v 1 2249 "25" "{25,20,1184,1184,1184,1184,16}" "{i,o,o,o,o,o,o}" "{filename,size,access,modification,change,creation,isdir}" pg_stat_file - _null_ ));
DESCR("Return file information");
DESCR("return file information");
DATA(insert OID = 2624 ( pg_read_file PGNSP PGUID 12 1 0 f f t f v 3 25 "25 20 20" _null_ _null_ _null_ pg_read_file - _null_ ));
DESCR("Read text from a file");
DESCR("read text from a file");
DATA(insert OID = 2625 ( pg_ls_dir PGNSP PGUID 12 1 1000 f f t t v 1 25 "25" _null_ _null_ _null_ pg_ls_dir - _null_ ));
DESCR("List all files in a directory");
DESCR("list all files in a directory");
DATA(insert OID = 2626 ( pg_sleep PGNSP PGUID 12 1 0 f f t f v 1 2278 "701" _null_ _null_ _null_ pg_sleep - _null_ ));
DESCR("Sleep for the specified time in seconds");
DESCR("sleep for the specified time in seconds");
DATA(insert OID = 2970 ( boolean PGNSP PGUID 12 1 0 f f t f i 1 16 "25" _null_ _null_ _null_ textbool - _null_ ));
DESCR("text to boolean");
DATA(insert OID = 2971 ( text PGNSP PGUID 12 1 0 f f t f i 1 25 "16" _null_ _null_ _null_ booltext - _null_ ));
DESCR("boolean to text");
DESCR("convert boolean to text");
/* Aggregates (moved here from pg_aggregate for 7.3) */
@ -3491,23 +3423,23 @@ DESCR("current user privilege on role by role oid");
DATA(insert OID = 1269 ( pg_column_size PGNSP PGUID 12 1 0 f f t f s 1 23 "2276" _null_ _null_ _null_ pg_column_size - _null_ ));
DESCR("bytes required to store the value, perhaps with compression");
DATA(insert OID = 2322 ( pg_tablespace_size PGNSP PGUID 12 1 0 f f t f v 1 20 "26" _null_ _null_ _null_ pg_tablespace_size_oid - _null_ ));
DESCR("Calculate total disk space usage for the specified tablespace");
DESCR("total disk space usage for the specified tablespace");
DATA(insert OID = 2323 ( pg_tablespace_size PGNSP PGUID 12 1 0 f f t f v 1 20 "19" _null_ _null_ _null_ pg_tablespace_size_name - _null_ ));
DESCR("Calculate total disk space usage for the specified tablespace");
DESCR("total disk space usage for the specified tablespace");
DATA(insert OID = 2324 ( pg_database_size PGNSP PGUID 12 1 0 f f t f v 1 20 "26" _null_ _null_ _null_ pg_database_size_oid - _null_ ));
DESCR("Calculate total disk space usage for the specified database");
DESCR("total disk space usage for the specified database");
DATA(insert OID = 2168 ( pg_database_size PGNSP PGUID 12 1 0 f f t f v 1 20 "19" _null_ _null_ _null_ pg_database_size_name - _null_ ));
DESCR("Calculate total disk space usage for the specified database");
DESCR("total disk space usage for the specified database");
DATA(insert OID = 2325 ( pg_relation_size PGNSP PGUID 12 1 0 f f t f v 1 20 "26" _null_ _null_ _null_ pg_relation_size_oid - _null_ ));
DESCR("Calculate disk space usage for the specified table or index");
DESCR("disk space usage for the specified table or index");
DATA(insert OID = 2289 ( pg_relation_size PGNSP PGUID 12 1 0 f f t f v 1 20 "25" _null_ _null_ _null_ pg_relation_size_name - _null_ ));
DESCR("Calculate disk space usage for the specified table or index");
DESCR("disk space usage for the specified table or index");
DATA(insert OID = 2286 ( pg_total_relation_size PGNSP PGUID 12 1 0 f f t f v 1 20 "26" _null_ _null_ _null_ pg_total_relation_size_oid - _null_ ));
DESCR("Calculate total disk space usage for the specified table and associated indexes and toast tables");
DESCR("total disk space usage for the specified table and associated indexes and toast tables");
DATA(insert OID = 2287 ( pg_total_relation_size PGNSP PGUID 12 1 0 f f t f v 1 20 "25" _null_ _null_ _null_ pg_total_relation_size_name - _null_ ));
DESCR("Calculate total disk space usage for the specified table and associated indexes and toast tables");
DESCR("total disk space usage for the specified table and associated indexes and toast tables");
DATA(insert OID = 2288 ( pg_size_pretty PGNSP PGUID 12 1 0 f f t f v 1 25 "20" _null_ _null_ _null_ pg_size_pretty - _null_ ));
DESCR("Convert a long int to a human readable text using size units");
DESCR("convert a long int to a human readable text using size units");
DATA(insert OID = 2290 ( record_in PGNSP PGUID 12 1 0 f f t f v 3 2249 "2275 26 23" _null_ _null_ _null_ record_in - _null_ ));
DESCR("I/O");
@ -4150,10 +4082,6 @@ DATA(insert OID = 2962 ( uuid_send PGNSP PGUID 12 1 0 f f t f i 1 17 "2950"
DESCR("I/O");
DATA(insert OID = 2963 ( uuid_hash PGNSP PGUID 12 1 0 f f t f i 1 23 "2950" _null_ _null_ _null_ uuid_hash - _null_ ));
DESCR("hash");
DATA(insert OID = 2964 ( uuid PGNSP PGUID 12 1 0 f f t f i 1 2950 "25" _null_ _null_ _null_ text_uuid - _null_ ));
DESCR("convert text to uuid");
DATA(insert OID = 2965 ( text PGNSP PGUID 12 1 0 f f t f i 1 25 "2950" _null_ _null_ _null_ uuid_text - _null_ ));
DESCR("convert uuid to text");
/* enum related procs */
DATA(insert OID = 3504 ( anyenum_in PGNSP PGUID 12 1 0 f f t f i 1 3500 "2275" _null_ _null_ _null_ anyenum_in - _null_ ));
@ -4190,10 +4118,6 @@ DATA(insert OID = 3528 ( enum_first PGNSP PGUID 12 1 0 f f f f s 1 3500 "3500"
DATA(insert OID = 3529 ( enum_last PGNSP PGUID 12 1 0 f f f f s 1 3500 "3500" _null_ _null_ _null_ enum_last - _null_ ));
DATA(insert OID = 3530 ( enum_range PGNSP PGUID 12 1 0 f f f f s 2 2277 "3500 3500" _null_ _null_ _null_ enum_range_bounds - _null_ ));
DATA(insert OID = 3531 ( enum_range PGNSP PGUID 12 1 0 f f f f s 1 2277 "3500" _null_ _null_ _null_ enum_range_all - _null_ ));
DATA(insert OID = 3532 ( text PGNSP PGUID 12 1 0 f f t f s 1 25 "3500" _null_ _null_ _null_ enum_text - _null_ ));
DESCR("convert enum to text");
DATA(insert OID = 3533 ( enum PGNSP PGUID 12 1 0 f f t f s 1 3500 "25" _null_ _null_ _null_ text_enum - _null_ ));
DESCR("convert text to enum");
/*
* Symbolic values for provolatile column: these indicate whether the result

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/nodes/execnodes.h,v 1.175 2007/05/21 17:57:34 tgl Exp $
* $PostgreSQL: pgsql/src/include/nodes/execnodes.h,v 1.176 2007/06/05 21:31:08 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -637,6 +637,19 @@ typedef struct FieldStoreState
TupleDesc argdesc; /* tupdesc for most recent input */
} FieldStoreState;
/* ----------------
* CoerceViaIOState node
* ----------------
*/
typedef struct CoerceViaIOState
{
ExprState xprstate;
ExprState *arg; /* input expression */
FmgrInfo outfunc; /* lookup info for source output function */
FmgrInfo infunc; /* lookup info for result input function */
Oid intypioparam; /* argument needed for input function */
} CoerceViaIOState;
/* ----------------
* ArrayCoerceExprState node
* ----------------

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/nodes/nodes.h,v 1.199 2007/04/26 16:13:14 neilc Exp $
* $PostgreSQL: pgsql/src/include/nodes/nodes.h,v 1.200 2007/06/05 21:31:08 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -121,6 +121,7 @@ typedef enum NodeTag
T_FieldSelect,
T_FieldStore,
T_RelabelType,
T_CoerceViaIO,
T_ArrayCoerceExpr,
T_ConvertRowtypeExpr,
T_CaseExpr,
@ -160,6 +161,7 @@ typedef enum NodeTag
T_SubPlanState,
T_FieldSelectState,
T_FieldStoreState,
T_CoerceViaIOState,
T_ArrayCoerceExprState,
T_ConvertRowtypeExprState,
T_CaseExprState,

View File

@ -10,7 +10,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/nodes/primnodes.h,v 1.129 2007/03/27 23:21:12 tgl Exp $
* $PostgreSQL: pgsql/src/include/nodes/primnodes.h,v 1.130 2007/06/05 21:31:08 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -550,6 +550,24 @@ typedef struct RelabelType
CoercionForm relabelformat; /* how to display this node */
} RelabelType;
/* ----------------
* CoerceViaIO
*
* CoerceViaIO represents a type coercion between two types whose textual
* representations are compatible, implemented by invoking the source type's
* typoutput function then the destination type's typinput function.
* ----------------
*/
typedef struct CoerceViaIO
{
Expr xpr;
Expr *arg; /* input expression */
Oid resulttype; /* output type of coercion */
/* output typmod is not stored, but is presumed -1 */
CoercionForm coerceformat; /* how to display this node */
} CoerceViaIO;
/* ----------------
* ArrayCoerceExpr
*

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/parser/parse_coerce.h,v 1.70 2007/03/27 23:21:12 tgl Exp $
* $PostgreSQL: pgsql/src/include/parser/parse_coerce.h,v 1.71 2007/06/05 21:31:08 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -17,6 +17,7 @@
#include "parser/parse_node.h"
/* Type categories (kluge ... ought to be extensible) */
typedef enum CATEGORY
{
INVALID_TYPE,
@ -33,6 +34,16 @@ typedef enum CATEGORY
USER_TYPE
} CATEGORY;
/* Result codes for find_coercion_pathway */
typedef enum CoercionPathType
{
COERCION_PATH_NONE, /* failed to find any coercion pathway */
COERCION_PATH_FUNC, /* apply the specified coercion function */
COERCION_PATH_RELABELTYPE, /* binary-compatible cast, no function */
COERCION_PATH_ARRAYCOERCE, /* need an ArrayCoerceExpr node */
COERCION_PATH_COERCEVIAIO /* need a CoerceViaIO node */
} CoercionPathType;
extern bool IsBinaryCoercible(Oid srctype, Oid targettype);
extern bool IsPreferredType(CATEGORY category, Oid type);
@ -75,10 +86,11 @@ extern Oid resolve_generic_type(Oid declared_type,
Oid context_actual_type,
Oid context_declared_type);
extern bool find_coercion_pathway(Oid targetTypeId, Oid sourceTypeId,
CoercionContext ccontext,
Oid *funcid, bool *arrayCoerce);
extern bool find_typmod_coercion_function(Oid typeId,
Oid *funcid, bool *arrayCoerce);
extern CoercionPathType find_coercion_pathway(Oid targetTypeId,
Oid sourceTypeId,
CoercionContext ccontext,
Oid *funcid);
extern CoercionPathType find_typmod_coercion_function(Oid typeId,
Oid *funcid);
#endif /* PARSE_COERCE_H */

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/utils/builtins.h,v 1.294 2007/06/01 23:40:19 neilc Exp $
* $PostgreSQL: pgsql/src/include/utils/builtins.h,v 1.295 2007/06/05 21:31:08 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -71,7 +71,6 @@ extern Datum boolout(PG_FUNCTION_ARGS);
extern Datum boolrecv(PG_FUNCTION_ARGS);
extern Datum boolsend(PG_FUNCTION_ARGS);
extern Datum booltext(PG_FUNCTION_ARGS);
extern Datum textbool(PG_FUNCTION_ARGS);
extern Datum booleq(PG_FUNCTION_ARGS);
extern Datum boolne(PG_FUNCTION_ARGS);
extern Datum boollt(PG_FUNCTION_ARGS);
@ -115,8 +114,6 @@ extern Datum enum_ne(PG_FUNCTION_ARGS);
extern Datum enum_ge(PG_FUNCTION_ARGS);
extern Datum enum_gt(PG_FUNCTION_ARGS);
extern Datum enum_cmp(PG_FUNCTION_ARGS);
extern Datum enum_text(PG_FUNCTION_ARGS);
extern Datum text_enum(PG_FUNCTION_ARGS);
extern Datum enum_smaller(PG_FUNCTION_ARGS);
extern Datum enum_larger(PG_FUNCTION_ARGS);
extern Datum enum_first(PG_FUNCTION_ARGS);
@ -140,12 +137,8 @@ extern Datum int4recv(PG_FUNCTION_ARGS);
extern Datum int4send(PG_FUNCTION_ARGS);
extern Datum i2toi4(PG_FUNCTION_ARGS);
extern Datum i4toi2(PG_FUNCTION_ARGS);
extern Datum int2_text(PG_FUNCTION_ARGS);
extern Datum text_int2(PG_FUNCTION_ARGS);
extern Datum int4_bool(PG_FUNCTION_ARGS);
extern Datum bool_int4(PG_FUNCTION_ARGS);
extern Datum int4_text(PG_FUNCTION_ARGS);
extern Datum text_int4(PG_FUNCTION_ARGS);
extern Datum int4eq(PG_FUNCTION_ARGS);
extern Datum int4ne(PG_FUNCTION_ARGS);
extern Datum int4lt(PG_FUNCTION_ARGS);
@ -334,10 +327,6 @@ extern Datum i4tof(PG_FUNCTION_ARGS);
extern Datum i2tof(PG_FUNCTION_ARGS);
extern Datum ftoi4(PG_FUNCTION_ARGS);
extern Datum ftoi2(PG_FUNCTION_ARGS);
extern Datum text_float8(PG_FUNCTION_ARGS);
extern Datum text_float4(PG_FUNCTION_ARGS);
extern Datum float8_text(PG_FUNCTION_ARGS);
extern Datum float4_text(PG_FUNCTION_ARGS);
extern Datum dround(PG_FUNCTION_ARGS);
extern Datum dceil(PG_FUNCTION_ARGS);
extern Datum dfloor(PG_FUNCTION_ARGS);
@ -446,8 +435,6 @@ extern Datum oidge(PG_FUNCTION_ARGS);
extern Datum oidgt(PG_FUNCTION_ARGS);
extern Datum oidlarger(PG_FUNCTION_ARGS);
extern Datum oidsmaller(PG_FUNCTION_ARGS);
extern Datum oid_text(PG_FUNCTION_ARGS);
extern Datum text_oid(PG_FUNCTION_ARGS);
extern Datum oidvectorin(PG_FUNCTION_ARGS);
extern Datum oidvectorout(PG_FUNCTION_ARGS);
extern Datum oidvectorrecv(PG_FUNCTION_ARGS);
@ -782,8 +769,6 @@ extern Datum network_show(PG_FUNCTION_ARGS);
extern Datum inet_abbrev(PG_FUNCTION_ARGS);
extern Datum cidr_abbrev(PG_FUNCTION_ARGS);
extern double convert_network_to_scalar(Datum value, Oid typid);
extern Datum text_cidr(PG_FUNCTION_ARGS);
extern Datum text_inet(PG_FUNCTION_ARGS);
extern Datum inet_to_cidr(PG_FUNCTION_ARGS);
extern Datum inet_set_masklen(PG_FUNCTION_ARGS);
extern Datum cidr_set_masklen(PG_FUNCTION_ARGS);
@ -814,8 +799,6 @@ extern Datum macaddr_ge(PG_FUNCTION_ARGS);
extern Datum macaddr_gt(PG_FUNCTION_ARGS);
extern Datum macaddr_ne(PG_FUNCTION_ARGS);
extern Datum macaddr_trunc(PG_FUNCTION_ARGS);
extern Datum macaddr_text(PG_FUNCTION_ARGS);
extern Datum text_macaddr(PG_FUNCTION_ARGS);
extern Datum hashmacaddr(PG_FUNCTION_ARGS);
/* numeric.c */
@ -866,8 +849,6 @@ extern Datum numeric_float8(PG_FUNCTION_ARGS);
extern Datum numeric_float8_no_overflow(PG_FUNCTION_ARGS);
extern Datum float4_numeric(PG_FUNCTION_ARGS);
extern Datum numeric_float4(PG_FUNCTION_ARGS);
extern Datum text_numeric(PG_FUNCTION_ARGS);
extern Datum numeric_text(PG_FUNCTION_ARGS);
extern Datum numeric_accum(PG_FUNCTION_ARGS);
extern Datum numeric_avg_accum(PG_FUNCTION_ARGS);
extern Datum int2_accum(PG_FUNCTION_ARGS);
@ -970,7 +951,5 @@ extern Datum uuid_gt(PG_FUNCTION_ARGS);
extern Datum uuid_ne(PG_FUNCTION_ARGS);
extern Datum uuid_cmp(PG_FUNCTION_ARGS);
extern Datum uuid_hash(PG_FUNCTION_ARGS);
extern Datum text_uuid(PG_FUNCTION_ARGS);
extern Datum uuid_text(PG_FUNCTION_ARGS);
#endif /* BUILTINS_H */

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/utils/date.h,v 1.36 2007/01/05 22:19:59 momjian Exp $
* $PostgreSQL: pgsql/src/include/utils/date.h,v 1.37 2007/06/05 21:31:08 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -133,8 +133,6 @@ extern Datum date_timestamptz(PG_FUNCTION_ARGS);
extern Datum timestamptz_date(PG_FUNCTION_ARGS);
extern Datum datetime_timestamp(PG_FUNCTION_ARGS);
extern Datum abstime_date(PG_FUNCTION_ARGS);
extern Datum text_date(PG_FUNCTION_ARGS);
extern Datum date_text(PG_FUNCTION_ARGS);
extern Datum time_in(PG_FUNCTION_ARGS);
extern Datum time_out(PG_FUNCTION_ARGS);
@ -158,8 +156,6 @@ extern Datum timestamp_time(PG_FUNCTION_ARGS);
extern Datum timestamptz_time(PG_FUNCTION_ARGS);
extern Datum time_interval(PG_FUNCTION_ARGS);
extern Datum interval_time(PG_FUNCTION_ARGS);
extern Datum text_time(PG_FUNCTION_ARGS);
extern Datum time_text(PG_FUNCTION_ARGS);
extern Datum time_pl_interval(PG_FUNCTION_ARGS);
extern Datum time_mi_interval(PG_FUNCTION_ARGS);
extern Datum time_part(PG_FUNCTION_ARGS);
@ -186,8 +182,6 @@ extern Datum timetz_time(PG_FUNCTION_ARGS);
extern Datum time_timetz(PG_FUNCTION_ARGS);
extern Datum timestamptz_timetz(PG_FUNCTION_ARGS);
extern Datum datetimetz_timestamptz(PG_FUNCTION_ARGS);
extern Datum text_timetz(PG_FUNCTION_ARGS);
extern Datum timetz_text(PG_FUNCTION_ARGS);
extern Datum timetz_part(PG_FUNCTION_ARGS);
extern Datum timetz_zone(PG_FUNCTION_ARGS);
extern Datum timetz_izone(PG_FUNCTION_ARGS);

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/utils/int8.h,v 1.46 2007/01/05 22:19:59 momjian Exp $
* $PostgreSQL: pgsql/src/include/utils/int8.h,v 1.47 2007/06/05 21:31:08 tgl Exp $
*
* NOTES
* These data types are supported on all 64-bit architectures, and may
@ -111,9 +111,6 @@ extern Datum ftoi8(PG_FUNCTION_ARGS);
extern Datum i8tooid(PG_FUNCTION_ARGS);
extern Datum oidtoi8(PG_FUNCTION_ARGS);
extern Datum int8_text(PG_FUNCTION_ARGS);
extern Datum text_int8(PG_FUNCTION_ARGS);
extern Datum generate_series_int8(PG_FUNCTION_ARGS);
extern Datum generate_series_step_int8(PG_FUNCTION_ARGS);

View File

@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/utils/timestamp.h,v 1.69 2007/04/30 21:01:53 tgl Exp $
* $PostgreSQL: pgsql/src/include/utils/timestamp.h,v 1.70 2007/06/05 21:31:08 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -252,10 +252,6 @@ extern Datum interval_justify_interval(PG_FUNCTION_ARGS);
extern Datum interval_justify_hours(PG_FUNCTION_ARGS);
extern Datum interval_justify_days(PG_FUNCTION_ARGS);
extern Datum timestamp_text(PG_FUNCTION_ARGS);
extern Datum text_timestamp(PG_FUNCTION_ARGS);
extern Datum interval_text(PG_FUNCTION_ARGS);
extern Datum text_interval(PG_FUNCTION_ARGS);
extern Datum timestamp_trunc(PG_FUNCTION_ARGS);
extern Datum interval_trunc(PG_FUNCTION_ARGS);
extern Datum timestamp_part(PG_FUNCTION_ARGS);
@ -291,8 +287,6 @@ extern Datum timestamp_mi_interval(PG_FUNCTION_ARGS);
extern Datum timestamp_age(PG_FUNCTION_ARGS);
extern Datum overlaps_timestamp(PG_FUNCTION_ARGS);
extern Datum timestamptz_text(PG_FUNCTION_ARGS);
extern Datum text_timestamptz(PG_FUNCTION_ARGS);
extern Datum timestamptz_pl_interval(PG_FUNCTION_ARGS);
extern Datum timestamptz_mi_interval(PG_FUNCTION_ARGS);
extern Datum timestamptz_age(PG_FUNCTION_ARGS);

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.196 2007/04/29 01:21:09 neilc Exp $
* $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.197 2007/06/05 21:31:08 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -4610,6 +4610,9 @@ exec_simple_check_node(Node *node)
case T_RelabelType:
return exec_simple_check_node((Node *) ((RelabelType *) node)->arg);
case T_CoerceViaIO:
return exec_simple_check_node((Node *) ((CoerceViaIO *) node)->arg);
case T_ArrayCoerceExpr:
return exec_simple_check_node((Node *) ((ArrayCoerceExpr *) node)->arg);

View File

@ -1125,10 +1125,12 @@ ALTER TABLE fktable ADD CONSTRAINT fk_3_1
FOREIGN KEY (x3) REFERENCES pktable(id1);
ERROR: foreign key constraint "fk_3_1" cannot be implemented
DETAIL: Key columns "x3" and "id1" are of incompatible types: real and integer.
-- should succeed
-- int4 promotes to text, so this is allowed (though pretty durn debatable)
-- int4 does not promote to text
ALTER TABLE fktable ADD CONSTRAINT fk_1_2
FOREIGN KEY (x1) REFERENCES pktable(id2);
ERROR: foreign key constraint "fk_1_2" cannot be implemented
DETAIL: Key columns "x1" and "id2" are of incompatible types: integer and character varying.
-- should succeed
-- int4 promotes to real
ALTER TABLE fktable ADD CONSTRAINT fk_1_3
FOREIGN KEY (x1) REFERENCES pktable(id3);
@ -1150,7 +1152,7 @@ FOREIGN KEY (x2,x5,x3) REFERENCES pktable(id2,id1,id3);
ALTER TABLE fktable ADD CONSTRAINT fk_123_231
FOREIGN KEY (x1,x2,x3) REFERENCES pktable(id2,id3,id1);
ERROR: foreign key constraint "fk_123_231" cannot be implemented
DETAIL: Key columns "x2" and "id3" are of incompatible types: character varying and real.
DETAIL: Key columns "x1" and "id2" are of incompatible types: integer and character varying.
ALTER TABLE fktable ADD CONSTRAINT fk_241_132
FOREIGN KEY (x2,x4,x1) REFERENCES pktable(id1,id3,id2);
ERROR: foreign key constraint "fk_241_132" cannot be implemented
@ -1162,7 +1164,6 @@ NOTICE: drop cascades to constraint fk_123_123 on table fktable
NOTICE: drop cascades to constraint fk_5_1 on table fktable
NOTICE: drop cascades to constraint fktable_x1_fkey on table fktable
NOTICE: drop cascades to constraint fk_4_2 on table fktable
NOTICE: drop cascades to constraint fk_1_2 on table fktable
NOTICE: drop cascades to constraint fktable_x2_fkey on table fktable
NOTICE: drop cascades to constraint fk_1_3 on table fktable
NOTICE: drop cascades to constraint fktable_x3_fkey on table fktable

View File

@ -450,7 +450,7 @@ SELECT POSITION('4' IN '1234567890') = '4' AS "4";
t
(1 row)
SELECT POSITION(5 IN '1234567890') = '5' AS "5";
SELECT POSITION('5' IN '1234567890') = '5' AS "5";
5
---
t

View File

@ -354,7 +354,7 @@ create rule shipped_view_insert as on insert to shipped_view do instead
insert into shipped values('wt', new.ordnum, new.partnum, new.value);
insert into parts (partnum, cost) values (1, 1234.56);
insert into shipped_view (ordnum, partnum, value)
values (0, 1, (select cost from parts where partnum = 1));
values (0, 1, (select cost from parts where partnum = '1'));
select * from shipped_view;
ttype | ordnum | partnum | value
-------+--------+---------+---------

View File

@ -760,12 +760,12 @@ FOREIGN KEY (x2) REFERENCES pktable(id1);
ALTER TABLE fktable ADD CONSTRAINT fk_3_1
FOREIGN KEY (x3) REFERENCES pktable(id1);
-- should succeed
-- int4 promotes to text, so this is allowed (though pretty durn debatable)
-- int4 does not promote to text
ALTER TABLE fktable ADD CONSTRAINT fk_1_2
FOREIGN KEY (x1) REFERENCES pktable(id2);
-- should succeed
-- int4 promotes to real
ALTER TABLE fktable ADD CONSTRAINT fk_1_3
FOREIGN KEY (x1) REFERENCES pktable(id3);

View File

@ -142,7 +142,7 @@ SELECT regexp_split_to_array('thE QUick bROWn FOx jUMPed ovEr THE lazy dOG', 'e'
-- E021-11 position expression
SELECT POSITION('4' IN '1234567890') = '4' AS "4";
SELECT POSITION(5 IN '1234567890') = '5' AS "5";
SELECT POSITION('5' IN '1234567890') = '5' AS "5";
-- T312 character overlay function
SELECT OVERLAY('abcdef' PLACING '45' FROM 4) AS "abc45f";

View File

@ -218,7 +218,7 @@ create rule shipped_view_insert as on insert to shipped_view do instead
insert into parts (partnum, cost) values (1, 1234.56);
insert into shipped_view (ordnum, partnum, value)
values (0, 1, (select cost from parts where partnum = 1));
values (0, 1, (select cost from parts where partnum = '1'));
select * from shipped_view;