diff options
author | Marc G. Fournier <scrappy@hub.org> | 1996-07-20 07:59:41 +0000 |
---|---|---|
committer | Marc G. Fournier <scrappy@hub.org> | 1996-07-20 07:59:41 +0000 |
commit | 94215d51c82eca99a21e0e7b1a43054b909bac6f (patch) | |
tree | 3f6c861ee28555abf189311bd8f11d7369201560 /src/backend/utils/adt/arrayfuncs.c | |
parent | baeb3aadc5c60611570ff2bb525e6a3f941c1c22 (diff) | |
download | postgresql-94215d51c82eca99a21e0e7b1a43054b909bac6f.tar.gz postgresql-94215d51c82eca99a21e0e7b1a43054b909bac6f.zip |
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>
Diffstat (limited to 'src/backend/utils/adt/arrayfuncs.c')
-rw-r--r-- | src/backend/utils/adt/arrayfuncs.c | 47 |
1 files changed, 46 insertions, 1 deletions
diff --git a/src/backend/utils/adt/arrayfuncs.c b/src/backend/utils/adt/arrayfuncs.c index 2e780fb03b6..8a2b0fd2910 100644 --- a/src/backend/utils/adt/arrayfuncs.c +++ b/src/backend/utils/adt/arrayfuncs.c @@ -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); |