diff options
Diffstat (limited to 'src/backend/access/common')
-rw-r--r-- | src/backend/access/common/heaptuple.c | 1603 | ||||
-rw-r--r-- | src/backend/access/common/heapvalid.c | 206 | ||||
-rw-r--r-- | src/backend/access/common/indextuple.c | 758 | ||||
-rw-r--r-- | src/backend/access/common/indexvalid.c | 104 | ||||
-rw-r--r-- | src/backend/access/common/printtup.c | 431 | ||||
-rw-r--r-- | src/backend/access/common/scankey.c | 54 | ||||
-rw-r--r-- | src/backend/access/common/tupdesc.c | 890 |
7 files changed, 2115 insertions, 1931 deletions
diff --git a/src/backend/access/common/heaptuple.c b/src/backend/access/common/heaptuple.c index 60ec3e4d3ab..17257690303 100644 --- a/src/backend/access/common/heaptuple.c +++ b/src/backend/access/common/heaptuple.c @@ -1,18 +1,18 @@ /*------------------------------------------------------------------------- * * heaptuple.c-- - * This file contains heap tuple accessor and mutator routines, as well - * as a few various tuple utilities. + * This file contains heap 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/heaptuple.c,v 1.21 1997/08/26 23:31:20 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/common/heaptuple.c,v 1.22 1997/09/07 04:37:30 momjian Exp $ * * NOTES - * The old interface functions have been converted to macros - * and moved to heapam.h + * The old interface functions have been converted to macros + * and moved to heapam.h * *------------------------------------------------------------------------- */ @@ -27,9 +27,9 @@ #include <utils/memutils.h> #ifndef HAVE_MEMMOVE -# include <regex/utils.h> +#include <regex/utils.h> #else -# include <string.h> +#include <string.h> #endif @@ -37,902 +37,991 @@ #if !defined(NO_ASSERT_CHECKING) && defined(sparc) && defined(sunos4) #define register -#endif /* !NO_ASSERT_CHECKING && sparc && sunos4 */ +#endif /* !NO_ASSERT_CHECKING && sparc && sunos4 */ /* ---------------------------------------------------------------- - * misc support routines + * misc support routines * ---------------------------------------------------------------- */ /* ---------------- - * ComputeDataSize + * ComputeDataSize * ---------------- */ Size ComputeDataSize(TupleDesc tupleDesc, - Datum value[], - char nulls[]) + Datum value[], + char nulls[]) { - uint32 data_length; - int i; - int numberOfAttributes = tupleDesc->natts; - AttributeTupleForm *att = tupleDesc->attrs; - - for (data_length = 0, i = 0; i < numberOfAttributes; i++) { - if (nulls[i] != ' ') continue; - - switch (att[i]->attlen) { - case -1: - /* - * This is the size of the disk representation and so - * must include the additional sizeof long. - */ - if (att[i]->attalign == 'd') { - data_length = DOUBLEALIGN(data_length) - + VARSIZE(DatumGetPointer(value[i])); - } else { - data_length = INTALIGN(data_length) - + VARSIZE(DatumGetPointer(value[i])); - } - break; - case sizeof(char): - data_length++; - break; - case sizeof(short): - data_length = SHORTALIGN(data_length + sizeof(short)); - break; - case sizeof(int32): - data_length = INTALIGN(data_length + sizeof(int32)); - break; - default: - if (att[i]->attlen < sizeof(int32)) - elog(WARN, "ComputeDataSize: attribute %d has len %d", - i, att[i]->attlen); - if (att[i]->attalign == 'd') - data_length = DOUBLEALIGN(data_length) + att[i]->attlen; - else - data_length = LONGALIGN(data_length) + att[i]->attlen; - break; + uint32 data_length; + int i; + int numberOfAttributes = tupleDesc->natts; + AttributeTupleForm *att = tupleDesc->attrs; + + for (data_length = 0, i = 0; i < numberOfAttributes; i++) + { + if (nulls[i] != ' ') + continue; + + switch (att[i]->attlen) + { + case -1: + + /* + * This is the size of the disk representation and so must + * include the additional sizeof long. + */ + if (att[i]->attalign == 'd') + { + data_length = DOUBLEALIGN(data_length) + + VARSIZE(DatumGetPointer(value[i])); + } + else + { + data_length = INTALIGN(data_length) + + VARSIZE(DatumGetPointer(value[i])); + } + break; + case sizeof(char): + data_length++; + break; + case sizeof(short): + data_length = SHORTALIGN(data_length + sizeof(short)); + break; + case sizeof(int32): + data_length = INTALIGN(data_length + sizeof(int32)); + break; + default: + if (att[i]->attlen < sizeof(int32)) + elog(WARN, "ComputeDataSize: attribute %d has len %d", + i, att[i]->attlen); + if (att[i]->attalign == 'd') + data_length = DOUBLEALIGN(data_length) + att[i]->attlen; + else + data_length = LONGALIGN(data_length) + att[i]->attlen; + break; + } } - } - - return data_length; + + return data_length; } /* ---------------- - * DataFill + * DataFill * ---------------- */ void DataFill(char *data, - TupleDesc tupleDesc, - Datum value[], - char nulls[], - char *infomask, - bits8 *bit) + TupleDesc tupleDesc, + Datum value[], + char nulls[], + char *infomask, + bits8 * bit) { - bits8 *bitP = 0; - int bitmask = 0; - uint32 data_length; - int i; - int numberOfAttributes = tupleDesc->natts; - AttributeTupleForm *att = tupleDesc->attrs; - - if (bit != NULL) { - bitP = &bit[-1]; - bitmask = CSIGNBIT; - } - - *infomask = 0; - - for (i = 0; i < numberOfAttributes; i++) { - if (bit != NULL) { - if (bitmask != CSIGNBIT) { - bitmask <<= 1; - } else { - bitP += 1; - *bitP = 0x0; - bitmask = 1; - } - - if (nulls[i] == 'n') { - *infomask |= HEAP_HASNULL; - continue; - } - - *bitP |= bitmask; + bits8 *bitP = 0; + int bitmask = 0; + uint32 data_length; + int i; + int numberOfAttributes = tupleDesc->natts; + AttributeTupleForm *att = tupleDesc->attrs; + + if (bit != NULL) + { + bitP = &bit[-1]; + bitmask = CSIGNBIT; } - - switch (att[i]->attlen) { - case -1: - *infomask |= HEAP_HASVARLENA; - if (att[i]->attalign=='d') { - data = (char *) DOUBLEALIGN(data); - } else { - data = (char *) INTALIGN(data); - } - data_length = VARSIZE(DatumGetPointer(value[i])); - memmove(data, DatumGetPointer(value[i]),data_length); - data += data_length; - break; - case sizeof(char): - *data = att[i]->attbyval ? - DatumGetChar(value[i]) : *((char *) value[i]); - data += sizeof(char); - break; - case sizeof(int16): - data = (char *) SHORTALIGN(data); - * (short *) data = (att[i]->attbyval ? - DatumGetInt16(value[i]) : - *((short *) value[i])); - data += sizeof(short); - break; - case sizeof(int32): - data = (char *) INTALIGN(data); - * (int32 *) data = (att[i]->attbyval ? - DatumGetInt32(value[i]) : - *((int32 *) value[i])); - data += sizeof(int32); - break; - default: - if (att[i]->attlen < sizeof(int32)) - elog(WARN, "DataFill: attribute %d has len %d", - i, att[i]->attlen); - if (att[i]->attalign == 'd') { - data = (char *) DOUBLEALIGN(data); - memmove(data, DatumGetPointer(value[i]), - att[i]->attlen); - data += att[i]->attlen; - } else { - data = (char *) LONGALIGN(data); - memmove(data, DatumGetPointer(value[i]), - att[i]->attlen); - data += att[i]->attlen; - } - break; + + *infomask = 0; + + for (i = 0; i < numberOfAttributes; i++) + { + if (bit != NULL) + { + if (bitmask != CSIGNBIT) + { + bitmask <<= 1; + } + else + { + bitP += 1; + *bitP = 0x0; + bitmask = 1; + } + + if (nulls[i] == 'n') + { + *infomask |= HEAP_HASNULL; + continue; + } + + *bitP |= bitmask; + } + + switch (att[i]->attlen) + { + case -1: + *infomask |= HEAP_HASVARLENA; + if (att[i]->attalign == 'd') + { + data = (char *) DOUBLEALIGN(data); + } + else + { + data = (char *) INTALIGN(data); + } + data_length = VARSIZE(DatumGetPointer(value[i])); + memmove(data, DatumGetPointer(value[i]), data_length); + data += data_length; + break; + case sizeof(char): + *data = att[i]->attbyval ? + DatumGetChar(value[i]) : *((char *) value[i]); + data += sizeof(char); + break; + case sizeof(int16): + data = (char *) SHORTALIGN(data); + *(short *) data = (att[i]->attbyval ? + DatumGetInt16(value[i]) : + *((short *) value[i])); + data += sizeof(short); + break; + case sizeof(int32): + data = (char *) INTALIGN(data); + *(int32 *) data = (att[i]->attbyval ? + DatumGetInt32(value[i]) : + *((int32 *) value[i])); + data += sizeof(int32); + break; + default: + if (att[i]->attlen < sizeof(int32)) + elog(WARN, "DataFill: attribute %d has len %d", + i, att[i]->attlen); + if (att[i]->attalign == 'd') + { + data = (char *) DOUBLEALIGN(data); + memmove(data, DatumGetPointer(value[i]), + att[i]->attlen); + data += att[i]->attlen; + } + else + { + data = (char *) LONGALIGN(data); + memmove(data, DatumGetPointer(value[i]), + att[i]->attlen); + data += att[i]->attlen; + } + break; + } } - } } /* ---------------------------------------------------------------- - * heap tuple interface + * heap tuple interface * ---------------------------------------------------------------- */ /* ---------------- - * heap_attisnull - returns 1 iff tuple attribute is not present + * heap_attisnull - returns 1 iff tuple attribute is not present * ---------------- */ int heap_attisnull(HeapTuple tup, int attnum) { - if (attnum > (int)tup->t_natts) - return (1); - - if (HeapTupleNoNulls(tup)) return(0); - - if (attnum > 0) { - return(att_isnull(attnum - 1, tup->t_bits)); - } else - switch (attnum) { - case SelfItemPointerAttributeNumber: - case ObjectIdAttributeNumber: - case MinTransactionIdAttributeNumber: - case MinCommandIdAttributeNumber: - case MaxTransactionIdAttributeNumber: - case MaxCommandIdAttributeNumber: - case ChainItemPointerAttributeNumber: - case AnchorItemPointerAttributeNumber: - case MinAbsoluteTimeAttributeNumber: - case MaxAbsoluteTimeAttributeNumber: - case VersionTypeAttributeNumber: - break; - - case 0: - elog(WARN, "heap_attisnull: zero attnum disallowed"); - - default: - elog(WARN, "heap_attisnull: undefined negative attnum"); + if (attnum > (int) tup->t_natts) + return (1); + + if (HeapTupleNoNulls(tup)) + return (0); + + if (attnum > 0) + { + return (att_isnull(attnum - 1, tup->t_bits)); } - - return (0); + else + switch (attnum) + { + case SelfItemPointerAttributeNumber: + case ObjectIdAttributeNumber: + case MinTransactionIdAttributeNumber: + case MinCommandIdAttributeNumber: + case MaxTransactionIdAttributeNumber: + case MaxCommandIdAttributeNumber: + case ChainItemPointerAttributeNumber: + case AnchorItemPointerAttributeNumber: + case MinAbsoluteTimeAttributeNumber: + case MaxAbsoluteTimeAttributeNumber: + case VersionTypeAttributeNumber: + break; + + case 0: + elog(WARN, "heap_attisnull: zero attnum disallowed"); + + default: + elog(WARN, "heap_attisnull: undefined negative attnum"); + } + + return (0); } /* ---------------------------------------------------------------- - * system attribute heap tuple support + * system attribute heap tuple support * ---------------------------------------------------------------- */ /* ---------------- - * heap_sysattrlen + * heap_sysattrlen * - * This routine returns the length of a system attribute. + * This routine returns the length of a system attribute. * ---------------- */ int heap_sysattrlen(AttrNumber attno) { - HeapTupleData *f = NULL; - - switch (attno) { - case SelfItemPointerAttributeNumber: return sizeof f->t_ctid; - case ObjectIdAttributeNumber: return sizeof f->t_oid; - case MinTransactionIdAttributeNumber: return sizeof f->t_xmin; - case MinCommandIdAttributeNumber: return sizeof f->t_cmin; - case MaxTransactionIdAttributeNumber: return sizeof f->t_xmax; - case MaxCommandIdAttributeNumber: return sizeof f->t_cmax; - case ChainItemPointerAttributeNumber: return sizeof f->t_chain; - case MinAbsoluteTimeAttributeNumber: return sizeof f->t_tmin; - case MaxAbsoluteTimeAttributeNumber: return sizeof f->t_tmax; - case VersionTypeAttributeNumber: return sizeof f->t_vtype; - - case AnchorItemPointerAttributeNumber: - elog(WARN, "heap_sysattrlen: field t_anchor does not exist!"); - return 0; - - default: - elog(WARN, "sysattrlen: System attribute number %d unknown.", attno); - return 0; - } + HeapTupleData *f = NULL; + + switch (attno) + { + case SelfItemPointerAttributeNumber: + return sizeof f->t_ctid; + case ObjectIdAttributeNumber: + return sizeof f->t_oid; + case MinTransactionIdAttributeNumber: + return sizeof f->t_xmin; + case MinCommandIdAttributeNumber: + return sizeof f->t_cmin; + case MaxTransactionIdAttributeNumber: + return sizeof f->t_xmax; + case MaxCommandIdAttributeNumber: + return sizeof f->t_cmax; + case ChainItemPointerAttributeNumber: + return sizeof f->t_chain; + case MinAbsoluteTimeAttributeNumber: + return sizeof f->t_tmin; + case MaxAbsoluteTimeAttributeNumber: + return sizeof f->t_tmax; + case VersionTypeAttributeNumber: + return sizeof f->t_vtype; + + case AnchorItemPointerAttributeNumber: + elog(WARN, "heap_sysattrlen: field t_anchor does not exist!"); + return 0; + + default: + elog(WARN, "sysattrlen: System attribute number %d unknown.", attno); + return 0; + } } /* ---------------- - * heap_sysattrbyval + * heap_sysattrbyval * - * This routine returns the "by-value" property of a system attribute. + * This routine returns the "by-value" property of a system attribute. * ---------------- */ bool heap_sysattrbyval(AttrNumber attno) { - bool byval; - - switch (attno) { - case SelfItemPointerAttributeNumber: - byval = false; - break; - case ObjectIdAttributeNumber: - byval = true; - break; - case MinTransactionIdAttributeNumber: - byval = true; - break; - case MinCommandIdAttributeNumber: - byval = true; - break; - case MaxTransactionIdAttributeNumber: - byval = true; - break; - case MaxCommandIdAttributeNumber: - byval = true; - break; - case ChainItemPointerAttributeNumber: - byval = false; - break; - case AnchorItemPointerAttributeNumber: - byval = false; - break; - case MinAbsoluteTimeAttributeNumber: - byval = true; - break; - case MaxAbsoluteTimeAttributeNumber: - byval = true; - break; - case VersionTypeAttributeNumber: - byval = true; - break; - default: - byval = true; - elog(WARN, "sysattrbyval: System attribute number %d unknown.", - attno); - break; - } - - return byval; + bool byval; + + switch (attno) + { + case SelfItemPointerAttributeNumber: + byval = false; + break; + case ObjectIdAttributeNumber: + byval = true; + break; + case MinTransactionIdAttributeNumber: + byval = true; + break; + case MinCommandIdAttributeNumber: + byval = true; + break; + case MaxTransactionIdAttributeNumber: + byval = true; + break; + case MaxCommandIdAttributeNumber: + byval = true; + break; + case ChainItemPointerAttributeNumber: + byval = false; + break; + case AnchorItemPointerAttributeNumber: + byval = false; + break; + case MinAbsoluteTimeAttributeNumber: + byval = true; + break; + case MaxAbsoluteTimeAttributeNumber: + byval = true; + break; + case VersionTypeAttributeNumber: + byval = true; + break; + default: + byval = true; + elog(WARN, "sysattrbyval: System attribute number %d unknown.", + attno); + break; + } + + return byval; } /* ---------------- - * heap_getsysattr + * heap_getsysattr * ---------------- */ -char * +char * heap_getsysattr(HeapTuple tup, Buffer b, int attnum) { - switch (attnum) { - case SelfItemPointerAttributeNumber: - return ((char *)&tup->t_ctid); - case ObjectIdAttributeNumber: - return ((char *) (long) tup->t_oid); - case MinTransactionIdAttributeNumber: - return ((char *) (long) tup->t_xmin); - case MinCommandIdAttributeNumber: - return ((char *) (long) tup->t_cmin); - case MaxTransactionIdAttributeNumber: - return ((char *) (long) tup->t_xmax); - case MaxCommandIdAttributeNumber: - return ((char *) (long) tup->t_cmax); - case ChainItemPointerAttributeNumber: - return ((char *) &tup->t_chain); - case AnchorItemPointerAttributeNumber: - elog(WARN, "heap_getsysattr: t_anchor does not exist!"); - break; - - /* - * For tmin and tmax, we need to do some extra work. These don't - * get filled in until the vacuum cleaner runs (or we manage to flush - * a page after setting the value correctly below). If the vacuum - * cleaner hasn't run yet, then the times stored in the tuple are - * wrong, and we need to look up the commit time of the transaction. - * We cache this value in the tuple to avoid doing the work more than - * once. - */ - - case MinAbsoluteTimeAttributeNumber: - if (!AbsoluteTimeIsBackwardCompatiblyValid(tup->t_tmin) && - TransactionIdDidCommit(tup->t_xmin)) - tup->t_tmin = TransactionIdGetCommitTime(tup->t_xmin); - return ((char *) (long) tup->t_tmin); - case MaxAbsoluteTimeAttributeNumber: - if (!AbsoluteTimeIsBackwardCompatiblyReal(tup->t_tmax)) { - if (TransactionIdDidCommit(tup->t_xmax)) - tup->t_tmax = TransactionIdGetCommitTime(tup->t_xmax); - else - tup->t_tmax = CURRENT_ABSTIME; + switch (attnum) + { + case SelfItemPointerAttributeNumber: + return ((char *) &tup->t_ctid); + case ObjectIdAttributeNumber: + return ((char *) (long) tup->t_oid); + case MinTransactionIdAttributeNumber: + return ((char *) (long) tup->t_xmin); + case MinCommandIdAttributeNumber: + return ((char *) (long) tup->t_cmin); + case MaxTransactionIdAttributeNumber: + return ((char *) (long) tup->t_xmax); + case MaxCommandIdAttributeNumber: + return ((char *) (long) tup->t_cmax); + case ChainItemPointerAttributeNumber: + return ((char *) &tup->t_chain); + case AnchorItemPointerAttributeNumber: + elog(WARN, "heap_getsysattr: t_anchor does not exist!"); + break; + + /* + * For tmin and tmax, we need to do some extra work. These don't + * get filled in until the vacuum cleaner runs (or we manage to + * flush a page after setting the value correctly below). If the + * vacuum cleaner hasn't run yet, then the times stored in the + * tuple are wrong, and we need to look up the commit time of the + * transaction. We cache this value in the tuple to avoid doing + * the work more than once. + */ + + case MinAbsoluteTimeAttributeNumber: + if (!AbsoluteTimeIsBackwardCompatiblyValid(tup->t_tmin) && + TransactionIdDidCommit(tup->t_xmin)) + tup->t_tmin = TransactionIdGetCommitTime(tup->t_xmin); + return ((char *) (long) tup->t_tmin); + case MaxAbsoluteTimeAttributeNumber: + if (!AbsoluteTimeIsBackwardCompatiblyReal(tup->t_tmax)) + { + if (TransactionIdDidCommit(tup->t_xmax)) + tup->t_tmax = TransactionIdGetCommitTime(tup->t_xmax); + else + tup->t_tmax = CURRENT_ABSTIME; + } + return ((char *) (long) tup->t_tmax); + case VersionTypeAttributeNumber: + return ((char *) (long) tup->t_vtype); + default: + elog(WARN, "heap_getsysattr: undefined attnum %d", attnum); } - return ((char *) (long) tup->t_tmax); - case VersionTypeAttributeNumber: - return ((char *) (long) tup->t_vtype); - default: - elog(WARN, "heap_getsysattr: undefined attnum %d", attnum); - } - return(NULL); + return (NULL); } /* ---------------- - * fastgetattr + * fastgetattr * - * This is a newer version of fastgetattr which attempts to be - * faster by caching attribute offsets in the attribute descriptor. + * This is a newer version of fastgetattr 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 * ---------------- */ -char * +char * fastgetattr(HeapTuple tup, - int attnum, - TupleDesc tupleDesc, - bool *isnull) + int attnum, + TupleDesc tupleDesc, + bool * isnull) { - char *tp; /* ptr to att in tuple */ - bits8 *bp = NULL; /* ptr to att in tuple */ - int slow; /* do we have to walk nulls? */ - AttributeTupleForm *att = tupleDesc->attrs; - - /* ---------------- - * sanity checks - * ---------------- - */ - - 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. - * ---------------- - */ - - if (isnull) - *isnull = false; - - if (HeapTupleNoNulls(tup)) { - attnum--; - if (att[attnum]->attcacheoff > 0) { - return (char *) - fetchatt( &(att[attnum]), - (char *)tup + tup->t_hoff + att[attnum]->attcacheoff); - } else if (attnum == 0) { - /* - * first attribute is always at position zero - */ - return((char *) fetchatt(&(att[0]), (char *) tup + tup->t_hoff)); - } - - tp = (char *) tup + tup->t_hoff; - - slow = 0; - } else { - /* - * there's a null somewhere in the tuple - */ + char *tp; /* ptr to att in tuple */ + bits8 *bp = NULL; /* ptr to att in tuple */ + int slow; /* do we have to walk nulls? */ + AttributeTupleForm *att = tupleDesc->attrs; - bp = tup->t_bits; - tp = (char *) tup + tup->t_hoff; - slow = 0; - attnum--; - /* ---------------- - * check to see if desired att is null + * sanity checks * ---------------- */ - - if (att_isnull(attnum, bp)) { - if (isnull) - *isnull = true; - return NULL; - } + + 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. * ---------------- */ - + + if (isnull) + *isnull = false; + + if (HeapTupleNoNulls(tup)) { - register int i = 0; /* current offset in bp */ - - for (i = 0; i < attnum && !slow; i++) { - if (att_isnull(i, bp)) slow = 1; - } + attnum--; + if (att[attnum]->attcacheoff > 0) + { + return (char *) + fetchatt(&(att[attnum]), + (char *) tup + tup->t_hoff + att[attnum]->attcacheoff); + } + else if (attnum == 0) + { + + /* + * first attribute is always at position zero + */ + return ((char *) fetchatt(&(att[0]), (char *) tup + tup->t_hoff)); + } + + tp = (char *) tup + tup->t_hoff; + + slow = 0; } - } - - /* - * now check for any non-fixed length attrs before our attribute - */ - if (!slow) { - if (att[attnum]->attcacheoff > 0) { - return (char *) - fetchatt(&(att[attnum]), - tp + att[attnum]->attcacheoff); - } else if (attnum == 0) { - return (char *) - fetchatt(&(att[0]), (char *) tup + tup->t_hoff); - } else if (!HeapTupleAllFixed(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 = tup->t_bits; + tp = (char *) tup + tup->t_hoff; + slow = 0; + attnum--; + + /* ---------------- + * check to see if desired att is null + * ---------------- + */ + + if (att_isnull(attnum, bp)) + { + if (isnull) + *isnull = true; + return NULL; + } + + /* ---------------- + * Now check to see if any preceeding bits are null... + * ---------------- + */ + + { + register int i = 0; /* current offset in bp */ + + for (i = 0; i < attnum && !slow; i++) + { + if (att_isnull(i, bp)) + slow = 1; + } + } } - } - - /* - * if slow is zero, and we got here, we know that we have a tuple with - * no nulls. We also 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 + * now check for any non-fixed length attrs before our attribute */ - - att[0]->attcacheoff = 0; - - while (att[j]->attcacheoff > 0) j++; - - off = att[j-1]->attcacheoff + att[j-1]->attlen; - - for (; j < attnum + 1; j++) { - 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)) { - elog(WARN, - "fastgetattr: attribute %d has len %d", - j, att[j]->attlen); + if (!slow) + { + if (att[attnum]->attcacheoff > 0) + { + return (char *) + fetchatt(&(att[attnum]), + tp + att[attnum]->attcacheoff); + } + else if (attnum == 0) + { + return (char *) + fetchatt(&(att[0]), (char *) tup + tup->t_hoff); + } + else if (!HeapTupleAllFixed(tup)) + { + register int j = 0; + + for (j = 0; j < attnum && !slow; j++) + if (att[j]->attlen < 1) + slow = 1; } - if (att[j]->attalign == 'd') - off = DOUBLEALIGN(off); - else - off = LONGALIGN(off); - break; - } - - att[j]->attcacheoff = off; - off += att[j]->attlen; } - - return - (char *)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. - * - * Note - This loop is a little tricky. On iteration i we - * first set the offset for attribute i and figure out how much - * the offset should be incremented. Finally, we need to align the - * offset based on the size of attribute i+1 (for which the offset - * has been computed). -mer 12 Dec 1991 + * if slow is zero, and we got here, we know that we have a tuple with + * no nulls. We also have to initialize the remainder of the + * attribute cached offset values. */ - - for (i = 0; i < attnum; i++) { - if (!HeapTupleNoNulls(tup)) { - if (att_isnull(i, bp)) { - usecache = false; - 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(WARN, - "fastgetattr2: 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 > 0) { - off = att[i]->attcacheoff; - if (att[i]->attlen == -1) { - usecache = false; + 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++) + { + 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)) + { + elog(WARN, + "fastgetattr: attribute %d has len %d", + j, att[j]->attlen); + } + if (att[j]->attalign == 'd') + off = DOUBLEALIGN(off); + else + off = LONGALIGN(off); + break; + } + + att[j]->attcacheoff = off; + off += att[j]->attlen; } - } else { - if (usecache) att[i]->attcacheoff = off; - } - - switch(att[i]->attlen) { - case sizeof(char): - off++; - break; - case sizeof(int16): - off += sizeof(int16); - break; - case sizeof(int32): - off += sizeof(int32); - break; - case -1: - usecache = false; - off += VARSIZE(tp + off); - break; - default: - off += att[i]->attlen; - break; - } + + return + (char *) fetchatt(&(att[attnum]), tp + att[attnum]->attcacheoff); } - 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; + else + { + register bool usecache = true; + register int off = 0; + register int i; + + /* + * Now we know that we have to walk the tuple CAREFULLY. + * + * Note - This loop is a little tricky. On iteration i we first set + * the offset for attribute i and figure out how much the offset + * should be incremented. Finally, we need to align the offset + * based on the size of attribute i+1 (for which the offset has + * been computed). -mer 12 Dec 1991 + */ + + for (i = 0; i < attnum; i++) + { + if (!HeapTupleNoNulls(tup)) + { + if (att_isnull(i, bp)) + { + usecache = false; + 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(WARN, + "fastgetattr2: 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 > 0) + { + off = att[i]->attcacheoff; + if (att[i]->attlen == -1) + { + usecache = false; + } + } + else + { + if (usecache) + att[i]->attcacheoff = off; + } + + switch (att[i]->attlen) + { + case sizeof(char): + off++; + break; + case sizeof(int16): + off += sizeof(int16); + break; + case sizeof(int32): + off += sizeof(int32); + break; + case -1: + usecache = false; + off += VARSIZE(tp + off); + break; + default: + off += att[i]->attlen; + break; + } + } + 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 ((char *) fetchatt(&(att[attnum]), tp + off)); } - return((char *) fetchatt(&(att[attnum]), tp + off)); - } } /* ---------------- - * heap_copytuple + * heap_copytuple * - * returns a copy of an entire tuple + * returns a copy of an entire tuple * ---------------- */ HeapTuple heap_copytuple(HeapTuple tuple) { - HeapTuple newTuple; + HeapTuple newTuple; - if (! HeapTupleIsValid(tuple)) - return (NULL); - - /* XXX For now, just prevent an undetectable executor related error */ - if (tuple->t_len > MAXTUPLEN) { - elog(WARN, "palloctup: cannot handle length %d tuples", - tuple->t_len); - } - - newTuple = (HeapTuple) palloc(tuple->t_len); - memmove((char *) newTuple, (char *) tuple, (int) tuple->t_len); - return(newTuple); + if (!HeapTupleIsValid(tuple)) + return (NULL); + + /* XXX For now, just prevent an undetectable executor related error */ + if (tuple->t_len > MAXTUPLEN) + { + elog(WARN, "palloctup: cannot handle length %d tuples", + tuple->t_len); + } + + newTuple = (HeapTuple) palloc(tuple->t_len); + memmove((char *) newTuple, (char *) tuple, (int) tuple->t_len); + return (newTuple); } #ifdef NOT_USED /* ---------------- - * heap_deformtuple + * heap_deformtuple * - * the inverse of heap_formtuple (see below) + * the inverse of heap_formtuple (see below) * ---------------- */ void heap_deformtuple(HeapTuple tuple, - TupleDesc tdesc, - Datum values[], - char nulls[]) + TupleDesc tdesc, + Datum values[], + char nulls[]) { - int i; - int natts; - - Assert(HeapTupleIsValid(tuple)); - - natts = tuple->t_natts; - for (i = 0; i<natts; i++) { - bool isnull; - - values[i] = (Datum)heap_getattr(tuple, - InvalidBuffer, - i+1, - tdesc, - &isnull); - if (isnull) - nulls[i] = 'n'; - else - nulls[i] = ' '; - } + int i; + int natts; + + Assert(HeapTupleIsValid(tuple)); + + natts = tuple->t_natts; + for (i = 0; i < natts; i++) + { + bool isnull; + + values[i] = (Datum) heap_getattr(tuple, + InvalidBuffer, + i + 1, + tdesc, + &isnull); + if (isnull) + nulls[i] = 'n'; + else + nulls[i] = ' '; + } } + #endif /* ---------------- - * heap_formtuple + * heap_formtuple * - * constructs a tuple from the given value[] and null[] arrays + * constructs a tuple from the given value[] and null[] arrays * * old comments - * Handles alignment by aligning 2 byte attributes on short boundries - * and 3 or 4 byte attributes on long word boundries on a vax; and - * aligning non-byte attributes on short boundries on a sun. Does - * not properly align fixed length arrays of 1 or 2 byte types (yet). + * Handles alignment by aligning 2 byte attributes on short boundries + * and 3 or 4 byte attributes on long word boundries on a vax; and + * aligning non-byte attributes on short boundries on a sun. Does + * not properly align fixed length arrays of 1 or 2 byte types (yet). * - * Null attributes are indicated by a 'n' in the appropriate byte - * of the null[]. Non-null attributes are indicated by a ' ' (space). + * Null attributes are indicated by a 'n' in the appropriate byte + * of the null[]. Non-null attributes are indicated by a ' ' (space). * - * Fix me. (Figure that must keep context if debug--allow give oid.) - * Assumes in order. + * Fix me. (Figure that must keep context if debug--allow give oid.) + * Assumes in order. * ---------------- */ HeapTuple heap_formtuple(TupleDesc tupleDescriptor, - Datum value[], - char nulls[]) + Datum value[], + char nulls[]) { - char *tp; /* tuple pointer */ - HeapTuple tuple; /* return tuple */ - int bitmaplen; - long len; - int hoff; - bool hasnull = false; - int i; - int numberOfAttributes = tupleDescriptor->natts; - - len = sizeof *tuple - sizeof tuple->t_bits; - - for (i = 0; i < numberOfAttributes && !hasnull; i++) { - if (nulls[i] != ' ') hasnull = true; - } - - if (numberOfAttributes > MaxHeapAttributeNumber) - elog(WARN, "heap_formtuple: numberOfAttributes of %d > %d", - numberOfAttributes, MaxHeapAttributeNumber); - - if (hasnull) { - bitmaplen = BITMAPLEN(numberOfAttributes); - len += bitmaplen; - } - - hoff = len = DOUBLEALIGN(len); /* be conservative here */ - - len += ComputeDataSize(tupleDescriptor, value, nulls); - - tp = (char *) palloc(len); - tuple = (HeapTuple) tp; - - memset(tp, 0, (int)len); - - tuple->t_len = len; - tuple->t_natts = numberOfAttributes; - tuple->t_hoff = hoff; - tuple->t_tmin = INVALID_ABSTIME; - tuple->t_tmax = CURRENT_ABSTIME; - - DataFill((char *)tuple + tuple->t_hoff, - tupleDescriptor, - value, - nulls, - &tuple->t_infomask, - (hasnull ? tuple->t_bits : NULL)); - - return (tuple); + char *tp; /* tuple pointer */ + HeapTuple tuple; /* return tuple */ + int bitmaplen; + long len; + int hoff; + bool hasnull = false; + int i; + int numberOfAttributes = tupleDescriptor->natts; + + len = sizeof *tuple - sizeof tuple->t_bits; + + for (i = 0; i < numberOfAttributes && !hasnull; i++) + { + if (nulls[i] != ' ') + hasnull = true; + } + + if (numberOfAttributes > MaxHeapAttributeNumber) + elog(WARN, "heap_formtuple: numberOfAttributes of %d > %d", + numberOfAttributes, MaxHeapAttributeNumber); + + if (hasnull) + { + bitmaplen = BITMAPLEN(numberOfAttributes); + len += bitmaplen; + } + + hoff = len = DOUBLEALIGN(len); /* be conservative here */ + + len += ComputeDataSize(tupleDescriptor, value, nulls); + + tp = (char *) palloc(len); + tuple = (HeapTuple) tp; + + memset(tp, 0, (int) len); + + tuple->t_len = len; + tuple->t_natts = numberOfAttributes; + tuple->t_hoff = hoff; + tuple->t_tmin = INVALID_ABSTIME; + tuple->t_tmax = CURRENT_ABSTIME; + + DataFill((char *) tuple + tuple->t_hoff, + tupleDescriptor, + value, + nulls, + &tuple->t_infomask, + (hasnull ? tuple->t_bits : NULL)); + + return (tuple); } /* ---------------- - * heap_modifytuple + * heap_modifytuple * - * forms a new tuple from an old tuple and a set of replacement values. + * forms a new tuple from an old tuple and a set of replacement values. * ---------------- */ HeapTuple heap_modifytuple(HeapTuple tuple, - Buffer buffer, - Relation relation, - Datum replValue[], - char replNull[], - char repl[]) + Buffer buffer, + Relation relation, + Datum replValue[], + char replNull[], + char repl[]) { - int attoff; - int numberOfAttributes; - Datum *value; - char *nulls; - bool isNull; - HeapTuple newTuple; - int madecopy; - uint8 infomask; - - /* ---------------- - * sanity checks - * ---------------- - */ - Assert(HeapTupleIsValid(tuple)); - Assert(BufferIsValid(buffer) || RelationIsValid(relation)); - Assert(HeapTupleIsValid(tuple)); - Assert(PointerIsValid(replValue)); - Assert(PointerIsValid(replNull)); - Assert(PointerIsValid(repl)); - - /* ---------------- - * if we're pointing to a disk page, then first - * make a copy of our tuple so that all the attributes - * are available. XXX this is inefficient -cim - * ---------------- - */ - madecopy = 0; - if (BufferIsValid(buffer) == true) { - relation = (Relation) BufferGetRelation(buffer); - tuple = heap_copytuple(tuple); - madecopy = 1; - } - - numberOfAttributes = RelationGetRelationTupleForm(relation)->relnatts; - - /* ---------------- - * allocate and fill value[] and nulls[] arrays from either - * the tuple or the repl information, as appropriate. - * ---------------- - */ - value = (Datum *) palloc(numberOfAttributes * sizeof *value); - nulls = (char *) palloc(numberOfAttributes * sizeof *nulls); - - for (attoff = 0; - attoff < numberOfAttributes; - attoff += 1) { - - if (repl[attoff] == ' ') { - char *attr; - - attr = - heap_getattr(tuple, - InvalidBuffer, - AttrOffsetGetAttrNumber(attoff), - RelationGetTupleDescriptor(relation), - &isNull) ; - value[attoff] = PointerGetDatum(attr); - nulls[attoff] = (isNull) ? 'n' : ' '; - - } else if (repl[attoff] != 'r') { - elog(WARN, "heap_modifytuple: repl is \\%3d", repl[attoff]); - - } else { /* == 'r' */ - value[attoff] = replValue[attoff]; - nulls[attoff] = replNull[attoff]; + int attoff; + int numberOfAttributes; + Datum *value; + char *nulls; + bool isNull; + HeapTuple newTuple; + int madecopy; + uint8 infomask; + + /* ---------------- + * sanity checks + * ---------------- + */ + Assert(HeapTupleIsValid(tuple)); + Assert(BufferIsValid(buffer) || RelationIsValid(relation)); + Assert(HeapTupleIsValid(tuple)); + Assert(PointerIsValid(replValue)); + Assert(PointerIsValid(replNull)); + Assert(PointerIsValid(repl)); + + /* ---------------- + * if we're pointing to a disk page, then first + * make a copy of our tuple so that all the attributes + * are available. XXX this is inefficient -cim + * ---------------- + */ + madecopy = 0; + if (BufferIsValid(buffer) == true) + { + relation = (Relation) BufferGetRelation(buffer); + tuple = heap_copytuple(tuple); + madecopy = 1; + } + + numberOfAttributes = RelationGetRelationTupleForm(relation)->relnatts; + + /* ---------------- + * allocate and fill value[] and nulls[] arrays from either + * the tuple or the repl information, as appropriate. + * ---------------- + */ + value = (Datum *) palloc(numberOfAttributes * sizeof *value); + nulls = (char *) palloc(numberOfAttributes * sizeof *nulls); + + for (attoff = 0; + attoff < numberOfAttributes; + attoff += 1) + { + + if (repl[attoff] == ' ') + { + char *attr; + + attr = + heap_getattr(tuple, + InvalidBuffer, + AttrOffsetGetAttrNumber(attoff), + RelationGetTupleDescriptor(relation), + &isNull); + value[attoff] = PointerGetDatum(attr); + nulls[attoff] = (isNull) ? 'n' : ' '; + + } + else if (repl[attoff] != 'r') + { + elog(WARN, "heap_modifytuple: repl is \\%3d", repl[attoff]); + + } + else + { /* == 'r' */ + value[attoff] = replValue[attoff]; + nulls[attoff] = replNull[attoff]; + } } - } - - /* ---------------- - * create a new tuple from the values[] and nulls[] arrays - * ---------------- - */ - newTuple = heap_formtuple(RelationGetTupleDescriptor(relation), - value, - nulls); - - /* ---------------- - * copy the header except for t_len, t_natts, t_hoff, t_bits, t_infomask - * ---------------- - */ - infomask = newTuple->t_infomask; - memmove((char *) &newTuple->t_ctid, /*XXX*/ - (char *) &tuple->t_ctid, - ((char *) &tuple->t_hoff - (char *) &tuple->t_ctid)); /*XXX*/ - newTuple->t_infomask = infomask; - newTuple->t_natts = numberOfAttributes; /* fix t_natts just in case */ - - /* ---------------- - * if we made a copy of the tuple, then free it. - * ---------------- - */ - if (madecopy) - pfree(tuple); - - return - newTuple; + + /* ---------------- + * create a new tuple from the values[] and nulls[] arrays + * ---------------- + */ + newTuple = heap_formtuple(RelationGetTupleDescriptor(relation), + value, + nulls); + + /* ---------------- + * copy the header except for t_len, t_natts, t_hoff, t_bits, t_infomask + * ---------------- + */ + infomask = newTuple->t_infomask; + memmove((char *) &newTuple->t_ctid, /* XXX */ + (char *) &tuple->t_ctid, + ((char *) &tuple->t_hoff - (char *) &tuple->t_ctid)); /* XXX */ + newTuple->t_infomask = infomask; + newTuple->t_natts = numberOfAttributes; /* fix t_natts just in + * case */ + + /* ---------------- + * if we made a copy of the tuple, then free it. + * ---------------- + */ + if (madecopy) + pfree(tuple); + + return + newTuple; } /* ---------------------------------------------------------------- - * other misc functions + * other misc functions * ---------------------------------------------------------------- */ HeapTuple heap_addheader(uint32 natts, /* max domain index */ - int structlen, /* its length */ - char *structure) /* pointer to the struct */ + int structlen, /* its length */ + char *structure) /* pointer to the struct */ { - register char *tp; /* tuple data pointer */ - HeapTuple tup; - long len; - int hoff; - - AssertArg(natts > 0); - - len = sizeof (HeapTupleData) - sizeof (tup->t_bits); - - hoff = len = DOUBLEALIGN(len); /* be conservative */ - len += structlen; - tp = (char *) palloc(len); - tup = (HeapTuple) tp; - memset((char*)tup, 0, len); - - tup->t_len = (short) len; /* XXX */ - tp += tup->t_hoff = hoff; - tup->t_natts = natts; - tup->t_infomask = 0; - - memmove(tp, structure, structlen); - - return (tup); + register char *tp; /* tuple data pointer */ + HeapTuple tup; + long len; + int hoff; + + AssertArg(natts > 0); + + len = sizeof(HeapTupleData) - sizeof(tup->t_bits); + + hoff = len = DOUBLEALIGN(len); /* be conservative */ + len += structlen; + tp = (char *) palloc(len); + tup = (HeapTuple) tp; + memset((char *) tup, 0, len); + + tup->t_len = (short) len; /* XXX */ + tp += tup->t_hoff = hoff; + tup->t_natts = natts; + tup->t_infomask = 0; + + memmove(tp, structure, structlen); + + return (tup); } diff --git a/src/backend/access/common/heapvalid.c b/src/backend/access/common/heapvalid.c index 186ee654b32..0caeb54e17c 100644 --- a/src/backend/access/common/heapvalid.c +++ b/src/backend/access/common/heapvalid.c @@ -1,13 +1,13 @@ /*------------------------------------------------------------------------- * * heapvalid.c-- - * heap tuple qualification validity checking code + * heap tuple qualification validity checking code * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/common/Attic/heapvalid.c,v 1.16 1997/08/29 09:12:20 vadim Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/common/Attic/heapvalid.c,v 1.17 1997/09/07 04:37:36 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -25,128 +25,138 @@ #include <utils/builtins.h> /* ---------------- - * heap_keytest + * heap_keytest * - * Test a heap tuple with respect to a scan key. + * Test a heap tuple with respect to a scan key. * ---------------- */ bool heap_keytest(HeapTuple t, - TupleDesc tupdesc, - int nkeys, - ScanKey keys) + TupleDesc tupdesc, + int nkeys, + ScanKey keys) { - bool isnull; - Datum atp; - int test; - - for (; nkeys--; keys++) { - atp = (Datum)heap_getattr(t, InvalidBuffer, - keys->sk_attno, - tupdesc, - &isnull); - - if (isnull) - /* XXX eventually should check if SK_ISNULL */ - return false; - - if (keys->sk_flags & SK_ISNULL) { - return (false); + bool isnull; + Datum atp; + int test; + + for (; nkeys--; keys++) + { + atp = (Datum) heap_getattr(t, InvalidBuffer, + keys->sk_attno, + tupdesc, + &isnull); + + if (isnull) + /* XXX eventually should check if SK_ISNULL */ + return false; + + if (keys->sk_flags & SK_ISNULL) + { + return (false); + } + + if (keys->sk_func == (func_ptr) oideq) /* optimization */ + test = (keys->sk_argument == atp); + else if (keys->sk_flags & SK_COMMUTE) + test = (long) FMGR_PTR2(keys->sk_func, keys->sk_procedure, + keys->sk_argument, atp); + else + test = (long) FMGR_PTR2(keys->sk_func, keys->sk_procedure, + atp, keys->sk_argument); + + if (!test == !(keys->sk_flags & SK_NEGATE)) + return false; } - if (keys->sk_func == (func_ptr)oideq) /* optimization */ - test = (keys->sk_argument == atp); - else if (keys->sk_flags & SK_COMMUTE) - test = (long) FMGR_PTR2(keys->sk_func, keys->sk_procedure, - keys->sk_argument, atp); - else - test = (long) FMGR_PTR2(keys->sk_func, keys->sk_procedure, - atp, keys->sk_argument); - - if (!test == !(keys->sk_flags & SK_NEGATE)) - return false; - } - - return true; + return true; } /* ---------------- - * heap_tuple_satisfies + * heap_tuple_satisfies * - * Returns a valid HeapTuple if it satisfies the timequal and keytest. - * Returns NULL otherwise. Used to be heap_satisifies (sic) which - * returned a boolean. It now returns a tuple so that we can avoid doing two - * PageGetItem's per tuple. + * Returns a valid HeapTuple if it satisfies the timequal and keytest. + * Returns NULL otherwise. Used to be heap_satisifies (sic) which + * returned a boolean. It now returns a tuple so that we can avoid doing two + * PageGetItem's per tuple. * - * Complete check of validity including LP_CTUP and keytest. - * This should perhaps be combined with valid somehow in the - * future. (Also, additional rule tests/time range tests.) + * Complete check of validity including LP_CTUP and keytest. + * This should perhaps be combined with valid somehow in the + * future. (Also, additional rule tests/time range tests.) * - * on 8/21/92 mao says: i rearranged the tests here to do keytest before - * SatisfiesTimeQual. profiling indicated that even for vacuumed relations, - * time qual checking was more expensive than key testing. time qual is - * least likely to fail, too. we should really add the time qual test to - * the restriction and optimize it in the normal way. this has interactions - * with joey's expensive function work. + * on 8/21/92 mao says: i rearranged the tests here to do keytest before + * SatisfiesTimeQual. profiling indicated that even for vacuumed relations, + * time qual checking was more expensive than key testing. time qual is + * least likely to fail, too. we should really add the time qual test to + * the restriction and optimize it in the normal way. this has interactions + * with joey's expensive function work. * ---------------- */ HeapTuple heap_tuple_satisfies(ItemId itemId, - Relation relation, - Buffer buffer, - PageHeader disk_page, - TimeQual qual, - int nKeys, - ScanKey key) + Relation relation, + Buffer buffer, + PageHeader disk_page, + TimeQual qual, + int nKeys, + ScanKey key) { - HeapTuple tuple, result; - bool res; - TransactionId old_tmin, old_tmax; - - if (! ItemIdIsUsed(itemId)) - return NULL; - - tuple = (HeapTuple) PageGetItem((Page) disk_page, itemId); - - if (key != NULL) - res = heap_keytest(tuple, RelationGetTupleDescriptor(relation), - nKeys, key); - else - res = TRUE; - - result = (HeapTuple)NULL; - if (res) { - if(relation->rd_rel->relkind == RELKIND_UNCATALOGED) { - result = tuple; - } else { - old_tmin = tuple->t_tmin; - old_tmax = tuple->t_tmax; - res = HeapTupleSatisfiesTimeQual(tuple,qual); - if(tuple->t_tmin != old_tmin || - tuple->t_tmax != old_tmax) { - SetBufferCommitInfoNeedsSave(buffer); - } - if(res) { - result = tuple; - } + HeapTuple tuple, + result; + bool res; + TransactionId old_tmin, + old_tmax; + + if (!ItemIdIsUsed(itemId)) + return NULL; + + tuple = (HeapTuple) PageGetItem((Page) disk_page, itemId); + + if (key != NULL) + res = heap_keytest(tuple, RelationGetTupleDescriptor(relation), + nKeys, key); + else + res = TRUE; + + result = (HeapTuple) NULL; + if (res) + { + if (relation->rd_rel->relkind == RELKIND_UNCATALOGED) + { + result = tuple; + } + else + { + old_tmin = tuple->t_tmin; + old_tmax = tuple->t_tmax; + res = HeapTupleSatisfiesTimeQual(tuple, qual); + if (tuple->t_tmin != old_tmin || + tuple->t_tmax != old_tmax) + { + SetBufferCommitInfoNeedsSave(buffer); + } + if (res) + { + result = tuple; + } + } } - } - return result; + return result; } /* - * TupleUpdatedByCurXactAndCmd() -- Returns true if this tuple has - * already been updated once by the current transaction/command - * pair. + * TupleUpdatedByCurXactAndCmd() -- Returns true if this tuple has + * already been updated once by the current transaction/command + * pair. */ bool TupleUpdatedByCurXactAndCmd(HeapTuple t) { - if (TransactionIdEquals(t->t_xmax, - GetCurrentTransactionId()) && - CommandIdGEScanCommandId (t->t_cmax)) - return true; - - return false; + if (TransactionIdEquals(t->t_xmax, + GetCurrentTransactionId()) && + CommandIdGEScanCommandId(t->t_cmax)) + return true; + + return false; } 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); +} diff --git a/src/backend/access/common/indexvalid.c b/src/backend/access/common/indexvalid.c index aff9af42f8d..9f8501beb2e 100644 --- a/src/backend/access/common/indexvalid.c +++ b/src/backend/access/common/indexvalid.c @@ -1,13 +1,13 @@ /*------------------------------------------------------------------------- * * indexvalid.c-- - * index tuple qualification validity checking code + * index tuple qualification validity checking code * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/common/Attic/indexvalid.c,v 1.14 1997/03/18 18:38:19 scrappy Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/common/Attic/indexvalid.c,v 1.15 1997/09/07 04:37:38 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -21,64 +21,70 @@ #include <executor/execdebug.h> /* ---------------------------------------------------------------- - * index scan key qualification code + * index scan key qualification code * ---------------------------------------------------------------- */ -int NIndexTupleProcessed; +int NIndexTupleProcessed; /* ---------------- - * index_keytest + * index_keytest * * old comments - * May eventually combine with other tests (like timeranges)? - * Should have Buffer buffer; as an argument and pass it to amgetattr. + * May eventually combine with other tests (like timeranges)? + * Should have Buffer buffer; as an argument and pass it to amgetattr. * ---------------- */ bool index_keytest(IndexTuple tuple, - TupleDesc tupdesc, - int scanKeySize, - ScanKey key) + TupleDesc tupdesc, + int scanKeySize, + ScanKey key) { - bool isNull; - Datum datum; - int test; - - IncrIndexProcessed(); - - while (scanKeySize > 0) { - datum = index_getattr(tuple, - key[0].sk_attno, - tupdesc, - &isNull); - - if (isNull) { - /* XXX eventually should check if SK_ISNULL */ - return (false); - } - - if (key[0].sk_flags & SK_ISNULL) { - return (false); - } + bool isNull; + Datum datum; + int test; - if (key[0].sk_flags & SK_COMMUTE) { - test = (*(key[0].sk_func)) - (DatumGetPointer(key[0].sk_argument), - datum) ? 1 : 0; - } else { - test = (*(key[0].sk_func)) - (datum, - DatumGetPointer(key[0].sk_argument)) ? 1 : 0; - } - - if (!test == !(key[0].sk_flags & SK_NEGATE)) { - return (false); + IncrIndexProcessed(); + + while (scanKeySize > 0) + { + datum = index_getattr(tuple, + key[0].sk_attno, + tupdesc, + &isNull); + + if (isNull) + { + /* XXX eventually should check if SK_ISNULL */ + return (false); + } + + if (key[0].sk_flags & SK_ISNULL) + { + return (false); + } + + if (key[0].sk_flags & SK_COMMUTE) + { + test = (*(key[0].sk_func)) + (DatumGetPointer(key[0].sk_argument), + datum) ? 1 : 0; + } + else + { + test = (*(key[0].sk_func)) + (datum, + DatumGetPointer(key[0].sk_argument)) ? 1 : 0; + } + + if (!test == !(key[0].sk_flags & SK_NEGATE)) + { + return (false); + } + + scanKeySize -= 1; + key++; } - - scanKeySize -= 1; - key++; - } - - return (true); -} + return (true); +} diff --git a/src/backend/access/common/printtup.c b/src/backend/access/common/printtup.c index 98fbddc639d..599ac59a455 100644 --- a/src/backend/access/common/printtup.c +++ b/src/backend/access/common/printtup.c @@ -1,14 +1,14 @@ /*------------------------------------------------------------------------- * * printtup.c-- - * Routines to print out tuples to the destination (binary or non-binary - * portals, frontend/interactive backend, etc.). + * Routines to print out tuples to the destination (binary or non-binary + * portals, frontend/interactive backend, etc.). * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/common/printtup.c,v 1.15 1997/08/26 23:31:23 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/common/printtup.c,v 1.16 1997/09/07 04:37:39 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -16,279 +16,304 @@ #include <string.h> #include <postgres.h> -#include <fmgr.h> -#include <access/heapam.h> -#include <access/printtup.h> +#include <fmgr.h> +#include <access/heapam.h> +#include <access/printtup.h> #include <catalog/pg_type.h> #include <libpq/libpq.h> #include <utils/syscache.h> /* ---------------------------------------------------------------- - * printtup / debugtup support + * printtup / debugtup support * ---------------------------------------------------------------- */ /* ---------------- - * typtoout - used by printtup and debugtup + * typtoout - used by printtup and debugtup * ---------------- */ Oid typtoout(Oid type) { - HeapTuple typeTuple; - - typeTuple = SearchSysCacheTuple(TYPOID, - ObjectIdGetDatum(type), - 0, 0, 0); - - if (HeapTupleIsValid(typeTuple)) - return((Oid) - ((TypeTupleForm) GETSTRUCT(typeTuple))->typoutput); - - elog(WARN, "typtoout: Cache lookup of type %d failed", type); - return(InvalidOid); + HeapTuple typeTuple; + + typeTuple = SearchSysCacheTuple(TYPOID, + ObjectIdGetDatum(type), + 0, 0, 0); + + if (HeapTupleIsValid(typeTuple)) + return ((Oid) + ((TypeTupleForm) GETSTRUCT(typeTuple))->typoutput); + + elog(WARN, "typtoout: Cache lookup of type %d failed", type); + return (InvalidOid); } Oid gettypelem(Oid type) { - HeapTuple typeTuple; - - typeTuple = SearchSysCacheTuple(TYPOID, - ObjectIdGetDatum(type), - 0,0,0); - - if (HeapTupleIsValid(typeTuple)) - return((Oid) - ((TypeTupleForm) GETSTRUCT(typeTuple))->typelem); - - elog(WARN, "typtoout: Cache lookup of type %d failed", type); - return(InvalidOid); + HeapTuple typeTuple; + + typeTuple = SearchSysCacheTuple(TYPOID, + ObjectIdGetDatum(type), + 0, 0, 0); + + if (HeapTupleIsValid(typeTuple)) + return ((Oid) + ((TypeTupleForm) GETSTRUCT(typeTuple))->typelem); + + elog(WARN, "typtoout: Cache lookup of type %d failed", type); + return (InvalidOid); } /* ---------------- - * printtup + * printtup * ---------------- */ void printtup(HeapTuple tuple, TupleDesc typeinfo) { - int i, j, k; - char *outputstr, *attr; - bool isnull; - Oid typoutput; - - /* ---------------- - * tell the frontend to expect new tuple data - * ---------------- - */ - pq_putnchar("D", 1); - - /* ---------------- - * send a bitmap of which attributes are null - * ---------------- - */ - j = 0; - k = 1 << 7; - for (i = 0; i < tuple->t_natts; ) { - i++; /* heap_getattr is a macro, so no increment */ - attr = heap_getattr(tuple, InvalidBuffer, i, typeinfo, &isnull); - if (!isnull) - j |= k; - k >>= 1; - if (!(i & 7)) { - pq_putint(j, 1); - j = 0; - k = 1 << 7; + int i, + j, + k; + char *outputstr, + *attr; + bool isnull; + Oid typoutput; + + /* ---------------- + * tell the frontend to expect new tuple data + * ---------------- + */ + pq_putnchar("D", 1); + + /* ---------------- + * send a bitmap of which attributes are null + * ---------------- + */ + j = 0; + k = 1 << 7; + for (i = 0; i < tuple->t_natts;) + { + i++; /* heap_getattr is a macro, so no + * increment */ + attr = heap_getattr(tuple, InvalidBuffer, i, typeinfo, &isnull); + if (!isnull) + j |= k; + k >>= 1; + if (!(i & 7)) + { + pq_putint(j, 1); + j = 0; + k = 1 << 7; + } } - } - if (i & 7) - pq_putint(j, 1); - - /* ---------------- - * send the attributes of this tuple - * ---------------- - */ - for (i = 0; i < tuple->t_natts; ++i) { - attr = heap_getattr(tuple, InvalidBuffer, i+1, typeinfo, &isnull); - typoutput = typtoout((Oid) typeinfo->attrs[i]->atttypid); - - if (!isnull && OidIsValid(typoutput)) { - outputstr = fmgr(typoutput, attr, - gettypelem(typeinfo->attrs[i]->atttypid)); - pq_putint(strlen(outputstr)+4, 4); - pq_putnchar(outputstr, strlen(outputstr)); - pfree(outputstr); + if (i & 7) + pq_putint(j, 1); + + /* ---------------- + * send the attributes of this tuple + * ---------------- + */ + for (i = 0; i < tuple->t_natts; ++i) + { + attr = heap_getattr(tuple, InvalidBuffer, i + 1, typeinfo, &isnull); + typoutput = typtoout((Oid) typeinfo->attrs[i]->atttypid); + + if (!isnull && OidIsValid(typoutput)) + { + outputstr = fmgr(typoutput, attr, + gettypelem(typeinfo->attrs[i]->atttypid)); + pq_putint(strlen(outputstr) + 4, 4); + pq_putnchar(outputstr, strlen(outputstr)); + pfree(outputstr); + } } - } } /* ---------------- - * printatt + * printatt * ---------------- */ static void printatt(unsigned attributeId, - AttributeTupleForm attributeP, - char *value) + AttributeTupleForm attributeP, + char *value) { - printf("\t%2d: %s%s%s%s\t(typeid = %u, len = %d, byval = %c)\n", - attributeId, - attributeP->attname.data, - value != NULL ? " = \"" : "", - value != NULL ? value : "", - value != NULL ? "\"" : "", - (unsigned int) (attributeP->atttypid), - attributeP->attlen, - attributeP->attbyval ? 't' : 'f'); + printf("\t%2d: %s%s%s%s\t(typeid = %u, len = %d, byval = %c)\n", + attributeId, + attributeP->attname.data, + value != NULL ? " = \"" : "", + value != NULL ? value : "", + value != NULL ? "\"" : "", + (unsigned int) (attributeP->atttypid), + attributeP->attlen, + attributeP->attbyval ? 't' : 'f'); } /* ---------------- - * showatts + * showatts * ---------------- */ void showatts(char *name, TupleDesc tupleDesc) { - int i; - int natts = tupleDesc->natts; - AttributeTupleForm *attinfo = tupleDesc->attrs; + int i; + int natts = tupleDesc->natts; + AttributeTupleForm *attinfo = tupleDesc->attrs; - puts(name); - for (i = 0; i < natts; ++i) - printatt((unsigned) i+1, attinfo[i], (char *) NULL); - printf("\t----\n"); + puts(name); + for (i = 0; i < natts; ++i) + printatt((unsigned) i + 1, attinfo[i], (char *) NULL); + printf("\t----\n"); } /* ---------------- - * debugtup + * debugtup * ---------------- */ void debugtup(HeapTuple tuple, TupleDesc typeinfo) { - register int i; - char *attr, *value; - bool isnull; - Oid typoutput; - - for (i = 0; i < tuple->t_natts; ++i) { - attr = heap_getattr(tuple, InvalidBuffer, i+1, typeinfo, &isnull); - typoutput = typtoout((Oid) typeinfo->attrs[i]->atttypid); - - if (!isnull && OidIsValid(typoutput)) { - value = fmgr(typoutput, attr, - gettypelem(typeinfo->attrs[i]->atttypid)); - printatt((unsigned) i+1, typeinfo->attrs[i], value); - pfree(value); + register int i; + char *attr, + *value; + bool isnull; + Oid typoutput; + + for (i = 0; i < tuple->t_natts; ++i) + { + attr = heap_getattr(tuple, InvalidBuffer, i + 1, typeinfo, &isnull); + typoutput = typtoout((Oid) typeinfo->attrs[i]->atttypid); + + if (!isnull && OidIsValid(typoutput)) + { + value = fmgr(typoutput, attr, + gettypelem(typeinfo->attrs[i]->atttypid)); + printatt((unsigned) i + 1, typeinfo->attrs[i], value); + pfree(value); + } } - } - printf("\t----\n"); + printf("\t----\n"); } /* ---------------- - * printtup_internal - * Protocol expects either T, D, C, E, or N. - * We use a different data prefix, e.g. 'B' instead of 'D' to - * indicate a tuple in internal (binary) form. + * printtup_internal + * Protocol expects either T, D, C, E, or N. + * We use a different data prefix, e.g. 'B' instead of 'D' to + * indicate a tuple in internal (binary) form. * - * This is same as printtup, except we don't use the typout func. + * This is same as printtup, except we don't use the typout func. * ---------------- */ void printtup_internal(HeapTuple tuple, TupleDesc typeinfo) { - int i, j, k; - char *attr; - bool isnull; - - /* ---------------- - * tell the frontend to expect new tuple data - * ---------------- - */ - pq_putnchar("B", 1); - - /* ---------------- - * send a bitmap of which attributes are null - * ---------------- - */ - j = 0; - k = 1 << 7; - for (i = 0; i < tuple->t_natts; ) { - i++; /* heap_getattr is a macro, so no increment */ - attr = heap_getattr(tuple, InvalidBuffer, i, typeinfo, &isnull); - if (!isnull) - j |= k; - k >>= 1; - if (!(i & 7)) { - pq_putint(j, 1); - j = 0; - k = 1 << 7; + int i, + j, + k; + char *attr; + bool isnull; + + /* ---------------- + * tell the frontend to expect new tuple data + * ---------------- + */ + pq_putnchar("B", 1); + + /* ---------------- + * send a bitmap of which attributes are null + * ---------------- + */ + j = 0; + k = 1 << 7; + for (i = 0; i < tuple->t_natts;) + { + i++; /* heap_getattr is a macro, so no + * increment */ + attr = heap_getattr(tuple, InvalidBuffer, i, typeinfo, &isnull); + if (!isnull) + j |= k; + k >>= 1; + if (!(i & 7)) + { + pq_putint(j, 1); + j = 0; + k = 1 << 7; + } } - } - if (i & 7) - pq_putint(j, 1); - - /* ---------------- - * send the attributes of this tuple - * ---------------- - */ + if (i & 7) + pq_putint(j, 1); + + /* ---------------- + * send the attributes of this tuple + * ---------------- + */ #ifdef IPORTAL_DEBUG - fprintf(stderr, "sending tuple with %d atts\n", tuple->t_natts); + fprintf(stderr, "sending tuple with %d atts\n", tuple->t_natts); #endif - for (i = 0; i < tuple->t_natts; ++i) { - int32 len = typeinfo->attrs[i]->attlen; - - attr = heap_getattr(tuple, InvalidBuffer, i+1, typeinfo, &isnull); - if (!isnull) { - /* # of bytes, and opaque data */ - if (len == -1) { - /* variable length, assume a varlena structure */ - len = VARSIZE(attr) - VARHDRSZ; - - pq_putint(len, sizeof(int32)); - pq_putnchar(VARDATA(attr), len); -#ifdef IPORTAL_DEBUG + for (i = 0; i < tuple->t_natts; ++i) + { + int32 len = typeinfo->attrs[i]->attlen; + + attr = heap_getattr(tuple, InvalidBuffer, i + 1, typeinfo, &isnull); + if (!isnull) { - char *d = VARDATA(attr); - - fprintf(stderr, "length %d data %x%x%x%x\n", - len, *d, *(d+1), *(d+2), *(d+3)); - } + /* # of bytes, and opaque data */ + if (len == -1) + { + /* variable length, assume a varlena structure */ + len = VARSIZE(attr) - VARHDRSZ; + + pq_putint(len, sizeof(int32)); + pq_putnchar(VARDATA(attr), len); +#ifdef IPORTAL_DEBUG + { + char *d = VARDATA(attr); + + fprintf(stderr, "length %d data %x%x%x%x\n", + len, *d, *(d + 1), *(d + 2), *(d + 3)); + } #endif - } else { - /* fixed size */ - if (typeinfo->attrs[i]->attbyval) { - int8 i8; - int16 i16; - int32 i32; - - pq_putint(len, sizeof(int32)); - switch (len) { - case sizeof(int8): - i8 = DatumGetChar(attr); - pq_putnchar((char *) &i8, len); - break; - case sizeof(int16): - i16 = DatumGetInt16(attr); - pq_putnchar((char *) &i16, len); - break; - case sizeof(int32): - i32 = DatumGetInt32(attr); - pq_putnchar((char *) &i32, len); - break; - } + } + else + { + /* fixed size */ + if (typeinfo->attrs[i]->attbyval) + { + int8 i8; + int16 i16; + int32 i32; + + pq_putint(len, sizeof(int32)); + switch (len) + { + case sizeof(int8): + i8 = DatumGetChar(attr); + pq_putnchar((char *) &i8, len); + break; + case sizeof(int16): + i16 = DatumGetInt16(attr); + pq_putnchar((char *) &i16, len); + break; + case sizeof(int32): + i32 = DatumGetInt32(attr); + pq_putnchar((char *) &i32, len); + break; + } #ifdef IPORTAL_DEBUG - fprintf(stderr, "byval length %d data %d\n", len, attr); + fprintf(stderr, "byval length %d data %d\n", len, attr); #endif - } else { - pq_putint(len, sizeof(int32)); - pq_putnchar(attr, len); + } + else + { + pq_putint(len, sizeof(int32)); + pq_putnchar(attr, len); #ifdef IPORTAL_DEBUG - fprintf(stderr, "byref length %d data %x\n", len, attr); + fprintf(stderr, "byref length %d data %x\n", len, attr); #endif + } + } } - } } - } } diff --git a/src/backend/access/common/scankey.c b/src/backend/access/common/scankey.c index fb242497ebc..9fbe264ae5c 100644 --- a/src/backend/access/common/scankey.c +++ b/src/backend/access/common/scankey.c @@ -1,13 +1,13 @@ /*------------------------------------------------------------------------- * * scan.c-- - * scan direction and key code + * scan direction and key code * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/common/scankey.c,v 1.9 1996/11/05 07:42:45 scrappy Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/common/scankey.c,v 1.10 1997/09/07 04:37:39 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -19,49 +19,49 @@ /* * ScanKeyEntryIsLegal -- - * True iff the scan key entry is legal. + * True iff the scan key entry is legal. */ #define ScanKeyEntryIsLegal(entry) \ - ((bool) (AssertMacro(PointerIsValid(entry)) && \ - AttributeNumberIsValid(entry->sk_attno))) + ((bool) (AssertMacro(PointerIsValid(entry)) && \ + AttributeNumberIsValid(entry->sk_attno))) /* * ScanKeyEntrySetIllegal -- - * Marks a scan key entry as illegal. + * Marks a scan key entry as illegal. */ void ScanKeyEntrySetIllegal(ScanKey entry) { - Assert(PointerIsValid(entry)); - - entry->sk_flags = 0; /* just in case... */ - entry->sk_attno = InvalidAttrNumber; - entry->sk_procedure = 0; /* should be InvalidRegProcedure */ + Assert(PointerIsValid(entry)); + + entry->sk_flags = 0; /* just in case... */ + entry->sk_attno = InvalidAttrNumber; + entry->sk_procedure = 0; /* should be InvalidRegProcedure */ } /* * ScanKeyEntryInitialize -- - * Initializes an scan key entry. + * Initializes an scan key entry. * * Note: - * Assumes the scan key entry is valid. - * Assumes the intialized scan key entry will be legal. + * Assumes the scan key entry is valid. + * Assumes the intialized scan key entry will be legal. */ void ScanKeyEntryInitialize(ScanKey entry, - bits16 flags, - AttrNumber attributeNumber, - RegProcedure procedure, - Datum argument) + bits16 flags, + AttrNumber attributeNumber, + RegProcedure procedure, + Datum argument) { - Assert(PointerIsValid(entry)); - - entry->sk_flags = flags; - entry->sk_attno = attributeNumber; - entry->sk_procedure = procedure; - entry->sk_argument = argument; - fmgr_info(procedure, &entry->sk_func, &entry->sk_nargs); - - Assert(ScanKeyEntryIsLegal(entry)); + Assert(PointerIsValid(entry)); + + entry->sk_flags = flags; + entry->sk_attno = attributeNumber; + entry->sk_procedure = procedure; + entry->sk_argument = argument; + fmgr_info(procedure, &entry->sk_func, &entry->sk_nargs); + + Assert(ScanKeyEntryIsLegal(entry)); } diff --git a/src/backend/access/common/tupdesc.c b/src/backend/access/common/tupdesc.c index a38a5229f28..e616702a8ea 100644 --- a/src/backend/access/common/tupdesc.c +++ b/src/backend/access/common/tupdesc.c @@ -1,17 +1,17 @@ /*------------------------------------------------------------------------- * * tupdesc.c-- - * POSTGRES tuple descriptor support code + * POSTGRES tuple descriptor support code * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/common/tupdesc.c,v 1.19 1997/08/22 02:55:39 vadim Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/common/tupdesc.c,v 1.20 1997/09/07 04:37:41 momjian Exp $ * * NOTES - * some of the executor utility code such as "ExecTypeFromTL" should be - * moved here. + * some of the executor utility code such as "ExecTypeFromTL" should be + * moved here. * *------------------------------------------------------------------------- */ @@ -28,518 +28,534 @@ #include <utils/syscache.h> #ifndef HAVE_MEMMOVE -# include <regex/utils.h> +#include <regex/utils.h> #else -# include <string.h> +#include <string.h> #endif /* ---------------------------------------------------------------- - * CreateTemplateTupleDesc + * CreateTemplateTupleDesc * - * This function allocates and zeros a tuple descriptor structure. + * This function allocates and zeros a tuple descriptor structure. * ---------------------------------------------------------------- */ TupleDesc CreateTemplateTupleDesc(int natts) { - uint32 size; - TupleDesc desc; - - /* ---------------- - * sanity checks - * ---------------- - */ - AssertArg(natts >= 1); - - /* ---------------- - * allocate enough memory for the tuple descriptor and - * zero it as TupleDescInitEntry assumes that the descriptor - * is filled with NULL pointers. - * ---------------- - */ - size = natts * sizeof (AttributeTupleForm); - desc = (TupleDesc) palloc(sizeof(struct tupleDesc)); - desc->attrs = (AttributeTupleForm*) palloc(size); - desc->constr = NULL; - memset(desc->attrs, 0, size); - - desc->natts = natts; - - return (desc); + uint32 size; + TupleDesc desc; + + /* ---------------- + * sanity checks + * ---------------- + */ + AssertArg(natts >= 1); + + /* ---------------- + * allocate enough memory for the tuple descriptor and + * zero it as TupleDescInitEntry assumes that the descriptor + * is filled with NULL pointers. + * ---------------- + */ + size = natts * sizeof(AttributeTupleForm); + desc = (TupleDesc) palloc(sizeof(struct tupleDesc)); + desc->attrs = (AttributeTupleForm *) palloc(size); + desc->constr = NULL; + memset(desc->attrs, 0, size); + + desc->natts = natts; + + return (desc); } /* ---------------------------------------------------------------- - * CreateTupleDesc + * CreateTupleDesc * - * This function allocates a new TupleDesc from AttributeTupleForm array + * This function allocates a new TupleDesc from AttributeTupleForm array * ---------------------------------------------------------------- */ TupleDesc -CreateTupleDesc(int natts, AttributeTupleForm* attrs) +CreateTupleDesc(int natts, AttributeTupleForm * attrs) { - TupleDesc desc; - - /* ---------------- - * sanity checks - * ---------------- - */ - AssertArg(natts >= 1); - - desc = (TupleDesc) palloc(sizeof(struct tupleDesc)); - desc->attrs = attrs; - desc->natts = natts; - desc->constr = NULL; - - return (desc); + TupleDesc desc; + + /* ---------------- + * sanity checks + * ---------------- + */ + AssertArg(natts >= 1); + + desc = (TupleDesc) palloc(sizeof(struct tupleDesc)); + desc->attrs = attrs; + desc->natts = natts; + desc->constr = NULL; + + return (desc); } /* ---------------------------------------------------------------- - * CreateTupleDescCopy + * CreateTupleDescCopy * - * This function creates a new TupleDesc by copying from an existing - * TupleDesc - * - * !!! Constraints are not copied !!! + * This function creates a new TupleDesc by copying from an existing + * TupleDesc + * + * !!! Constraints are not copied !!! * ---------------------------------------------------------------- */ TupleDesc CreateTupleDescCopy(TupleDesc tupdesc) { - TupleDesc desc; - int i, size; - - desc = (TupleDesc) palloc(sizeof(struct tupleDesc)); - desc->natts = tupdesc->natts; - size = desc->natts * sizeof (AttributeTupleForm); - desc->attrs = (AttributeTupleForm*) palloc(size); - for (i=0;i<desc->natts;i++) { - desc->attrs[i] = - (AttributeTupleForm)palloc(ATTRIBUTE_TUPLE_SIZE); - memmove(desc->attrs[i], - tupdesc->attrs[i], - ATTRIBUTE_TUPLE_SIZE); - desc->attrs[i]->attnotnull = false; - desc->attrs[i]->atthasdef = false; - } - desc->constr = NULL; - - return desc; + TupleDesc desc; + int i, + size; + + desc = (TupleDesc) palloc(sizeof(struct tupleDesc)); + desc->natts = tupdesc->natts; + size = desc->natts * sizeof(AttributeTupleForm); + desc->attrs = (AttributeTupleForm *) palloc(size); + for (i = 0; i < desc->natts; i++) + { + desc->attrs[i] = + (AttributeTupleForm) palloc(ATTRIBUTE_TUPLE_SIZE); + memmove(desc->attrs[i], + tupdesc->attrs[i], + ATTRIBUTE_TUPLE_SIZE); + desc->attrs[i]->attnotnull = false; + desc->attrs[i]->atthasdef = false; + } + desc->constr = NULL; + + return desc; } /* ---------------------------------------------------------------- - * CreateTupleDescCopyConstr + * CreateTupleDescCopyConstr + * + * This function creates a new TupleDesc by copying from an existing + * TupleDesc (with Constraints) * - * This function creates a new TupleDesc by copying from an existing - * TupleDesc (with Constraints) - * * ---------------------------------------------------------------- */ TupleDesc CreateTupleDescCopyConstr(TupleDesc tupdesc) { - TupleDesc desc; - TupleConstr *constr = tupdesc->constr; - int i, size; - - desc = (TupleDesc) palloc(sizeof(struct tupleDesc)); - desc->natts = tupdesc->natts; - size = desc->natts * sizeof (AttributeTupleForm); - desc->attrs = (AttributeTupleForm*) palloc(size); - for (i=0;i<desc->natts;i++) { - desc->attrs[i] = - (AttributeTupleForm)palloc(ATTRIBUTE_TUPLE_SIZE); - memmove(desc->attrs[i], - tupdesc->attrs[i], - ATTRIBUTE_TUPLE_SIZE); - } - if (constr) - { - TupleConstr *cpy = (TupleConstr *) palloc(sizeof(TupleConstr)); - - cpy->has_not_null = constr->has_not_null; - - if ( ( cpy->num_defval = constr->num_defval ) > 0 ) - { - cpy->defval = (AttrDefault *) palloc (cpy->num_defval * sizeof (AttrDefault)); - memcpy (cpy->defval, constr->defval, cpy->num_defval * sizeof (AttrDefault)); - for (i = cpy->num_defval - 1; i >= 0; i--) - { - if ( constr->defval[i].adbin ) - cpy->defval[i].adbin = pstrdup (constr->defval[i].adbin); - if ( constr->defval[i].adsrc ) - cpy->defval[i].adsrc = pstrdup (constr->defval[i].adsrc); - } - } - - if ( ( cpy->num_check = constr->num_check ) > 0 ) - { - cpy->check = (ConstrCheck *) palloc (cpy->num_check * sizeof (ConstrCheck)); - memcpy (cpy->check, constr->check, cpy->num_check * sizeof (ConstrCheck)); - for (i = cpy->num_check - 1; i >= 0; i--) - { - if ( constr->check[i].ccname ) - cpy->check[i].ccname = pstrdup (constr->check[i].ccname); - if ( constr->check[i].ccbin ) - cpy->check[i].ccbin = pstrdup (constr->check[i].ccbin); - if ( constr->check[i].ccsrc ) - cpy->check[i].ccsrc = pstrdup (constr->check[i].ccsrc); - } - } - - desc->constr = cpy; - } - else - desc->constr = NULL; - - return desc; + TupleDesc desc; + TupleConstr *constr = tupdesc->constr; + int i, + size; + + desc = (TupleDesc) palloc(sizeof(struct tupleDesc)); + desc->natts = tupdesc->natts; + size = desc->natts * sizeof(AttributeTupleForm); + desc->attrs = (AttributeTupleForm *) palloc(size); + for (i = 0; i < desc->natts; i++) + { + desc->attrs[i] = + (AttributeTupleForm) palloc(ATTRIBUTE_TUPLE_SIZE); + memmove(desc->attrs[i], + tupdesc->attrs[i], + ATTRIBUTE_TUPLE_SIZE); + } + if (constr) + { + TupleConstr *cpy = (TupleConstr *) palloc(sizeof(TupleConstr)); + + cpy->has_not_null = constr->has_not_null; + + if ((cpy->num_defval = constr->num_defval) > 0) + { + cpy->defval = (AttrDefault *) palloc(cpy->num_defval * sizeof(AttrDefault)); + memcpy(cpy->defval, constr->defval, cpy->num_defval * sizeof(AttrDefault)); + for (i = cpy->num_defval - 1; i >= 0; i--) + { + if (constr->defval[i].adbin) + cpy->defval[i].adbin = pstrdup(constr->defval[i].adbin); + if (constr->defval[i].adsrc) + cpy->defval[i].adsrc = pstrdup(constr->defval[i].adsrc); + } + } + + if ((cpy->num_check = constr->num_check) > 0) + { + cpy->check = (ConstrCheck *) palloc(cpy->num_check * sizeof(ConstrCheck)); + memcpy(cpy->check, constr->check, cpy->num_check * sizeof(ConstrCheck)); + for (i = cpy->num_check - 1; i >= 0; i--) + { + if (constr->check[i].ccname) + cpy->check[i].ccname = pstrdup(constr->check[i].ccname); + if (constr->check[i].ccbin) + cpy->check[i].ccbin = pstrdup(constr->check[i].ccbin); + if (constr->check[i].ccsrc) + cpy->check[i].ccsrc = pstrdup(constr->check[i].ccsrc); + } + } + + desc->constr = cpy; + } + else + desc->constr = NULL; + + return desc; } void -FreeTupleDesc (TupleDesc tupdesc) +FreeTupleDesc(TupleDesc tupdesc) { - int i; - - for (i = 0; i < tupdesc->natts; i++) - pfree (tupdesc->attrs[i]); - pfree (tupdesc->attrs); - if ( tupdesc->constr ) - { - if ( tupdesc->constr->num_defval > 0 ) - { - AttrDefault *attrdef = tupdesc->constr->defval; - - for (i = tupdesc->constr->num_defval - 1; i >= 0; i--) - { - if ( attrdef[i].adbin ) - pfree (attrdef[i].adbin); - if ( attrdef[i].adsrc ) - pfree (attrdef[i].adsrc); - } - pfree (attrdef); - } - if ( tupdesc->constr->num_check > 0 ) - { - ConstrCheck *check = tupdesc->constr->check; - - for (i = tupdesc->constr->num_check - 1; i >= 0; i--) - { - if ( check[i].ccname ) - pfree (check[i].ccname); - if ( check[i].ccbin ) - pfree (check[i].ccbin); - if ( check[i].ccsrc ) - pfree (check[i].ccsrc); - } - pfree (check); - } - pfree (tupdesc->constr); - } - - pfree (tupdesc); + int i; + + for (i = 0; i < tupdesc->natts; i++) + pfree(tupdesc->attrs[i]); + pfree(tupdesc->attrs); + if (tupdesc->constr) + { + if (tupdesc->constr->num_defval > 0) + { + AttrDefault *attrdef = tupdesc->constr->defval; + + for (i = tupdesc->constr->num_defval - 1; i >= 0; i--) + { + if (attrdef[i].adbin) + pfree(attrdef[i].adbin); + if (attrdef[i].adsrc) + pfree(attrdef[i].adsrc); + } + pfree(attrdef); + } + if (tupdesc->constr->num_check > 0) + { + ConstrCheck *check = tupdesc->constr->check; + + for (i = tupdesc->constr->num_check - 1; i >= 0; i--) + { + if (check[i].ccname) + pfree(check[i].ccname); + if (check[i].ccbin) + pfree(check[i].ccbin); + if (check[i].ccsrc) + pfree(check[i].ccsrc); + } + pfree(check); + } + pfree(tupdesc->constr); + } + + pfree(tupdesc); } /* ---------------------------------------------------------------- - * TupleDescInitEntry + * TupleDescInitEntry * - * This function initializes a single attribute structure in - * a preallocated tuple descriptor. + * This function initializes a single attribute structure in + * a preallocated tuple descriptor. * ---------------------------------------------------------------- */ bool TupleDescInitEntry(TupleDesc desc, - AttrNumber attributeNumber, - char *attributeName, - char *typeName, - int attdim, - bool attisset) + AttrNumber attributeNumber, + char *attributeName, + char *typeName, + int attdim, + bool attisset) { - HeapTuple tuple; - TypeTupleForm typeForm; - AttributeTupleForm att; - - /* ---------------- - * sanity checks - * ---------------- - */ - AssertArg(PointerIsValid(desc)); - AssertArg(attributeNumber >= 1); - /* attributeName's are sometimes NULL, - from resdom's. I don't know why that is, though -- Jolly */ -/* AssertArg(NameIsValid(attributeName));*/ -/* AssertArg(NameIsValid(typeName));*/ - - AssertArg(!PointerIsValid(desc->attrs[attributeNumber - 1])); - - - /* ---------------- - * allocate storage for this attribute - * ---------------- - */ - - att = (AttributeTupleForm) palloc(ATTRIBUTE_TUPLE_SIZE); - desc->attrs[attributeNumber - 1] = att; - - /* ---------------- - * initialize some of the attribute fields - * ---------------- - */ - att->attrelid = 0; /* dummy value */ - - if (attributeName != NULL) - namestrcpy(&(att->attname), attributeName); - else - memset(att->attname.data,0,NAMEDATALEN); - - - att->attdisbursion = 0; /* dummy value */ - att->attcacheoff = -1; - - att->attnum = attributeNumber; - att->attnelems = attdim; - att->attisset = attisset; - - att->attnotnull = false; - att->atthasdef = false; - - /* ---------------- - * search the system cache for the type tuple of the attribute - * we are creating so that we can get the typeid and some other - * stuff. - * - * Note: in the special case of - * - * create EMP (name = char16, manager = EMP) - * - * RelationNameCreateHeapRelation() calls BuildDesc() which - * calls this routine and since EMP does not exist yet, the - * system cache lookup below fails. That's fine, but rather - * then doing a elog(WARN) we just leave that information - * uninitialized, return false, then fix things up later. - * -cim 6/14/90 - * ---------------- - */ - tuple = SearchSysCacheTuple(TYPNAME, PointerGetDatum(typeName), - 0,0,0); - if (! HeapTupleIsValid(tuple)) { + HeapTuple tuple; + TypeTupleForm typeForm; + AttributeTupleForm att; + /* ---------------- - * here type info does not exist yet so we just fill - * the attribute with dummy information and return false. + * sanity checks * ---------------- */ - att->atttypid = InvalidOid; - att->attlen = (int16) 0; - att->attbyval = (bool) 0; - att->attalign = 'i'; - return false; - } - - /* ---------------- - * type info exists so we initialize our attribute - * information from the type tuple we found.. - * ---------------- - */ - typeForm = (TypeTupleForm) GETSTRUCT(tuple); - - att->atttypid = tuple->t_oid; - att->attalign = typeForm->typalign; - - /* ------------------------ - If this attribute is a set, what is really stored in the - attribute is the OID of a tuple in the pg_proc catalog. - The pg_proc tuple contains the query string which defines - this set - i.e., the query to run to get the set. - So the atttypid (just assigned above) refers to the type returned - by this query, but the actual length of this attribute is the - length (size) of an OID. - - Why not just make the atttypid point to the OID type, instead - of the type the query returns? Because the executor uses the atttypid - to tell the front end what type will be returned (in BeginCommand), - and in the end the type returned will be the result of the query, not - an OID. - - Why not wait until the return type of the set is known (i.e., the - recursive call to the executor to execute the set has returned) - before telling the front end what the return type will be? Because - the executor is a delicate thing, and making sure that the correct - order of front-end commands is maintained is messy, especially - considering that target lists may change as inherited attributes - are considered, etc. Ugh. - ----------------------------------------- - */ - if (attisset) { - Type t = type("oid"); - att->attlen = tlen(t); - att->attbyval = tbyval(t); - } else { - att->attlen = typeForm->typlen; - att->attbyval = typeForm->typbyval; - } - - - return true; + AssertArg(PointerIsValid(desc)); + AssertArg(attributeNumber >= 1); + + /* + * attributeName's are sometimes NULL, from resdom's. I don't know + * why that is, though -- Jolly + */ +/* AssertArg(NameIsValid(attributeName));*/ +/* AssertArg(NameIsValid(typeName));*/ + + AssertArg(!PointerIsValid(desc->attrs[attributeNumber - 1])); + + + /* ---------------- + * allocate storage for this attribute + * ---------------- + */ + + att = (AttributeTupleForm) palloc(ATTRIBUTE_TUPLE_SIZE); + desc->attrs[attributeNumber - 1] = att; + + /* ---------------- + * initialize some of the attribute fields + * ---------------- + */ + att->attrelid = 0; /* dummy value */ + + if (attributeName != NULL) + namestrcpy(&(att->attname), attributeName); + else + memset(att->attname.data, 0, NAMEDATALEN); + + + att->attdisbursion = 0; /* dummy value */ + att->attcacheoff = -1; + + att->attnum = attributeNumber; + att->attnelems = attdim; + att->attisset = attisset; + + att->attnotnull = false; + att->atthasdef = false; + + /* ---------------- + * search the system cache for the type tuple of the attribute + * we are creating so that we can get the typeid and some other + * stuff. + * + * Note: in the special case of + * + * create EMP (name = char16, manager = EMP) + * + * RelationNameCreateHeapRelation() calls BuildDesc() which + * calls this routine and since EMP does not exist yet, the + * system cache lookup below fails. That's fine, but rather + * then doing a elog(WARN) we just leave that information + * uninitialized, return false, then fix things up later. + * -cim 6/14/90 + * ---------------- + */ + tuple = SearchSysCacheTuple(TYPNAME, PointerGetDatum(typeName), + 0, 0, 0); + if (!HeapTupleIsValid(tuple)) + { + /* ---------------- + * here type info does not exist yet so we just fill + * the attribute with dummy information and return false. + * ---------------- + */ + att->atttypid = InvalidOid; + att->attlen = (int16) 0; + att->attbyval = (bool) 0; + att->attalign = 'i'; + return false; + } + + /* ---------------- + * type info exists so we initialize our attribute + * information from the type tuple we found.. + * ---------------- + */ + typeForm = (TypeTupleForm) GETSTRUCT(tuple); + + att->atttypid = tuple->t_oid; + att->attalign = typeForm->typalign; + + /* ------------------------ + If this attribute is a set, what is really stored in the + attribute is the OID of a tuple in the pg_proc catalog. + The pg_proc tuple contains the query string which defines + this set - i.e., the query to run to get the set. + So the atttypid (just assigned above) refers to the type returned + by this query, but the actual length of this attribute is the + length (size) of an OID. + + Why not just make the atttypid point to the OID type, instead + of the type the query returns? Because the executor uses the atttypid + to tell the front end what type will be returned (in BeginCommand), + and in the end the type returned will be the result of the query, not + an OID. + + Why not wait until the return type of the set is known (i.e., the + recursive call to the executor to execute the set has returned) + before telling the front end what the return type will be? Because + the executor is a delicate thing, and making sure that the correct + order of front-end commands is maintained is messy, especially + considering that target lists may change as inherited attributes + are considered, etc. Ugh. + ----------------------------------------- + */ + if (attisset) + { + Type t = type("oid"); + + att->attlen = tlen(t); + att->attbyval = tbyval(t); + } + else + { + att->attlen = typeForm->typlen; + att->attbyval = typeForm->typbyval; + } + + + return true; } /* ---------------------------------------------------------------- - * TupleDescMakeSelfReference + * TupleDescMakeSelfReference * - * This function initializes a "self-referential" attribute like - * manager in "create EMP (name=text, manager = EMP)". - * It calls TypeShellMake() which inserts a "shell" type - * tuple into pg_type. A self-reference is one kind of set, so - * its size and byval are the same as for a set. See the comments - * above in TupleDescInitEntry. + * This function initializes a "self-referential" attribute like + * manager in "create EMP (name=text, manager = EMP)". + * It calls TypeShellMake() which inserts a "shell" type + * tuple into pg_type. A self-reference is one kind of set, so + * its size and byval are the same as for a set. See the comments + * above in TupleDescInitEntry. * ---------------------------------------------------------------- */ static void TupleDescMakeSelfReference(TupleDesc desc, - AttrNumber attnum, - char *relname) + AttrNumber attnum, + char *relname) { - AttributeTupleForm att; - Type t = type("oid"); - - att = desc->attrs[attnum-1]; - att->atttypid = TypeShellMake(relname); - att->attlen = tlen(t); - att->attbyval = tbyval(t); - att->attnelems = 0; + AttributeTupleForm att; + Type t = type("oid"); + + att = desc->attrs[attnum - 1]; + att->atttypid = TypeShellMake(relname); + att->attlen = tlen(t); + att->attbyval = tbyval(t); + att->attnelems = 0; } /* ---------------------------------------------------------------- - * BuildDescForRelation + * BuildDescForRelation * - * This is a general purpose function identical to BuildDesc - * but is used by the DefineRelation() code to catch the - * special case where you + * This is a general purpose function identical to BuildDesc + * but is used by the DefineRelation() code to catch the + * special case where you * - * create FOO ( ..., x = FOO ) + * create FOO ( ..., x = FOO ) * - * here, the initial type lookup for "x = FOO" will fail - * because FOO isn't in the catalogs yet. But since we - * are creating FOO, instead of doing an elog() we add - * a shell type tuple to pg_type and fix things later - * in amcreate(). + * here, the initial type lookup for "x = FOO" will fail + * because FOO isn't in the catalogs yet. But since we + * are creating FOO, instead of doing an elog() we add + * a shell type tuple to pg_type and fix things later + * in amcreate(). * ---------------------------------------------------------------- */ TupleDesc -BuildDescForRelation(List *schema, char *relname) +BuildDescForRelation(List * schema, char *relname) { - int natts; - AttrNumber attnum; - List *p; - TupleDesc desc; - AttrDefault *attrdef = NULL; - TupleConstr *constr = (TupleConstr *) palloc(sizeof(TupleConstr)); - char *attname; - char *typename; - int attdim; - int ndef = 0; - bool attisset; - - /* ---------------- - * allocate a new tuple descriptor - * ---------------- - */ - natts = length(schema); - desc = CreateTemplateTupleDesc(natts); - constr->has_not_null = false; - - attnum = 0; - - typename = palloc(NAMEDATALEN); - - foreach(p, schema) { - ColumnDef *entry; - List *arry; + int natts; + AttrNumber attnum; + List *p; + TupleDesc desc; + AttrDefault *attrdef = NULL; + TupleConstr *constr = (TupleConstr *) palloc(sizeof(TupleConstr)); + char *attname; + char *typename; + int attdim; + int ndef = 0; + bool attisset; /* ---------------- - * for each entry in the list, get the name and type - * information from the list and have TupleDescInitEntry - * fill in the attribute information we need. + * allocate a new tuple descriptor * ---------------- - */ - attnum++; - - entry = lfirst(p); - attname = entry->colname; - arry = entry->typename->arrayBounds; - attisset = entry->typename->setof; - - strNcpy(typename, entry->typename->name,NAMEDATALEN-1); - if (arry != NIL) - attdim = length(arry); - else - attdim = 0; - - if (! TupleDescInitEntry(desc, attnum, attname, - typename, attdim, attisset)) { - /* ---------------- - * if TupleDescInitEntry() fails, it means there is - * no type in the system catalogs. So now we check if - * the type name equals the relation name. If so we - * have a self reference, otherwise it's an error. - * ---------------- - */ - if (!strcmp(typename, relname)) { - TupleDescMakeSelfReference(desc, attnum, relname); - } else - elog(WARN, "DefineRelation: no such type %s", - typename); - } - - /* - * this is for char() and varchar(). When an entry is of type - * char() or varchar(), typlen is set to the appropriate length, - * which we'll use here instead. (The catalog lookup only returns - * the length of bpchar and varchar which is not what we want!) - * - ay 6/95 */ - if (entry->typename->typlen > 0) { - desc->attrs[attnum - 1]->attlen = entry->typename->typlen; - } + natts = length(schema); + desc = CreateTemplateTupleDesc(natts); + constr->has_not_null = false; - /* This is for constraints */ - if (entry->is_not_null) - constr->has_not_null = true; - desc->attrs[attnum-1]->attnotnull = entry->is_not_null; - - if ( entry->defval != NULL ) + attnum = 0; + + typename = palloc(NAMEDATALEN); + + foreach(p, schema) { - if ( attrdef == NULL ) - attrdef = (AttrDefault*) palloc (natts * sizeof (AttrDefault)); - attrdef[ndef].adnum = attnum; - attrdef[ndef].adbin = NULL; - attrdef[ndef].adsrc = entry->defval; - ndef++; - desc->attrs[attnum-1]->atthasdef = true; + ColumnDef *entry; + List *arry; + + /* ---------------- + * for each entry in the list, get the name and type + * information from the list and have TupleDescInitEntry + * fill in the attribute information we need. + * ---------------- + */ + attnum++; + + entry = lfirst(p); + attname = entry->colname; + arry = entry->typename->arrayBounds; + attisset = entry->typename->setof; + + strNcpy(typename, entry->typename->name, NAMEDATALEN - 1); + if (arry != NIL) + attdim = length(arry); + else + attdim = 0; + + if (!TupleDescInitEntry(desc, attnum, attname, + typename, attdim, attisset)) + { + /* ---------------- + * if TupleDescInitEntry() fails, it means there is + * no type in the system catalogs. So now we check if + * the type name equals the relation name. If so we + * have a self reference, otherwise it's an error. + * ---------------- + */ + if (!strcmp(typename, relname)) + { + TupleDescMakeSelfReference(desc, attnum, relname); + } + else + elog(WARN, "DefineRelation: no such type %s", + typename); + } + + /* + * this is for char() and varchar(). When an entry is of type + * char() or varchar(), typlen is set to the appropriate length, + * which we'll use here instead. (The catalog lookup only returns + * the length of bpchar and varchar which is not what we want!) - + * ay 6/95 + */ + if (entry->typename->typlen > 0) + { + desc->attrs[attnum - 1]->attlen = entry->typename->typlen; + } + + /* This is for constraints */ + if (entry->is_not_null) + constr->has_not_null = true; + desc->attrs[attnum - 1]->attnotnull = entry->is_not_null; + + if (entry->defval != NULL) + { + if (attrdef == NULL) + attrdef = (AttrDefault *) palloc(natts * sizeof(AttrDefault)); + attrdef[ndef].adnum = attnum; + attrdef[ndef].adbin = NULL; + attrdef[ndef].adsrc = entry->defval; + ndef++; + desc->attrs[attnum - 1]->atthasdef = true; + } + } + if (constr->has_not_null || ndef > 0) + { + desc->constr = constr; - } - if ( constr->has_not_null || ndef > 0 ) - { - desc->constr = constr; - - if ( ndef > 0 ) /* DEFAULTs */ - { - if ( ndef < natts ) - constr->defval = (AttrDefault*) - repalloc (attrdef, ndef * sizeof (AttrDefault)); - else - constr->defval = attrdef; - constr->num_defval = ndef; - } - else - constr->num_defval = 0; - constr->num_check = 0; - } - else - { - pfree (constr); - desc->constr = NULL; - } - return desc; + if (ndef > 0) /* DEFAULTs */ + { + if (ndef < natts) + constr->defval = (AttrDefault *) + repalloc(attrdef, ndef * sizeof(AttrDefault)); + else + constr->defval = attrdef; + constr->num_defval = ndef; + } + else + constr->num_defval = 0; + constr->num_check = 0; + } + else + { + pfree(constr); + desc->constr = NULL; + } + return desc; } - |