aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/src/sgml/datatype.sgml16
-rw-r--r--doc/src/sgml/extend.sgml18
-rw-r--r--doc/src/sgml/func.sgml46
-rw-r--r--doc/src/sgml/plpgsql.sgml8
-rw-r--r--doc/src/sgml/xfunc.sgml8
-rw-r--r--src/backend/catalog/pg_proc.c4
-rw-r--r--src/backend/executor/functions.c10
-rw-r--r--src/backend/parser/parse_agg.c4
-rw-r--r--src/backend/parser/parse_coerce.c123
-rw-r--r--src/backend/parser/parse_func.c8
-rw-r--r--src/backend/utils/adt/pseudotypes.c28
-rw-r--r--src/backend/utils/adt/xml.c4
-rw-r--r--src/backend/utils/fmgr/funcapi.c39
-rw-r--r--src/include/catalog/catversion.h4
-rw-r--r--src/include/catalog/pg_operator.h8
-rw-r--r--src/include/catalog/pg_proc.h21
-rw-r--r--src/include/catalog/pg_type.h5
-rw-r--r--src/include/utils/builtins.h4
-rw-r--r--src/include/utils/lsyscache.h4
-rw-r--r--src/pl/plpgsql/src/pl_comp.c5
-rw-r--r--src/test/regress/expected/text.out28
-rw-r--r--src/test/regress/sql/text.sql15
22 files changed, 301 insertions, 109 deletions
diff --git a/doc/src/sgml/datatype.sgml b/doc/src/sgml/datatype.sgml
index 3802aa24dff..c64b040e457 100644
--- a/doc/src/sgml/datatype.sgml
+++ b/doc/src/sgml/datatype.sgml
@@ -1,4 +1,4 @@
-<!-- $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">
<title id="datatype-title">Data Types</title>
@@ -3677,11 +3677,15 @@ SELECT * FROM pg_attribute
</indexterm>
<indexterm zone="datatype-pseudo">
+ <primary>anyelement</primary>
+ </indexterm>
+
+ <indexterm zone="datatype-pseudo">
<primary>anyarray</primary>
</indexterm>
<indexterm zone="datatype-pseudo">
- <primary>anyelement</primary>
+ <primary>anynonarray</primary>
</indexterm>
<indexterm zone="datatype-pseudo">
@@ -3761,6 +3765,12 @@ SELECT * FROM pg_attribute
</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>
<entry><type>cstring</></entry>
<entry>Indicates that a function accepts or returns a null-terminated C string.</entry>
</row>
@@ -3813,7 +3823,7 @@ SELECT * FROM pg_attribute
only <type>void</> and <type>record</> as a result type (plus
<type>trigger</> when the function is used as a trigger). Some also
support polymorphic functions using the types <type>anyarray</>,
- <type>anyelement</> and <type>anyenum</>.
+ <type>anyelement</>, <type>anyenum</>, and <type>anynonarray</>.
</para>
<para>
diff --git a/doc/src/sgml/extend.sgml b/doc/src/sgml/extend.sgml
index bb5834e74a9..28bdfb85322 100644
--- a/doc/src/sgml/extend.sgml
+++ b/doc/src/sgml/extend.sgml
@@ -1,4 +1,4 @@
-<!-- $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">
<title>Extending <acronym>SQL</acronym></title>
@@ -193,8 +193,8 @@
</indexterm>
<para>
- Three pseudo-types of special interest are <type>anyelement</>,
- <type>anyarray</>, and <type>anyenum</>,
+ Four pseudo-types of special interest are <type>anyelement</>,
+ <type>anyarray</>, <type>anynonarray</>, and <type>anyenum</>,
which are collectively called <firstterm>polymorphic types</>.
Any function declared using these types is said to be
a <firstterm>polymorphic function</>. A polymorphic function can
@@ -216,6 +216,9 @@
<type>anyelement</type>, the actual array type in the
<type>anyarray</type> positions must be an array whose elements are
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</>,
but adds the additional constraint that the actual type must
be an enum type.
@@ -242,6 +245,15 @@
is that a function declared as <literal>f(anyarray) returns anyenum</>
will only accept arrays of enum types.
</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>
</sect1>
diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml
index c2f3371dc48..387c4e81c8f 100644
--- a/doc/src/sgml/func.sgml
+++ b/doc/src/sgml/func.sgml
@@ -1,4 +1,4 @@
-<!-- $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">
<title>Functions and Operators</title>
@@ -986,24 +986,36 @@
<para>
This section describes functions and operators for examining and
manipulating string values. Strings in this context include values
- of all the types <type>character</type>, <type>character
- varying</type>, and <type>text</type>. Unless otherwise noted, all
+ of the types <type>character</type>, <type>character varying</type>,
+ and <type>text</type>. Unless otherwise noted, all
of the functions listed below work on all of these types, but be
- wary of potential effects of the automatic padding when using the
- <type>character</type> type. Generally, the functions described
- here also work on data of non-string types by converting that data
- to a string representation first. Some functions also exist
+ wary of potential effects of automatic space-padding when using the
+ <type>character</type> type. Some functions also exist
natively for the bit-string types.
</para>
<para>
- <acronym>SQL</acronym> defines some string functions with a special syntax where
- certain key words rather than commas are used to separate the
+ <acronym>SQL</acronym> defines some string functions with a special syntax
+ wherein certain key words rather than commas are used to separate the
arguments. Details are in <xref linkend="functions-string-sql">.
These functions are also implemented using the regular syntax for
function invocation. (See <xref linkend="functions-string-other">.)
</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>
<primary>bit_length</primary>
</indexterm>
@@ -1065,6 +1077,22 @@
</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>
<entry><literal><function>bit_length</function>(<parameter>string</parameter>)</literal></entry>
<entry><type>int</type></entry>
<entry>Number of bits in string</entry>
diff --git a/doc/src/sgml/plpgsql.sgml b/doc/src/sgml/plpgsql.sgml
index c1f57ddf4f8..d14519b6133 100644
--- a/doc/src/sgml/plpgsql.sgml
+++ b/doc/src/sgml/plpgsql.sgml
@@ -1,4 +1,4 @@
-<!-- $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">
<title><application>PL/pgSQL</application> - <acronym>SQL</acronym> Procedural Language</title>
@@ -210,8 +210,8 @@ $$ LANGUAGE plpgsql;
<para>
<application>PL/pgSQL</> functions can also be declared to accept
and return the polymorphic types
- <type>anyelement</type>, <type>anyarray</type>, and <type>anyenum</>.
- The actual
+ <type>anyelement</type>, <type>anyarray</type>, <type>anynonarray</type>,
+ and <type>anyenum</>. The actual
data types handled by a polymorphic function can vary from call to
call, as discussed in <xref linkend="extend-types-polymorphic">.
An example is shown in <xref linkend="plpgsql-declaration-aliases">.
@@ -700,7 +700,7 @@ $$ LANGUAGE plpgsql;
<para>
When the return type of a <application>PL/pgSQL</application>
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>
is created. Its data type is the actual return type of the function,
as deduced from the actual input types (see <xref
diff --git a/doc/src/sgml/xfunc.sgml b/doc/src/sgml/xfunc.sgml
index 553b33e1732..de7eed5a6db 100644
--- a/doc/src/sgml/xfunc.sgml
+++ b/doc/src/sgml/xfunc.sgml
@@ -1,4 +1,4 @@
-<!-- $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">
<title>User-Defined Functions</title>
@@ -718,7 +718,8 @@ SELECT name, listchildren(name) FROM nodes;
<para>
<acronym>SQL</acronym> functions can be declared to accept and
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
explanation of polymorphic functions. Here is a polymorphic
function <function>make_array</function> that builds up an array
@@ -2831,7 +2832,8 @@ CREATE OR REPLACE FUNCTION retcomposite(IN integer, IN integer,
<para>
C-language functions can be declared to accept and
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
of polymorphic functions. When function arguments or return types
are defined as polymorphic types, the function author cannot know
diff --git a/src/backend/catalog/pg_proc.c b/src/backend/catalog/pg_proc.c
index 26c5eb75e3e..9db3ef4edbb 100644
--- a/src/backend/catalog/pg_proc.c
+++ b/src/backend/catalog/pg_proc.c
@@ -8,7 +8,7 @@
*
*
* 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,
{
case ANYARRAYOID:
case ANYELEMENTOID:
+ case ANYNONARRAYOID:
case ANYENUMOID:
genericInParam = true;
break;
@@ -170,6 +171,7 @@ ProcedureCreate(const char *procedureName,
{
case ANYARRAYOID:
case ANYELEMENTOID:
+ case ANYNONARRAYOID:
case ANYENUMOID:
genericOutParam = true;
break;
diff --git a/src/backend/executor/functions.c b/src/backend/executor/functions.c
index 9ad13916123..8beea3f5396 100644
--- a/src/backend/executor/functions.c
+++ b/src/backend/executor/functions.c
@@ -8,7 +8,7 @@
*
*
* 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)
* to be sure that the user is returning the type he claims.
*
* For a polymorphic function the passed rettype must be the actual resolved
- * output type of the function; we should never see ANYARRAY, ANYENUM or
- * ANYELEMENT as rettype. (This means we can't check the type during function
- * definition of a polymorphic function.)
+ * output type of the function; we should never see a polymorphic pseudotype
+ * such as ANYELEMENT as rettype. (This means we can't check the type during
+ * function definition of a polymorphic function.)
*
* This function returns true if the sql function returns the entire tuple
* 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,
char fn_typtype;
Oid restype;
+ AssertArg(!IsPolymorphicType(rettype));
+
if (junkFilter)
*junkFilter = NULL; /* default result */
diff --git a/src/backend/parser/parse_agg.c b/src/backend/parser/parse_agg.c
index 1409285cda4..1afc55bc9a7 100644
--- a/src/backend/parser/parse_agg.c
+++ b/src/backend/parser/parse_agg.c
@@ -8,7 +8,7 @@
*
*
* 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,
*
* agg_input_types, agg_state_type, agg_result_type identify the input,
* 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
* may be InvalidOid.
diff --git a/src/backend/parser/parse_coerce.c b/src/backend/parser/parse_coerce.c
index 98cc6691124..abc05685811 100644
--- a/src/backend/parser/parse_coerce.c
+++ b/src/backend/parser/parse_coerce.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/parser/parse_coerce.c,v 2.154 2007/06/05 21:31:05 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/parser/parse_coerce.c,v 2.155 2007/06/06 23:00:37 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -133,6 +133,7 @@ coerce_type(ParseState *pstate, Node *node,
}
if (targetTypeId == ANYOID ||
targetTypeId == ANYELEMENTOID ||
+ targetTypeId == ANYNONARRAYOID ||
(targetTypeId == ANYARRAYOID && inputTypeId != UNKNOWNOID) ||
(targetTypeId == ANYENUMOID && inputTypeId != UNKNOWNOID))
{
@@ -141,12 +142,12 @@ coerce_type(ParseState *pstate, Node *node,
*
* Note: by returning the unmodified node here, we are saying that
* it's OK to treat an UNKNOWN constant as a valid input for a
- * function accepting ANY or ANYELEMENT. This should be all right,
- * since an UNKNOWN value is still a perfectly valid Datum. However
- * an UNKNOWN value is definitely *not* an array, and so we mustn't
- * accept it for ANYARRAY. (Instead, we will call anyarray_in below,
- * which will produce an error.) Likewise, UNKNOWN input is no good
- * for ANYENUM.
+ * function accepting ANY, ANYELEMENT, or ANYNONARRAY. This should be
+ * all right, since an UNKNOWN value is still a perfectly valid Datum.
+ * However an UNKNOWN value is definitely *not* an array, and so we
+ * mustn't accept it for ANYARRAY. (Instead, we will call anyarray_in
+ * below, which will produce an error.) Likewise, UNKNOWN input is no
+ * good for ANYENUM.
*
* NB: we do NOT want a RelabelType here.
*/
@@ -1078,9 +1079,13 @@ coerce_to_common_type(ParseState *pstate, Node *node,
* 4) ANYENUM is treated the same as ANYELEMENT except that if it is used
* (alone or in combination with plain ANYELEMENT), we add the extra
* condition that the ANYELEMENT type must be an enum.
+ * 5) ANYNONARRAY is treated the same as ANYELEMENT except that if it is used,
+ * we add the extra condition that the ANYELEMENT type must not be an array.
+ * (This is a no-op if used in combination with ANYARRAY or ANYENUM, but
+ * is an extra restriction if not.)
*
- * If we have UNKNOWN input (ie, an untyped literal) for any ANYELEMENT
- * or ANYARRAY argument, assume it is okay.
+ * If we have UNKNOWN input (ie, an untyped literal) for any polymorphic
+ * argument, assume it is okay.
*
* If an input is of type ANYARRAY (ie, we know it's an array, but not
* what element type), we will accept it as a match to an argument declared
@@ -1100,21 +1105,26 @@ check_generic_type_consistency(Oid *actual_arg_types,
Oid array_typeid = InvalidOid;
Oid array_typelem;
bool have_anyelement = false;
+ bool have_anynonarray = false;
bool have_anyenum = false;
/*
- * Loop through the arguments to see if we have any that are ANYARRAY or
- * ANYELEMENT. If so, require the actual types to be self-consistent
+ * Loop through the arguments to see if we have any that are polymorphic.
+ * If so, require the actual types to be consistent.
*/
for (j = 0; j < nargs; j++)
{
+ Oid decl_type = declared_arg_types[j];
Oid actual_type = actual_arg_types[j];
- if (declared_arg_types[j] == ANYELEMENTOID ||
- declared_arg_types[j] == ANYENUMOID)
+ if (decl_type == ANYELEMENTOID ||
+ decl_type == ANYNONARRAYOID ||
+ decl_type == ANYENUMOID)
{
have_anyelement = true;
- if (declared_arg_types[j] == ANYENUMOID)
+ if (decl_type == ANYNONARRAYOID)
+ have_anynonarray = true;
+ else if (decl_type == ANYENUMOID)
have_anyenum = true;
if (actual_type == UNKNOWNOID)
continue;
@@ -1122,7 +1132,7 @@ check_generic_type_consistency(Oid *actual_arg_types,
return false;
elem_typeid = actual_type;
}
- else if (declared_arg_types[j] == ANYARRAYOID)
+ else if (decl_type == ANYARRAYOID)
{
if (actual_type == UNKNOWNOID)
continue;
@@ -1161,6 +1171,13 @@ check_generic_type_consistency(Oid *actual_arg_types,
}
}
+ if (have_anynonarray)
+ {
+ /* require the element type to not be an array */
+ if (type_is_array(elem_typeid))
+ return false;
+ }
+
if (have_anyenum)
{
/* require the element type to be an enum */
@@ -1177,7 +1194,7 @@ check_generic_type_consistency(Oid *actual_arg_types,
* Make sure a polymorphic function is legally callable, and
* deduce actual argument and result types.
*
- * If ANYARRAY, ANYELEMENT, or ANYENUM is used for a function's arguments or
+ * If any polymorphic pseudotype is used in a function's arguments or
* return type, we make sure the actual data types are consistent with
* each other. The argument consistency rules are shown above for
* check_generic_type_consistency().
@@ -1211,6 +1228,10 @@ check_generic_type_consistency(Oid *actual_arg_types,
* 7) ANYENUM is treated the same as ANYELEMENT except that if it is used
* (alone or in combination with plain ANYELEMENT), we add the extra
* condition that the ANYELEMENT type must be an enum.
+ * 8) ANYNONARRAY is treated the same as ANYELEMENT except that if it is used,
+ * we add the extra condition that the ANYELEMENT type must not be an array.
+ * (This is a no-op if used in combination with ANYARRAY or ANYENUM, but
+ * is an extra restriction if not.)
*/
Oid
enforce_generic_type_consistency(Oid *actual_arg_types,
@@ -1225,22 +1246,28 @@ enforce_generic_type_consistency(Oid *actual_arg_types,
Oid array_typeid = InvalidOid;
Oid array_typelem;
bool have_anyelement = (rettype == ANYELEMENTOID ||
+ rettype == ANYNONARRAYOID ||
rettype == ANYENUMOID);
+ bool have_anynonarray = (rettype == ANYNONARRAYOID);
bool have_anyenum = (rettype == ANYENUMOID);
/*
- * Loop through the arguments to see if we have any that are ANYARRAY or
- * ANYELEMENT. If so, require the actual types to be self-consistent
+ * Loop through the arguments to see if we have any that are polymorphic.
+ * If so, require the actual types to be consistent.
*/
for (j = 0; j < nargs; j++)
{
+ Oid decl_type = declared_arg_types[j];
Oid actual_type = actual_arg_types[j];
- if (declared_arg_types[j] == ANYELEMENTOID ||
- declared_arg_types[j] == ANYENUMOID)
+ if (decl_type == ANYELEMENTOID ||
+ decl_type == ANYNONARRAYOID ||
+ decl_type == ANYENUMOID)
{
have_generics = have_anyelement = true;
- if (declared_arg_types[j] == ANYENUMOID)
+ if (decl_type == ANYNONARRAYOID)
+ have_anynonarray = true;
+ else if (decl_type == ANYENUMOID)
have_anyenum = true;
if (actual_type == UNKNOWNOID)
{
@@ -1256,7 +1283,7 @@ enforce_generic_type_consistency(Oid *actual_arg_types,
format_type_be(actual_type))));
elem_typeid = actual_type;
}
- else if (declared_arg_types[j] == ANYARRAYOID)
+ else if (decl_type == ANYARRAYOID)
{
have_generics = true;
if (actual_type == UNKNOWNOID)
@@ -1326,6 +1353,16 @@ enforce_generic_type_consistency(Oid *actual_arg_types,
errmsg("could not determine polymorphic type because input has type \"unknown\"")));
}
+ if (have_anynonarray)
+ {
+ /* require the element type to not be an array */
+ if (type_is_array(elem_typeid))
+ ereport(ERROR,
+ (errcode(ERRCODE_DATATYPE_MISMATCH),
+ errmsg("type matched to anynonarray is an array type: %s",
+ format_type_be(elem_typeid))));
+ }
+
if (have_anyenum)
{
/* require the element type to be an enum */
@@ -1343,15 +1380,17 @@ enforce_generic_type_consistency(Oid *actual_arg_types,
{
for (j = 0; j < nargs; j++)
{
+ Oid decl_type = declared_arg_types[j];
Oid actual_type = actual_arg_types[j];
if (actual_type != UNKNOWNOID)
continue;
- if (declared_arg_types[j] == ANYELEMENTOID ||
- declared_arg_types[j] == ANYENUMOID)
+ if (decl_type == ANYELEMENTOID ||
+ decl_type == ANYNONARRAYOID ||
+ decl_type == ANYENUMOID)
declared_arg_types[j] = elem_typeid;
- else if (declared_arg_types[j] == ANYARRAYOID)
+ else if (decl_type == ANYARRAYOID)
{
if (!OidIsValid(array_typeid))
{
@@ -1383,7 +1422,9 @@ enforce_generic_type_consistency(Oid *actual_arg_types,
}
/* if we return ANYELEMENT use the appropriate argument type */
- if (rettype == ANYELEMENTOID || rettype == ANYENUMOID)
+ if (rettype == ANYELEMENTOID ||
+ rettype == ANYNONARRAYOID ||
+ rettype == ANYENUMOID)
return elem_typeid;
/* we don't return a generic type; send back the original return type */
@@ -1423,6 +1464,7 @@ resolve_generic_type(Oid declared_type,
return context_actual_type;
}
else if (context_declared_type == ANYELEMENTOID ||
+ context_declared_type == ANYNONARRAYOID ||
context_declared_type == ANYENUMOID)
{
/* Use the array type corresponding to actual type */
@@ -1436,7 +1478,9 @@ resolve_generic_type(Oid declared_type,
return array_typeid;
}
}
- else if (declared_type == ANYELEMENTOID || declared_type == ANYENUMOID)
+ else if (declared_type == ANYELEMENTOID ||
+ declared_type == ANYNONARRAYOID ||
+ declared_type == ANYENUMOID)
{
if (context_declared_type == ANYARRAYOID)
{
@@ -1451,6 +1495,7 @@ resolve_generic_type(Oid declared_type,
return array_typelem;
}
else if (context_declared_type == ANYELEMENTOID ||
+ context_declared_type == ANYNONARRAYOID ||
context_declared_type == ANYENUMOID)
{
/* Use the actual type; it doesn't matter if array or not */
@@ -1564,6 +1609,7 @@ TypeCategory(Oid inType)
case (INTERNALOID):
case (OPAQUEOID):
case (ANYELEMENTOID):
+ case (ANYNONARRAYOID):
case (ANYENUMOID):
result = GENERIC_TYPE;
break;
@@ -1707,7 +1753,12 @@ IsBinaryCoercible(Oid srctype, Oid targettype)
/* Also accept any array type as coercible to ANYARRAY */
if (targettype == ANYARRAYOID)
- if (get_element_type(srctype) != InvalidOid)
+ if (type_is_array(srctype))
+ return true;
+
+ /* Also accept any non-array type as coercible to ANYNONARRAY */
+ if (targettype == ANYNONARRAYOID)
+ if (!type_is_array(srctype))
return true;
/* Also accept any enum type as coercible to ANYENUM */
@@ -1864,22 +1915,6 @@ find_coercion_pathway(Oid targetTypeId, Oid sourceTypeId,
}
/*
- * If we still haven't found a possibility, check for enums,
- * and retry looking for a cast to or from ANYENUM. But don't
- * mistakenly conclude that ANYENUM-to-some-enum-type is a
- * trivial cast.
- */
- if (result == COERCION_PATH_NONE)
- {
- if (type_is_enum(sourceTypeId))
- result = find_coercion_pathway(targetTypeId, ANYENUMOID,
- ccontext, funcid);
- else if (sourceTypeId != ANYENUMOID && type_is_enum(targetTypeId))
- result = find_coercion_pathway(ANYENUMOID, sourceTypeId,
- 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.
diff --git a/src/backend/parser/parse_func.c b/src/backend/parser/parse_func.c
index 5e7a1cccffa..393fa6c41ac 100644
--- a/src/backend/parser/parse_func.c
+++ b/src/backend/parser/parse_func.c
@@ -8,7 +8,7 @@
*
*
* 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,
}
/*
- * enforce consistency with ANYARRAY and ANYELEMENT argument and return
- * types, possibly adjusting return type or declared_arg_types (which will
- * be used as the cast destination by make_fn_arguments)
+ * enforce consistency with polymorphic argument and return types,
+ * possibly adjusting return type or declared_arg_types (which will be
+ * used as the cast destination by make_fn_arguments)
*/
rettype = enforce_generic_type_consistency(actual_arg_types,
declared_arg_types,
diff --git a/src/backend/utils/adt/pseudotypes.c b/src/backend/utils/adt/pseudotypes.c
index fc9f3324827..248bcfa3058 100644
--- a/src/backend/utils/adt/pseudotypes.c
+++ b/src/backend/utils/adt/pseudotypes.c
@@ -16,7 +16,7 @@
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
@@ -348,6 +348,32 @@ anyelement_out(PG_FUNCTION_ARGS)
}
/*
+ * 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).
*/
Datum
diff --git a/src/backend/utils/adt/xml.c b/src/backend/utils/adt/xml.c
index f9fd48db661..2e84fac1d70 100644
--- a/src/backend/utils/adt/xml.c
+++ b/src/backend/utils/adt/xml.c
@@ -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/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)
initStringInfo(&buf);
- if (is_array_type(type))
+ if (type_is_array(type))
{
int i;
ArrayType *array;
diff --git a/src/backend/utils/fmgr/funcapi.c b/src/backend/utils/fmgr/funcapi.c
index c32130c3ec1..53a505858b1 100644
--- a/src/backend/utils/fmgr/funcapi.c
+++ b/src/backend/utils/fmgr/funcapi.c
@@ -7,7 +7,7 @@
* Copyright (c) 2002-2007, PostgreSQL Global Development Group
*
* 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)
* only when we couldn't resolve the actual rowtype for lack of information.
*
* The other hard case that this handles is resolution of polymorphism.
- * We will never return ANYELEMENT, ANYARRAY or ANYENUM, either as a scalar
- * result type or as a component of a rowtype.
+ * We will never return polymorphic pseudotypes (ANYELEMENT etc), either
+ * as a scalar result type or as a component of a rowtype.
*
* This function is relatively expensive --- in a function returning set,
* try to call it only the first time through.
@@ -389,9 +389,9 @@ internal_get_result_type(Oid funcid,
/*
* Given the result tuple descriptor for a function with OUT parameters,
- * replace any polymorphic columns (ANYELEMENT/ANYARRAY/ANYENUM) with correct
- * data types deduced from the input arguments. Returns TRUE if able to deduce
- * all types, FALSE if not.
+ * replace any polymorphic columns (ANYELEMENT etc) with correct data types
+ * deduced from the input arguments. Returns TRUE if able to deduce all types,
+ * FALSE if not.
*/
static bool
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;
bool have_anyelement_result = false;
bool have_anyarray_result = false;
+ bool have_anynonarray = false;
bool have_anyenum = false;
Oid anyelement_type = InvalidOid;
Oid anyarray_type = InvalidOid;
@@ -417,6 +418,10 @@ resolve_polymorphic_tupdesc(TupleDesc tupdesc, oidvector *declared_args,
case ANYARRAYOID:
have_anyarray_result = true;
break;
+ case ANYNONARRAYOID:
+ have_anyelement_result = true;
+ have_anynonarray = true;
+ break;
case ANYENUMOID:
have_anyelement_result = true;
have_anyenum = true;
@@ -440,6 +445,7 @@ resolve_polymorphic_tupdesc(TupleDesc tupdesc, oidvector *declared_args,
switch (declared_args->values[i])
{
case ANYELEMENTOID:
+ case ANYNONARRAYOID:
case ANYENUMOID:
if (!OidIsValid(anyelement_type))
anyelement_type = get_call_expr_argtype(call_expr, i);
@@ -467,7 +473,11 @@ resolve_polymorphic_tupdesc(TupleDesc tupdesc, oidvector *declared_args,
anyelement_type,
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))
return false;
@@ -477,6 +487,7 @@ resolve_polymorphic_tupdesc(TupleDesc tupdesc, oidvector *declared_args,
switch (tupdesc->attrs[i]->atttypid)
{
case ANYELEMENTOID:
+ case ANYNONARRAYOID:
case ANYENUMOID:
TupleDescInitEntry(tupdesc, i + 1,
NameStr(tupdesc->attrs[i]->attname),
@@ -500,11 +511,11 @@ resolve_polymorphic_tupdesc(TupleDesc tupdesc, oidvector *declared_args,
}
/*
- * Given the declared argument types and modes for a function,
- * replace any polymorphic types (ANYELEMENT/ANYARRAY/ANYENUM) with correct
- * data types deduced from the input arguments. Returns TRUE if able to deduce
- * all types, FALSE if not. This is the same logic as
- * resolve_polymorphic_tupdesc, but with a different argument representation.
+ * Given the declared argument types and modes for a function, replace any
+ * polymorphic types (ANYELEMENT etc) with correct data types deduced from the
+ * input arguments. Returns TRUE if able to deduce all types, FALSE if not.
+ * This is the same logic as resolve_polymorphic_tupdesc, but with a different
+ * argument representation.
*
* 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,
switch (argtypes[i])
{
case ANYELEMENTOID:
+ case ANYNONARRAYOID:
case ANYENUMOID:
if (argmode == PROARGMODE_OUT)
have_anyelement_result = true;
@@ -583,7 +595,7 @@ resolve_polymorphic_argtypes(int numargs, Oid *argtypes, char *argmodes,
anyelement_type,
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 */
for (i = 0; i < numargs; i++)
@@ -591,6 +603,7 @@ resolve_polymorphic_argtypes(int numargs, Oid *argtypes, char *argmodes,
switch (argtypes[i])
{
case ANYELEMENTOID:
+ case ANYNONARRAYOID:
case ANYENUMOID:
argtypes[i] = anyelement_type;
break;
diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h
index ec6d5167139..8dfca8ecc72 100644
--- a/src/include/catalog/catversion.h
+++ b/src/include/catalog/catversion.h
@@ -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.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 @@
*/
/* yyyymmddN */
-#define CATALOG_VERSION_NO 200706051
+#define CATALOG_VERSION_NO 200706061
#endif
diff --git a/src/include/catalog/pg_operator.h b/src/include/catalog/pg_operator.h
index 6848b274e45..e3b2910eb22 100644
--- a/src/include/catalog/pg_operator.h
+++ b/src/include/catalog/pg_operator.h
@@ -8,7 +8,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_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
* 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
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 = 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 = 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
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 ));
+/* 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 */
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 ));
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
index c656c7a6717..49c1429e377 100644
--- a/src/include/catalog/pg_proc.h
+++ b/src/include/catalog/pg_proc.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.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
* 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
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_ ));
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");
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");
@@ -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_ ));
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");
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");
@@ -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_ ));
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");
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
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_ ));
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");
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");
@@ -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_ ));
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_ ));
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_ ));
@@ -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");
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");
+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 */
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");
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");
-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");
/* uuid */
diff --git a/src/include/catalog/pg_type.h b/src/include/catalog/pg_type.h
index 0d9ff0d6eef..753487348b4 100644
--- a/src/include/catalog/pg_type.h
+++ b/src/include/catalog/pg_type.h
@@ -8,7 +8,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_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
* 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
#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_ ));
#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_ ));
#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
#define IsPolymorphicType(typid) \
((typid) == ANYELEMENTOID || \
(typid) == ANYARRAYOID || \
+ (typid) == ANYNONARRAYOID || \
(typid) == ANYENUMOID)
/*
diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h
index 5ff4fe738fc..faf8b692621 100644
--- a/src/include/utils/builtins.h
+++ b/src/include/utils/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/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);
extern Datum anyarray_out(PG_FUNCTION_ARGS);
extern Datum anyarray_recv(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_out(PG_FUNCTION_ARGS);
extern Datum void_in(PG_FUNCTION_ARGS);
diff --git a/src/include/utils/lsyscache.h b/src/include/utils/lsyscache.h
index 25782e322e9..0a326cb9ba9 100644
--- a/src/include/utils/lsyscache.h
+++ b/src/include/utils/lsyscache.h
@@ -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/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);
extern Oid get_roleid(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')
diff --git a/src/pl/plpgsql/src/pl_comp.c b/src/pl/plpgsql/src/pl_comp.c
index 74918c890ca..a547d174c1b 100644
--- a/src/pl/plpgsql/src/pl_comp.c
+++ b/src/pl/plpgsql/src/pl_comp.c
@@ -8,7 +8,7 @@
*
*
* 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,
{
if (rettypeid == ANYARRAYOID)
rettypeid = INT4ARRAYOID;
- else
+ else /* ANYELEMENT or ANYNONARRAY */
rettypeid = INT4OID;
/* XXX what could we use for ANYENUM? */
}
@@ -2027,6 +2027,7 @@ plpgsql_resolve_polymorphic_argtypes(int numargs,
switch (argtypes[i])
{
case ANYELEMENTOID:
+ case ANYNONARRAYOID:
case ANYENUMOID: /* XXX dubious */
argtypes[i] = INT4OID;
break;
diff --git a/src/test/regress/expected/text.out b/src/test/regress/expected/text.out
index 2d732f6844a..08d002fe71e 100644
--- a/src/test/regress/expected/text.out
+++ b/src/test/regress/expected/text.out
@@ -23,3 +23,31 @@ SELECT '' AS two, * FROM TEXT_TBL;
| hi de ho neighbor
(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.
diff --git a/src/test/regress/sql/text.sql b/src/test/regress/sql/text.sql
index 60daf7077c6..b739e56e2d6 100644
--- a/src/test/regress/sql/text.sql
+++ b/src/test/regress/sql/text.sql
@@ -13,3 +13,18 @@ INSERT INTO TEXT_TBL VALUES ('hi de ho neighbor');
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;