33 * procedural language
44 *
55 * IDENTIFICATION
6- * $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.127 2005/01/13 23:07:34 tgl Exp $
6+ * $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.128 2005/02/01 19:35:14 tgl Exp $
77 *
88 * This software is copyrighted by Jan Wieck - Hamburg.
99 *
@@ -3069,11 +3069,13 @@ exec_assign_value(PLpgSQL_execstate *estate,
30693069oldarrayisnull ;
30703070Oid arraytypeid ,
30713071arrayelemtypeid ;
3072- int16 elemtyplen ;
3072+ int16 arraytyplen ,
3073+ elemtyplen ;
30733074bool elemtypbyval ;
30743075char elemtypalign ;
3075- Datum oldarrayval ,
3076+ Datum oldarraydatum ,
30763077coerced_value ;
3078+ ArrayType * oldarrayval ;
30773079ArrayType * newarrayval ;
30783080
30793081/*
@@ -3102,14 +3104,20 @@ exec_assign_value(PLpgSQL_execstate *estate,
31023104
31033105/* Fetch current value of array datum */
31043106exec_eval_datum (estate ,target ,InvalidOid ,
3105- & arraytypeid ,& oldarrayval ,& oldarrayisnull );
3107+ & arraytypeid ,& oldarraydatum ,& oldarrayisnull );
31063108
31073109arrayelemtypeid = get_element_type (arraytypeid );
31083110if (!OidIsValid (arrayelemtypeid ))
31093111ereport (ERROR ,
31103112(errcode (ERRCODE_DATATYPE_MISMATCH ),
31113113errmsg ("subscripted object is not an array" )));
31123114
3115+ get_typlenbyvalalign (arrayelemtypeid ,
3116+ & elemtyplen ,
3117+ & elemtypbyval ,
3118+ & elemtypalign );
3119+ arraytyplen = get_typlen (arraytypeid );
3120+
31133121/*
31143122 * Evaluate the subscripts, switch into left-to-right
31153123 * order
@@ -3127,14 +3135,36 @@ exec_assign_value(PLpgSQL_execstate *estate,
31273135}
31283136
31293137/*
3130- * Skip the assignment if we have any nulls, either in the
3131- * original array value, the subscripts, or the righthand
3132- * side. This is pretty bogus but it corresponds to the
3133- * current behavior of ExecEvalArrayRef().
3138+ * Skip the assignment if we have any nulls in the subscripts
3139+ * or the righthand side. This is pretty bogus but it
3140+ * corresponds to the current behavior of ExecEvalArrayRef().
31343141 */
3135- if (oldarrayisnull || havenullsubscript || * isNull )
3142+ if (havenullsubscript || * isNull )
31363143return ;
31373144
3145+ /*
3146+ * If the original array is null, cons up an empty array
3147+ * so that the assignment can proceed; we'll end with a
3148+ * one-element array containing just the assigned-to
3149+ * subscript. This only works for varlena arrays, though;
3150+ * for fixed-length array types we skip the assignment.
3151+ * Again, this corresponds to the current behavior of
3152+ * ExecEvalArrayRef().
3153+ */
3154+ if (oldarrayisnull )
3155+ {
3156+ if (arraytyplen > 0 )/* fixed-length array? */
3157+ return ;
3158+
3159+ oldarrayval = construct_md_array (NULL ,0 ,NULL ,NULL ,
3160+ arrayelemtypeid ,
3161+ elemtyplen ,
3162+ elemtypbyval ,
3163+ elemtypalign );
3164+ }
3165+ else
3166+ oldarrayval = (ArrayType * )DatumGetPointer (oldarraydatum );
3167+
31383168/* Coerce source value to match array element type. */
31393169coerced_value = exec_simple_cast_value (value ,
31403170valtype ,
@@ -3145,16 +3175,11 @@ exec_assign_value(PLpgSQL_execstate *estate,
31453175/*
31463176 * Build the modified array value.
31473177 */
3148- get_typlenbyvalalign (arrayelemtypeid ,
3149- & elemtyplen ,
3150- & elemtypbyval ,
3151- & elemtypalign );
3152-
3153- newarrayval = array_set ((ArrayType * )DatumGetPointer (oldarrayval ),
3178+ newarrayval = array_set (oldarrayval ,
31543179nsubscripts ,
31553180subscriptvals ,
31563181coerced_value ,
3157- get_typlen ( arraytypeid ) ,
3182+ arraytyplen ,
31583183elemtyplen ,
31593184elemtypbyval ,
31603185elemtypalign ,