]> granicus.if.org Git - postgresql/commitdiff
This patch for Versions 1 and 2 corrects the following bug:
authorMarc G. Fournier <scrappy@hub.org>
Sat, 24 Aug 1996 20:56:16 +0000 (20:56 +0000)
committerMarc G. Fournier <scrappy@hub.org>
Sat, 24 Aug 1996 20:56:16 +0000 (20:56 +0000)
In a catalog class that has a "name" type attribute, UPDATEing of an
instance of that class may destroy all of the attributes of that
instance that are stored as or after the "name" attribute.

This is caused by the alignment value of the "name" type being set to
"double" in Class pg_type, but "integer" in Class pg_attribute.
Postgres constructs a tuple using double alignment, but interprets it
using integer alignment.

The fix is to change the alignment to integer in pg_type.

Note that this corrects the problem for new Postgres systems.  Existing
databases already contain the error and it can't easily be repaired because
this very bug prevents updating the class that contains it.

--
Bryan Henderson                                    Phone 408-227-6803
San Jose, California

src/backend/catalog/pg_attribute.h
src/backend/catalog/pg_type.h

index 4de5884005299f06833d36aca8d48b62fd4ff71d..1629462199143a2bf9c6edfc25f517a24e7e9bab 100644 (file)
@@ -7,7 +7,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pg_attribute.h,v 1.2 1996/08/21 04:25:47 scrappy Exp $
+ * $Id: pg_attribute.h,v 1.3 1996/08/24 20:56:13 scrappy Exp $
  *
  * NOTES
  *    the genbki.sh script reads this file and generates .bki
@@ -44,13 +44,19 @@ CATALOG(pg_attribute) BOOTSTRAP {
     Oid        attrelid;      
     NameData   attname;
     Oid        atttypid;
+      /* atttypid is the OID of the instance in Catalog Class pg_type that
+         defines the data type of this attribute (e.g. int4).  Information in
+         that instance is redundant with the attlen, attbyval, and attalign
+         attributes of this instance, so they had better match or Postgres
+         will fail.
+         */
     Oid        attdefrel;
     int4       attnvals;
     Oid        atttyparg;      /* type arg for arrays/spquel/procs */
     int2       attlen;
-      /* attlen is the number of bytes we use to represent the value 
-         of this attribute, e.g. 4 for an int4.  But for a variable length 
-         attribute, attlen is -1.
+      /* attlen is a copy of the typlen field from pg_type for this
+         attribute.  See atttypid above.  See struct TypeTupleFormData for
+         definition.
          */
     int2       attnum;
       /* attnum is the "attribute number" for the attribute:  A 
@@ -68,6 +74,10 @@ CATALOG(pg_attribute) BOOTSTRAP {
          */
     int2       attbound;
     bool       attbyval;
+      /* attbyval is a copy of the typbyval field from pg_type for this
+         attribute.  See atttypid above.  See struct TypeTupleFormData for
+         definition.
+         */
     bool       attcanindex;
     Oid        attproc;        /* spquel? */
     int4       attnelems;
@@ -80,7 +90,11 @@ CATALOG(pg_attribute) BOOTSTRAP {
          walking process.  
          */
     bool        attisset;
-    char       attalign;  /* alignment (c=char, s=short, i=int, d=double) */
+    char       attalign; 
+      /* attalign is a copy of the typalign field from pg_type for this
+         attribute.  See atttypid above.  See struct TypeTupleFormData for
+         definition.
+         */
 } FormData_pg_attribute;
 
 /*
index 029c25a781f39418776ed6f76891f8a3e0547d8c..39ebdb6bdaf16096bb323cf9106926c5d518c9a9 100644 (file)
@@ -7,7 +7,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pg_type.h,v 1.3 1996/07/19 05:21:28 scrappy Exp $
+ * $Id: pg_type.h,v 1.4 1996/08/24 20:56:16 scrappy Exp $
  *
  * NOTES
  *    the genbki.sh script reads this file and generates .bki
 /* ----------------
  *     pg_type definition.  cpp turns this into
  *     typedef struct FormData_pg_type
+ *
+ *      Some of the values in a pg_type instance are copied into 
+ *      pg_attribute intances.  Some parts of Postgres use the pg_type copy,
+ *      while others use the pg_attribute copy, so they must match.
+ *      See struct FormData_pg_attribute for details.
  * ----------------
  */
 CATALOG(pg_type) BOOTSTRAP {
     NameData   typname;
     Oid        typowner;
     int2       typlen;
+      /* typlen is the number of bytes we use to represent a value of
+         this type, e.g. 4 for an int4.  But for a variable length
+         attribute, typlen is -1.  
+         */
     int2       typprtlen;
     bool       typbyval;
+      /* typbyval determines whether internal Postgres routines pass a value
+         of this type by value or by reference.  Postgres uses a 4 byte 
+         area for passing class data, so if the value is not 1, 2,
+         or 4 bytes long, Postgres does not have the option of passing by
+         value and ignores typbyval.  
+
+         (I don't understand why this attribute exists.  The above description
+         may be an oversimplification.  Also, there appear to be bugs in which
+         Postgres doesn't ignore typbyval when it should, but I'm 
+         afraid to change them until I see proof of damage. -BRYANH 96.08).
+         */
     char       typtype;
     bool       typisdefined;
     char       typdelim;
@@ -47,7 +67,23 @@ CATALOG(pg_type) BOOTSTRAP {
     regproc    typoutput;
     regproc    typreceive;
     regproc    typsend;
-    char       typalign;       /* alignment (c=char, s=short, i=int, d=double) */
+    char       typalign;
+      /* typalign is the alignment required when storing a value of this
+         type.  It applies to storage on disk as well as most representations
+         of the value inside Postgres.  When multiple values are stored 
+         consecutively, such as in the representation of a complete tuple
+         on disk, padding is inserted before a datum of this type so that it
+         begins on the specified boundary.  The alignment reference is the 
+         beginning of the first datum in the sequence.
+
+         'c' = 1 byte alignment.
+         's' = 2 byte alignment.
+         'i' = 4 byte alignment.
+         'd' = 8 byte alignment.
+
+         (This might actually be flexible depending on machine architecture,
+         but I doubt it - BRYANH 96.08).
+         */
     text       typdefault;     /* VARIABLE LENGTH FIELD */
 } TypeTupleFormData;
 
@@ -87,6 +123,11 @@ typedef TypeTupleFormData   *TypeTupleForm;
 
 /* keep the following ordered by OID so that later changes can be made easier*/
 
+/* Make sure the typlen, typbyval, and typalign values here match the initial
+   values for attlen, attbyval, and attalign in both places in pg_attribute.h 
+   for every instance.
+*/
+
 /* OIDS 1 - 99 */
 DATA(insert OID = 16 (  bool       PGUID  1   1 t b t \054 0   0 boolin boolout boolin boolout c _null_ ));
 
@@ -95,7 +136,7 @@ DATA(insert OID = 16 (  bool       PGUID  1   1 t b t \054 0   0 boolin boolout
 DATA(insert OID = 17 (  bytea      PGUID -1  -1 f b t \054 0  18 byteain byteaout byteain byteaout i _null_ ));
 DATA(insert OID = 18 (  char       PGUID  1   1 t b t \054 0   0 charin charout charin charout c _null_ ));
 
-DATA(insert OID = 19 (  name      PGUID NAMEDATALEN NAMEDATALEN  f b t \054 0  18 namein nameout namein nameout d _null_ ));
+DATA(insert OID = 19 (  name      PGUID NAMEDATALEN NAMEDATALEN  f b t \054 0  18 namein nameout namein nameout i _null_ ));
 DATA(insert OID = 20 (  char16     PGUID 16  16 f b t \054 0  18 char16in char16out char16in char16out i _null_ ));
 /*DATA(insert OID = 20 (  dt         PGUID  4  10 t b t \054 0   0 dtin dtout dtin dtout i _null_ )); */
 DATA(insert OID = 21 (  int2       PGUID  2   5 t b t \054 0   0 int2in int2out int2in int2out s _null_ ));