mirror of https://github.com/postgres/postgres
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:
parent
1120b99445
commit
31edbadf4a
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
--
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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:
|
||||
--
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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</> —
|
||||
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</> —
|
||||
which it is not — 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>
|
||||
|
|
|
@ -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">
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -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:
|
||||
*/
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
* ----------------
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
*
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
-------+--------+---------+---------
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
Loading…
Reference in New Issue