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

Adjust plpgsql to allow assignment to an element of an array that is

initially NULL.  For 8.0 we changed the main executor to have this
behavior in an UPDATE of an array column, but plpgsql's equivalent case
was overlooked.  Per report from Sven Willenberger.
parent 68b0e298
......@@ -3,7 +3,7 @@
* procedural language
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.127 2005/01/13 23:07:34 tgl Exp $
* $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.128 2005/02/01 19:35:14 tgl Exp $
*
* This software is copyrighted by Jan Wieck - Hamburg.
*
......@@ -3069,11 +3069,13 @@ exec_assign_value(PLpgSQL_execstate *estate,
oldarrayisnull;
Oid arraytypeid,
arrayelemtypeid;
int16 elemtyplen;
int16 arraytyplen,
elemtyplen;
bool elemtypbyval;
char elemtypalign;
Datum oldarrayval,
Datum oldarraydatum,
coerced_value;
ArrayType *oldarrayval;
ArrayType *newarrayval;
/*
......@@ -3102,7 +3104,7 @@ exec_assign_value(PLpgSQL_execstate *estate,
/* Fetch current value of array datum */
exec_eval_datum(estate, target, InvalidOid,
&arraytypeid, &oldarrayval, &oldarrayisnull);
&arraytypeid, &oldarraydatum, &oldarrayisnull);
arrayelemtypeid = get_element_type(arraytypeid);
if (!OidIsValid(arrayelemtypeid))
......@@ -3110,6 +3112,12 @@ exec_assign_value(PLpgSQL_execstate *estate,
(errcode(ERRCODE_DATATYPE_MISMATCH),
errmsg("subscripted object is not an array")));
get_typlenbyvalalign(arrayelemtypeid,
&elemtyplen,
&elemtypbyval,
&elemtypalign);
arraytyplen = get_typlen(arraytypeid);
/*
* Evaluate the subscripts, switch into left-to-right
* order
......@@ -3127,14 +3135,36 @@ exec_assign_value(PLpgSQL_execstate *estate,
}
/*
* Skip the assignment if we have any nulls, either in the
* original array value, the subscripts, or the righthand
* side. This is pretty bogus but it corresponds to the
* current behavior of ExecEvalArrayRef().
* Skip the assignment if we have any nulls in the subscripts
* or the righthand side. This is pretty bogus but it
* corresponds to the current behavior of ExecEvalArrayRef().
*/
if (oldarrayisnull || havenullsubscript || *isNull)
if (havenullsubscript || *isNull)
return;
/*
* If the original array is null, cons up an empty array
* so that the assignment can proceed; we'll end with a
* one-element array containing just the assigned-to
* subscript. This only works for varlena arrays, though;
* for fixed-length array types we skip the assignment.
* Again, this corresponds to the current behavior of
* ExecEvalArrayRef().
*/
if (oldarrayisnull)
{
if (arraytyplen > 0) /* fixed-length array? */
return;
oldarrayval = construct_md_array(NULL, 0, NULL, NULL,
arrayelemtypeid,
elemtyplen,
elemtypbyval,
elemtypalign);
}
else
oldarrayval = (ArrayType *) DatumGetPointer(oldarraydatum);
/* Coerce source value to match array element type. */
coerced_value = exec_simple_cast_value(value,
valtype,
......@@ -3145,16 +3175,11 @@ exec_assign_value(PLpgSQL_execstate *estate,
/*
* Build the modified array value.
*/
get_typlenbyvalalign(arrayelemtypeid,
&elemtyplen,
&elemtypbyval,
&elemtypalign);
newarrayval = array_set((ArrayType *) DatumGetPointer(oldarrayval),
newarrayval = array_set(oldarrayval,
nsubscripts,
subscriptvals,
coerced_value,
get_typlen(arraytypeid),
arraytyplen,
elemtyplen,
elemtypbyval,
elemtypalign,
......
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