diff options
Diffstat (limited to 'src/backend/access/common/indextuple.c')
-rw-r--r-- | src/backend/access/common/indextuple.c | 758 |
1 files changed, 398 insertions, 360 deletions
diff --git a/src/backend/access/common/indextuple.c b/src/backend/access/common/indextuple.c index a71fc46dc98..c133693801b 100644 --- a/src/backend/access/common/indextuple.c +++ b/src/backend/access/common/indextuple.c @@ -1,14 +1,14 @@ /*------------------------------------------------------------------------- * * indextuple.c-- - * This file contains index tuple accessor and mutator routines, - * as well as a few various tuple utilities. + * This file contains index tuple accessor and mutator routines, + * as well as a few various tuple utilities. * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/common/indextuple.c,v 1.15 1997/08/19 21:28:50 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/common/indextuple.c,v 1.16 1997/09/07 04:37:37 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -21,402 +21,438 @@ #include <access/tupmacs.h> #ifndef HAVE_MEMMOVE -# include <regex/utils.h> +#include <regex/utils.h> #else -# include <string.h> +#include <string.h> #endif -static Size IndexInfoFindDataOffset(unsigned short t_info); -static char *fastgetiattr(IndexTuple tup, int attnum, - TupleDesc att, bool *isnull); +static Size IndexInfoFindDataOffset(unsigned short t_info); +static char * +fastgetiattr(IndexTuple tup, int attnum, + TupleDesc att, bool * isnull); /* ---------------------------------------------------------------- - * index_ tuple interface routines + * index_ tuple interface routines * ---------------------------------------------------------------- */ /* ---------------- - * index_formtuple + * index_formtuple * ---------------- */ IndexTuple index_formtuple(TupleDesc tupleDescriptor, - Datum value[], - char null[]) + Datum value[], + char null[]) { - register char *tp; /* tuple pointer */ - IndexTuple tuple; /* return tuple */ - Size size, hoff; - int i; - unsigned short infomask = 0; - bool hasnull = false; - char tupmask = 0; - int numberOfAttributes = tupleDescriptor->natts; - - if (numberOfAttributes > MaxIndexAttributeNumber) - elog(WARN, "index_formtuple: numberOfAttributes of %d > %d", - numberOfAttributes, MaxIndexAttributeNumber); - - - for (i = 0; i < numberOfAttributes && !hasnull; i++) { - if (null[i] != ' ') hasnull = true; - } - - if (hasnull) infomask |= INDEX_NULL_MASK; - - hoff = IndexInfoFindDataOffset(infomask); - size = hoff - + ComputeDataSize(tupleDescriptor, - value, null); - size = DOUBLEALIGN(size); /* be conservative */ - - tp = (char *) palloc(size); - tuple = (IndexTuple) tp; - memset(tp,0,(int)size); - - DataFill((char *)tp + hoff, - tupleDescriptor, - value, - null, - &tupmask, - (hasnull ? (bits8*)tp + sizeof(*tuple) : NULL)); - - /* - * We do this because DataFill wants to initialize a "tupmask" which - * is used for HeapTuples, but we want an indextuple infomask. The only - * "relevent" info is the "has variable attributes" field, which is in - * mask position 0x02. We have already set the null mask above. - */ - - if (tupmask & 0x02) infomask |= INDEX_VAR_MASK; - - /* - * Here we make sure that we can actually hold the size. We also want - * to make sure that size is not aligned oddly. This actually is a - * rather odd way to make sure the size is not too large overall. - */ - - if (size & 0xE000) - elog(WARN, "index_formtuple: data takes %d bytes: too big", size); - - - infomask |= size; - - /* ---------------- - * initialize metadata - * ---------------- - */ - tuple->t_info = infomask; - return (tuple); + register char *tp; /* tuple pointer */ + IndexTuple tuple; /* return tuple */ + Size size, + hoff; + int i; + unsigned short infomask = 0; + bool hasnull = false; + char tupmask = 0; + int numberOfAttributes = tupleDescriptor->natts; + + if (numberOfAttributes > MaxIndexAttributeNumber) + elog(WARN, "index_formtuple: numberOfAttributes of %d > %d", + numberOfAttributes, MaxIndexAttributeNumber); + + + for (i = 0; i < numberOfAttributes && !hasnull; i++) + { + if (null[i] != ' ') + hasnull = true; + } + + if (hasnull) + infomask |= INDEX_NULL_MASK; + + hoff = IndexInfoFindDataOffset(infomask); + size = hoff + + ComputeDataSize(tupleDescriptor, + value, null); + size = DOUBLEALIGN(size); /* be conservative */ + + tp = (char *) palloc(size); + tuple = (IndexTuple) tp; + memset(tp, 0, (int) size); + + DataFill((char *) tp + hoff, + tupleDescriptor, + value, + null, + &tupmask, + (hasnull ? (bits8 *) tp + sizeof(*tuple) : NULL)); + + /* + * We do this because DataFill wants to initialize a "tupmask" which + * is used for HeapTuples, but we want an indextuple infomask. The + * only "relevent" info is the "has variable attributes" field, which + * is in mask position 0x02. We have already set the null mask above. + */ + + if (tupmask & 0x02) + infomask |= INDEX_VAR_MASK; + + /* + * Here we make sure that we can actually hold the size. We also want + * to make sure that size is not aligned oddly. This actually is a + * rather odd way to make sure the size is not too large overall. + */ + + if (size & 0xE000) + elog(WARN, "index_formtuple: data takes %d bytes: too big", size); + + + infomask |= size; + + /* ---------------- + * initialize metadata + * ---------------- + */ + tuple->t_info = infomask; + return (tuple); } /* ---------------- - * fastgetiattr + * fastgetiattr * - * This is a newer version of fastgetiattr which attempts to be - * faster by caching attribute offsets in the attribute descriptor. + * This is a newer version of fastgetiattr which attempts to be + * faster by caching attribute offsets in the attribute descriptor. * - * 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. + * 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 - * you cache the offsets once, examining all the other tuples using - * the same attribute descriptor will go much quicker. -cim 5/4/91 + * This scheme will be slightly slower than that, but should + * preform 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 * ---------------- */ -static char * +static char * fastgetiattr(IndexTuple tup, - int attnum, - TupleDesc tupleDesc, - bool *isnull) + int attnum, + TupleDesc tupleDesc, + bool * isnull) { - register char *tp; /* ptr to att in tuple */ - register char *bp = NULL; /* ptr to att in tuple */ - int slow; /* do we have to walk nulls? */ - register int data_off; /* tuple data offset */ - AttributeTupleForm *att = tupleDesc->attrs; - - /* ---------------- - * sanity checks - * ---------------- - */ - - Assert(PointerIsValid(isnull)); - Assert(attnum > 0); - - /* ---------------- - * Three cases: - * - * 1: No nulls and no variable length attributes. - * 2: Has a null or a varlena AFTER att. - * 3: Has nulls or varlenas BEFORE att. - * ---------------- - */ - - *isnull = false; - data_off = IndexTupleHasMinHeader(tup) ? sizeof *tup : - IndexInfoFindDataOffset(tup->t_info); - - if (IndexTupleNoNulls(tup)) { - - /* first attribute is always at position zero */ - - if (attnum == 1) { - return(fetchatt(&(att[0]), (char *) tup + data_off)); - } - attnum--; - - if (att[attnum]->attcacheoff > 0) { - return(fetchatt(&(att[attnum]), - (char *) tup + data_off + - att[attnum]->attcacheoff)); - } - - tp = (char *) tup + data_off; - - slow = 0; - }else { /* there's a null somewhere in the tuple */ - - bp = (char *) tup + sizeof(*tup); /* "knows" t_bits are here! */ - slow = 0; + register char *tp; /* ptr to att in tuple */ + register char *bp = NULL; /* ptr to att in tuple */ + int slow; /* do we have to walk nulls? */ + register int data_off; /* tuple data offset */ + AttributeTupleForm *att = tupleDesc->attrs; + /* ---------------- - * check to see if desired att is null + * sanity checks * ---------------- */ - - attnum--; - { - if (att_isnull(attnum, bp)) { - *isnull = true; - return NULL; - } - } + + Assert(PointerIsValid(isnull)); + Assert(attnum > 0); + /* ---------------- - * Now check to see if any preceeding bits are null... + * Three cases: + * + * 1: No nulls and no variable length attributes. + * 2: Has a null or a varlena AFTER att. + * 3: Has nulls or varlenas BEFORE att. * ---------------- */ + + *isnull = false; + data_off = IndexTupleHasMinHeader(tup) ? sizeof *tup : + IndexInfoFindDataOffset(tup->t_info); + + if (IndexTupleNoNulls(tup)) { - 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; - - byte = attnum >> 3; - finalbit = attnum & 0x07; - - for (; i <= byte; i++) { - n = bp[i]; - if (i < byte) { - /* check for nulls in any "earlier" bytes */ - if ((~n) != 0) { - slow++; - break; - } - } else { - /* check for nulls "before" final bit of last byte*/ - mask = (finalbit << 1) - 1; - if ((~n) & mask) - slow++; + + /* first attribute is always at position zero */ + + if (attnum == 1) + { + return (fetchatt(&(att[0]), (char *) tup + data_off)); + } + attnum--; + + if (att[attnum]->attcacheoff > 0) + { + return (fetchatt(&(att[attnum]), + (char *) tup + data_off + + att[attnum]->attcacheoff)); } - } + + tp = (char *) tup + data_off; + + slow = 0; } - tp = (char *) tup + data_off; - } - - /* now check for any non-fixed length attrs before our attribute */ - - if (!slow) { - if (att[attnum]->attcacheoff > 0) { - return(fetchatt(&(att[attnum]), - tp + att[attnum]->attcacheoff)); - }else if (!IndexTupleAllFixed(tup)) { - register int j = 0; - - for (j = 0; j < attnum && !slow; j++) - if (att[j]->attlen < 1) slow = 1; + else + { /* there's a null somewhere in the tuple */ + + bp = (char *) tup + sizeof(*tup); /* "knows" t_bits are + * here! */ + slow = 0; + /* ---------------- + * check to see if desired att is null + * ---------------- + */ + + attnum--; + { + if (att_isnull(attnum, bp)) + { + *isnull = true; + return NULL; + } + } + /* ---------------- + * 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; + + byte = attnum >> 3; + finalbit = attnum & 0x07; + + for (; i <= byte; i++) + { + n = bp[i]; + if (i < byte) + { + /* check for nulls in any "earlier" bytes */ + if ((~n) != 0) + { + slow++; + break; + } + } + else + { + /* check for nulls "before" final bit of last byte */ + mask = (finalbit << 1) - 1; + if ((~n) & mask) + slow++; + } + } + } + tp = (char *) tup + data_off; } - } - - /* - * 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) { - register int j = 1; - register long off; - - /* - * need to set cache for some atts - */ - - att[0]->attcacheoff = 0; - - while (att[j]->attcacheoff > 0) j++; - - off = att[j-1]->attcacheoff + - att[j-1]->attlen; - - for (; j < attnum + 1; j++) { - /* - * Fix me when going to a machine with more than a four-byte - * word! - */ - - switch(att[j]->attlen) + + /* now check for any non-fixed length attrs before our attribute */ + + if (!slow) + { + if (att[attnum]->attcacheoff > 0) { - case -1: - off = (att[j]->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[j]->attlen > sizeof(int32)) - off = (att[j]->attalign=='d')? - DOUBLEALIGN(off) : LONGALIGN(off); - else - elog(WARN, "fastgetiattr: attribute %d has len %d", - j, att[j]->attlen); - break; - + return (fetchatt(&(att[attnum]), + tp + att[attnum]->attcacheoff)); + } + else if (!IndexTupleAllFixed(tup)) + { + register int j = 0; + + for (j = 0; j < attnum && !slow; j++) + if (att[j]->attlen < 1) + slow = 1; } - - att[j]->attcacheoff = off; - off += att[j]->attlen; } - - return(fetchatt( &(att[attnum]), - tp + att[attnum]->attcacheoff)); - }else { - register bool usecache = true; - register int off = 0; - register int i; - + /* - * Now we know that we have to walk the tuple CAREFULLY. + * 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. */ - - for (i = 0; i < attnum; i++) { - if (!IndexTupleNoNulls(tup)) { - if (att_isnull(i, bp)) { - usecache = false; - continue; + + if (!slow) + { + register int j = 1; + register long off; + + /* + * need to set cache for some atts + */ + + att[0]->attcacheoff = 0; + + while (att[j]->attcacheoff > 0) + j++; + + off = att[j - 1]->attcacheoff + + att[j - 1]->attlen; + + 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 = (att[j]->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[j]->attlen > sizeof(int32)) + off = (att[j]->attalign == 'd') ? + DOUBLEALIGN(off) : LONGALIGN(off); + else + elog(WARN, "fastgetiattr: attribute %d has len %d", + j, att[j]->attlen); + break; + + } + + att[j]->attcacheoff = off; + off += att[j]->attlen; } - } - - if (usecache && att[i]->attcacheoff > 0) { - off = att[i]->attcacheoff; - if (att[i]->attlen == -1) - usecache = false; - else - continue; - } - - if (usecache) att[i]->attcacheoff = off; - switch(att[i]->attlen) + + return (fetchatt(&(att[attnum]), + tp + att[attnum]->attcacheoff)); + } + else + { + register bool usecache = true; + register int off = 0; + register int i; + + /* + * Now we know that we have to walk the tuple CAREFULLY. + */ + + for (i = 0; i < attnum; i++) { + if (!IndexTupleNoNulls(tup)) + { + if (att_isnull(i, bp)) + { + usecache = false; + continue; + } + } + + if (usecache && att[i]->attcacheoff > 0) + { + off = att[i]->attcacheoff; + if (att[i]->attlen == -1) + usecache = false; + else + continue; + } + + if (usecache) + att[i]->attcacheoff = off; + switch (att[i]->attlen) + { + case sizeof(char): + off++; + break; + case sizeof(short): + off = SHORTALIGN(off) +sizeof(short); + break; + case sizeof(int32): + off = INTALIGN(off) + sizeof(int32); + break; + case -1: + usecache = false; + off = (att[i]->attalign == 'd') ? + DOUBLEALIGN(off) : INTALIGN(off); + off += VARSIZE(tp + off); + 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(WARN, "fastgetiattr2: attribute %d has len %d", + i, att[i]->attlen); + + break; + } + } + + /* + * I don't know why this code was missed here! I've got it from + * heaptuple.c:fastgetattr(). - vadim 06/12/97 + */ + switch (att[attnum]->attlen) + { + case -1: + off = (att[attnum]->attalign == 'd') ? + DOUBLEALIGN(off) : INTALIGN(off); + break; case sizeof(char): - off++; - break; + break; case sizeof(short): - off = SHORTALIGN(off) + sizeof(short); - break; + off = SHORTALIGN(off); + break; case sizeof(int32): - off = INTALIGN(off) + sizeof(int32); - break; - case -1: - usecache = false; - off = (att[i]->attalign=='d')? - DOUBLEALIGN(off):INTALIGN(off); - off += VARSIZE(tp + off); - break; + off = INTALIGN(off); + 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(WARN, "fastgetiattr2: attribute %d has len %d", - i, att[i]->attlen); - - break; + if (att[attnum]->attlen < sizeof(int32)) + elog(WARN, "fastgetattr3: attribute %d has len %d", + attnum, att[attnum]->attlen); + if (att[attnum]->attalign == 'd') + off = DOUBLEALIGN(off); + else + off = LONGALIGN(off); + break; } + + return (fetchatt(&att[attnum], tp + off)); } - /* - * I don't know why this code was missed here! - * I've got it from heaptuple.c:fastgetattr(). - * - vadim 06/12/97 - */ - switch (att[attnum]->attlen) { - case -1: - off = (att[attnum]->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[attnum]->attlen < sizeof(int32)) - elog(WARN, "fastgetattr3: attribute %d has len %d", - attnum, att[attnum]->attlen); - if (att[attnum]->attalign == 'd') - off = DOUBLEALIGN(off); - else - off = LONGALIGN(off); - break; - } - - return(fetchatt(&att[attnum], tp + off)); - } } /* ---------------- - * index_getattr + * index_getattr * ---------------- */ Datum index_getattr(IndexTuple tuple, - AttrNumber attNum, - TupleDesc tupDesc, - bool *isNullOutP) + AttrNumber attNum, + TupleDesc tupDesc, + bool * isNullOutP) { - Assert (attNum > 0); + Assert(attNum > 0); - return (Datum) - fastgetiattr(tuple, attNum, tupDesc, isNullOutP); + return (Datum) + fastgetiattr(tuple, attNum, tupDesc, isNullOutP); } RetrieveIndexResult FormRetrieveIndexResult(ItemPointer indexItemPointer, - ItemPointer heapItemPointer) + ItemPointer heapItemPointer) { - RetrieveIndexResult result; - - Assert(ItemPointerIsValid(indexItemPointer)); - Assert(ItemPointerIsValid(heapItemPointer)); - - result = (RetrieveIndexResult) palloc(sizeof *result); - - result->index_iptr = *indexItemPointer; - result->heap_iptr = *heapItemPointer; - - return (result); + RetrieveIndexResult result; + + Assert(ItemPointerIsValid(indexItemPointer)); + Assert(ItemPointerIsValid(heapItemPointer)); + + result = (RetrieveIndexResult) palloc(sizeof *result); + + result->index_iptr = *indexItemPointer; + result->heap_iptr = *heapItemPointer; + + return (result); } /* @@ -425,19 +461,21 @@ FormRetrieveIndexResult(ItemPointer indexItemPointer, * * Change me if adding an attribute to IndexTuples!!!!!!!!!!! */ -static Size +static Size IndexInfoFindDataOffset(unsigned short t_info) { - if (!(t_info & INDEX_NULL_MASK)) - return((Size) sizeof(IndexTupleData)); - else { - Size size = sizeof(IndexTupleData); - - if (t_info & INDEX_NULL_MASK) { - size += sizeof(IndexAttributeBitMapData); + if (!(t_info & INDEX_NULL_MASK)) + return ((Size) sizeof(IndexTupleData)); + else + { + Size size = sizeof(IndexTupleData); + + if (t_info & INDEX_NULL_MASK) + { + size += sizeof(IndexAttributeBitMapData); + } + return DOUBLEALIGN(size); /* be conservative */ } - return DOUBLEALIGN(size); /* be conservative */ - } } /* @@ -445,17 +483,17 @@ IndexInfoFindDataOffset(unsigned short t_info) * we assume we have space that is already palloc'ed. */ void -CopyIndexTuple(IndexTuple source, IndexTuple *target) +CopyIndexTuple(IndexTuple source, IndexTuple * target) { - Size size; - IndexTuple ret; - - size = IndexTupleSize(source); - if (*target == NULL) { - *target = (IndexTuple) palloc(size); - } - - ret = *target; - memmove((char*)ret, (char*)source, size); -} + Size size; + IndexTuple ret; + + size = IndexTupleSize(source); + if (*target == NULL) + { + *target = (IndexTuple) palloc(size); + } + ret = *target; + memmove((char *) ret, (char *) source, size); +} |