]> granicus.if.org Git - postgresql/commitdiff
Fixes:
authorMarc G. Fournier <scrappy@hub.org>
Sat, 20 Jul 1996 07:59:41 +0000 (07:59 +0000)
committerMarc G. Fournier <scrappy@hub.org>
Sat, 20 Jul 1996 07:59:41 +0000 (07:59 +0000)
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>

src/Makefile.global
src/backend/parser/analyze.c
src/backend/utils/adt/arrayfuncs.c
src/test/regress/create.source

index 19ad705c3341148849da0b4558434dbaef8fdda0..b09925c6ab038acbd6a6fd3567918ff3c90f2167 100644 (file)
@@ -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
 
 ##############################################################################
 #
index 3f44037ca74db5dbe09efc9f0f954cacd2274a8e..cba2e2119949538ad20fcde395689c52439ccc4a 100644 (file)
@@ -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
                        */
index 2e780fb03b629cf5a8ddcd5518f626c260106e52..8a2b0fd2910098ea012eff2f03fb42d339f065e4 100644 (file)
@@ -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);
index f3fb711dc721d6d837533fa382989efbc4f5c463..050c9a86a62741b63d2c7fc573df89b502b1c17b 100644 (file)
@@ -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"}',