summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarc G. Fournier1996-07-20 07:59:41 +0000
committerMarc G. Fournier1996-07-20 07:59:41 +0000
commit94215d51c82eca99a21e0e7b1a43054b909bac6f (patch)
tree3f6c861ee28555abf189311bd8f11d7369201560
parentbaeb3aadc5c60611570ff2bb525e6a3f941c1c22 (diff)
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 <[email protected]>
-rw-r--r--src/Makefile.global4
-rw-r--r--src/backend/parser/analyze.c16
-rw-r--r--src/backend/utils/adt/arrayfuncs.c47
-rw-r--r--src/test/regress/create.source4
4 files changed, 66 insertions, 5 deletions
diff --git a/src/Makefile.global b/src/Makefile.global
index 19ad705c334..b09925c6ab0 100644
--- a/src/Makefile.global
+++ b/src/Makefile.global
@@ -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
##############################################################################
#
diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c
index 3f44037ca74..cba2e211994 100644
--- a/src/backend/parser/analyze.c
+++ b/src/backend/parser/analyze.c
@@ -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
*/
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);
diff --git a/src/test/regress/create.source b/src/test/regress/create.source
index f3fb711dc72..050c9a86a62 100644
--- a/src/test/regress/create.source
+++ b/src/test/regress/create.source
@@ -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"}',