- /*-------------------------------------------------------------------------
+/*-------------------------------------------------------------------------
*
* heaptuple.c--
* This file contains heap tuple accessor and mutator routines, as well
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/access/common/heaptuple.c,v 1.31 1998/01/31 04:38:02 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/access/common/heaptuple.c,v 1.32 1998/02/04 21:32:08 momjian Exp $
*
* NOTES
* The old interface functions have been converted to macros
#include <access/htup.h>
#include <access/transam.h>
#include <access/tupmacs.h>
+#include <catalog/pg_type.h>
#include <storage/bufpage.h>
#include <utils/memutils.h>
}
else if (attnum == 0)
{
-
/*
* first attribute is always at position zero
*/
}
#endif
- tp = (char *) tup + tup->t_hoff;
-
slow = 0;
}
else
* Now check to see if any preceeding bits are null...
* ----------------
*/
-
{
register int i = 0; /* current offset in bp */
+ register int mask; /* bit in byte we're looking at */
+ register char n; /* current byte in bp */
+ register int byte,
+ finalbit;
- for (i = 0; i < attnum && !slow; i++)
+ byte = attnum >> 3;
+ finalbit = attnum & 0x07;
+
+ for (; i <= byte && !slow; i++)
{
- if (att_isnull(i, bp))
- slow = 1;
+ n = bp[i];
+ if (i < byte)
+ {
+ /* check for nulls in any "earlier" bytes */
+ if ((~n) != 0)
+ slow=1;
+ }
+ else
+ {
+ /* check for nulls "before" final bit of last byte */
+ mask = (1 << finalbit) - 1;
+ if ((~n) & mask)
+ slow=1;
+ }
}
}
}
+ tp = (char *) tup + tup->t_hoff;
+
/*
* now check for any non-fixed length attrs before our attribute
*/
{
if (att[attnum]->attcacheoff > 0)
{
- return (Datum)
- fetchatt(&(att[attnum]),
- tp + att[attnum]->attcacheoff);
+ return (Datum)fetchatt(&(att[attnum]),
+ tp + att[attnum]->attcacheoff);
}
else if (attnum == 0)
{
- return (Datum)
- fetchatt(&(att[0]), (char *) tup + tup->t_hoff);
+ return ((Datum) fetchatt(&(att[0]), (char *) tp));
}
else if (!HeapTupleAllFixed(tup))
{
register int j = 0;
for (j = 0; j < attnum && !slow; j++)
- if (att[j]->attlen < 1)
+ if (att[j]->attlen < 1 && !VARLENA_FIXED_SIZE(att[j]))
slow = 1;
}
}
while (att[j]->attcacheoff > 0)
j++;
- off = att[j - 1]->attcacheoff + att[j - 1]->attlen;
+ if (!VARLENA_FIXED_SIZE(att[j]))
+ off = att[j - 1]->attcacheoff + att[j - 1]->attlen;
+ else
+ off = att[j - 1]->attcacheoff + att[j - 1]->atttypmod;
for (; j < attnum + 1; j++)
{
+ /*
+ * Fix me when going to a machine with more than a four-byte
+ * word!
+ */
+
switch (att[j]->attlen)
{
case -1:
off = INTALIGN(off);
break;
default:
- if (att[j]->attlen < sizeof(int32))
- {
- elog(ERROR,
- "nocachegetattr: attribute %d has len %d",
- j, att[j]->attlen);
- }
- if (att[j]->attalign == 'd')
- off = DOUBLEALIGN(off);
+ if (att[j]->attlen > sizeof(int32))
+ off = (att[j]->attalign == 'd') ?
+ DOUBLEALIGN(off) : LONGALIGN(off);
else
- off = LONGALIGN(off);
+ elog(ERROR, "nocache_index_getattr: attribute %d has len %d",
+ j, att[j]->attlen);
break;
}
att[j]->attcacheoff = off;
- off += att[j]->attlen;
+
+ /* 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;
+ }
}
- return
- (Datum) fetchatt(&(att[attnum]), tp + att[attnum]->attcacheoff);
+ return (Datum) fetchatt(&(att[attnum]), tp + att[attnum]->attcacheoff);
}
else
{
continue;
}
}
- switch (att[i]->attlen)
- {
- case -1:
- off = (att[i]->attalign == 'd') ?
- DOUBLEALIGN(off) : INTALIGN(off);
- break;
- case sizeof(char):
- break;
- case sizeof(short):
- off = SHORTALIGN(off);
- break;
- case sizeof(int32):
- off = INTALIGN(off);
- break;
- default:
- if (att[i]->attlen < sizeof(int32))
- elog(ERROR,
- "nocachegetattr2: attribute %d has len %d",
- i, att[i]->attlen);
- if (att[i]->attalign == 'd')
- off = DOUBLEALIGN(off);
- else
- off = LONGALIGN(off);
- break;
- }
+
+ /* If we know the next offset, we can skip the rest */
if (usecache && att[i]->attcacheoff > 0)
- {
off = att[i]->attcacheoff;
- if (att[i]->attlen == -1)
- {
- usecache = false;
- }
- }
else
{
+ switch (att[i]->attlen)
+ {
+ case -1:
+ off = (att[i]->attalign == 'd') ?
+ DOUBLEALIGN(off) : INTALIGN(off);
+ break;
+ case sizeof(char):
+ break;
+ case sizeof(short):
+ off = SHORTALIGN(off);
+ break;
+ case sizeof(int32):
+ off = INTALIGN(off);
+ break;
+ default:
+ if (att[i]->attlen < sizeof(int32))
+ elog(ERROR,
+ "nocachegetattr2: attribute %d has len %d",
+ i, att[i]->attlen);
+ if (att[i]->attalign == 'd')
+ off = DOUBLEALIGN(off);
+ else
+ off = LONGALIGN(off);
+ break;
+ }
if (usecache)
att[i]->attcacheoff = off;
}
case sizeof(char):
off++;
break;
- case sizeof(int16):
- off += sizeof(int16);
+ case sizeof(short):
+ off += sizeof(short);
break;
case sizeof(int32):
off += sizeof(int32);
break;
case -1:
- usecache = false;
+ 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;
}
}
+
switch (att[attnum]->attlen)
{
case -1:
off = LONGALIGN(off);
break;
}
- return ((Datum) fetchatt(&(att[attnum]), tp + off));
+
+ return (Datum) fetchatt(&(att[attnum]), tp + off);
}
}
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/access/common/indextuple.c,v 1.23 1998/01/31 04:38:03 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/access/common/indextuple.c,v 1.24 1998/02/04 21:32:09 momjian Exp $
*
*-------------------------------------------------------------------------
*/
#include <access/ibit.h>
#include <access/itup.h>
#include <access/tupmacs.h>
+#include <catalog/pg_type.h>
#ifndef HAVE_MEMMOVE
#include <regex/utils.h>
}
#endif
- tp = (char *) tup + data_off;
-
slow = 0;
}
else
register int mask; /* bit in byte we're looking at */
register char n; /* current byte in bp */
register int byte,
- finalbit;
+ finalbit;
byte = attnum >> 3;
finalbit = attnum & 0x07;
- for (; i <= byte; i++)
+ for (; i <= byte && !slow; i++)
{
n = bp[i];
if (i < byte)
{
/* check for nulls in any "earlier" bytes */
if ((~n) != 0)
- {
- slow++;
- break;
- }
+ slow=1;
}
else
{
/* check for nulls "before" final bit of last byte */
- mask = (finalbit << 1) - 1;
+ mask = (1 << finalbit) - 1;
if ((~n) & mask)
- slow++;
+ slow=1;
}
}
}
- tp = (char *) tup + data_off;
}
+ tp = (char *) tup + data_off;
+
/* now check for any non-fixed length attrs before our attribute */
if (!slow)
return (Datum) fetchatt(&(att[attnum]),
tp + att[attnum]->attcacheoff);
}
+ else if (attnum == 0)
+ {
+ return ((Datum) fetchatt(&(att[0]), (char *) tp));
+ }
else if (!IndexTupleAllFixed(tup))
{
register int j = 0;
for (j = 0; j < attnum && !slow; j++)
- if (att[j]->attlen < 1)
+ if (att[j]->attlen < 1 && !VARLENA_FIXED_SIZE(att[j]))
slow = 1;
}
}
while (att[j]->attcacheoff > 0)
j++;
- off = att[j - 1]->attcacheoff +
- att[j - 1]->attlen;
+ if (!VARLENA_FIXED_SIZE(att[j]))
+ off = att[j - 1]->attcacheoff + att[j - 1]->attlen;
+ else
+ off = att[j - 1]->attcacheoff + att[j - 1]->atttypmod;
for (; j < attnum + 1; j++)
{
-
/*
* Fix me when going to a machine with more than a four-byte
* word!
}
att[j]->attcacheoff = off;
- off += att[j]->attlen;
+
+ /* 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;
+ }
}
- return (Datum) fetchatt(&(att[attnum]),
- tp + att[attnum]->attcacheoff);
+ return (Datum) fetchatt(&(att[attnum]), tp + att[attnum]->attcacheoff);
}
else
{
}
}
+ /* If we know the next offset, we can skip the rest */
if (usecache && att[i]->attcacheoff > 0)
- {
off = att[i]->attcacheoff;
- if (att[i]->attlen == -1)
- usecache = false;
- else
- continue;
+ else
+ {
+ switch (att[i]->attlen)
+ {
+ case -1:
+ off = (att[i]->attalign == 'd') ?
+ DOUBLEALIGN(off) : INTALIGN(off);
+ break;
+ case sizeof(char):
+ break;
+ case sizeof(short):
+ off = SHORTALIGN(off);
+ break;
+ case sizeof(int32):
+ off = INTALIGN(off);
+ break;
+ default:
+ if (att[i]->attlen < sizeof(int32))
+ elog(ERROR,
+ "nocachegetiattr2: attribute %d has len %d",
+ i, att[i]->attlen);
+ if (att[i]->attalign == 'd')
+ off = DOUBLEALIGN(off);
+ else
+ off = LONGALIGN(off);
+ break;
+ }
+ if (usecache)
+ att[i]->attcacheoff = off;
}
- if (usecache)
- att[i]->attcacheoff = off;
switch (att[i]->attlen)
{
case sizeof(char):
off++;
break;
case sizeof(short):
- off = SHORTALIGN(off) +sizeof(short);
+ off += sizeof(short);
break;
case sizeof(int32):
- off = INTALIGN(off) +sizeof(int32);
+ off += sizeof(int32);
break;
case -1:
- usecache = false;
- off = (att[i]->attalign == 'd') ?
- DOUBLEALIGN(off) : INTALIGN(off);
+ 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:
- if (att[i]->attlen > sizeof(int32))
- off = (att[i]->attalign == 'd') ?
- DOUBLEALIGN(off) + att[i]->attlen :
- LONGALIGN(off) + att[i]->attlen;
- else
- elog(ERROR, "nocache_index_getattr2: attribute %d has len %d",
- i, att[i]->attlen);
-
+ off += att[i]->attlen;
break;
}
}
- /*
- * I don't know why this code was missed here! I've got it from
- * heaptuple.c:nocachegetattr(). - vadim 06/12/97
- */
switch (att[attnum]->attlen)
{
case -1: