diff --git a/src/backend/access/common/heaptuple.c b/src/backend/access/common/heaptuple.c index 4640b2022438a19a69499319a919cc6023bc1789..e76fa5a5652873125de876b9a4cc03da080ed6a3 100644 --- a/src/backend/access/common/heaptuple.c +++ b/src/backend/access/common/heaptuple.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/common/heaptuple.c,v 1.66 2000/11/14 21:04:32 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/common/heaptuple.c,v 1.67 2000/11/30 18:38:45 tgl Exp $ * * NOTES * The old interface functions have been converted to macros @@ -300,11 +300,11 @@ nocachegetattr(HeapTuple tuple, TupleDesc tupleDesc, bool *isnull) { - char *tp; /* ptr to att in tuple */ HeapTupleHeader tup = tuple->t_data; - bits8 *bp = tup->t_bits; /* ptr to att in tuple */ Form_pg_attribute *att = tupleDesc->attrs; - int slow = 0; /* do we have to walk nulls? */ + char *tp; /* ptr to att in tuple */ + bits8 *bp = tup->t_bits; /* ptr to null bitmask in tuple */ + bool slow = false; /* do we have to walk nulls? */ (void) isnull; /* not used */ #ifdef IN_MACRO @@ -336,14 +336,6 @@ nocachegetattr(HeapTuple tuple, fetchatt(&(att[attnum]), (char *) tup + tup->t_hoff + att[attnum]->attcacheoff); } - else if (attnum == 0) - { - - /* - * first attribute is always at position zero - */ - return (Datum) fetchatt(&(att[0]), (char *) tup + tup->t_hoff); - } #endif } else @@ -378,7 +370,7 @@ nocachegetattr(HeapTuple tuple, /* check for nulls "before" final bit of last byte */ if ((~bp[byte]) & ((1 << finalbit) - 1)) - slow = 1; + slow = true; else { /* check for nulls in any "earlier" bytes */ @@ -388,7 +380,7 @@ nocachegetattr(HeapTuple tuple, { if (bp[i] != 0xFF) { - slow = 1; + slow = true; break; } } @@ -408,21 +400,19 @@ nocachegetattr(HeapTuple tuple, return (Datum) fetchatt(&(att[attnum]), tp + att[attnum]->attcacheoff); } - else if (attnum == 0) - return (Datum) fetchatt(&(att[0]), tp); else if (!HeapTupleAllFixed(tuple)) { int j; /* - * In for(), we make this <= and not < because we want to test + * In for(), we test <= and not < because we want to see * if we can go past it in initializing offsets. */ for (j = 0; j <= attnum; j++) { - if (att[j]->attlen < 1 && !VARLENA_FIXED_SIZE(att[j])) + if (att[j]->attlen <= 0) { - slow = 1; + slow = true; break; } } @@ -430,7 +420,7 @@ nocachegetattr(HeapTuple tuple, } /* - * If slow is zero, and we got here, we know that we have a tuple with + * If slow is false, and we got here, we know that we have a tuple with * no nulls or varlenas before the target attribute. If possible, we * also want to initialize the remainder of the attribute cached * offset values. @@ -446,21 +436,17 @@ nocachegetattr(HeapTuple tuple, att[0]->attcacheoff = 0; - while (att[j]->attcacheoff > 0) + while (j < attnum && att[j]->attcacheoff > 0) j++; - if (!VARLENA_FIXED_SIZE(att[j - 1])) - off = att[j - 1]->attcacheoff + att[j - 1]->attlen; - else - off = att[j - 1]->attcacheoff + att[j - 1]->atttypmod; + off = att[j - 1]->attcacheoff + att[j - 1]->attlen; for (; j <= attnum || /* Can we compute more? We will probably need them */ (j < tup->t_natts && att[j]->attcacheoff == -1 && (HeapTupleNoNulls(tuple) || !att_isnull(j, bp)) && - (HeapTupleAllFixed(tuple) || - att[j]->attlen > 0 || VARLENA_FIXED_SIZE(att[j]))); j++) + (HeapTupleAllFixed(tuple) || att[j]->attlen > 0)); j++) { /* @@ -516,8 +502,7 @@ nocachegetattr(HeapTuple tuple, off = att_addlength(off, att[i]->attlen, tp + off); - if (usecache && - att[i]->attlen == -1 && !VARLENA_FIXED_SIZE(att[i])) + if (usecache && att[i]->attlen == -1) usecache = false; } diff --git a/src/backend/access/common/indextuple.c b/src/backend/access/common/indextuple.c index 15ed18245607afd8380c783e817e2eba562d69d3..9f2bfb02c530a9545a4ff33641c25895801d85f8 100644 --- a/src/backend/access/common/indextuple.c +++ b/src/backend/access/common/indextuple.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/common/indextuple.c,v 1.46 2000/11/16 05:50:57 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/common/indextuple.c,v 1.47 2000/11/30 18:38:45 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -160,13 +160,13 @@ index_formtuple(TupleDesc tupleDescriptor, * * This caches attribute offsets in the attribute descriptor. * - * an alternate way to speed things up would be to cache offsets + * An alternate way to speed things up would be to cache offsets * with the tuple, but that seems more difficult unless you take * the storage hit of actually putting those offsets into the * tuple you send to disk. Yuck. * * This scheme will be slightly slower than that, but should - * preform well for queries which hit large #'s of tuples. After + * perform well for queries which hit large #'s of tuples. After * you cache the offsets once, examining all the other tuples using * the same attribute descriptor will go much quicker. -cim 5/4/91 * ---------------- @@ -177,13 +177,13 @@ nocache_index_getattr(IndexTuple tup, TupleDesc tupleDesc, bool *isnull) { + Form_pg_attribute *att = tupleDesc->attrs; char *tp; /* ptr to att in tuple */ - char *bp = NULL; /* ptr to att in tuple */ - int slow; /* do we have to walk nulls? */ + bits8 *bp = NULL; /* ptr to null bitmask in tuple */ + bool slow = false; /* do we have to walk nulls? */ int data_off; /* tuple data offset */ - Form_pg_attribute *att = tupleDesc->attrs; - (void) isnull; + (void) isnull; /* not used */ /* ---------------- * sanity checks * ---------------- @@ -209,17 +209,12 @@ nocache_index_getattr(IndexTuple tup, data_off = IndexTupleHasMinHeader(tup) ? sizeof *tup : IndexInfoFindDataOffset(tup->t_info); + attnum--; + if (IndexTupleNoNulls(tup)) { - attnum--; - #ifdef IN_MACRO /* This is handled in the macro */ - - /* first attribute is always at position zero */ - - if (attnum == 1) - return (Datum) fetchatt(&(att[0]), (char *) tup + data_off); if (att[attnum]->attcacheoff != -1) { return (Datum) fetchatt(&(att[attnum]), @@ -227,20 +222,13 @@ nocache_index_getattr(IndexTuple tup, att[attnum]->attcacheoff); } #endif - - slow = 0; } else { /* there's a null somewhere in the tuple */ - - slow = 0; /* ---------------- * check to see if desired att is null * ---------------- */ - - attnum--; - bp = (char *) tup + sizeof(*tup); /* "knows" t_bits are * here! */ #ifdef IN_MACRO @@ -254,34 +242,28 @@ nocache_index_getattr(IndexTuple tup, #endif /* ---------------- - * Now check to see if any preceeding bits are null... + * Now check to see if any preceding bits are null... * ---------------- */ { - int i = 0; /* current offset in bp */ - int mask; /* bit in byte we're looking at */ - char n; /* current byte in bp */ - int byte, - finalbit; + int byte = attnum >> 3; + int finalbit = attnum & 0x07; - byte = attnum >> 3; - finalbit = attnum & 0x07; - - for (; i <= byte && !slow; i++) + /* check for nulls "before" final bit of last byte */ + if ((~bp[byte]) & ((1 << finalbit) - 1)) + slow = true; + else { - n = bp[i]; - if (i < byte) - { - /* check for nulls in any "earlier" bytes */ - if ((~n) != 0) - slow = 1; - } - else + /* check for nulls in any "earlier" bytes */ + int i; + + for (i = 0; i < byte; i++) { - /* check for nulls "before" final bit of last byte */ - mask = (1 << finalbit) - 1; - if ((~n) & mask) - slow = 1; + if (bp[i] != 0xFF) + { + slow = true; + break; + } } } } @@ -298,24 +280,25 @@ nocache_index_getattr(IndexTuple tup, return (Datum) fetchatt(&(att[attnum]), tp + att[attnum]->attcacheoff); } - else if (attnum == 0) - return (Datum) fetchatt(&(att[0]), (char *) tp); else if (!IndexTupleAllFixed(tup)) { - int j = 0; + int j; - for (j = 0; j < attnum && !slow; j++) - if (att[j]->attlen < 1 && !VARLENA_FIXED_SIZE(att[j])) - slow = 1; + for (j = 0; j < attnum; j++) + if (att[j]->attlen <= 0) + { + slow = true; + break; + } } } /* - * if slow is zero, and we got here, we know that we have a tuple with - * no nulls. We also know that we have to initialize the remainder of - * the attribute cached offset values. + * If slow is false, and we got here, we know that we have a tuple with + * no nulls or varlenas before the target attribute. If possible, we + * also want to initialize the remainder of the attribute cached + * offset values. */ - if (!slow) { int j = 1; @@ -327,15 +310,12 @@ nocache_index_getattr(IndexTuple tup, att[0]->attcacheoff = 0; - while (att[j]->attcacheoff != -1) + while (j < attnum && att[j]->attcacheoff > 0) j++; - if (!VARLENA_FIXED_SIZE(att[j - 1])) - off = att[j - 1]->attcacheoff + att[j - 1]->attlen; - else - off = att[j - 1]->attcacheoff + att[j - 1]->atttypmod; + off = att[j - 1]->attcacheoff + att[j - 1]->attlen; - for (; j < attnum + 1; j++) + for (; j <= attnum; j++) { /* @@ -347,14 +327,7 @@ nocache_index_getattr(IndexTuple tup, att[j]->attcacheoff = off; - /* The only varlena/-1 length value to get here is this */ - if (!VARLENA_FIXED_SIZE(att[j])) - off += att[j]->attlen; - else - { - Assert(att[j]->atttypmod == VARSIZE(tp + off)); - off += att[j]->atttypmod; - } + off += att[j]->attlen; } return (Datum) fetchatt(&(att[attnum]), tp + att[attnum]->attcacheoff); @@ -391,27 +364,14 @@ nocache_index_getattr(IndexTuple tup, att[i]->attcacheoff = off; } - switch (att[i]->attlen) + if (att[i]->attlen == -1) { - case sizeof(char): - off++; - break; - case sizeof(short): - off += sizeof(short); - break; - case sizeof(int32): - off += sizeof(int32); - break; - case -1: - Assert(!VARLENA_FIXED_SIZE(att[i]) || - att[i]->atttypmod == VARSIZE(tp + off)); - off += VARSIZE(tp + off); - if (!VARLENA_FIXED_SIZE(att[i])) - usecache = false; - break; - default: - off += att[i]->attlen; - break; + off += VARSIZE(tp + off); + usecache = false; + } + else + { + off += att[i]->attlen; } } diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c index 7b60a897aa468e5de8cd5dcb40e228acf0b43fb0..f345df7cc110e34d03c78fdac450c7cf2e927f58 100644 --- a/src/backend/access/heap/heapam.c +++ b/src/backend/access/heap/heapam.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.97 2000/11/30 08:46:20 vadim Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.98 2000/11/30 18:38:45 tgl Exp $ * * * INTERFACE ROUTINES @@ -535,18 +535,11 @@ fastgetattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, ((isnull) ? (*(isnull) = false) : (dummyret) NULL), HeapTupleNoNulls(tup) ? ( - ((tupleDesc)->attrs[(attnum) - 1]->attcacheoff != -1 || - (attnum) == 1) ? + (tupleDesc)->attrs[(attnum) - 1]->attcacheoff >= 0 ? ( (Datum) fetchatt(&((tupleDesc)->attrs[(attnum) - 1]), (char *) (tup)->t_data + (tup)->t_data->t_hoff + - ( - ((attnum) != 1) ? - (tupleDesc)->attrs[(attnum) - 1]->attcacheoff - : - 0 - ) - ) + (tupleDesc)->attrs[(attnum) - 1]->attcacheoff) ) : nocachegetattr((tup), (attnum), (tupleDesc), (isnull)) diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index 2f4697a39b84f5083d315b2693840d4b2037ec8f..e4551d4c604b2dd48d4b6a1f06ece095752d44c7 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.117 2000/11/30 08:46:24 vadim Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.118 2000/11/30 18:38:46 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -630,6 +630,32 @@ build_tupdesc_seq(RelationBuildDescInfo buildinfo, heap_endscan(pg_attribute_scan); heap_close(pg_attribute_desc, AccessShareLock); + /* ---------------- + * The attcacheoff values we read from pg_attribute should all be -1 + * ("unknown"). Verify this if assert checking is on. They will be + * computed when and if needed during tuple access. + * ---------------- + */ +#ifdef USE_ASSERT_CHECKING + { + int i; + + for (i = 0; i < relation->rd_rel->relnatts; i++) + { + Assert(relation->rd_att->attrs[i]->attcacheoff == -1); + } + } +#endif + + /* ---------------- + * However, we can easily set the attcacheoff value for the first + * attribute: it must be zero. This eliminates the need for special + * cases for attnum=1 that used to exist in fastgetattr() and + * index_getattr(). + * ---------------- + */ + relation->rd_att->attrs[0]->attcacheoff = 0; + SetConstrOfRelation(relation, constr, ndef, attrdef); } @@ -715,6 +741,28 @@ build_tupdesc_ind(RelationBuildDescInfo buildinfo, heap_close(attrel, AccessShareLock); + /* ---------------- + * The attcacheoff values we read from pg_attribute should all be -1 + * ("unknown"). Verify this if assert checking is on. They will be + * computed when and if needed during tuple access. + * ---------------- + */ +#ifdef USE_ASSERT_CHECKING + for (i = 0; i < relation->rd_rel->relnatts; i++) + { + Assert(relation->rd_att->attrs[i]->attcacheoff == -1); + } +#endif + + /* ---------------- + * However, we can easily set the attcacheoff value for the first + * attribute: it must be zero. This eliminates the need for special + * cases for attnum=1 that used to exist in fastgetattr() and + * index_getattr(). + * ---------------- + */ + relation->rd_att->attrs[0]->attcacheoff = 0; + SetConstrOfRelation(relation, constr, ndef, attrdef); } diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h index de4f29348535d14d481bf15d720bbd936aa2037c..db40344dc4668cce1817f25c5c03d3b55a4a9c93 100644 --- a/src/include/access/heapam.h +++ b/src/include/access/heapam.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: heapam.h,v 1.58 2000/11/21 21:16:05 petere Exp $ + * $Id: heapam.h,v 1.59 2000/11/30 18:38:46 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -107,18 +107,11 @@ extern Datum nocachegetattr(HeapTuple tup, int attnum, ((isnull) ? (*(isnull) = false) : (dummyret)NULL), \ HeapTupleNoNulls(tup) ? \ ( \ - ((tupleDesc)->attrs[(attnum)-1]->attcacheoff != -1 || \ - (attnum) == 1) ? \ + (tupleDesc)->attrs[(attnum)-1]->attcacheoff >= 0 ? \ ( \ - (Datum)fetchatt(&((tupleDesc)->attrs[(attnum)-1]), \ + (Datum) fetchatt(&((tupleDesc)->attrs[(attnum)-1]), \ (char *) (tup)->t_data + (tup)->t_data->t_hoff + \ - ( \ - ((attnum) != 1) ? \ - (tupleDesc)->attrs[(attnum)-1]->attcacheoff \ - : \ - 0 \ - ) \ - ) \ + (tupleDesc)->attrs[(attnum)-1]->attcacheoff) \ ) \ : \ nocachegetattr((tup), (attnum), (tupleDesc), (isnull)) \ diff --git a/src/include/access/itup.h b/src/include/access/itup.h index a5047729616ce140246533c24cda382f0338dafe..18639eb7f209ff31ddac9562317f67e40797e2c5 100644 --- a/src/include/access/itup.h +++ b/src/include/access/itup.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: itup.h,v 1.25 2000/07/14 22:17:53 tgl Exp $ + * $Id: itup.h,v 1.26 2000/11/30 18:38:46 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -109,24 +109,17 @@ typedef RetrieveIndexResultData *RetrieveIndexResult; *(isnull) = false, \ IndexTupleNoNulls(tup) ? \ ( \ - ((tupleDesc)->attrs[(attnum)-1]->attcacheoff != -1 || \ - (attnum) == 1) ? \ + (tupleDesc)->attrs[(attnum)-1]->attcacheoff >= 0 ? \ ( \ - (Datum)fetchatt(&((tupleDesc)->attrs[(attnum)-1]), \ + (Datum) fetchatt(&((tupleDesc)->attrs[(attnum)-1]), \ (char *) (tup) + \ ( \ IndexTupleHasMinHeader(tup) ? \ sizeof (*(tup)) \ : \ IndexInfoFindDataOffset((tup)->t_info) \ - ) + \ - ( \ - ((attnum) != 1) ? \ - (tupleDesc)->attrs[(attnum)-1]->attcacheoff \ - : \ - 0 \ - ) \ ) \ + + (tupleDesc)->attrs[(attnum)-1]->attcacheoff) \ ) \ : \ nocache_index_getattr((tup), (attnum), (tupleDesc), (isnull)) \ diff --git a/src/include/catalog/pg_type.h b/src/include/catalog/pg_type.h index 48cf26d172a27ad2b9114a586736218811ec2898..f9f7372fd7800aabfd09ce1372d0917af244d1f5 100644 --- a/src/include/catalog/pg_type.h +++ b/src/include/catalog/pg_type.h @@ -8,7 +8,7 @@ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: pg_type.h,v 1.97 2000/08/21 04:48:52 tgl Exp $ + * $Id: pg_type.h,v 1.98 2000/11/30 18:38:47 tgl Exp $ * * NOTES * the genbki.sh script reads this file and generates .bki @@ -415,7 +415,6 @@ DATA(insert OID = 1700 ( numeric PGUID -1 -1 f b t \054 0 0 numeric_in nume DESCR("numeric(precision, decimal), arbitrary precision number"); #define NUMERICOID 1700 -#define VARLENA_FIXED_SIZE(attr) ((attr)->atttypid == BPCHAROID && (attr)->atttypmod > 0) /* * prototypes for functions in pg_type.c