88 *
99 *
1010 * IDENTIFICATION
11- * $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.75 2000/07/22 03:34:27 tgl Exp $
11+ * $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.76 2000/07/23 01:35:58 tgl Exp $
1212 *
1313 *-------------------------------------------------------------------------
1414 */
@@ -64,18 +64,30 @@ static Datum ExecEvalVar(Var *variable, ExprContext *econtext, bool *isNull);
6464static Datum ExecMakeFunctionResult (Node * node ,List * arguments ,
6565ExprContext * econtext ,bool * isNull ,bool * isDone );
6666
67- /*
67+ /*----------
6868 * ExecEvalArrayRef
6969 *
7070 * This function takes an ArrayRef and returns the extracted Datum
7171 * if it's a simple reference, or the modified array value if it's
72- * an array assignment (read array element insertion).
72+ * an array assignment (i.e., array element or slice insertion).
73+ *
74+ * NOTE: if we get a NULL result from a subexpression, we return NULL when
75+ * it's an array reference, or the unmodified source array when it's an
76+ * array assignment. This may seem peculiar, but if we return NULL (as was
77+ * done in versions up through 7.0) then an assignment like
78+ *UPDATE table SET arrayfield[4] = NULL
79+ * will result in setting the whole array to NULL, which is certainly not
80+ * very desirable. By returning the source array we make the assignment
81+ * into a no-op, instead. (Eventually we need to redesign arrays so that
82+ * individual elements can be NULL, but for now, let's try to protect users
83+ * from shooting themselves in the foot.)
7384 *
7485 * NOTE: we deliberately refrain from applying DatumGetArrayTypeP() here,
7586 * even though that might seem natural, because this code needs to support
7687 * both varlena arrays and fixed-length array types. DatumGetArrayTypeP()
7788 * only works for the varlena kind. The routines we call in arrayfuncs.c
7889 * have to know the difference (that's what they need refattrlength for).
90+ *----------
7991 */
8092static Datum
8193ExecEvalArrayRef (ArrayRef * arrayRef ,
@@ -85,6 +97,7 @@ ExecEvalArrayRef(ArrayRef *arrayRef,
8597{
8698ArrayType * array_source ;
8799ArrayType * resultArray ;
100+ bool isAssignment = (arrayRef -> refassgnexpr != NULL );
88101List * elt ;
89102int i = 0 ,
90103j = 0 ;
@@ -102,15 +115,19 @@ ExecEvalArrayRef(ArrayRef *arrayRef,
102115econtext ,
103116isNull ,
104117isDone ));
105- /* If refexpr yields NULL, result is always NULL, for now anyway */
118+ /*
119+ * If refexpr yields NULL, result is always NULL, for now anyway.
120+ * (This means you cannot assign to an element or slice of an array
121+ * that's NULL; it'll just stay NULL.)
122+ */
106123if (* isNull )
107124return (Datum )NULL ;
108125}
109126else
110127{
111128
112129/*
113- *Null refexpr indicates we are doing an INSERT into an array
130+ *Empty refexpr indicates we are doing an INSERT into an array
114131 * column. For now, we just take the refassgnexpr (which the
115132 * parser will have ensured is an array value) and return it
116133 * as-is, ignoring any subscripts that may have been supplied in
@@ -130,9 +147,14 @@ ExecEvalArrayRef(ArrayRef *arrayRef,
130147econtext ,
131148isNull ,
132149& dummy ));
133- /* If any index expr yields NULL, result is NULL */
150+ /* If any index expr yields NULL, result is NULLor source array */
134151if (* isNull )
135- return (Datum )NULL ;
152+ {
153+ if (!isAssignment || array_source == NULL )
154+ return (Datum )NULL ;
155+ * isNull = false;
156+ return PointerGetDatum (array_source );
157+ }
136158}
137159
138160if (arrayRef -> reflowerindexpr != NIL )
@@ -147,9 +169,14 @@ ExecEvalArrayRef(ArrayRef *arrayRef,
147169econtext ,
148170isNull ,
149171& dummy ));
150- /* If any index expr yields NULL, result is NULL */
172+ /* If any index expr yields NULL, result is NULLor source array */
151173if (* isNull )
152- return (Datum )NULL ;
174+ {
175+ if (!isAssignment || array_source == NULL )
176+ return (Datum )NULL ;
177+ * isNull = false;
178+ return PointerGetDatum (array_source );
179+ }
153180}
154181if (i != j )
155182elog (ERROR ,
@@ -159,18 +186,26 @@ ExecEvalArrayRef(ArrayRef *arrayRef,
159186else
160187lIndex = NULL ;
161188
162- if (arrayRef -> refassgnexpr != NULL )
189+ if (isAssignment )
163190{
164191Datum sourceData = ExecEvalExpr (arrayRef -> refassgnexpr ,
165192econtext ,
166193isNull ,
167194& dummy );
168- /* For now, can't cope with inserting NULL into an array */
195+ /*
196+ * For now, can't cope with inserting NULL into an array,
197+ * so make it a no-op per discussion above...
198+ */
169199if (* isNull )
170- return (Datum )NULL ;
200+ {
201+ if (array_source == NULL )
202+ return (Datum )NULL ;
203+ * isNull = false;
204+ return PointerGetDatum (array_source );
205+ }
171206
172207if (array_source == NULL )
173- return sourceData ;/* XXX do something else? */
208+ return sourceData ;/* XXX do something else? */
174209
175210if (lIndex == NULL )
176211resultArray = array_set (array_source ,i ,