mirror of
https://git.postgresql.org/git/postgresql.git
synced 2025-01-12 18:34:36 +08:00
Fixes:
The updating of array fields is broken in Postgres95-1.01, An array can be only replaced with a new array but not have some elements modified. This is caused by two bugs in the parser and in the array utilities. Furthermore it is not possible to update array with a base type of variable length. - submitted by: Massimo Dal Zotto <dz@cs.unitn.it>
This commit is contained in:
parent
baeb3aadc5
commit
94215d51c8
@ -7,7 +7,7 @@
|
||||
#
|
||||
#
|
||||
# IDENTIFICATION
|
||||
# $Header: /cvsroot/pgsql/src/Attic/Makefile.global,v 1.6 1996/07/20 07:29:33 scrappy Exp $
|
||||
# $Header: /cvsroot/pgsql/src/Attic/Makefile.global,v 1.7 1996/07/20 07:57:49 scrappy Exp $
|
||||
#
|
||||
# NOTES
|
||||
# This is seen by any Makefiles that include mk/postgres.mk. To
|
||||
@ -287,6 +287,8 @@ CFLAGS+= $(CFLAGS_BE)
|
||||
LDADD+= $(LDADD_BE)
|
||||
LDFLAGS+= $(LDFLAGS_BE)
|
||||
|
||||
# enable patches to array update code
|
||||
CFLAGS += -DARRAY_PATCH
|
||||
|
||||
##############################################################################
|
||||
#
|
||||
|
@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.2 1996/07/19 07:24:06 scrappy Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.3 1996/07/20 07:58:04 scrappy Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -1386,6 +1386,16 @@ make_targetlist_expr(ParseState *pstate,
|
||||
if (attrtype != type_id) {
|
||||
if (IsA(expr,Const)) {
|
||||
/* try to cast the constant */
|
||||
#ifdef ARRAY_PATCH
|
||||
if (arrayRef && !(((A_Indices *)lfirst(arrayRef))->lidx)) {
|
||||
/* updating a single item */
|
||||
Oid typelem = get_typelem(attrtype);
|
||||
expr = (Node*)parser_typecast2(expr,
|
||||
type_id,
|
||||
get_id_type((long)typelem),
|
||||
attrlen);
|
||||
} else
|
||||
#endif
|
||||
expr = (Node*)parser_typecast2(expr,
|
||||
type_id,
|
||||
get_id_type((long)attrtype),
|
||||
@ -1418,7 +1428,11 @@ make_targetlist_expr(ParseState *pstate,
|
||||
&pstate->p_last_resno);
|
||||
while(ar!=NIL) {
|
||||
A_Indices *ind = lfirst(ar);
|
||||
#ifdef ARRAY_PATCH
|
||||
if (lowerIndexpr || (!upperIndexpr && ind->lidx)) {
|
||||
#else
|
||||
if (lowerIndexpr) {
|
||||
#endif
|
||||
/* XXX assume all lowerIndexpr is non-null in
|
||||
* this case
|
||||
*/
|
||||
|
@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/adt/arrayfuncs.c,v 1.1.1.1 1996/07/09 06:22:03 scrappy Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/adt/arrayfuncs.c,v 1.2 1996/07/20 07:58:44 scrappy Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -877,7 +877,11 @@ array_set(ArrayType *array,
|
||||
* fixed length arrays -- these are assumed to be 1-d
|
||||
*/
|
||||
if (indx[0]*elmlen > arraylen)
|
||||
#ifdef ARRAY_PATCH
|
||||
elog(WARN, "array_ref: array bound exceeded");
|
||||
#else
|
||||
elog(WARN, "array_set: array bound exceeded");
|
||||
#endif
|
||||
pos = (char *)array + indx[0]*elmlen;
|
||||
ArrayCastAndSet(dataPtr, (bool) reftype, elmlen, pos);
|
||||
return((char *)array);
|
||||
@ -888,7 +892,14 @@ array_set(ArrayType *array,
|
||||
nbytes = (* (int32 *) array) - ARR_OVERHEAD(ndim);
|
||||
|
||||
if (!SanityCheckInput(ndim, n, dim, lb, indx))
|
||||
#ifdef ARRAY_PATCH
|
||||
{
|
||||
elog(WARN, "array_set: array bound exceeded");
|
||||
return((char *)array);
|
||||
}
|
||||
#else
|
||||
return((char *)array);
|
||||
#endif
|
||||
offset = GetOffset( n, dim, lb, indx);
|
||||
|
||||
if (ARR_IS_LO(array)) {
|
||||
@ -924,7 +935,41 @@ array_set(ArrayType *array,
|
||||
if (nbytes - offset < 1) return((char *)array);
|
||||
pos = ARR_DATA_PTR (array) + offset;
|
||||
} else {
|
||||
#ifdef ARRAY_PATCH
|
||||
ArrayType *newarray;
|
||||
char *elt_ptr;
|
||||
int oldsize, newsize, oldlen, newlen, lth0, lth1, lth2;
|
||||
|
||||
elt_ptr = array_seek(ARR_DATA_PTR(array), -1, offset);
|
||||
oldlen = INTALIGN(*(int32 *)elt_ptr);
|
||||
newlen = INTALIGN(*(int32 *)dataPtr);
|
||||
|
||||
if (oldlen == newlen) {
|
||||
/* new element with same size, overwrite old data */
|
||||
ArrayCastAndSet(dataPtr, (bool)reftype, elmlen, elt_ptr);
|
||||
return((char *)array);
|
||||
}
|
||||
|
||||
/* new element with different size, reallocate the array */
|
||||
oldsize = array->size;
|
||||
lth0 = ARR_OVERHEAD(n);
|
||||
lth1 = (int)(elt_ptr - ARR_DATA_PTR(array));
|
||||
lth2 = (int)(oldsize - lth0 - lth1 - oldlen);
|
||||
newsize = lth0 + lth1 + newlen + lth2;
|
||||
|
||||
newarray = (ArrayType *)palloc(newsize);
|
||||
memmove((char *)newarray, (char *)array, lth0+lth1);
|
||||
newarray->size = newsize;
|
||||
newlen = ArrayCastAndSet(dataPtr, (bool)reftype, elmlen,
|
||||
(char *)newarray+lth0+lth1);
|
||||
memmove((char *)newarray+lth0+lth1+newlen,
|
||||
(char *)array+lth0+lth1+oldlen, lth2);
|
||||
|
||||
/* ??? who should free this storage ??? */
|
||||
return((char *)newarray);
|
||||
#else
|
||||
elog(WARN, "array_set: update of variable length fields not supported");
|
||||
#endif
|
||||
}
|
||||
ArrayCastAndSet(dataPtr, (bool) reftype, elmlen, pos);
|
||||
return((char *)array);
|
||||
|
@ -555,9 +555,9 @@ COPY bt_f8_heap FROM '_CWD_/data/hash.data';
|
||||
INSERT INTO arrtest (a[5], b[2][1][2], c, d)
|
||||
VALUES ('{1,2,3,4,5}', '{{{},{1,2}}}', '{}', '{}');
|
||||
|
||||
-- UPDATE arrtest SET e[0] = '1.1';
|
||||
UPDATE arrtest SET e[0] = '1.1';
|
||||
|
||||
-- UPDATE arrtest SET e[1] = '2.2';
|
||||
UPDATE arrtest SET e[1] = '2.2';
|
||||
|
||||
INSERT INTO arrtest (a, b[2][2][1], c, d, e)
|
||||
VALUES ('{11,12,23}', '{{3,4},{4,5}}', '{"foobar"}',
|
||||
|
Loading…
Reference in New Issue
Block a user