aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2005-02-01 19:35:14 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2005-02-01 19:35:14 +0000
commit2a8874841dc79e06762c4d6584bbf5efd08c3356 (patch)
tree891e90921b1f50c873e47cc731b1ad275f090265
parent68b0e29800f618d39600173de8bdbb8c13132a3e (diff)
downloadpostgresql-2a8874841dc79e06762c4d6584bbf5efd08c3356.tar.gz
postgresql-2a8874841dc79e06762c4d6584bbf5efd08c3356.zip
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.
-rw-r--r--src/pl/plpgsql/src/pl_exec.c57
1 files changed, 41 insertions, 16 deletions
diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c
index bd2c6a00bed..1f3d4c4ab2c 100644
--- a/src/pl/plpgsql/src/pl_exec.c
+++ b/src/pl/plpgsql/src/pl_exec.c
@@ -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,