Commit 2d4db367 authored by Tom Lane's avatar Tom Lane

Fix up text concatenation so that it accepts all the reasonable cases that

were accepted by prior Postgres releases.  This takes care of the loose end
left by the preceding patch to downgrade implicit casts-to-text.  To avoid
breaking desirable behavior for array concatenation, introduce a new
polymorphic pseudo-type "anynonarray" --- the added concatenation operators
are actually text || anynonarray and anynonarray || text.
parent 7dab4f75
<!-- $PostgreSQL: pgsql/doc/src/sgml/datatype.sgml,v 1.203 2007/06/01 23:40:18 neilc Exp $ --> <!-- $PostgreSQL: pgsql/doc/src/sgml/datatype.sgml,v 1.204 2007/06/06 23:00:35 tgl Exp $ -->
<chapter id="datatype"> <chapter id="datatype">
<title id="datatype-title">Data Types</title> <title id="datatype-title">Data Types</title>
...@@ -3676,12 +3676,16 @@ SELECT * FROM pg_attribute ...@@ -3676,12 +3676,16 @@ SELECT * FROM pg_attribute
<primary>any</primary> <primary>any</primary>
</indexterm> </indexterm>
<indexterm zone="datatype-pseudo">
<primary>anyelement</primary>
</indexterm>
<indexterm zone="datatype-pseudo"> <indexterm zone="datatype-pseudo">
<primary>anyarray</primary> <primary>anyarray</primary>
</indexterm> </indexterm>
<indexterm zone="datatype-pseudo"> <indexterm zone="datatype-pseudo">
<primary>anyelement</primary> <primary>anynonarray</primary>
</indexterm> </indexterm>
<indexterm zone="datatype-pseudo"> <indexterm zone="datatype-pseudo">
...@@ -3760,6 +3764,12 @@ SELECT * FROM pg_attribute ...@@ -3760,6 +3764,12 @@ SELECT * FROM pg_attribute
<xref linkend="datatype-enum">).</entry> <xref linkend="datatype-enum">).</entry>
</row> </row>
<row>
<entry><type>anynonarray</></entry>
<entry>Indicates that a function accepts any non-array data type
(see <xref linkend="extend-types-polymorphic">).</entry>
</row>
<row> <row>
<entry><type>cstring</></entry> <entry><type>cstring</></entry>
<entry>Indicates that a function accepts or returns a null-terminated C string.</entry> <entry>Indicates that a function accepts or returns a null-terminated C string.</entry>
...@@ -3813,7 +3823,7 @@ SELECT * FROM pg_attribute ...@@ -3813,7 +3823,7 @@ SELECT * FROM pg_attribute
only <type>void</> and <type>record</> as a result type (plus only <type>void</> and <type>record</> as a result type (plus
<type>trigger</> when the function is used as a trigger). Some also <type>trigger</> when the function is used as a trigger). Some also
support polymorphic functions using the types <type>anyarray</>, support polymorphic functions using the types <type>anyarray</>,
<type>anyelement</> and <type>anyenum</>. <type>anyelement</>, <type>anyenum</>, and <type>anynonarray</>.
</para> </para>
<para> <para>
......
<!-- $PostgreSQL: pgsql/doc/src/sgml/extend.sgml,v 1.34 2007/04/02 03:49:36 tgl Exp $ --> <!-- $PostgreSQL: pgsql/doc/src/sgml/extend.sgml,v 1.35 2007/06/06 23:00:35 tgl Exp $ -->
<chapter id="extend"> <chapter id="extend">
<title>Extending <acronym>SQL</acronym></title> <title>Extending <acronym>SQL</acronym></title>
...@@ -193,8 +193,8 @@ ...@@ -193,8 +193,8 @@
</indexterm> </indexterm>
<para> <para>
Three pseudo-types of special interest are <type>anyelement</>, Four pseudo-types of special interest are <type>anyelement</>,
<type>anyarray</>, and <type>anyenum</>, <type>anyarray</>, <type>anynonarray</>, and <type>anyenum</>,
which are collectively called <firstterm>polymorphic types</>. which are collectively called <firstterm>polymorphic types</>.
Any function declared using these types is said to be Any function declared using these types is said to be
a <firstterm>polymorphic function</>. A polymorphic function can a <firstterm>polymorphic function</>. A polymorphic function can
...@@ -216,6 +216,9 @@ ...@@ -216,6 +216,9 @@
<type>anyelement</type>, the actual array type in the <type>anyelement</type>, the actual array type in the
<type>anyarray</type> positions must be an array whose elements are <type>anyarray</type> positions must be an array whose elements are
the same type appearing in the <type>anyelement</type> positions. the same type appearing in the <type>anyelement</type> positions.
<type>anynonarray</> is treated exactly the same as <type>anyelement</>,
but adds the additional constraint that the actual type must not be
an array type.
<type>anyenum</> is treated exactly the same as <type>anyelement</>, <type>anyenum</> is treated exactly the same as <type>anyelement</>,
but adds the additional constraint that the actual type must but adds the additional constraint that the actual type must
be an enum type. be an enum type.
...@@ -242,6 +245,15 @@ ...@@ -242,6 +245,15 @@
is that a function declared as <literal>f(anyarray) returns anyenum</> is that a function declared as <literal>f(anyarray) returns anyenum</>
will only accept arrays of enum types. will only accept arrays of enum types.
</para> </para>
<para>
Note that <type>anynonarray</> and <type>anyenum</> do not represent
separate type variables; they are the same type as
<type>anyelement</type>, just with an additional constraint. For
example, declaring a function as <literal>f(anyelement, anyenum)</>
is equivalent to declaring it as <literal>f(anyenum, anyenum)</>:
both actual arguments have to be the same enum type.
</para>
</sect2> </sect2>
</sect1> </sect1>
......
<!-- $PostgreSQL: pgsql/doc/src/sgml/func.sgml,v 1.381 2007/05/30 18:13:29 momjian Exp $ --> <!-- $PostgreSQL: pgsql/doc/src/sgml/func.sgml,v 1.382 2007/06/06 23:00:35 tgl Exp $ -->
<chapter id="functions"> <chapter id="functions">
<title>Functions and Operators</title> <title>Functions and Operators</title>
...@@ -986,24 +986,36 @@ ...@@ -986,24 +986,36 @@
<para> <para>
This section describes functions and operators for examining and This section describes functions and operators for examining and
manipulating string values. Strings in this context include values manipulating string values. Strings in this context include values
of all the types <type>character</type>, <type>character of the types <type>character</type>, <type>character varying</type>,
varying</type>, and <type>text</type>. Unless otherwise noted, all and <type>text</type>. Unless otherwise noted, all
of the functions listed below work on all of these types, but be of the functions listed below work on all of these types, but be
wary of potential effects of the automatic padding when using the wary of potential effects of automatic space-padding when using the
<type>character</type> type. Generally, the functions described <type>character</type> type. Some functions also exist
here also work on data of non-string types by converting that data
to a string representation first. Some functions also exist
natively for the bit-string types. natively for the bit-string types.
</para> </para>
<para> <para>
<acronym>SQL</acronym> defines some string functions with a special syntax where <acronym>SQL</acronym> defines some string functions with a special syntax
certain key words rather than commas are used to separate the wherein certain key words rather than commas are used to separate the
arguments. Details are in <xref linkend="functions-string-sql">. arguments. Details are in <xref linkend="functions-string-sql">.
These functions are also implemented using the regular syntax for These functions are also implemented using the regular syntax for
function invocation. (See <xref linkend="functions-string-other">.) function invocation. (See <xref linkend="functions-string-other">.)
</para> </para>
<note>
<para>
Before <productname>PostgreSQL</productname> 8.3, these functions would
silently accept values of several non-string data types as well, due to
the presence of implicit coercions from those data types to
<type>text</>. Those coercions have been removed because they frequently
caused surprising behaviors. However, the string concatenation operator
(<literal>||</>) still accepts non-string input, so long as at least one
input is of a string type, as shown in <xref
linkend="functions-string-sql">. For other cases, insert an explicit
coercion to <type>text</> if you need to duplicate the previous behavior.
</para>
</note>
<indexterm> <indexterm>
<primary>bit_length</primary> <primary>bit_length</primary>
</indexterm> </indexterm>
...@@ -1064,6 +1076,22 @@ ...@@ -1064,6 +1076,22 @@
<entry><literal>PostgreSQL</literal></entry> <entry><literal>PostgreSQL</literal></entry>
</row> </row>
<row>
<entry>
<literal><parameter>string</parameter> <literal>||</literal>
<parameter>non-string</parameter></literal>
or
<literal><parameter>non-string</parameter> <literal>||</literal>
<parameter>string</parameter></literal>
</entry>
<entry> <type>text</type> </entry>
<entry>
String concatenation with one non-string input
</entry>
<entry><literal>'Value: ' || 42</literal></entry>
<entry><literal>Value: 42</literal></entry>
</row>
<row> <row>
<entry><literal><function>bit_length</function>(<parameter>string</parameter>)</literal></entry> <entry><literal><function>bit_length</function>(<parameter>string</parameter>)</literal></entry>
<entry><type>int</type></entry> <entry><type>int</type></entry>
......
<!-- $PostgreSQL: pgsql/doc/src/sgml/plpgsql.sgml,v 1.109 2007/04/29 01:21:08 neilc Exp $ --> <!-- $PostgreSQL: pgsql/doc/src/sgml/plpgsql.sgml,v 1.110 2007/06/06 23:00:36 tgl Exp $ -->
<chapter id="plpgsql"> <chapter id="plpgsql">
<title><application>PL/pgSQL</application> - <acronym>SQL</acronym> Procedural Language</title> <title><application>PL/pgSQL</application> - <acronym>SQL</acronym> Procedural Language</title>
...@@ -210,8 +210,8 @@ $$ LANGUAGE plpgsql; ...@@ -210,8 +210,8 @@ $$ LANGUAGE plpgsql;
<para> <para>
<application>PL/pgSQL</> functions can also be declared to accept <application>PL/pgSQL</> functions can also be declared to accept
and return the polymorphic types and return the polymorphic types
<type>anyelement</type>, <type>anyarray</type>, and <type>anyenum</>. <type>anyelement</type>, <type>anyarray</type>, <type>anynonarray</type>,
The actual and <type>anyenum</>. The actual
data types handled by a polymorphic function can vary from call to data types handled by a polymorphic function can vary from call to
call, as discussed in <xref linkend="extend-types-polymorphic">. call, as discussed in <xref linkend="extend-types-polymorphic">.
An example is shown in <xref linkend="plpgsql-declaration-aliases">. An example is shown in <xref linkend="plpgsql-declaration-aliases">.
...@@ -700,7 +700,7 @@ $$ LANGUAGE plpgsql; ...@@ -700,7 +700,7 @@ $$ LANGUAGE plpgsql;
<para> <para>
When the return type of a <application>PL/pgSQL</application> When the return type of a <application>PL/pgSQL</application>
function is declared as a polymorphic type (<type>anyelement</type>, function is declared as a polymorphic type (<type>anyelement</type>,
<type>anyarray</type>, or <type>anyenum</>), <type>anyarray</type>, <type>anynonarray</type>, or <type>anyenum</>),
a special parameter <literal>$0</literal> a special parameter <literal>$0</literal>
is created. Its data type is the actual return type of the function, is created. Its data type is the actual return type of the function,
as deduced from the actual input types (see <xref as deduced from the actual input types (see <xref
......
<!-- $PostgreSQL: pgsql/doc/src/sgml/xfunc.sgml,v 1.127 2007/04/02 03:49:37 tgl Exp $ --> <!-- $PostgreSQL: pgsql/doc/src/sgml/xfunc.sgml,v 1.128 2007/06/06 23:00:36 tgl Exp $ -->
<sect1 id="xfunc"> <sect1 id="xfunc">
<title>User-Defined Functions</title> <title>User-Defined Functions</title>
...@@ -718,7 +718,8 @@ SELECT name, listchildren(name) FROM nodes; ...@@ -718,7 +718,8 @@ SELECT name, listchildren(name) FROM nodes;
<para> <para>
<acronym>SQL</acronym> functions can be declared to accept and <acronym>SQL</acronym> functions can be declared to accept and
return the polymorphic types <type>anyelement</type>, return the polymorphic types <type>anyelement</type>,
<type>anyarray</type>, and <type>anyenum</type>. See <xref <type>anyarray</type>, <type>anynonarray</type>, and
<type>anyenum</type>. See <xref
linkend="extend-types-polymorphic"> for a more detailed linkend="extend-types-polymorphic"> for a more detailed
explanation of polymorphic functions. Here is a polymorphic explanation of polymorphic functions. Here is a polymorphic
function <function>make_array</function> that builds up an array function <function>make_array</function> that builds up an array
...@@ -2831,7 +2832,8 @@ CREATE OR REPLACE FUNCTION retcomposite(IN integer, IN integer, ...@@ -2831,7 +2832,8 @@ CREATE OR REPLACE FUNCTION retcomposite(IN integer, IN integer,
<para> <para>
C-language functions can be declared to accept and C-language functions can be declared to accept and
return the polymorphic types return the polymorphic types
<type>anyelement</type>, <type>anyarray</type>, and <type>anyenum</type>. <type>anyelement</type>, <type>anyarray</type>, <type>anynonarray</type>,
and <type>anyenum</type>.
See <xref linkend="extend-types-polymorphic"> for a more detailed explanation See <xref linkend="extend-types-polymorphic"> for a more detailed explanation
of polymorphic functions. When function arguments or return types of polymorphic functions. When function arguments or return types
are defined as polymorphic types, the function author cannot know are defined as polymorphic types, the function author cannot know
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/catalog/pg_proc.c,v 1.144 2007/04/02 03:49:37 tgl Exp $ * $PostgreSQL: pgsql/src/backend/catalog/pg_proc.c,v 1.145 2007/06/06 23:00:37 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -147,6 +147,7 @@ ProcedureCreate(const char *procedureName, ...@@ -147,6 +147,7 @@ ProcedureCreate(const char *procedureName,
{ {
case ANYARRAYOID: case ANYARRAYOID:
case ANYELEMENTOID: case ANYELEMENTOID:
case ANYNONARRAYOID:
case ANYENUMOID: case ANYENUMOID:
genericInParam = true; genericInParam = true;
break; break;
...@@ -170,6 +171,7 @@ ProcedureCreate(const char *procedureName, ...@@ -170,6 +171,7 @@ ProcedureCreate(const char *procedureName,
{ {
case ANYARRAYOID: case ANYARRAYOID:
case ANYELEMENTOID: case ANYELEMENTOID:
case ANYNONARRAYOID:
case ANYENUMOID: case ANYENUMOID:
genericOutParam = true; genericOutParam = true;
break; break;
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/executor/functions.c,v 1.116 2007/04/27 22:05:47 tgl Exp $ * $PostgreSQL: pgsql/src/backend/executor/functions.c,v 1.117 2007/06/06 23:00:37 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -849,9 +849,9 @@ ShutdownSQLFunction(Datum arg) ...@@ -849,9 +849,9 @@ ShutdownSQLFunction(Datum arg)
* to be sure that the user is returning the type he claims. * to be sure that the user is returning the type he claims.
* *
* For a polymorphic function the passed rettype must be the actual resolved * For a polymorphic function the passed rettype must be the actual resolved
* output type of the function; we should never see ANYARRAY, ANYENUM or * output type of the function; we should never see a polymorphic pseudotype
* ANYELEMENT as rettype. (This means we can't check the type during function * such as ANYELEMENT as rettype. (This means we can't check the type during
* definition of a polymorphic function.) * function definition of a polymorphic function.)
* *
* This function returns true if the sql function returns the entire tuple * This function returns true if the sql function returns the entire tuple
* result of its final SELECT, and false otherwise. Note that because we * result of its final SELECT, and false otherwise. Note that because we
...@@ -874,6 +874,8 @@ check_sql_fn_retval(Oid func_id, Oid rettype, List *queryTreeList, ...@@ -874,6 +874,8 @@ check_sql_fn_retval(Oid func_id, Oid rettype, List *queryTreeList,
char fn_typtype; char fn_typtype;
Oid restype; Oid restype;
AssertArg(!IsPolymorphicType(rettype));
if (junkFilter) if (junkFilter)
*junkFilter = NULL; /* default result */ *junkFilter = NULL; /* default result */
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/parser/parse_agg.c,v 1.77 2007/02/01 19:10:27 momjian Exp $ * $PostgreSQL: pgsql/src/backend/parser/parse_agg.c,v 1.78 2007/06/06 23:00:37 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -363,7 +363,7 @@ check_ungrouped_columns_walker(Node *node, ...@@ -363,7 +363,7 @@ check_ungrouped_columns_walker(Node *node,
* *
* agg_input_types, agg_state_type, agg_result_type identify the input, * agg_input_types, agg_state_type, agg_result_type identify the input,
* transition, and result types of the aggregate. These should all be * transition, and result types of the aggregate. These should all be
* resolved to actual types (ie, none should ever be ANYARRAY or ANYELEMENT). * resolved to actual types (ie, none should ever be ANYELEMENT etc).
* *
* transfn_oid and finalfn_oid identify the funcs to be called; the latter * transfn_oid and finalfn_oid identify the funcs to be called; the latter
* may be InvalidOid. * may be InvalidOid.
......
This diff is collapsed.
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/parser/parse_func.c,v 1.196 2007/06/05 21:31:06 tgl Exp $ * $PostgreSQL: pgsql/src/backend/parser/parse_func.c,v 1.197 2007/06/06 23:00:37 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -227,9 +227,9 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs, ...@@ -227,9 +227,9 @@ ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs,
} }
/* /*
* enforce consistency with ANYARRAY and ANYELEMENT argument and return * enforce consistency with polymorphic argument and return types,
* types, possibly adjusting return type or declared_arg_types (which will * possibly adjusting return type or declared_arg_types (which will be
* be used as the cast destination by make_fn_arguments) * used as the cast destination by make_fn_arguments)
*/ */
rettype = enforce_generic_type_consistency(actual_arg_types, rettype = enforce_generic_type_consistency(actual_arg_types,
declared_arg_types, declared_arg_types,
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/adt/pseudotypes.c,v 1.19 2007/04/02 03:49:39 tgl Exp $ * $PostgreSQL: pgsql/src/backend/utils/adt/pseudotypes.c,v 1.20 2007/06/06 23:00:39 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -347,6 +347,32 @@ anyelement_out(PG_FUNCTION_ARGS) ...@@ -347,6 +347,32 @@ anyelement_out(PG_FUNCTION_ARGS)
PG_RETURN_VOID(); /* keep compiler quiet */ PG_RETURN_VOID(); /* keep compiler quiet */
} }
/*
* anynonarray_in - input routine for pseudo-type ANYNONARRAY.
*/
Datum
anynonarray_in(PG_FUNCTION_ARGS)
{
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("cannot accept a value of type anynonarray")));
PG_RETURN_VOID(); /* keep compiler quiet */
}
/*
* anynonarray_out - output routine for pseudo-type ANYNONARRAY.
*/
Datum
anynonarray_out(PG_FUNCTION_ARGS)
{
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("cannot display a value of type anynonarray")));
PG_RETURN_VOID(); /* keep compiler quiet */
}
/* /*
* shell_in - input routine for "shell" types (those not yet filled in). * shell_in - input routine for "shell" types (those not yet filled in).
*/ */
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/backend/utils/adt/xml.c,v 1.43 2007/05/21 17:10:29 petere Exp $ * $PostgreSQL: pgsql/src/backend/utils/adt/xml.c,v 1.44 2007/06/06 23:00:39 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -1481,7 +1481,7 @@ map_sql_value_to_xml_value(Datum value, Oid type) ...@@ -1481,7 +1481,7 @@ map_sql_value_to_xml_value(Datum value, Oid type)
initStringInfo(&buf); initStringInfo(&buf);
if (is_array_type(type)) if (type_is_array(type))
{ {
int i; int i;
ArrayType *array; ArrayType *array;
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Copyright (c) 2002-2007, PostgreSQL Global Development Group * Copyright (c) 2002-2007, PostgreSQL Global Development Group
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/fmgr/funcapi.c,v 1.34 2007/04/02 03:49:39 tgl Exp $ * $PostgreSQL: pgsql/src/backend/utils/fmgr/funcapi.c,v 1.35 2007/06/06 23:00:39 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -193,8 +193,8 @@ shutdown_MultiFuncCall(Datum arg) ...@@ -193,8 +193,8 @@ shutdown_MultiFuncCall(Datum arg)
* only when we couldn't resolve the actual rowtype for lack of information. * only when we couldn't resolve the actual rowtype for lack of information.
* *
* The other hard case that this handles is resolution of polymorphism. * The other hard case that this handles is resolution of polymorphism.
* We will never return ANYELEMENT, ANYARRAY or ANYENUM, either as a scalar * We will never return polymorphic pseudotypes (ANYELEMENT etc), either
* result type or as a component of a rowtype. * as a scalar result type or as a component of a rowtype.
* *
* This function is relatively expensive --- in a function returning set, * This function is relatively expensive --- in a function returning set,
* try to call it only the first time through. * try to call it only the first time through.
...@@ -389,9 +389,9 @@ internal_get_result_type(Oid funcid, ...@@ -389,9 +389,9 @@ internal_get_result_type(Oid funcid,
/* /*
* Given the result tuple descriptor for a function with OUT parameters, * Given the result tuple descriptor for a function with OUT parameters,
* replace any polymorphic columns (ANYELEMENT/ANYARRAY/ANYENUM) with correct * replace any polymorphic columns (ANYELEMENT etc) with correct data types
* data types deduced from the input arguments. Returns TRUE if able to deduce * deduced from the input arguments. Returns TRUE if able to deduce all types,
* all types, FALSE if not. * FALSE if not.
*/ */
static bool static bool
resolve_polymorphic_tupdesc(TupleDesc tupdesc, oidvector *declared_args, resolve_polymorphic_tupdesc(TupleDesc tupdesc, oidvector *declared_args,
...@@ -401,6 +401,7 @@ resolve_polymorphic_tupdesc(TupleDesc tupdesc, oidvector *declared_args, ...@@ -401,6 +401,7 @@ resolve_polymorphic_tupdesc(TupleDesc tupdesc, oidvector *declared_args,
int nargs = declared_args->dim1; int nargs = declared_args->dim1;
bool have_anyelement_result = false; bool have_anyelement_result = false;
bool have_anyarray_result = false; bool have_anyarray_result = false;
bool have_anynonarray = false;
bool have_anyenum = false; bool have_anyenum = false;
Oid anyelement_type = InvalidOid; Oid anyelement_type = InvalidOid;
Oid anyarray_type = InvalidOid; Oid anyarray_type = InvalidOid;
...@@ -417,6 +418,10 @@ resolve_polymorphic_tupdesc(TupleDesc tupdesc, oidvector *declared_args, ...@@ -417,6 +418,10 @@ resolve_polymorphic_tupdesc(TupleDesc tupdesc, oidvector *declared_args,
case ANYARRAYOID: case ANYARRAYOID:
have_anyarray_result = true; have_anyarray_result = true;
break; break;
case ANYNONARRAYOID:
have_anyelement_result = true;
have_anynonarray = true;
break;
case ANYENUMOID: case ANYENUMOID:
have_anyelement_result = true; have_anyelement_result = true;
have_anyenum = true; have_anyenum = true;
...@@ -440,6 +445,7 @@ resolve_polymorphic_tupdesc(TupleDesc tupdesc, oidvector *declared_args, ...@@ -440,6 +445,7 @@ resolve_polymorphic_tupdesc(TupleDesc tupdesc, oidvector *declared_args,
switch (declared_args->values[i]) switch (declared_args->values[i])
{ {
case ANYELEMENTOID: case ANYELEMENTOID:
case ANYNONARRAYOID:
case ANYENUMOID: case ANYENUMOID:
if (!OidIsValid(anyelement_type)) if (!OidIsValid(anyelement_type))
anyelement_type = get_call_expr_argtype(call_expr, i); anyelement_type = get_call_expr_argtype(call_expr, i);
...@@ -467,7 +473,11 @@ resolve_polymorphic_tupdesc(TupleDesc tupdesc, oidvector *declared_args, ...@@ -467,7 +473,11 @@ resolve_polymorphic_tupdesc(TupleDesc tupdesc, oidvector *declared_args,
anyelement_type, anyelement_type,
ANYELEMENTOID); ANYELEMENTOID);
/* Check for enum if needed */ /* Enforce ANYNONARRAY if needed */
if (have_anynonarray && type_is_array(anyelement_type))
return false;
/* Enforce ANYENUM if needed */
if (have_anyenum && !type_is_enum(anyelement_type)) if (have_anyenum && !type_is_enum(anyelement_type))
return false; return false;
...@@ -477,6 +487,7 @@ resolve_polymorphic_tupdesc(TupleDesc tupdesc, oidvector *declared_args, ...@@ -477,6 +487,7 @@ resolve_polymorphic_tupdesc(TupleDesc tupdesc, oidvector *declared_args,
switch (tupdesc->attrs[i]->atttypid) switch (tupdesc->attrs[i]->atttypid)
{ {
case ANYELEMENTOID: case ANYELEMENTOID:
case ANYNONARRAYOID:
case ANYENUMOID: case ANYENUMOID:
TupleDescInitEntry(tupdesc, i + 1, TupleDescInitEntry(tupdesc, i + 1,
NameStr(tupdesc->attrs[i]->attname), NameStr(tupdesc->attrs[i]->attname),
...@@ -500,11 +511,11 @@ resolve_polymorphic_tupdesc(TupleDesc tupdesc, oidvector *declared_args, ...@@ -500,11 +511,11 @@ resolve_polymorphic_tupdesc(TupleDesc tupdesc, oidvector *declared_args,
} }
/* /*
* Given the declared argument types and modes for a function, * Given the declared argument types and modes for a function, replace any
* replace any polymorphic types (ANYELEMENT/ANYARRAY/ANYENUM) with correct * polymorphic types (ANYELEMENT etc) with correct data types deduced from the
* data types deduced from the input arguments. Returns TRUE if able to deduce * input arguments. Returns TRUE if able to deduce all types, FALSE if not.
* all types, FALSE if not. This is the same logic as * This is the same logic as resolve_polymorphic_tupdesc, but with a different
* resolve_polymorphic_tupdesc, but with a different argument representation. * argument representation.
* *
* argmodes may be NULL, in which case all arguments are assumed to be IN mode. * argmodes may be NULL, in which case all arguments are assumed to be IN mode.
*/ */
...@@ -528,6 +539,7 @@ resolve_polymorphic_argtypes(int numargs, Oid *argtypes, char *argmodes, ...@@ -528,6 +539,7 @@ resolve_polymorphic_argtypes(int numargs, Oid *argtypes, char *argmodes,
switch (argtypes[i]) switch (argtypes[i])
{ {
case ANYELEMENTOID: case ANYELEMENTOID:
case ANYNONARRAYOID:
case ANYENUMOID: case ANYENUMOID:
if (argmode == PROARGMODE_OUT) if (argmode == PROARGMODE_OUT)
have_anyelement_result = true; have_anyelement_result = true;
...@@ -583,7 +595,7 @@ resolve_polymorphic_argtypes(int numargs, Oid *argtypes, char *argmodes, ...@@ -583,7 +595,7 @@ resolve_polymorphic_argtypes(int numargs, Oid *argtypes, char *argmodes,
anyelement_type, anyelement_type,
ANYELEMENTOID); ANYELEMENTOID);
/* XXX do we need to enforce ANYENUM here? I think not */ /* XXX do we need to enforce ANYNONARRAY or ANYENUM here? I think not */
/* And finally replace the output column types as needed */ /* And finally replace the output column types as needed */
for (i = 0; i < numargs; i++) for (i = 0; i < numargs; i++)
...@@ -591,6 +603,7 @@ resolve_polymorphic_argtypes(int numargs, Oid *argtypes, char *argmodes, ...@@ -591,6 +603,7 @@ resolve_polymorphic_argtypes(int numargs, Oid *argtypes, char *argmodes,
switch (argtypes[i]) switch (argtypes[i])
{ {
case ANYELEMENTOID: case ANYELEMENTOID:
case ANYNONARRAYOID:
case ANYENUMOID: case ANYENUMOID:
argtypes[i] = anyelement_type; argtypes[i] = anyelement_type;
break; break;
......
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.410 2007/06/05 21:31:07 tgl Exp $ * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.411 2007/06/06 23:00:40 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -53,6 +53,6 @@ ...@@ -53,6 +53,6 @@
*/ */
/* yyyymmddN */ /* yyyymmddN */
#define CATALOG_VERSION_NO 200706051 #define CATALOG_VERSION_NO 200706061
#endif #endif
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/catalog/pg_operator.h,v 1.152 2007/05/08 18:56:47 neilc Exp $ * $PostgreSQL: pgsql/src/include/catalog/pg_operator.h,v 1.153 2007/06/06 23:00:41 tgl Exp $
* *
* NOTES * NOTES
* the genbki.sh script reads this file and generates .bki * the genbki.sh script reads this file and generates .bki
...@@ -701,7 +701,7 @@ DATA(insert OID = 1793 ( "#" PGNSP PGUID b f f 1560 1560 1560 1793 0 bitxor ...@@ -701,7 +701,7 @@ DATA(insert OID = 1793 ( "#" PGNSP PGUID b f f 1560 1560 1560 1793 0 bitxor
DATA(insert OID = 1794 ( "~" PGNSP PGUID l f f 0 1560 1560 0 0 bitnot - - )); DATA(insert OID = 1794 ( "~" PGNSP PGUID l f f 0 1560 1560 0 0 bitnot - - ));
DATA(insert OID = 1795 ( "<<" PGNSP PGUID b f f 1560 23 1560 0 0 bitshiftleft - - )); DATA(insert OID = 1795 ( "<<" PGNSP PGUID b f f 1560 23 1560 0 0 bitshiftleft - - ));
DATA(insert OID = 1796 ( ">>" PGNSP PGUID b f f 1560 23 1560 0 0 bitshiftright - - )); DATA(insert OID = 1796 ( ">>" PGNSP PGUID b f f 1560 23 1560 0 0 bitshiftright - - ));
DATA(insert OID = 1797 ( "||" PGNSP PGUID b f f 1560 1560 1560 0 0 bitcat - - )); DATA(insert OID = 1797 ( "||" PGNSP PGUID b f f 1562 1562 1562 0 0 bitcat - - ));
DATA(insert OID = 1800 ( "+" PGNSP PGUID b f f 1083 1186 1083 1849 0 time_pl_interval - - )); DATA(insert OID = 1800 ( "+" PGNSP PGUID b f f 1083 1186 1083 1849 0 time_pl_interval - - ));
DATA(insert OID = 1801 ( "-" PGNSP PGUID b f f 1083 1186 1083 0 0 time_mi_interval - - )); DATA(insert OID = 1801 ( "-" PGNSP PGUID b f f 1083 1186 1083 0 0 time_mi_interval - - ));
...@@ -875,6 +875,10 @@ DATA(insert OID = 2750 ( "&&" PGNSP PGUID b f f 2277 2277 16 2750 0 arrayov ...@@ -875,6 +875,10 @@ DATA(insert OID = 2750 ( "&&" PGNSP PGUID b f f 2277 2277 16 2750 0 arrayov
DATA(insert OID = 2751 ( "@>" PGNSP PGUID b f f 2277 2277 16 2752 0 arraycontains contsel contjoinsel )); DATA(insert OID = 2751 ( "@>" PGNSP PGUID b f f 2277 2277 16 2752 0 arraycontains contsel contjoinsel ));
DATA(insert OID = 2752 ( "<@" PGNSP PGUID b f f 2277 2277 16 2751 0 arraycontained contsel contjoinsel )); DATA(insert OID = 2752 ( "<@" PGNSP PGUID b f f 2277 2277 16 2751 0 arraycontained contsel contjoinsel ));
/* capturing operators to preserve pre-8.3 behavior of text concatenation */
DATA(insert OID = 2779 ( "||" PGNSP PGUID b f f 25 2776 25 0 0 textanycat - - ));
DATA(insert OID = 2780 ( "||" PGNSP PGUID b f f 2776 25 25 0 0 anytextcat - - ));
/* obsolete names for contains/contained-by operators; remove these someday */ /* obsolete names for contains/contained-by operators; remove these someday */
DATA(insert OID = 2860 ( "@" PGNSP PGUID b f f 604 604 16 2861 0 poly_contained contsel contjoinsel )); DATA(insert OID = 2860 ( "@" PGNSP PGUID b f f 604 604 16 2861 0 poly_contained contsel contjoinsel ));
DATA(insert OID = 2861 ( "~" PGNSP PGUID b f f 604 604 16 2860 0 poly_contain contsel contjoinsel )); DATA(insert OID = 2861 ( "~" PGNSP PGUID b f f 604 604 16 2860 0 poly_contain contsel contjoinsel ));
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.458 2007/06/05 21:31:07 tgl Exp $ * $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.459 2007/06/06 23:00:41 tgl Exp $
* *
* NOTES * NOTES
* The script catalog/genbki.sh reads this file and generates .bki * The script catalog/genbki.sh reads this file and generates .bki
...@@ -1425,7 +1425,7 @@ DATA(insert OID = 1156 ( timestamptz_ge PGNSP PGUID 12 1 0 f f t f i 2 16 "11 ...@@ -1425,7 +1425,7 @@ DATA(insert OID = 1156 ( timestamptz_ge PGNSP PGUID 12 1 0 f f t f i 2 16 "11
DESCR("greater-than-or-equal"); DESCR("greater-than-or-equal");
DATA(insert OID = 1157 ( timestamptz_gt PGNSP PGUID 12 1 0 f f t f i 2 16 "1184 1184" _null_ _null_ _null_ timestamp_gt - _null_ )); DATA(insert OID = 1157 ( timestamptz_gt PGNSP PGUID 12 1 0 f f t f i 2 16 "1184 1184" _null_ _null_ _null_ timestamp_gt - _null_ ));
DESCR("greater-than"); DESCR("greater-than");
DATA(insert OID = 1158 ( to_timestamp PGNSP PGUID 14 1 0 f f t f i 1 1184 "701" _null_ _null_ _null_ "select (''epoch''::timestamptz + $1 * ''1 second''::interval)" - _null_ )); DATA(insert OID = 1158 ( to_timestamp PGNSP PGUID 14 1 0 f f t f i 1 1184 "701" _null_ _null_ _null_ "select (''epoch''::pg_catalog.timestamptz + $1 * ''1 second''::pg_catalog.interval)" - _null_ ));
DESCR("convert UNIX epoch to timestamptz"); DESCR("convert UNIX epoch to timestamptz");
DATA(insert OID = 1159 ( timezone PGNSP PGUID 12 1 0 f f t f i 2 1114 "25 1184" _null_ _null_ _null_ timestamptz_zone - _null_ )); DATA(insert OID = 1159 ( timezone PGNSP PGUID 12 1 0 f f t f i 2 1114 "25 1184" _null_ _null_ _null_ timestamptz_zone - _null_ ));
DESCR("adjust timestamp to new time zone"); DESCR("adjust timestamp to new time zone");
...@@ -1509,7 +1509,7 @@ DESCR("adjust interval precision"); ...@@ -1509,7 +1509,7 @@ DESCR("adjust interval precision");
DATA(insert OID = 1215 ( obj_description PGNSP PGUID 14 100 0 f f t f s 2 25 "26 19" _null_ _null_ _null_ "select description from pg_catalog.pg_description where objoid = $1 and classoid = (select oid from pg_catalog.pg_class where relname = $2 and relnamespace = PGNSP) and objsubid = 0" - _null_ )); DATA(insert OID = 1215 ( obj_description PGNSP PGUID 14 100 0 f f t f s 2 25 "26 19" _null_ _null_ _null_ "select description from pg_catalog.pg_description where objoid = $1 and classoid = (select oid from pg_catalog.pg_class where relname = $2 and relnamespace = PGNSP) and objsubid = 0" - _null_ ));
DESCR("get description for object id and catalog name"); DESCR("get description for object id and catalog name");
DATA(insert OID = 1216 ( col_description PGNSP PGUID 14 100 0 f f t f s 2 25 "26 23" _null_ _null_ _null_ "select description from pg_catalog.pg_description where objoid = $1 and classoid = ''pg_catalog.pg_class''::regclass and objsubid = $2" - _null_ )); DATA(insert OID = 1216 ( col_description PGNSP PGUID 14 100 0 f f t f s 2 25 "26 23" _null_ _null_ _null_ "select description from pg_catalog.pg_description where objoid = $1 and classoid = ''pg_catalog.pg_class''::pg_catalog.regclass and objsubid = $2" - _null_ ));
DESCR("get description for table column"); DESCR("get description for table column");
DATA(insert OID = 1993 ( shobj_description PGNSP PGUID 14 100 0 f f t f s 2 25 "26 19" _null_ _null_ _null_ "select description from pg_catalog.pg_shdescription where objoid = $1 and classoid = (select oid from pg_catalog.pg_class where relname = $2 and relnamespace = PGNSP)" - _null_ )); DATA(insert OID = 1993 ( shobj_description PGNSP PGUID 14 100 0 f f t f s 2 25 "26 19" _null_ _null_ _null_ "select description from pg_catalog.pg_shdescription where objoid = $1 and classoid = (select oid from pg_catalog.pg_class where relname = $2 and relnamespace = PGNSP)" - _null_ ));
DESCR("get description for object id and shared catalog name"); DESCR("get description for object id and shared catalog name");
...@@ -1722,7 +1722,7 @@ DESCR("less-equal-greater"); ...@@ -1722,7 +1722,7 @@ DESCR("less-equal-greater");
DATA(insert OID = 1359 ( timestamptz PGNSP PGUID 12 1 0 f f t f i 2 1184 "1082 1266" _null_ _null_ _null_ datetimetz_timestamptz - _null_ )); DATA(insert OID = 1359 ( timestamptz PGNSP PGUID 12 1 0 f f t f i 2 1184 "1082 1266" _null_ _null_ _null_ datetimetz_timestamptz - _null_ ));
DESCR("convert date and time with time zone to timestamp with time zone"); DESCR("convert date and time with time zone to timestamp with time zone");
DATA(insert OID = 1364 ( time PGNSP PGUID 14 1 0 f f t f s 1 1083 "702" _null_ _null_ _null_ "select cast(cast($1 as timestamp without time zone) as time)" - _null_ )); DATA(insert OID = 1364 ( time PGNSP PGUID 14 1 0 f f t f s 1 1083 "702" _null_ _null_ _null_ "select cast(cast($1 as timestamp without time zone) as pg_catalog.time)" - _null_ ));
DESCR("convert abstime to time"); DESCR("convert abstime to time");
DATA(insert OID = 1367 ( character_length PGNSP PGUID 12 1 0 f f t f i 1 23 "1042" _null_ _null_ _null_ bpcharlen - _null_ )); DATA(insert OID = 1367 ( character_length PGNSP PGUID 12 1 0 f f t f i 1 23 "1042" _null_ _null_ _null_ bpcharlen - _null_ ));
...@@ -2328,7 +2328,7 @@ DATA(insert OID = 1677 ( bitshiftleft PGNSP PGUID 12 1 0 f f t f i 2 1560 "156 ...@@ -2328,7 +2328,7 @@ DATA(insert OID = 1677 ( bitshiftleft PGNSP PGUID 12 1 0 f f t f i 2 1560 "156
DESCR("bitwise left shift"); DESCR("bitwise left shift");
DATA(insert OID = 1678 ( bitshiftright PGNSP PGUID 12 1 0 f f t f i 2 1560 "1560 23" _null_ _null_ _null_ bitshiftright - _null_ )); DATA(insert OID = 1678 ( bitshiftright PGNSP PGUID 12 1 0 f f t f i 2 1560 "1560 23" _null_ _null_ _null_ bitshiftright - _null_ ));
DESCR("bitwise right shift"); DESCR("bitwise right shift");
DATA(insert OID = 1679 ( bitcat PGNSP PGUID 12 1 0 f f t f i 2 1560 "1560 1560" _null_ _null_ _null_ bitcat - _null_ )); DATA(insert OID = 1679 ( bitcat PGNSP PGUID 12 1 0 f f t f i 2 1562 "1562 1562" _null_ _null_ _null_ bitcat - _null_ ));
DESCR("bitwise concatenation"); DESCR("bitwise concatenation");
DATA(insert OID = 1680 ( substring PGNSP PGUID 12 1 0 f f t f i 3 1560 "1560 23 23" _null_ _null_ _null_ bitsubstr - _null_ )); DATA(insert OID = 1680 ( substring PGNSP PGUID 12 1 0 f f t f i 3 1560 "1560 23 23" _null_ _null_ _null_ bitsubstr - _null_ ));
DESCR("return portion of bitstring"); DESCR("return portion of bitstring");
...@@ -2981,6 +2981,11 @@ DESCR("adjust time precision"); ...@@ -2981,6 +2981,11 @@ DESCR("adjust time precision");
DATA(insert OID = 1969 ( timetz PGNSP PGUID 12 1 0 f f t f i 2 1266 "1266 23" _null_ _null_ _null_ timetz_scale - _null_ )); DATA(insert OID = 1969 ( timetz PGNSP PGUID 12 1 0 f f t f i 2 1266 "1266 23" _null_ _null_ _null_ timetz_scale - _null_ ));
DESCR("adjust time with time zone precision"); DESCR("adjust time with time zone precision");
DATA(insert OID = 2003 ( textanycat PGNSP PGUID 14 1 0 f f t f i 2 25 "25 2776" _null_ _null_ _null_ "select $1 || $2::pg_catalog.text" - _null_ ));
DESCR("concatenate");
DATA(insert OID = 2004 ( anytextcat PGNSP PGUID 14 1 0 f f t f i 2 25 "2776 25" _null_ _null_ _null_ "select $1::pg_catalog.text || $2" - _null_ ));
DESCR("concatenate");
DATA(insert OID = 2005 ( bytealike PGNSP PGUID 12 1 0 f f t f i 2 16 "17 17" _null_ _null_ _null_ bytealike - _null_ )); DATA(insert OID = 2005 ( bytealike PGNSP PGUID 12 1 0 f f t f i 2 16 "17 17" _null_ _null_ _null_ bytealike - _null_ ));
DESCR("matches LIKE expression"); DESCR("matches LIKE expression");
DATA(insert OID = 2006 ( byteanlike PGNSP PGUID 12 1 0 f f t f i 2 16 "17 17" _null_ _null_ _null_ byteanlike - _null_ )); DATA(insert OID = 2006 ( byteanlike PGNSP PGUID 12 1 0 f f t f i 2 16 "17 17" _null_ _null_ _null_ byteanlike - _null_ ));
...@@ -3489,6 +3494,10 @@ DATA(insert OID = 2597 ( domain_in PGNSP PGUID 12 1 0 f f f f v 3 2276 "2275 ...@@ -3489,6 +3494,10 @@ DATA(insert OID = 2597 ( domain_in PGNSP PGUID 12 1 0 f f f f v 3 2276 "2275
DESCR("I/O"); DESCR("I/O");
DATA(insert OID = 2598 ( domain_recv PGNSP PGUID 12 1 0 f f f f v 3 2276 "2281 26 23" _null_ _null_ _null_ domain_recv - _null_ )); DATA(insert OID = 2598 ( domain_recv PGNSP PGUID 12 1 0 f f f f v 3 2276 "2281 26 23" _null_ _null_ _null_ domain_recv - _null_ ));
DESCR("I/O"); DESCR("I/O");
DATA(insert OID = 2777 ( anynonarray_in PGNSP PGUID 12 1 0 f f t f i 1 2776 "2275" _null_ _null_ _null_ anynonarray_in - _null_ ));
DESCR("I/O");
DATA(insert OID = 2778 ( anynonarray_out PGNSP PGUID 12 1 0 f f t f i 1 2275 "2776" _null_ _null_ _null_ anynonarray_out - _null_ ));
DESCR("I/O");
/* cryptographic */ /* cryptographic */
DATA(insert OID = 2311 ( md5 PGNSP PGUID 12 1 0 f f t f i 1 25 "25" _null_ _null_ _null_ md5_text - _null_ )); DATA(insert OID = 2311 ( md5 PGNSP PGUID 12 1 0 f f t f i 1 25 "25" _null_ _null_ _null_ md5_text - _null_ ));
...@@ -4054,7 +4063,7 @@ DESCR("map database contents and structure to XML and XML Schema"); ...@@ -4054,7 +4063,7 @@ DESCR("map database contents and structure to XML and XML Schema");
DATA(insert OID = 2931 ( xpath PGNSP PGUID 12 1 0 f f t f i 3 143 "25 142 1009" _null_ _null_ _null_ xpath - _null_ )); DATA(insert OID = 2931 ( xpath PGNSP PGUID 12 1 0 f f t f i 3 143 "25 142 1009" _null_ _null_ _null_ xpath - _null_ ));
DESCR("evaluate XPath expression, with namespaces support"); DESCR("evaluate XPath expression, with namespaces support");
DATA(insert OID = 2932 ( xpath PGNSP PGUID 14 1 0 f f t f i 2 143 "25 142" _null_ _null_ _null_ "select pg_catalog.xpath($1, $2, ''{}''::_text)" - _null_ )); DATA(insert OID = 2932 ( xpath PGNSP PGUID 14 1 0 f f t f i 2 143 "25 142" _null_ _null_ _null_ "select pg_catalog.xpath($1, $2, ''{}''::pg_catalog.text[])" - _null_ ));
DESCR("evaluate XPath expression"); DESCR("evaluate XPath expression");
/* uuid */ /* uuid */
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/catalog/pg_type.h,v 1.184 2007/05/12 00:54:59 tgl Exp $ * $PostgreSQL: pgsql/src/include/catalog/pg_type.h,v 1.185 2007/06/06 23:00:43 tgl Exp $
* *
* NOTES * NOTES
* the genbki.sh script reads this file and generates .bki * the genbki.sh script reads this file and generates .bki
...@@ -575,6 +575,8 @@ DATA(insert OID = 2282 ( opaque PGNSP PGUID 4 t p t \054 0 0 0 opaque_in opaq ...@@ -575,6 +575,8 @@ DATA(insert OID = 2282 ( opaque PGNSP PGUID 4 t p t \054 0 0 0 opaque_in opaq
#define OPAQUEOID 2282 #define OPAQUEOID 2282
DATA(insert OID = 2283 ( anyelement PGNSP PGUID 4 t p t \054 0 0 0 anyelement_in anyelement_out - - - - - i p f 0 -1 0 _null_ _null_ )); DATA(insert OID = 2283 ( anyelement PGNSP PGUID 4 t p t \054 0 0 0 anyelement_in anyelement_out - - - - - i p f 0 -1 0 _null_ _null_ ));
#define ANYELEMENTOID 2283 #define ANYELEMENTOID 2283
DATA(insert OID = 2776 ( anynonarray PGNSP PGUID 4 t p t \054 0 0 0 anynonarray_in anynonarray_out - - - - - i p f 0 -1 0 _null_ _null_ ));
#define ANYNONARRAYOID 2776
DATA(insert OID = 3500 ( anyenum PGNSP PGUID 4 t p t \054 0 0 0 anyenum_in anyenum_out - - - - - i p f 0 -1 0 _null_ _null_ )); DATA(insert OID = 3500 ( anyenum PGNSP PGUID 4 t p t \054 0 0 0 anyenum_in anyenum_out - - - - - i p f 0 -1 0 _null_ _null_ ));
#define ANYENUMOID 3500 #define ANYENUMOID 3500
...@@ -592,6 +594,7 @@ DATA(insert OID = 3500 ( anyenum PGNSP PGUID 4 t p t \054 0 0 0 anyenum_in any ...@@ -592,6 +594,7 @@ DATA(insert OID = 3500 ( anyenum PGNSP PGUID 4 t p t \054 0 0 0 anyenum_in any
#define IsPolymorphicType(typid) \ #define IsPolymorphicType(typid) \
((typid) == ANYELEMENTOID || \ ((typid) == ANYELEMENTOID || \
(typid) == ANYARRAYOID || \ (typid) == ANYARRAYOID || \
(typid) == ANYNONARRAYOID || \
(typid) == ANYENUMOID) (typid) == ANYENUMOID)
/* /*
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/utils/builtins.h,v 1.295 2007/06/05 21:31:08 tgl Exp $ * $PostgreSQL: pgsql/src/include/utils/builtins.h,v 1.296 2007/06/06 23:00:46 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -458,6 +458,8 @@ extern Datum anyarray_in(PG_FUNCTION_ARGS); ...@@ -458,6 +458,8 @@ extern Datum anyarray_in(PG_FUNCTION_ARGS);
extern Datum anyarray_out(PG_FUNCTION_ARGS); extern Datum anyarray_out(PG_FUNCTION_ARGS);
extern Datum anyarray_recv(PG_FUNCTION_ARGS); extern Datum anyarray_recv(PG_FUNCTION_ARGS);
extern Datum anyarray_send(PG_FUNCTION_ARGS); extern Datum anyarray_send(PG_FUNCTION_ARGS);
extern Datum anynonarray_in(PG_FUNCTION_ARGS);
extern Datum anynonarray_out(PG_FUNCTION_ARGS);
extern Datum anyenum_in(PG_FUNCTION_ARGS); extern Datum anyenum_in(PG_FUNCTION_ARGS);
extern Datum anyenum_out(PG_FUNCTION_ARGS); extern Datum anyenum_out(PG_FUNCTION_ARGS);
extern Datum void_in(PG_FUNCTION_ARGS); extern Datum void_in(PG_FUNCTION_ARGS);
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/utils/lsyscache.h,v 1.118 2007/04/02 03:49:41 tgl Exp $ * $PostgreSQL: pgsql/src/include/utils/lsyscache.h,v 1.119 2007/06/06 23:00:47 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -130,7 +130,7 @@ extern char *get_namespace_name(Oid nspid); ...@@ -130,7 +130,7 @@ extern char *get_namespace_name(Oid nspid);
extern Oid get_roleid(const char *rolname); extern Oid get_roleid(const char *rolname);
extern Oid get_roleid_checked(const char *rolname); extern Oid get_roleid_checked(const char *rolname);
#define is_array_type(typid) (get_element_type(typid) != InvalidOid) #define type_is_array(typid) (get_element_type(typid) != InvalidOid)
#define TypeIsToastable(typid) (get_typstorage(typid) != 'p') #define TypeIsToastable(typid) (get_typstorage(typid) != 'p')
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_comp.c,v 1.114 2007/04/02 03:49:41 tgl Exp $ * $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_comp.c,v 1.115 2007/06/06 23:00:48 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -480,7 +480,7 @@ do_compile(FunctionCallInfo fcinfo, ...@@ -480,7 +480,7 @@ do_compile(FunctionCallInfo fcinfo,
{ {
if (rettypeid == ANYARRAYOID) if (rettypeid == ANYARRAYOID)
rettypeid = INT4ARRAYOID; rettypeid = INT4ARRAYOID;
else else /* ANYELEMENT or ANYNONARRAY */
rettypeid = INT4OID; rettypeid = INT4OID;
/* XXX what could we use for ANYENUM? */ /* XXX what could we use for ANYENUM? */
} }
...@@ -2027,6 +2027,7 @@ plpgsql_resolve_polymorphic_argtypes(int numargs, ...@@ -2027,6 +2027,7 @@ plpgsql_resolve_polymorphic_argtypes(int numargs,
switch (argtypes[i]) switch (argtypes[i])
{ {
case ANYELEMENTOID: case ANYELEMENTOID:
case ANYNONARRAYOID:
case ANYENUMOID: /* XXX dubious */ case ANYENUMOID: /* XXX dubious */
argtypes[i] = INT4OID; argtypes[i] = INT4OID;
break; break;
......
...@@ -23,3 +23,31 @@ SELECT '' AS two, * FROM TEXT_TBL; ...@@ -23,3 +23,31 @@ SELECT '' AS two, * FROM TEXT_TBL;
| hi de ho neighbor | hi de ho neighbor
(2 rows) (2 rows)
-- As of 8.3 we have removed most implicit casts to text, so that for example
-- this no longer works:
select length(42);
ERROR: function length(integer) does not exist
LINE 1: select length(42);
^
HINT: No function matches the given name and argument types. You might need to add explicit type casts.
-- But as a special exception for usability's sake, we still allow implicit
-- casting to text in concatenations, so long as the other input is text or
-- an unknown literal. So these work:
select 'four: '::text || 2+2;
?column?
----------
four: 4
(1 row)
select 'four: ' || 2+2;
?column?
----------
four: 4
(1 row)
-- but not this:
select 3 || 4.0;
ERROR: operator does not exist: integer || numeric
LINE 1: select 3 || 4.0;
^
HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts.
...@@ -13,3 +13,18 @@ INSERT INTO TEXT_TBL VALUES ('hi de ho neighbor'); ...@@ -13,3 +13,18 @@ INSERT INTO TEXT_TBL VALUES ('hi de ho neighbor');
SELECT '' AS two, * FROM TEXT_TBL; SELECT '' AS two, * FROM TEXT_TBL;
-- As of 8.3 we have removed most implicit casts to text, so that for example
-- this no longer works:
select length(42);
-- But as a special exception for usability's sake, we still allow implicit
-- casting to text in concatenations, so long as the other input is text or
-- an unknown literal. So these work:
select 'four: '::text || 2+2;
select 'four: ' || 2+2;
-- but not this:
select 3 || 4.0;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment