1
0
mirror of https://github.com/postgres/postgres.git synced 2025-12-01 12:18:01 +03:00

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.
This commit is contained in:
Tom Lane
2007-06-06 23:00:50 +00:00
parent 7dab4f75ca
commit 2d4db3675f
22 changed files with 301 additions and 109 deletions

View File

@@ -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 $
*
*-------------------------------------------------------------------------
*/
@@ -347,6 +347,32 @@ anyelement_out(PG_FUNCTION_ARGS)
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).
*/

View File

@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/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;

View File

@@ -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;