提交 e4e6459c 编写于 作者: T Tom Lane

Further cleanup of array behavior. Slice assignments to arrays with

varlena elements work now.  Allow assignment to previously-nonexistent
subscript position to extend array, but only for 1-D arrays and only
if adjacent to existing positions (could do more if we had a way to
represent nulls in arrays, but I don't want to tackle that now).
Arrange for assignment of NULL to an array element in UPDATE to be a
no-op, rather than setting the entire array to NULL as it used to.
(Throwing an error would be a reasonable alternative, but it's never
done that...)  Update regress test accordingly.
上级 ef2a6b8b
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.75 2000/07/22 03:34:27 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.76 2000/07/23 01:35:58 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -64,18 +64,30 @@ static Datum ExecEvalVar(Var *variable, ExprContext *econtext, bool *isNull);
static Datum ExecMakeFunctionResult(Node *node, List *arguments,
ExprContext *econtext, bool *isNull, bool *isDone);
/*
/*----------
* ExecEvalArrayRef
*
* This function takes an ArrayRef and returns the extracted Datum
* if it's a simple reference, or the modified array value if it's
* an array assignment (read array element insertion).
* an array assignment (i.e., array element or slice insertion).
*
* NOTE: if we get a NULL result from a subexpression, we return NULL when
* it's an array reference, or the unmodified source array when it's an
* array assignment. This may seem peculiar, but if we return NULL (as was
* done in versions up through 7.0) then an assignment like
* UPDATE table SET arrayfield[4] = NULL
* will result in setting the whole array to NULL, which is certainly not
* very desirable. By returning the source array we make the assignment
* into a no-op, instead. (Eventually we need to redesign arrays so that
* individual elements can be NULL, but for now, let's try to protect users
* from shooting themselves in the foot.)
*
* NOTE: we deliberately refrain from applying DatumGetArrayTypeP() here,
* even though that might seem natural, because this code needs to support
* both varlena arrays and fixed-length array types. DatumGetArrayTypeP()
* only works for the varlena kind. The routines we call in arrayfuncs.c
* have to know the difference (that's what they need refattrlength for).
*----------
*/
static Datum
ExecEvalArrayRef(ArrayRef *arrayRef,
......@@ -85,6 +97,7 @@ ExecEvalArrayRef(ArrayRef *arrayRef,
{
ArrayType *array_source;
ArrayType *resultArray;
bool isAssignment = (arrayRef->refassgnexpr != NULL);
List *elt;
int i = 0,
j = 0;
......@@ -102,7 +115,11 @@ ExecEvalArrayRef(ArrayRef *arrayRef,
econtext,
isNull,
isDone));
/* If refexpr yields NULL, result is always NULL, for now anyway */
/*
* If refexpr yields NULL, result is always NULL, for now anyway.
* (This means you cannot assign to an element or slice of an array
* that's NULL; it'll just stay NULL.)
*/
if (*isNull)
return (Datum) NULL;
}
......@@ -110,7 +127,7 @@ ExecEvalArrayRef(ArrayRef *arrayRef,
{
/*
* Null refexpr indicates we are doing an INSERT into an array
* Empty refexpr indicates we are doing an INSERT into an array
* column. For now, we just take the refassgnexpr (which the
* parser will have ensured is an array value) and return it
* as-is, ignoring any subscripts that may have been supplied in
......@@ -130,9 +147,14 @@ ExecEvalArrayRef(ArrayRef *arrayRef,
econtext,
isNull,
&dummy));
/* If any index expr yields NULL, result is NULL */
/* If any index expr yields NULL, result is NULL or source array */
if (*isNull)
return (Datum) NULL;
{
if (! isAssignment || array_source == NULL)
return (Datum) NULL;
*isNull = false;
return PointerGetDatum(array_source);
}
}
if (arrayRef->reflowerindexpr != NIL)
......@@ -147,9 +169,14 @@ ExecEvalArrayRef(ArrayRef *arrayRef,
econtext,
isNull,
&dummy));
/* If any index expr yields NULL, result is NULL */
/* If any index expr yields NULL, result is NULL or source array */
if (*isNull)
return (Datum) NULL;
{
if (! isAssignment || array_source == NULL)
return (Datum) NULL;
*isNull = false;
return PointerGetDatum(array_source);
}
}
if (i != j)
elog(ERROR,
......@@ -159,18 +186,26 @@ ExecEvalArrayRef(ArrayRef *arrayRef,
else
lIndex = NULL;
if (arrayRef->refassgnexpr != NULL)
if (isAssignment)
{
Datum sourceData = ExecEvalExpr(arrayRef->refassgnexpr,
econtext,
isNull,
&dummy);
/* For now, can't cope with inserting NULL into an array */
/*
* For now, can't cope with inserting NULL into an array,
* so make it a no-op per discussion above...
*/
if (*isNull)
return (Datum) NULL;
{
if (array_source == NULL)
return (Datum) NULL;
*isNull = false;
return PointerGetDatum(array_source);
}
if (array_source == NULL)
return sourceData; /* XXX do something else? */
return sourceData; /* XXX do something else? */
if (lIndex == NULL)
resultArray = array_set(array_source, i,
......
此差异已折叠。
......@@ -39,17 +39,17 @@ SELECT a[1:3],
a | b | c | d
------------+-----------------+---------------+-------------------
{1,2,3} | {{{0,0},{1,2}}} | |
{11,12,23} | | | {{"elt1","elt2"}}
{11,12,23} | | {"foobar"} | {{"elt1","elt2"}}
| | {"foo","bar"} |
(3 rows)
-- returns three different results--
SELECT array_dims(arrtest.b) AS x;
x
-----------------
[1:1][1:2][1:2]
[1:2][1:2]
[1:2]
SELECT array_dims(a) AS a,array_dims(b) AS b,array_dims(c) AS c
FROM arrtest;
a | b | c
-------+-----------------+-------
[1:5] | [1:1][1:2][1:2] |
[1:3] | [1:2][1:2] | [1:1]
| [1:2] | [1:2]
(3 rows)
-- returns nothing
......@@ -62,18 +62,32 @@ SELECT *
(0 rows)
UPDATE arrtest
SET a[1:2] = '{16,25}',
b[1:1][1:1][1:2] = '{113, 117}',
c[1:1] = '{"new_word"}';
SET a[1:2] = '{16,25}'
WHERE NOT a = '{}'::_int2;
UPDATE arrtest
SET b[1:1][1:1][1:2] = '{113, 117}',
b[1:1][1:2][2:2] = '{142, 147}'
WHERE array_dims(b) = '[1:1][1:2][1:2]';
UPDATE arrtest
SET c[2:2] = '{"new_word"}'
WHERE array_dims(c) is not null;
SELECT a,b,c FROM arrtest;
a | b | c
---------------+-----------------------+-----------------------
{16,25,3,4,5} | {{{113,142},{1,147}}} | {}
{16,25,23} | {{3,4},{4,5}} | {"foobar","new_word"}
{} | {3,4} | {"foo","new_word"}
(3 rows)
SELECT a[1:3],
b[1:1][1:2][1:2],
c[1:2],
d[1:1][2:2]
FROM arrtest;
a | b | c | d
------------+---------------------+--------------------+------------
{16,25,3} | {{{113,117},{1,2}}} | |
{16,25,23} | | | {{"elt2"}}
| | {"new_word","bar"} |
a | b | c | d
------------+-----------------------+-----------------------+------------
{16,25,3} | {{{113,142},{1,147}}} | |
{16,25,23} | | {"foobar","new_word"} | {{"elt2"}}
| | {"foo","new_word"} |
(3 rows)
......@@ -20,8 +20,8 @@ SELECT a[1:3],
d[1:1][1:2]
FROM arrtest;
-- returns three different results--
SELECT array_dims(arrtest.b) AS x;
SELECT array_dims(a) AS a,array_dims(b) AS b,array_dims(c) AS c
FROM arrtest;
-- returns nothing
SELECT *
......@@ -30,9 +30,19 @@ SELECT *
c = '{"foobar"}'::_name;
UPDATE arrtest
SET a[1:2] = '{16,25}',
b[1:1][1:1][1:2] = '{113, 117}',
c[1:1] = '{"new_word"}';
SET a[1:2] = '{16,25}'
WHERE NOT a = '{}'::_int2;
UPDATE arrtest
SET b[1:1][1:1][1:2] = '{113, 117}',
b[1:1][1:2][2:2] = '{142, 147}'
WHERE array_dims(b) = '[1:1][1:2][1:2]';
UPDATE arrtest
SET c[2:2] = '{"new_word"}'
WHERE array_dims(c) is not null;
SELECT a,b,c FROM arrtest;
SELECT a[1:3],
b[1:1][1:2][1:2],
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册