From: Marc G. Fournier Date: Wed, 21 Aug 1996 04:25:49 +0000 (+0000) Subject: Here's a patch for Versions 1 and 2 that fixes the following bug: X-Git-Tag: REL2_0~630 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=5e773a4f70dd07d57e07cfbc856e7822dc6defdc;p=postgresql Here's a patch for Versions 1 and 2 that fixes the following bug: When you try to do any UPDATE of the catalog class pg_class, such as to change ownership of a class, the backend crashes. This is really two serial bugs: 1) there is a hardcoded copy of the schema of pg_class in the postgres program, and it doesn't match the actual class that initdb creates in the database; 2) Parts of postgres determine whether to pass an attribute value by value or by reference based on the attbyval attribute of the attribute in class pg_attribute. Other parts of postgres have it hardcoded. For the relacl[] attribute in class pg_class, attbyval does not match the hardcoded expectation. The fix is to correct the hardcoded schema for pg_attribute and to change the fetchatt macro so it ignores attbyval for all variable length attributes. The fix also adds a bunch of logic documentation and extends genbki.sh so it allows source files to contain such documentation. -- Bryan Henderson Phone 408-227-6803 San Jose, California --- diff --git a/src/backend/access/tupmacs.h b/src/backend/access/tupmacs.h index 9a9bcce3b4..168a4669c3 100644 --- a/src/backend/access/tupmacs.h +++ b/src/backend/access/tupmacs.h @@ -6,7 +6,7 @@ * * Copyright (c) 1994, Regents of the University of California * - * $Id: tupmacs.h,v 1.1.1.1 1996/07/09 06:21:09 scrappy Exp $ + * $Id: tupmacs.h,v 1.2 1996/08/21 04:25:37 scrappy Exp $ * *------------------------------------------------------------------------- */ @@ -22,6 +22,12 @@ * given a AttributeTupleForm and a pointer into a tuple's data * area, return the correct value or pointer. * + * We return a 4 byte (char *) value in all cases. If the attribute has + * "byval" false or has variable length, we return the same pointer + * into the tuple data area that we're passed. Otherwise, we return + * the 1, 2, or 4 bytes pointed to by it, properly extended to 4 + * bytes, depending on the length of the attribute. + * * note that T must already be properly LONGALIGN/SHORTALIGN'd for * this to work correctly. * @@ -30,9 +36,15 @@ * sign-extension may get weird if you use an integer type that * isn't the same size as (char *) for the first cast. (on the other * hand, it's safe to use another type for the (foo *)(T).) + * + * attbyval seems to be fairly redundant. We have to return a pointer if + * the value is longer than 4 bytes or has variable length; returning the + * value would be useless. In fact, for at least the variable length case, + * the caller assumes we return a pointer regardless of attbyval. + * I would eliminate attbyval altogether, but I don't know how. -BRYANH. */ #define fetchatt(A, T) \ - ((*(A))->attbyval \ + ((*(A))->attbyval && (*(A))->attlen != -1 \ ? ((*(A))->attlen > sizeof(int16) \ ? (char *) (long) *((int32 *)(T)) \ : ((*(A))->attlen < sizeof(int16) \ diff --git a/src/backend/catalog/genbki.sh b/src/backend/catalog/genbki.sh index d8f5d29025..c42beff980 100644 --- a/src/backend/catalog/genbki.sh +++ b/src/backend/catalog/genbki.sh @@ -10,7 +10,7 @@ # # # IDENTIFICATION -# $Header: /cvsroot/pgsql/src/backend/catalog/Attic/genbki.sh,v 1.2 1996/08/19 13:52:02 scrappy Exp $ +# $Header: /cvsroot/pgsql/src/backend/catalog/Attic/genbki.sh,v 1.3 1996/08/21 04:25:44 scrappy Exp $ # # NOTES # non-essential whitespace is removed from the generated file. @@ -58,8 +58,11 @@ done cat $SYSFILES | \ sed -e 's/\/\*.*\*\///g' \ -e 's/;[ ]*$//g' \ + -e 's/^[ ]*//g' \ -e 's/\ Oid/\ oid/g' \ -e 's/\ NameData/\ name/g' \ + -e 's/^Oid/oid/g' \ + -e 's/^NameData/\name/g' \ -e 's/(NameData/(name/g' \ -e 's/(Oid/(oid/g' | \ gawk ' @@ -78,8 +81,21 @@ BEGIN { bootstrap = 0; nc = 0; reln_open = 0; + comment_level = 0; } +# ---------------- +# Anything in a /* .. */ block should be ignored. +# Blank lines also go. +# Note that any /* */ comment on a line by itself was removed from the line +# by the sed above. +# ---------------- +/^\/\*/ { comment_level += 1; next; } +/^*\// { comment_level -= 1; next; } +comment_level > 0 { next; } + +/^[ ]*$/ { next; } + # ---------------- # anything in a BKI_BEGIN .. BKI_END block should be passed # along without interpretation. diff --git a/src/backend/catalog/pg_attribute.h b/src/backend/catalog/pg_attribute.h index d8133177d5..4de5884005 100644 --- a/src/backend/catalog/pg_attribute.h +++ b/src/backend/catalog/pg_attribute.h @@ -7,7 +7,7 @@ * * Copyright (c) 1994, Regents of the University of California * - * $Id: pg_attribute.h,v 1.1.1.1 1996/07/09 06:21:16 scrappy Exp $ + * $Id: pg_attribute.h,v 1.2 1996/08/21 04:25:47 scrappy Exp $ * * NOTES * the genbki.sh script reads this file and generates .bki @@ -18,12 +18,6 @@ * these changes, be sure and change the appropriate Schema_xxx * macros! -cim 2/5/91 * - * fastgetattr() now uses attcacheoff to cache byte offsets of - * attributes in heap tuples. The data actually stored in - * pg_attribute (-1) indicates no cached value. But when we copy - * these tuples into a tuple descriptor, we may then update attcacheoff - * in the copies. This speeds up the attribute walking process. - * *------------------------------------------------------------------------- */ #ifndef PG_ATTRIBUTE_H @@ -54,15 +48,39 @@ CATALOG(pg_attribute) BOOTSTRAP { 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. + */ int2 attnum; + /* attnum is the "attribute number" for the attribute: A + value that uniquely identifies this attribute within its class. + For user attributes, Attribute numbers are greater than 0 and + not greater than the number of attributes in the class. + I.e. if the Class pg_class says that Class XYZ has 10 + attributes, then the user attribute numbers in Class + pg_attribute must be 1-10. + + System attributes have attribute numbers less than 0 that are + unique within the class, but not constrained to any particular range. + + Note that (attnum - 1) is often used as the index to an array. + */ int2 attbound; bool attbyval; bool attcanindex; Oid attproc; /* spquel? */ int4 attnelems; int4 attcacheoff; + /* fastgetattr() uses attcacheoff to cache byte offsets of + attributes in heap tuples. The data actually stored in + pg_attribute (-1) indicates no cached value. But when we + copy these tuples into a tuple descriptor, we may then update + attcacheoff in the copies. This speeds up the attribute + walking process. + */ bool attisset; - char attalign; /* alignment (c=char, s=short, i=int, d=double) */ + char attalign; /* alignment (c=char, s=short, i=int, d=double) */ } FormData_pg_attribute; /* @@ -380,43 +398,43 @@ DATA(insert OID = 0 ( 75 vtype 18 0 0 0 1 -11 0 t t 0 0 -1 f c)); * ---------------- */ #define Schema_pg_class \ -{ 83l, {"relname"}, 19l, 83l, 0l, 0l, NAMEDATALEN, 1, 0, '\0', '\001', 0l, 0l, -1l, '\0', 'i' }, \ -{ 83l, {"reltype"}, 26l, 83l, 0l, 0l, 4, 2, 0, '\001', '\001', 0l, 0l, -1l, '\0', 'i' }, \ -{ 83l, {"relowner"}, 26l, 83l, 0l, 0l, 4, 2, 0, '\001', '\001', 0l, 0l, -1l, '\0', 'i' }, \ -{ 83l, {"relam"}, 26l, 83l, 0l, 0l, 4, 3, 0, '\001', '\001', 0l, 0l, -1l, '\0', 'i' }, \ -{ 83l, {"relpages"}, 23, 83l, 0l, 0l, 4, 4, 0, '\001', '\001', 0l, 0l, -1l, '\0', 'i' }, \ -{ 83l, {"reltuples"}, 23, 83l, 0l, 0l, 4, 5, 0, '\001', '\001', 0l, 0l, -1l, '\0', 'i' }, \ -{ 83l, {"relexpires"}, 702, 83l, 0l, 0l, 4, 6, 0, '\001', '\001', 0l, 0l, -1l, '\0', 'i' }, \ -{ 83l, {"relpreserved"}, 703, 83l, 0l, 0l, 4, 7, 0, '\001', '\001', 0l, 0l, -1l, '\0', 'i' }, \ -{ 83l, {"relhasindex"}, 16, 83l, 0l, 0l, 1, 8, 0, '\001', '\001', 0l, 0l, -1l, '\0', 'c' }, \ -{ 83l, {"relisshared"}, 16, 83l, 0l, 0l, 1, 9, 0, '\001', '\001', 0l, 0l, -1l, '\0', 'c' }, \ -{ 83l, {"relkind"}, 18, 83l, 0l, 0l, 1, 10, 0, '\001', '\001', 0l, 0l, -1l, '\0', 'c' }, \ -{ 83l, {"relarch"}, 18, 83l, 0l, 0l, 1, 11, 0, '\001', '\001', 0l, 0l, -1l, '\0', 'c' }, \ -{ 83l, {"relnatts"}, 21, 83l, 0l, 0l, 2, 12, 0, '\001', '\001', 0l, 0l, -1l, '\0', 's' }, \ -{ 83l, {"relsmgr"}, 210l, 83l, 0l, 0l, 2, 13, 0, '\001', '\001', 0l, 0l, -1l, '\0', 's' }, \ -{ 83l, {"relkey"}, 22, 83l, 0l, 0l, 16, 14, 0, '\0', '\001', 0l, 0l, -1l, '\0', 'i' }, \ -{ 83l, {"relkeyop"}, 30, 83l, 0l, 0l, 32, 15, 0, '\0', '\001', 0l, 0l, -1l, '\0', 'i' }, \ -{ 83l, {"relhasrules"}, 16, 83l, 0l, 0l, 1, 16, 0, '\001', '\001', 0l, 0l, -1l, '\0', 'c' }, \ -{ 83l, {"relacl"}, 1034l, 83l, 0l, 0l, -1, 17, 0, '\0', '\001', 0l, 0l, -1l, '\0', 'i' } +{ 83l, {"relname"}, 19l, 83l, 0l, 0l, NAMEDATALEN, 1, 0, '\000', '\001', 0l, 0l, -1l, '\0', 'i' }, \ +{ 83l, {"reltype"}, 26l, 83l, 0l, 0l, 4, 2, 0, '\001', '\001', 0l, 0l, -1l, '\0', 'i' }, \ +{ 83l, {"relowner"}, 26l, 83l, 0l, 0l, 4, 3, 0, '\001', '\001', 0l, 0l, -1l, '\0', 'i' }, \ +{ 83l, {"relam"}, 26l, 83l, 0l, 0l, 4, 4, 0, '\001', '\001', 0l, 0l, -1l, '\0', 'i' }, \ +{ 83l, {"relpages"}, 23, 83l, 0l, 0l, 4, 5, 0, '\001', '\001', 0l, 0l, -1l, '\0', 'i' }, \ +{ 83l, {"reltuples"}, 23, 83l, 0l, 0l, 4, 6, 0, '\001', '\001', 0l, 0l, -1l, '\0', 'i' }, \ +{ 83l, {"relexpires"}, 702, 83l, 0l, 0l, 4, 7, 0, '\001', '\001', 0l, 0l, -1l, '\0', 'i' }, \ +{ 83l, {"relpreserved"}, 703, 83l, 0l, 0l, 4, 8, 0, '\001', '\001', 0l, 0l, -1l, '\0', 'i' }, \ +{ 83l, {"relhasindex"}, 16, 83l, 0l, 0l, 1, 9, 0, '\001', '\001', 0l, 0l, -1l, '\0', 'c' }, \ +{ 83l, {"relisshared"}, 16, 83l, 0l, 0l, 1, 10, 0, '\001', '\001', 0l, 0l, -1l, '\0', 'c' }, \ +{ 83l, {"relkind"}, 18, 83l, 0l, 0l, 1, 11, 0, '\001', '\001', 0l, 0l, -1l, '\0', 'c' }, \ +{ 83l, {"relarch"}, 18, 83l, 0l, 0l, 1, 12, 0, '\001', '\001', 0l, 0l, -1l, '\0', 'c' }, \ +{ 83l, {"relnatts"}, 21, 83l, 0l, 0l, 2, 13, 0, '\001', '\001', 0l, 0l, -1l, '\0', 's' }, \ +{ 83l, {"relsmgr"}, 210l, 83l, 0l, 0l, 2, 14, 0, '\001', '\001', 0l, 0l, -1l, '\0', 's' }, \ +{ 83l, {"relkey"}, 22, 83l, 0l, 0l, 16, 15, 0, '\000', '\001', 0l, 0l, -1l, '\0', 'i' }, \ +{ 83l, {"relkeyop"}, 30, 83l, 0l, 0l, 32, 16, 0, '\000', '\001', 0l, 0l, -1l, '\0', 'i' }, \ +{ 83l, {"relhasrules"}, 16, 83l, 0l, 0l, 1, 17, 0, '\001', '\001', 0l, 0l, -1l, '\0', 'c' }, \ +{ 83l, {"relacl"}, 1034l, 83l, 0l, 0l, -1, 18, 0, '\000', '\001', 0l, 0l, -1l, '\0', 'i' } DATA(insert OID = 0 ( 83 relname 19 0 0 0 NAMEDATALEN 1 0 f t 0 0 -1 f i)); DATA(insert OID = 0 ( 83 reltype 26 0 0 0 4 2 0 t t 0 0 -1 f i)); -DATA(insert OID = 0 ( 83 relowner 26 0 0 0 4 2 0 t t 0 0 -1 f i)); -DATA(insert OID = 0 ( 83 relam 26 0 0 0 4 3 0 t t 0 0 -1 f i)); -DATA(insert OID = 0 ( 83 relpages 23 0 0 0 4 4 0 t t 0 0 -1 f i)); -DATA(insert OID = 0 ( 83 reltuples 23 0 0 0 4 5 0 t t 0 0 -1 f i)); -DATA(insert OID = 0 ( 83 relexpires 702 0 0 0 4 6 0 t t 0 0 -1 f i)); -DATA(insert OID = 0 ( 83 relpreserved 702 0 0 0 4 7 0 t t 0 0 -1 f i)); -DATA(insert OID = 0 ( 83 relhasindex 16 0 0 0 1 8 0 t t 0 0 -1 f c)); -DATA(insert OID = 0 ( 83 relisshared 16 0 0 0 1 9 0 t t 0 0 -1 f c)); -DATA(insert OID = 0 ( 83 relkind 18 0 0 0 1 10 0 t t 0 0 -1 f c)); -DATA(insert OID = 0 ( 83 relarch 18 0 0 0 1 11 0 t t 0 0 -1 f c)); -DATA(insert OID = 0 ( 83 relnatts 21 0 0 0 2 12 0 t t 0 0 -1 f s)); -DATA(insert OID = 0 ( 83 relsmgr 210 0 0 0 2 13 0 t t 0 0 -1 f s)); -DATA(insert OID = 0 ( 83 relkey 22 0 0 0 16 14 0 f t 0 0 -1 f i)); -DATA(insert OID = 0 ( 83 relkeyop 30 0 0 0 32 15 0 f t 0 0 -1 f i)); -DATA(insert OID = 0 ( 83 relhasrules 16 0 0 0 1 16 0 t t 0 0 -1 f c)); -DATA(insert OID = 0 ( 83 relacl 1034 0 0 0 -1 17 0 f t 0 0 -1 f i)); +DATA(insert OID = 0 ( 83 relowner 26 0 0 0 4 3 0 t t 0 0 -1 f i)); +DATA(insert OID = 0 ( 83 relam 26 0 0 0 4 4 0 t t 0 0 -1 f i)); +DATA(insert OID = 0 ( 83 relpages 23 0 0 0 4 5 0 t t 0 0 -1 f i)); +DATA(insert OID = 0 ( 83 reltuples 23 0 0 0 4 6 0 t t 0 0 -1 f i)); +DATA(insert OID = 0 ( 83 relexpires 702 0 0 0 4 7 0 t t 0 0 -1 f i)); +DATA(insert OID = 0 ( 83 relpreserved 703 0 0 0 4 8 0 t t 0 0 -1 f i)); +DATA(insert OID = 0 ( 83 relhasindex 16 0 0 0 1 9 0 t t 0 0 -1 f c)); +DATA(insert OID = 0 ( 83 relisshared 16 0 0 0 1 10 0 t t 0 0 -1 f c)); +DATA(insert OID = 0 ( 83 relkind 18 0 0 0 1 11 0 t t 0 0 -1 f c)); +DATA(insert OID = 0 ( 83 relarch 18 0 0 0 1 12 0 t t 0 0 -1 f c)); +DATA(insert OID = 0 ( 83 relnatts 21 0 0 0 2 13 0 t t 0 0 -1 f s)); +DATA(insert OID = 0 ( 83 relsmgr 210 0 0 0 2 14 0 t t 0 0 -1 f s)); +DATA(insert OID = 0 ( 83 relkey 22 0 0 0 16 15 0 f t 0 0 -1 f i)); +DATA(insert OID = 0 ( 83 relkeyop 30 0 0 0 32 16 0 f t 0 0 -1 f i)); +DATA(insert OID = 0 ( 83 relhasrules 16 0 0 0 1 17 0 t t 0 0 -1 f c)); +DATA(insert OID = 0 ( 83 relacl 1034 0 0 0 -1 18 0 f t 0 0 -1 f i)); DATA(insert OID = 0 ( 83 ctid 27 0 0 0 6 -1 0 f t 0 0 -1 f i)); DATA(insert OID = 0 ( 83 oid 26 0 0 0 4 -2 0 t t 0 0 -1 f i)); DATA(insert OID = 0 ( 83 xmin 28 0 0 0 4 -3 0 f t 0 0 -1 f i)); diff --git a/src/backend/catalog/pg_class.h b/src/backend/catalog/pg_class.h index f9fdbfb1c3..d60e694a44 100644 --- a/src/backend/catalog/pg_class.h +++ b/src/backend/catalog/pg_class.h @@ -7,7 +7,7 @@ * * Copyright (c) 1994, Regents of the University of California * - * $Id: pg_class.h,v 1.2 1996/08/04 22:00:13 scrappy Exp $ + * $Id: pg_class.h,v 1.3 1996/08/21 04:25:49 scrappy Exp $ * * NOTES * ``pg_relation'' is being replaced by ``pg_class''. currently @@ -66,6 +66,10 @@ CATALOG(pg_class) BOOTSTRAP { char relkind; char relarch; /* 'h' = heavy, 'l' = light, 'n' = no archival*/ int2 relnatts; + /* relnatts is the number of user attributes this class has. There + must be exactly this many instances in Class pg_attribute for this + class which have attnum > 0 (= user attribute). + */ int2 relsmgr; int28 relkey; /* not used */ oid8 relkeyop; /* not used */