diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2000-12-27 23:59:14 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2000-12-27 23:59:14 +0000 |
commit | 8609d4abf248f0eede4ed9505226da3f7e3e7c84 (patch) | |
tree | 39e5a813099835056d76dd385478069d01a8dcbf /src | |
parent | 97799fc4757fd2699e0238254875994253659582 (diff) | |
download | postgresql-8609d4abf248f0eede4ed9505226da3f7e3e7c84.tar.gz postgresql-8609d4abf248f0eede4ed9505226da3f7e3e7c84.zip |
Fix portability problems recently exposed by regression tests on Alphas.
1. Distinguish cases where a Datum representing a tuple datatype is an OID
from cases where it is a pointer to TupleTableSlot, and make sure we use
the right typlen in each case.
2. Make fetchatt() and related code support 8-byte by-value datatypes on
machines where Datum is 8 bytes. Centralize knowledge of the available
by-value datatype sizes in two macros in tupmacs.h, so that this will be
easier if we ever have to do it again.
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/access/common/heaptuple.c | 234 | ||||
-rw-r--r-- | src/backend/access/common/indextuple.c | 16 | ||||
-rw-r--r-- | src/backend/access/common/printtup.c | 35 | ||||
-rw-r--r-- | src/backend/access/common/tupdesc.c | 86 | ||||
-rw-r--r-- | src/backend/access/heap/heapam.c | 4 | ||||
-rw-r--r-- | src/backend/catalog/catalog.c | 58 | ||||
-rw-r--r-- | src/backend/catalog/heap.c | 8 | ||||
-rw-r--r-- | src/backend/commands/copy.c | 62 | ||||
-rw-r--r-- | src/backend/executor/execTuples.c | 46 | ||||
-rw-r--r-- | src/backend/executor/execUtils.c | 14 | ||||
-rw-r--r-- | src/backend/parser/parse_func.c | 14 | ||||
-rw-r--r-- | src/backend/utils/adt/arrayfuncs.c | 148 | ||||
-rw-r--r-- | src/backend/utils/cache/lsyscache.c | 25 | ||||
-rw-r--r-- | src/include/access/heapam.h | 70 | ||||
-rw-r--r-- | src/include/access/htup.h | 8 | ||||
-rw-r--r-- | src/include/access/itup.h | 4 | ||||
-rw-r--r-- | src/include/access/tupmacs.h | 149 | ||||
-rw-r--r-- | src/include/catalog/catalog.h | 4 | ||||
-rw-r--r-- | src/include/catalog/pg_type.h | 14 | ||||
-rw-r--r-- | src/include/config.h.in | 7 |
20 files changed, 406 insertions, 600 deletions
diff --git a/src/backend/access/common/heaptuple.c b/src/backend/access/common/heaptuple.c index e76fa5a5652..6405320f85d 100644 --- a/src/backend/access/common/heaptuple.c +++ b/src/backend/access/common/heaptuple.c @@ -2,14 +2,14 @@ * * heaptuple.c * This file contains heap tuple accessor and mutator routines, as well - * as a few various tuple utilities. + * as various tuple utilities. * * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/common/heaptuple.c,v 1.67 2000/11/30 18:38:45 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/common/heaptuple.c,v 1.68 2000/12/27 23:59:10 tgl Exp $ * * NOTES * The old interface functions have been converted to macros @@ -23,16 +23,6 @@ #include "access/heapam.h" #include "catalog/pg_type.h" -/* Used by heap_getattr() macro, for speed */ -long heap_sysoffset[] = { -/* Only the first one is pass-by-ref, and is handled specially in the macro */ - offsetof(HeapTupleHeaderData, t_ctid), - offsetof(HeapTupleHeaderData, t_oid), - offsetof(HeapTupleHeaderData, t_xmin), - offsetof(HeapTupleHeaderData, t_cmin), - offsetof(HeapTupleHeaderData, t_xmax), - offsetof(HeapTupleHeaderData, t_cmax) -}; /* ---------------------------------------------------------------- * misc support routines @@ -48,12 +38,12 @@ ComputeDataSize(TupleDesc tupleDesc, Datum *value, char *nulls) { - uint32 data_length; + uint32 data_length = 0; int i; int numberOfAttributes = tupleDesc->natts; Form_pg_attribute *att = tupleDesc->attrs; - for (data_length = 0, i = 0; i < numberOfAttributes; i++) + for (i = 0; i < numberOfAttributes; i++) { if (nulls[i] != ' ') continue; @@ -114,38 +104,33 @@ DataFill(char *data, *bitP |= bitmask; } + /* XXX we are aligning the pointer itself, not the offset */ data = (char *) att_align((long) data, att[i]->attlen, att[i]->attalign); - switch (att[i]->attlen) + + if (att[i]->attbyval) { - case -1: - *infomask |= HEAP_HASVARLENA; - if (VARATT_IS_EXTERNAL(value[i])) - *infomask |= HEAP_HASEXTERNAL; - if (VARATT_IS_COMPRESSED(value[i])) - *infomask |= HEAP_HASCOMPRESSED; - data_length = VARATT_SIZE(DatumGetPointer(value[i])); - memmove(data, DatumGetPointer(value[i]), data_length); - break; - case sizeof(char): - *data = att[i]->attbyval ? - DatumGetChar(value[i]) : *((char *) value[i]); - break; - case sizeof(int16): - *(short *) data = (att[i]->attbyval ? - DatumGetInt16(value[i]) : - *((short *) value[i])); - break; - case sizeof(int32): - *(int32 *) data = (att[i]->attbyval ? - DatumGetInt32(value[i]) : - *((int32 *) value[i])); - break; - default: - Assert(att[i]->attlen >= 0); - memmove(data, DatumGetPointer(value[i]), - (size_t) (att[i]->attlen)); - break; + /* pass-by-value */ + store_att_byval(data, value[i], att[i]->attlen); + } + else if (att[i]->attlen == -1) + { + /* varlena */ + *infomask |= HEAP_HASVARLENA; + if (VARATT_IS_EXTERNAL(value[i])) + *infomask |= HEAP_HASEXTERNAL; + if (VARATT_IS_COMPRESSED(value[i])) + *infomask |= HEAP_HASCOMPRESSED; + data_length = VARATT_SIZE(DatumGetPointer(value[i])); + memcpy(data, DatumGetPointer(value[i]), data_length); + } + else + { + /* fixed-length pass-by-reference */ + Assert(att[i]->attlen >= 0); + memcpy(data, DatumGetPointer(value[i]), + (size_t) (att[i]->attlen)); } + data = (char *) att_addlength((long) data, att[i]->attlen, value[i]); } } @@ -192,89 +177,6 @@ heap_attisnull(HeapTuple tup, int attnum) return 0; } -/* ---------------------------------------------------------------- - * system attribute heap tuple support - * ---------------------------------------------------------------- - */ - -/* ---------------- - * heap_sysattrlen - * - * This routine returns the length of a system attribute. - * ---------------- - */ -int -heap_sysattrlen(AttrNumber attno) -{ - HeapTupleHeader f = NULL; - - switch (attno) - { - case TableOidAttributeNumber: - return sizeof f->t_oid; - 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; - - default: - elog(ERROR, "sysattrlen: System attribute number %d unknown.", attno); - return 0; - } -} - -/* ---------------- - * heap_sysattrbyval - * - * This routine returns the "by-value" property of a system attribute. - * ---------------- - */ -bool -heap_sysattrbyval(AttrNumber attno) -{ - bool byval; - - switch (attno) - { - case TableOidAttributeNumber: - byval = true; - break; - 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; - default: - byval = true; - elog(ERROR, "sysattrbyval: System attribute number %d unknown.", - attno); - break; - } - - return byval; -} - /* ---------------- * nocachegetattr * @@ -332,8 +234,7 @@ nocachegetattr(HeapTuple tuple, /* This is handled in the macro */ if (att[attnum]->attcacheoff != -1) { - return (Datum) - fetchatt(&(att[attnum]), + return fetchatt(att[attnum], (char *) tup + tup->t_hoff + att[attnum]->attcacheoff); } #endif @@ -397,8 +298,8 @@ nocachegetattr(HeapTuple tuple, { if (att[attnum]->attcacheoff != -1) { - return (Datum) fetchatt(&(att[attnum]), - tp + att[attnum]->attcacheoff); + return fetchatt(att[attnum], + tp + att[attnum]->attcacheoff); } else if (!HeapTupleAllFixed(tuple)) { @@ -460,7 +361,7 @@ nocachegetattr(HeapTuple tuple, off = att_addlength(off, att[j]->attlen, tp + off); } - return (Datum) fetchatt(&(att[attnum]), tp + att[attnum]->attcacheoff); + return fetchatt(att[attnum], tp + att[attnum]->attcacheoff); } else { @@ -508,11 +409,67 @@ nocachegetattr(HeapTuple tuple, off = att_align(off, att[attnum]->attlen, att[attnum]->attalign); - return (Datum) fetchatt(&(att[attnum]), tp + off); + return fetchatt(att[attnum], tp + off); } } /* ---------------- + * heap_getsysattr + * + * Fetch the value of a system attribute for a tuple. + * + * This is a support routine for the heap_getattr macro. The macro + * has already determined that the attnum refers to a system attribute. + * ---------------- + */ +Datum +heap_getsysattr(HeapTuple tup, int attnum, bool *isnull) +{ + Datum result; + + Assert(tup); + + /* Currently, no sys attribute ever reads as NULL. */ + if (isnull) + *isnull = false; + + switch (attnum) + { + case SelfItemPointerAttributeNumber: + /* pass-by-reference datatype */ + result = PointerGetDatum(&(tup->t_self)); + break; + case ObjectIdAttributeNumber: + result = ObjectIdGetDatum(tup->t_data->t_oid); + break; + case MinTransactionIdAttributeNumber: + /* XXX should have a TransactionIdGetDatum macro */ + result = (Datum) (tup->t_data->t_xmin); + break; + case MinCommandIdAttributeNumber: + /* XXX should have a CommandIdGetDatum macro */ + result = (Datum) (tup->t_data->t_cmin); + break; + case MaxTransactionIdAttributeNumber: + /* XXX should have a TransactionIdGetDatum macro */ + result = (Datum) (tup->t_data->t_xmax); + break; + case MaxCommandIdAttributeNumber: + /* XXX should have a CommandIdGetDatum macro */ + result = (Datum) (tup->t_data->t_cmax); + break; + case TableOidAttributeNumber: + result = ObjectIdGetDatum(tup->t_tableOid); + break; + default: + elog(ERROR, "heap_getsysattr: invalid attnum %d", attnum); + result = 0; /* keep compiler quiet */ + break; + } + return result; +} + +/* ---------------- * heap_copytuple * * returns a copy of an entire tuple @@ -630,18 +587,21 @@ heap_formtuple(TupleDesc tupleDescriptor, int i; int numberOfAttributes = tupleDescriptor->natts; + if (numberOfAttributes > MaxHeapAttributeNumber) + elog(ERROR, "heap_formtuple: numberOfAttributes of %d > %d", + numberOfAttributes, MaxHeapAttributeNumber); + len = offsetof(HeapTupleHeaderData, t_bits); - for (i = 0; i < numberOfAttributes && !hasnull; i++) + for (i = 0; i < numberOfAttributes; i++) { if (nulls[i] != ' ') + { hasnull = true; + break; + } } - if (numberOfAttributes > MaxHeapAttributeNumber) - elog(ERROR, "heap_formtuple: numberOfAttributes of %d > %d", - numberOfAttributes, MaxHeapAttributeNumber); - if (hasnull) { bitmaplen = BITMAPLEN(numberOfAttributes); diff --git a/src/backend/access/common/indextuple.c b/src/backend/access/common/indextuple.c index 837b7f632bb..d473ce6c94d 100644 --- a/src/backend/access/common/indextuple.c +++ b/src/backend/access/common/indextuple.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/common/indextuple.c,v 1.48 2000/12/07 02:00:47 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/common/indextuple.c,v 1.49 2000/12/27 23:59:10 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -217,9 +217,9 @@ nocache_index_getattr(IndexTuple tup, /* This is handled in the macro */ if (att[attnum]->attcacheoff != -1) { - return (Datum) fetchatt(&(att[attnum]), - (char *) tup + data_off + - att[attnum]->attcacheoff); + return fetchatt(att[attnum], + (char *) tup + data_off + + att[attnum]->attcacheoff); } #endif } @@ -279,8 +279,8 @@ nocache_index_getattr(IndexTuple tup, { if (att[attnum]->attcacheoff != -1) { - return (Datum) fetchatt(&(att[attnum]), - tp + att[attnum]->attcacheoff); + return fetchatt(att[attnum], + tp + att[attnum]->attcacheoff); } else if (!IndexTupleAllFixed(tup)) { @@ -332,7 +332,7 @@ nocache_index_getattr(IndexTuple tup, off += att[j]->attlen; } - return (Datum) fetchatt(&(att[attnum]), tp + att[attnum]->attcacheoff); + return fetchatt(att[attnum], tp + att[attnum]->attcacheoff); } else { @@ -379,7 +379,7 @@ nocache_index_getattr(IndexTuple tup, off = att_align(off, att[attnum]->attlen, att[attnum]->attalign); - return (Datum) fetchatt(&att[attnum], tp + off); + return fetchatt(att[attnum], tp + off); } } diff --git a/src/backend/access/common/printtup.c b/src/backend/access/common/printtup.c index b05902068ee..5b79cb84a48 100644 --- a/src/backend/access/common/printtup.c +++ b/src/backend/access/common/printtup.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/common/printtup.c,v 1.55 2000/12/01 22:10:31 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/common/printtup.c,v 1.56 2000/12/27 23:59:10 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -436,30 +436,17 @@ printtup_internal(HeapTuple tuple, TupleDesc typeinfo, DestReceiver *self) pq_sendint(&buf, len, sizeof(int32)); if (typeinfo->attrs[i]->attbyval) { - int8 i8; - int16 i16; - int32 i32; - - switch (len) - { - case sizeof(int8): - i8 = DatumGetChar(attr); - pq_sendbytes(&buf, (char *) &i8, len); - break; - case sizeof(int16): - i16 = DatumGetInt16(attr); - pq_sendbytes(&buf, (char *) &i16, len); - break; - case sizeof(int32): - i32 = DatumGetInt32(attr); - pq_sendbytes(&buf, (char *) &i32, len); - break; - default: - elog(ERROR, "printtup_internal: unexpected typlen"); - break; - } + Datum datumBuf; + + /* + * We need this horsing around because we don't know how + * shorter data values are aligned within a Datum. + */ + store_att_byval(&datumBuf, attr, len); + pq_sendbytes(&buf, (char *) &datumBuf, len); #ifdef IPORTAL_DEBUG - fprintf(stderr, "byval length %d data %d\n", len, attr); + fprintf(stderr, "byval length %d data %ld\n", len, + (long) attr); #endif } else diff --git a/src/backend/access/common/tupdesc.c b/src/backend/access/common/tupdesc.c index 8b9b7cd537f..83977d6a387 100644 --- a/src/backend/access/common/tupdesc.c +++ b/src/backend/access/common/tupdesc.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/common/tupdesc.c,v 1.69 2000/11/16 22:30:15 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/common/tupdesc.c,v 1.70 2000/12/27 23:59:10 tgl Exp $ * * NOTES * some of the executor utility code such as "ExecTypeFromTL" should be @@ -352,7 +352,6 @@ TupleDescInitEntry(TupleDesc desc, AssertArg(!PointerIsValid(desc->attrs[attributeNumber - 1])); - /* ---------------- * allocate storage for this attribute * ---------------- @@ -362,7 +361,7 @@ TupleDescInitEntry(TupleDesc desc, desc->attrs[attributeNumber - 1] = att; /* ---------------- - * initialize some of the attribute fields + * initialize the attribute fields * ---------------- */ att->attrelid = 0; /* dummy value */ @@ -372,7 +371,6 @@ TupleDescInitEntry(TupleDesc desc, else MemSet(NameStr(att->attname), 0, NAMEDATALEN); - att->attdispersion = 0; /* dummy value */ att->attcacheoff = -1; att->atttypmod = typmod; @@ -414,8 +412,8 @@ TupleDescInitEntry(TupleDesc desc, att->atttypid = InvalidOid; att->attlen = (int16) 0; att->attbyval = (bool) 0; - att->attstorage = 'p'; att->attalign = 'i'; + att->attstorage = 'p'; return false; } @@ -427,42 +425,63 @@ TupleDescInitEntry(TupleDesc desc, typeForm = (Form_pg_type) GETSTRUCT(tuple); att->atttypid = tuple->t_data->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. - ----------------------------------------- - */ + + /*------------------------ + * There are a couple of cases where we must override the information + * stored in pg_type. + * + * First: 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.) + * + * Second: if we are dealing with a complex type (a tuple type), then + * pg_type will say that the representation is the same as Oid. But + * if typmod is sizeof(Pointer) then the internal representation is + * actually a pointer to a TupleTableSlot, and we have to substitute + * that information. + * + * A set of complex type is first and foremost a set, so its + * representation is Oid not pointer. So, test that case first. + *----------------------------------------- + */ if (attisset) { att->attlen = sizeof(Oid); att->attbyval = true; + att->attalign = 'i'; + att->attstorage = 'p'; + } + else if (typeForm->typtype == 'c' && typmod == sizeof(Pointer)) + { + att->attlen = sizeof(Pointer); + att->attbyval = true; + att->attalign = 'd'; /* kluge to work with 8-byte pointers */ + /* XXX ought to have a separate attalign value for pointers ... */ att->attstorage = 'p'; } else { att->attlen = typeForm->typlen; att->attbyval = typeForm->typbyval; + att->attalign = typeForm->typalign; att->attstorage = typeForm->typstorage; } @@ -494,6 +513,7 @@ TupleDescMakeSelfReference(TupleDesc desc, att->atttypid = TypeShellMake(relname); att->attlen = sizeof(Oid); att->attbyval = true; + att->attalign = 'i'; att->attstorage = 'p'; att->attnelems = 0; } @@ -582,15 +602,13 @@ BuildDescForRelation(List *schema, char *relname) * have a self reference, otherwise it's an error. * ---------------- */ - if (!strcmp(typename, relname)) + if (strcmp(typename, relname) == 0) TupleDescMakeSelfReference(desc, attnum, relname); else elog(ERROR, "DefineRelation: no such type %s", typename); } - desc->attrs[attnum - 1]->atttypmod = entry->typename->typmod; - /* This is for constraints */ if (entry->is_not_null) constr->has_not_null = true; diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c index 48c75f5d17f..8832d6ec9b5 100644 --- a/src/backend/access/heap/heapam.c +++ b/src/backend/access/heap/heapam.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.101 2000/12/11 09:14:03 inoue Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.102 2000/12/27 23:59:10 tgl Exp $ * * * INTERFACE ROUTINES @@ -537,7 +537,7 @@ fastgetattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, ( (tupleDesc)->attrs[(attnum) - 1]->attcacheoff >= 0 ? ( - (Datum) fetchatt(&((tupleDesc)->attrs[(attnum) - 1]), + fetchatt((tupleDesc)->attrs[(attnum) - 1], (char *) (tup)->t_data + (tup)->t_data->t_hoff + (tupleDesc)->attrs[(attnum) - 1]->attcacheoff) ) diff --git a/src/backend/catalog/catalog.c b/src/backend/catalog/catalog.c index aed3864e900..a88a9ea931f 100644 --- a/src/backend/catalog/catalog.c +++ b/src/backend/catalog/catalog.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/catalog/catalog.c,v 1.37 2000/11/16 22:30:17 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/catalog/catalog.c,v 1.38 2000/12/27 23:59:11 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -223,7 +223,7 @@ IsSharedSystemRelationName(const char *relname) * user programs to use them for temporary object identifiers. */ Oid -newoid() +newoid(void) { Oid lastoid; @@ -232,57 +232,3 @@ newoid() elog(ERROR, "newoid: GetNewObjectId returns invalid oid"); return lastoid; } - -/* - * fillatt - fills the ATTRIBUTE relation fields from the TYP - * - * Expects that the atttypid domain is set for each att[]. - * Returns with the attnum, and attlen domains set. - * attnum, attproc, atttyparg, ... should be set by the user. - * - * In the future, attnum may not be set?!? or may be passed as an arg?!? - * - * Current implementation is very inefficient--should cashe the - * information if this is at all possible. - * - * Check to see if this is really needed, and especially in the case - * of index tuples. - */ -void -fillatt(TupleDesc tupleDesc) -{ - int natts = tupleDesc->natts; - Form_pg_attribute *att = tupleDesc->attrs; - Form_pg_attribute *attributeP; - int i; - - if (natts < 0 || natts > MaxHeapAttributeNumber) - elog(ERROR, "fillatt: %d attributes is too large", natts); - if (natts == 0) - { - elog(DEBUG, "fillatt: called with natts == 0"); - return; - } - - attributeP = &att[0]; - - for (i = 1; i <= natts; i++) - { - (*attributeP)->attnum = (int16) i; - - /* - * Check if the attr is a set before messing with the length - * and byval, since those were already set in - * TupleDescInitEntry. In fact, this seems redundant here, - * but who knows what I'll break if I take it out... - */ - if (!(*attributeP)->attisset) - { - get_typlenbyval((*attributeP)->atttypid, - & (*attributeP)->attlen, - & (*attributeP)->attbyval); - } - - attributeP++; - } -} diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c index 174b8ca85bb..abcc9951b4b 100644 --- a/src/backend/catalog/heap.c +++ b/src/backend/catalog/heap.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.154 2000/12/22 23:12:03 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.155 2000/12/27 23:59:11 tgl Exp $ * * * INTERFACE ROUTINES @@ -584,12 +584,6 @@ AddNewAttributeTuples(Oid new_rel_oid, CatalogOpenIndices(Num_pg_attr_indices, Name_pg_attr_indices, idescs); /* ---------------- - * initialize tuple descriptor. - * ---------------- - */ - fillatt(tupdesc); - - /* ---------------- * first we add the user attributes.. * ---------------- */ diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c index 6cdba327295..f9507342d6d 100644 --- a/src/backend/commands/copy.c +++ b/src/backend/commands/copy.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.125 2000/12/02 20:49:24 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.126 2000/12/27 23:59:14 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -49,7 +49,6 @@ static void CopyTo(Relation rel, bool binary, bool oids, FILE *fp, char *delim, static void CopyFrom(Relation rel, bool binary, bool oids, FILE *fp, char *delim, char *null_print); static Oid GetInputFunction(Oid type); static Oid GetTypeElement(Oid type); -static bool IsTypeByVal(Oid type); static void CopyReadNewline(FILE *fp, int *newline); static char *CopyReadAttribute(FILE *fp, bool *isnull, char *delim, int *newline, char *null_print); static void CopyAttributeOut(FILE *fp, char *string, char *delim); @@ -586,7 +585,6 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp, Oid in_func_oid; Datum *values; char *nulls; - bool *byval; bool isnull; int done = 0; char *string = NULL, @@ -653,13 +651,9 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp, values = (Datum *) palloc(attr_count * sizeof(Datum)); nulls = (char *) palloc(attr_count * sizeof(char)); - byval = (bool *) palloc(attr_count * sizeof(bool)); for (i = 0; i < attr_count; i++) - { nulls[i] = ' '; - byval[i] = IsTypeByVal(attr[i]->atttypid); - } lineno = 0; fe_eof = false; @@ -742,36 +736,11 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp, for (i = 0; i < attr_count; i++) { - if (byval[i] && nulls[i] != 'n') - { - - switch (attr[i]->attlen) - { - case sizeof(char): - values[i] = (Datum) *(unsigned char *) ptr; - ptr += sizeof(char); - break; - case sizeof(short): - ptr = (char *) SHORTALIGN(ptr); - values[i] = (Datum) *(unsigned short *) ptr; - ptr += sizeof(short); - break; - case sizeof(int32): - ptr = (char *) INTALIGN(ptr); - values[i] = (Datum) *(uint32 *) ptr; - ptr += sizeof(int32); - break; - default: - elog(ERROR, "COPY BINARY: impossible size"); - break; - } - } - else if (nulls[i] != 'n') - { - ptr = (char *) att_align(ptr, attr[i]->attlen, attr[i]->attalign); - values[i] = (Datum) ptr; - ptr = att_addlength(ptr, attr[i]->attlen, ptr); - } + if (nulls[i] == 'n') + continue; + ptr = (char *) att_align((long) ptr, attr[i]->attlen, attr[i]->attalign); + values[i] = fetchatt(attr[i], ptr); + ptr = att_addlength(ptr, attr[i]->attlen, ptr); } } } @@ -832,7 +801,7 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp, for (i = 0; i < attr_count; i++) { - if (!byval[i] && nulls[i] != 'n') + if (!attr[i]->attbyval && nulls[i] != 'n') { if (!binary) pfree((void *) values[i]); @@ -855,7 +824,6 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp, pfree(values); pfree(nulls); - pfree(byval); if (!binary) { @@ -902,22 +870,6 @@ GetTypeElement(Oid type) return result; } -static bool -IsTypeByVal(Oid type) -{ - HeapTuple typeTuple; - bool result; - - typeTuple = SearchSysCache(TYPEOID, - ObjectIdGetDatum(type), - 0, 0, 0); - if (!HeapTupleIsValid(typeTuple)) - elog(ERROR, "IsTypeByVal: Cache lookup of type %u failed", type); - result = ((Form_pg_type) GETSTRUCT(typeTuple))->typbyval; - ReleaseSysCache(typeTuple); - return result; -} - /* * Reads input from fp until an end of line is seen. diff --git a/src/backend/executor/execTuples.c b/src/backend/executor/execTuples.c index 65eef4141f4..e27e91071f3 100644 --- a/src/backend/executor/execTuples.c +++ b/src/backend/executor/execTuples.c @@ -15,7 +15,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/execTuples.c,v 1.43 2000/11/12 00:36:57 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/execTuples.c,v 1.44 2000/12/27 23:59:11 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -835,7 +835,7 @@ ExecGetTupType(Plan *node) return tupType; } -/* +#ifdef NOT_USED TupleDesc ExecCopyTupType(TupleDesc td, int natts) { @@ -852,30 +852,23 @@ ExecCopyTupType(TupleDesc td, int natts) } return newTd; } -*/ +#endif /* ---------------------------------------------------------------- * ExecTypeFromTL * + * Generate a tuple descriptor for the result tuple of a targetlist. + * Note that resjunk columns, if any, are included in the result. + * * Currently there are about 4 different places where we create * TupleDescriptors. They should all be merged, or perhaps * be rewritten to call BuildDesc(). - * - * old comments - * Forms attribute type info from the target list in the node. - * It assumes all domains are individually specified in the target list. - * It fails if the target list contains something like Emp.all - * which represents all the attributes from EMP relation. - * - * Conditions: - * The inner and outer subtrees should be initialized because it - * might be necessary to know the type infos of the subtrees. * ---------------------------------------------------------------- */ TupleDesc ExecTypeFromTL(List *targetList) { - List *tlcdr; + List *tlitem; TupleDesc typeInfo; Resdom *resdom; Oid restype; @@ -897,14 +890,12 @@ ExecTypeFromTL(List *targetList) typeInfo = CreateTemplateTupleDesc(len); /* ---------------- - * notes: get resdom from (resdom expr) - * get_typbyval comes from src/lib/l-lisp/lsyscache.c + * scan list, generate type info for each entry * ---------------- */ - tlcdr = targetList; - while (tlcdr != NIL) + foreach(tlitem, targetList) { - TargetEntry *tle = lfirst(tlcdr); + TargetEntry *tle = lfirst(tlitem); if (tle->resdom != NULL) { @@ -920,7 +911,7 @@ ExecTypeFromTL(List *targetList) 0, false); -/* +#ifdef NOT_USED ExecSetTypeInfo(resdom->resno - 1, typeInfo, (Oid) restype, @@ -929,13 +920,14 @@ ExecTypeFromTL(List *targetList) NameStr(*resdom->resname), get_typbyval(restype), get_typalign(restype)); -*/ +#endif } else { + /* XXX this branch looks fairly broken ... tgl 12/2000 */ Resdom *fjRes; List *fjTlistP; - List *fjList = lfirst(tlcdr); + List *fjList = lfirst(tlitem); #ifdef SETS_FIXED TargetEntry *tle; @@ -953,7 +945,7 @@ ExecTypeFromTL(List *targetList) fjRes->restypmod, 0, false); -/* +#ifdef NOT_USED ExecSetTypeInfo(fjRes->resno - 1, typeInfo, (Oid) restype, @@ -962,7 +954,7 @@ ExecTypeFromTL(List *targetList) (char *) fjRes->resname, get_typbyval(restype), get_typalign(restype)); -*/ +#endif foreach(fjTlistP, lnext(fjList)) { @@ -978,7 +970,7 @@ ExecTypeFromTL(List *targetList) 0, false); -/* +#ifdef NOT_USED ExecSetTypeInfo(fjRes->resno - 1, typeInfo, (Oid) fjRes->restype, @@ -987,11 +979,9 @@ ExecTypeFromTL(List *targetList) (char *) fjRes->resname, get_typbyval(fjRes->restype), get_typalign(fjRes->restype)); -*/ +#endif } } - - tlcdr = lnext(tlcdr); } return typeInfo; diff --git a/src/backend/executor/execUtils.c b/src/backend/executor/execUtils.c index 3b05a78e83a..5d4d7f145b3 100644 --- a/src/backend/executor/execUtils.c +++ b/src/backend/executor/execUtils.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/execUtils.c,v 1.69 2000/11/16 22:30:20 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/execUtils.c,v 1.70 2000/12/27 23:59:11 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -274,16 +274,10 @@ ExecAssignResultTypeFromTL(Plan *node, CommonState *commonstate) { List *targetList; TupleDesc tupDesc; - int len; targetList = node->targetlist; tupDesc = ExecTypeFromTL(targetList); - len = ExecTargetListLength(targetList); - - if (len > 0) - ExecAssignResultType(commonstate, tupDesc); - else - ExecAssignResultType(commonstate, (TupleDesc) NULL); + ExecAssignResultType(commonstate, tupDesc); } /* ---------------- @@ -582,8 +576,8 @@ ExecSetTypeInfo(int index, } /* ---------------- - * ExecFreeTypeInfo frees the array of attrbutes - * created by ExecMakeTypeInfo and returned by ExecTypeFromTL... + * ExecFreeTypeInfo frees the array of attributes + * created by ExecMakeTypeInfo and returned by ExecTypeFromTL * ---------------- */ void diff --git a/src/backend/parser/parse_func.c b/src/backend/parser/parse_func.c index 9902b0cf92d..0e1b782fd97 100644 --- a/src/backend/parser/parse_func.c +++ b/src/backend/parser/parse_func.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.95 2000/12/15 19:22:03 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.96 2000/12/27 23:59:11 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -442,10 +442,12 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs, /* * for func(relname), the param to the function is the tuple - * under consideration. we build a special VarNode to reflect + * under consideration. We build a special VarNode to reflect * this -- it has varno set to the correct range table entry, * but has varattno == 0 to signal that the whole tuple is the - * argument. + * argument. Also, it has typmod set to sizeof(Pointer) to + * signal that the runtime representation will be a pointer + * not an Oid. */ if (rte->relname == NULL) elog(ERROR, @@ -453,7 +455,11 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs, toid = typenameTypeId(rte->relname); /* replace it in the arg list */ - lfirst(i) = makeVar(vnum, 0, toid, -1, sublevels_up); + lfirst(i) = makeVar(vnum, + InvalidAttrNumber, + toid, + sizeof(Pointer), + sublevels_up); } else if (!attisset) toid = exprType(arg); diff --git a/src/backend/utils/adt/arrayfuncs.c b/src/backend/utils/adt/arrayfuncs.c index 6379f041ad6..23dc57ce8a5 100644 --- a/src/backend/utils/adt/arrayfuncs.c +++ b/src/backend/utils/adt/arrayfuncs.c @@ -8,15 +8,15 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/arrayfuncs.c,v 1.67 2000/12/03 20:45:35 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/arrayfuncs.c,v 1.68 2000/12/27 23:59:12 tgl Exp $ * *------------------------------------------------------------------------- */ +#include "postgres.h" #include <ctype.h> -#include "postgres.h" - +#include "access/tupmacs.h" #include "catalog/catalog.h" #include "catalog/pg_type.h" #include "utils/array.h" @@ -596,48 +596,24 @@ array_out(PG_FUNCTION_ARGS) values = (char **) palloc(nitems * sizeof(char *)); for (i = 0; i < nitems; i++) { - if (typbyval) - { - switch (typlen) - { - case 1: - values[i] = DatumGetCString(FunctionCall3(&outputproc, - CharGetDatum(*p), - ObjectIdGetDatum(typelem), - Int32GetDatum(-1))); - break; - case 2: - values[i] = DatumGetCString(FunctionCall3(&outputproc, - Int16GetDatum(*(int16 *) p), - ObjectIdGetDatum(typelem), - Int32GetDatum(-1))); - break; - case 3: - case 4: - values[i] = DatumGetCString(FunctionCall3(&outputproc, - Int32GetDatum(*(int32 *) p), - ObjectIdGetDatum(typelem), - Int32GetDatum(-1))); - break; - } + Datum itemvalue; + + itemvalue = fetch_att(p, typbyval, typlen); + values[i] = DatumGetCString(FunctionCall3(&outputproc, + itemvalue, + ObjectIdGetDatum(typelem), + Int32GetDatum(-1))); + if (typlen > 0) p += typlen; - } else - { - values[i] = DatumGetCString(FunctionCall3(&outputproc, - PointerGetDatum(p), - ObjectIdGetDatum(typelem), - Int32GetDatum(-1))); - if (typlen > 0) - p += typlen; - else - p += INTALIGN(*(int32 *) p); + p += INTALIGN(*(int32 *) p); - /* - * For the pair of double quotes - */ + /* + * For the pair of double quotes + */ + if (!typbyval) overall_length += 2; - } + for (tmp = values[i]; *tmp; tmp++) { overall_length += 1; @@ -1358,35 +1334,12 @@ array_map(FunctionCallInfo fcinfo, Oid inpType, Oid retType) for (i = 0; i < nitems; i++) { /* Get source element */ - if (inp_typbyval) - { - switch (inp_typlen) - { - case 1: - elt = CharGetDatum(*s); - break; - case 2: - elt = Int16GetDatum(*(int16 *) s); - break; - case 4: - elt = Int32GetDatum(*(int32 *) s); - break; - default: - elog(ERROR, "array_map: unsupported byval length %d", - inp_typlen); - elt = 0; /* keep compiler quiet */ - break; - } + elt = fetch_att(s, inp_typbyval, inp_typlen); + + if (inp_typlen > 0) s += inp_typlen; - } else - { - elt = PointerGetDatum(s); - if (inp_typlen > 0) - s += inp_typlen; - else - s += INTALIGN(*(int32 *) s); - } + s += INTALIGN(*(int32 *) s); /* * Apply the given function to source elt and extra args. @@ -1516,30 +1469,11 @@ deconstruct_array(ArrayType *array, p = ARR_DATA_PTR(array); for (i = 0; i < nelems; i++) { - if (elmbyval) - { - switch (elmlen) - { - case 1: - elems[i] = CharGetDatum(*p); - break; - case 2: - elems[i] = Int16GetDatum(*(int16 *) p); - break; - case 4: - elems[i] = Int32GetDatum(*(int32 *) p); - break; - } + elems[i] = fetch_att(p, elmbyval, elmlen); + if (elmlen > 0) p += elmlen; - } else - { - elems[i] = PointerGetDatum(p); - if (elmlen > 0) - p += elmlen; - else - p += INTALIGN(VARSIZE(p)); - } + p += INTALIGN(VARSIZE(p)); } } @@ -1616,22 +1550,7 @@ system_cache_lookup(Oid element_type, static Datum ArrayCast(char *value, bool byval, int len) { - if (! byval) - return PointerGetDatum(value); - - switch (len) - { - case 1: - return CharGetDatum(*value); - case 2: - return Int16GetDatum(*(int16 *) value); - case 4: - return Int32GetDatum(*(int32 *) value); - default: - elog(ERROR, "ArrayCast: unsupported byval length %d", len); - break; - } - return 0; /* keep compiler quiet */ + return fetch_att(value, byval, len); } /* @@ -1651,22 +1570,7 @@ ArrayCastAndSet(Datum src, { if (typbyval) { - switch (typlen) - { - case 1: - *dest = DatumGetChar(src); - break; - case 2: - *(int16 *) dest = DatumGetInt16(src); - break; - case 4: - *(int32 *) dest = DatumGetInt32(src); - break; - default: - elog(ERROR, "ArrayCastAndSet: unsupported byval length %d", - typlen); - break; - } + store_att_byval(dest, src, typlen); /* For by-val types, assume no alignment padding is needed */ inc = typlen; } diff --git a/src/backend/utils/cache/lsyscache.c b/src/backend/utils/cache/lsyscache.c index 24b2cbada95..905c9e1633b 100644 --- a/src/backend/utils/cache/lsyscache.c +++ b/src/backend/utils/cache/lsyscache.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.48 2000/11/20 20:36:49 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.49 2000/12/27 23:59:12 tgl Exp $ * * NOTES * Eventually, the index information should go through here, too. @@ -15,6 +15,7 @@ */ #include "postgres.h" +#include "access/tupmacs.h" #include "catalog/pg_operator.h" #include "catalog/pg_proc.h" #include "catalog/pg_type.h" @@ -807,28 +808,8 @@ get_typdefault(Oid typid) if (typByVal) { - int8 i8; - int16 i16; - int32 i32 = 0; - if (dataSize == typLen) - { - switch (typLen) - { - case sizeof(int8): - memcpy((char *) &i8, VARDATA(typDefault), sizeof(int8)); - i32 = i8; - break; - case sizeof(int16): - memcpy((char *) &i16, VARDATA(typDefault), sizeof(int16)); - i32 = i16; - break; - case sizeof(int32): - memcpy((char *) &i32, VARDATA(typDefault), sizeof(int32)); - break; - } - returnValue = Int32GetDatum(i32); - } + returnValue = fetch_att(VARDATA(typDefault), typByVal, typLen); else returnValue = PointerGetDatum(NULL); } diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h index db40344dc46..7618cc55ae5 100644 --- a/src/include/access/heapam.h +++ b/src/include/access/heapam.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: heapam.h,v 1.59 2000/11/30 18:38:46 tgl Exp $ + * $Id: heapam.h,v 1.60 2000/12/27 23:59:13 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -90,9 +90,15 @@ typedef HeapAccessStatisticsData *HeapAccessStatistics; /* ---------------- * fastgetattr * - * This gets called many times, so we macro the cacheable and NULL - * lookups, and call noncachegetattr() for the rest. + * Fetch a user attribute's value as a Datum (might be either a + * value, or a pointer into the data area of the tuple). + * + * This must not be used when a system attribute might be requested. + * Furthermore, the passed attnum MUST be valid. Use heap_getattr() + * instead, if in doubt. * + * This gets called many times, so we macro the cacheable and NULL + * lookups, and call nocachegetattr() for the rest. * ---------------- */ @@ -109,7 +115,7 @@ extern Datum nocachegetattr(HeapTuple tup, int attnum, ( \ (tupleDesc)->attrs[(attnum)-1]->attcacheoff >= 0 ? \ ( \ - (Datum) fetchatt(&((tupleDesc)->attrs[(attnum)-1]), \ + fetchatt((tupleDesc)->attrs[(attnum)-1], \ (char *) (tup)->t_data + (tup)->t_data->t_hoff + \ (tupleDesc)->attrs[(attnum)-1]->attcacheoff) \ ) \ @@ -132,9 +138,8 @@ extern Datum nocachegetattr(HeapTuple tup, int attnum, #else /* defined(DISABLE_COMPLEX_MACRO) */ -extern Datum -fastgetattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, - bool *isnull); +extern Datum fastgetattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, + bool *isnull); #endif /* defined(DISABLE_COMPLEX_MACRO) */ @@ -142,60 +147,39 @@ fastgetattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, /* ---------------- * heap_getattr * - * Find a particular field in a row represented as a heap tuple. - * We return a pointer into that heap tuple, which points to the - * first byte of the value of the field in question. + * Extract an attribute of a heap tuple and return it as a Datum. + * This works for either system or user attributes. The given attnum + * is properly range-checked. * - * If the field in question has a NULL value, we return a null - * pointer and return <*isnull> == true. Otherwise, we return - * <*isnull> == false. + * If the field in question has a NULL value, we return a zero Datum + * and set *isnull == true. Otherwise, we set *isnull == false. * * <tup> is the pointer to the heap tuple. <attnum> is the attribute * number of the column (field) caller wants. <tupleDesc> is a * pointer to the structure describing the row and all its fields. - * - * Because this macro is often called with constants, it generates - * compiler warnings about 'left-hand comma expression has no effect. - * * ---------------- */ #define heap_getattr(tup, attnum, tupleDesc, isnull) \ ( \ - AssertMacro((tup) != NULL && \ - (attnum) > FirstLowInvalidHeapAttributeNumber && \ - (attnum) != 0), \ - ((attnum) > (int) (tup)->t_data->t_natts) ? \ - ( \ - ((isnull) ? (*(isnull) = true) : (dummyret)NULL), \ - (Datum)NULL \ - ) \ - : \ + AssertMacro((tup) != NULL), \ ( \ ((attnum) > 0) ? \ ( \ - fastgetattr((tup), (attnum), (tupleDesc), (isnull)) \ - ) \ - : \ - ( \ - ((isnull) ? (*(isnull) = false) : (dummyret)NULL), \ - ((attnum) == SelfItemPointerAttributeNumber) ? \ + ((attnum) > (int) (tup)->t_data->t_natts) ? \ ( \ - (Datum)((char *)&((tup)->t_self)) \ + ((isnull) ? (*(isnull) = true) : (dummyret)NULL), \ + (Datum)NULL \ ) \ : \ - (((attnum) == TableOidAttributeNumber) ? \ - ( \ - (Datum)((tup)->t_tableOid) \ - ) \ - : \ - ( \ - (Datum)*(unsigned int *) \ - ((char *)(tup)->t_data + heap_sysoffset[-(attnum)-1]) \ - )) \ + fastgetattr((tup), (attnum), (tupleDesc), (isnull)) \ ) \ + : \ + heap_getsysattr((tup), (attnum), (isnull)) \ ) \ ) +extern Datum heap_getsysattr(HeapTuple tup, int attnum, bool *isnull); + extern HeapAccessStatistics heap_access_stats; /* in stats.c */ /* ---------------- @@ -238,8 +222,6 @@ extern void DataFill(char *data, TupleDesc tupleDesc, Datum *value, char *nulls, uint16 *infomask, bits8 *bit); extern int heap_attisnull(HeapTuple tup, int attnum); -extern int heap_sysattrlen(AttrNumber attno); -extern bool heap_sysattrbyval(AttrNumber attno); extern Datum nocachegetattr(HeapTuple tup, int attnum, TupleDesc att, bool *isnull); extern HeapTuple heap_copytuple(HeapTuple tuple); diff --git a/src/include/access/htup.h b/src/include/access/htup.h index eebc1570f54..56631043e3b 100644 --- a/src/include/access/htup.h +++ b/src/include/access/htup.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: htup.h,v 1.41 2000/11/30 08:46:25 vadim Exp $ + * $Id: htup.h,v 1.42 2000/12/27 23:59:13 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -147,6 +147,9 @@ typedef struct xl_heap_update #define MaxAttrSize (10 * 1024 * 1024) +/* + * Attribute numbers for the system-defined attributes + */ #define SelfItemPointerAttributeNumber (-1) #define ObjectIdAttributeNumber (-2) #define MinTransactionIdAttributeNumber (-3) @@ -156,9 +159,6 @@ typedef struct xl_heap_update #define TableOidAttributeNumber (-7) #define FirstLowInvalidHeapAttributeNumber (-8) -/* If you make any changes above, the order of offsets in this must change */ -extern long heap_sysoffset[]; - /* * This new HeapTuple for version >= 6.5 and this is why it was changed: * diff --git a/src/include/access/itup.h b/src/include/access/itup.h index 18639eb7f20..f840ead4cb7 100644 --- a/src/include/access/itup.h +++ b/src/include/access/itup.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: itup.h,v 1.26 2000/11/30 18:38:46 tgl Exp $ + * $Id: itup.h,v 1.27 2000/12/27 23:59:13 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -111,7 +111,7 @@ typedef RetrieveIndexResultData *RetrieveIndexResult; ( \ (tupleDesc)->attrs[(attnum)-1]->attcacheoff >= 0 ? \ ( \ - (Datum) fetchatt(&((tupleDesc)->attrs[(attnum)-1]), \ + fetchatt((tupleDesc)->attrs[(attnum)-1], \ (char *) (tup) + \ ( \ IndexTupleHasMinHeader(tup) ? \ diff --git a/src/include/access/tupmacs.h b/src/include/access/tupmacs.h index ab856087a70..eb977189e14 100644 --- a/src/include/access/tupmacs.h +++ b/src/include/access/tupmacs.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: tupmacs.h,v 1.14 2000/03/17 02:36:37 tgl Exp $ + * $Id: tupmacs.h,v 1.15 2000/12/27 23:59:13 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -22,50 +22,79 @@ #define att_isnull(ATT, BITS) (!((BITS)[(ATT) >> 3] & (1 << ((ATT) & 0x07)))) /* - * given a Form_pg_attribute and a pointer into a tuple's data - * area, return the correct value or pointer. + * Given a Form_pg_attribute and a pointer into a tuple's data area, + * return the correct value or pointer. * - * We return a 4 byte (char *) value in all cases. If the attribute has - * "byval" false or has variable length, we return the same pointer - * into the tuple data area that we're passed. Otherwise, we return - * the 1, 2, or 4 bytes pointed to by it, properly extended to 4 - * bytes, depending on the length of the attribute. + * We return a Datum value in all cases. If the attribute has "byval" false, + * we return the same pointer into the tuple data area that we're passed. + * Otherwise, we return the correct number of bytes fetched from the data + * area and extended to Datum form. * - * note that T must already be properly LONGALIGN/SHORTALIGN'd for - * this to work correctly. + * On machines where Datum is 8 bytes, we support fetching 8-byte byval + * attributes; otherwise, only 1, 2, and 4-byte values are supported. * - * the double-cast is to stop gcc from (correctly) complaining about - * casting integer types with size < sizeof(char *) to (char *). - * sign-extension may get weird if you use an integer type that - * isn't the same size as (char *) for the first cast. (on the other - * hand, it's safe to use another type for the (foo *)(T).) - * - * attbyval seems to be fairly redundant. We have to return a pointer if - * the value is longer than 4 bytes or has variable length; returning the - * value would be useless. In fact, for at least the variable length case, - * the caller assumes we return a pointer regardless of attbyval. - * I would eliminate attbyval altogether, but I don't know how. -BRYANH. + * Note that T must already be properly aligned for this to work correctly. + */ +#define fetchatt(A,T) fetch_att(T, (A)->attbyval, (A)->attlen) + +/* + * Same, but work from byval/len parameters rather than Form_pg_attribute. */ -#define fetchatt(A, T) \ +#if SIZEOF_DATUM == 8 + +#define fetch_att(T,attbyval,attlen) \ ( \ - (*(A))->attbyval && (*(A))->attlen != -1 ? \ + (attbyval) ? \ ( \ - (*(A))->attlen > (int) sizeof(int16) ? \ + (attlen) == (int) sizeof(Datum) ? \ + *((Datum *)(T)) \ + : \ + ( \ + (attlen) == (int) sizeof(int32) ? \ + Int32GetDatum(*((int32 *)(T))) \ + : \ ( \ - (char *) (long) *((int32 *)(T)) \ + (attlen) == (int) sizeof(int16) ? \ + Int16GetDatum(*((int16 *)(T))) \ + : \ + ( \ + AssertMacro((attlen) == 1), \ + CharGetDatum(*((char *)(T))) \ + ) \ ) \ + ) \ + ) \ + : \ + PointerGetDatum((char *) (T)) \ +) + +#else /* SIZEOF_DATUM != 8 */ + +#define fetch_att(T,attbyval,attlen) \ +( \ + (attbyval) ? \ + ( \ + (attlen) == (int) sizeof(int32) ? \ + Int32GetDatum(*((int32 *)(T))) \ : \ ( \ - (*(A))->attlen < (int) sizeof(int16) ? \ - (char *) (long) *((char *)(T)) \ + (attlen) == (int) sizeof(int16) ? \ + Int16GetDatum(*((int16 *)(T))) \ : \ - (char *) (long) *((int16 *)(T))) \ + ( \ + AssertMacro((attlen) == 1), \ + CharGetDatum(*((char *)(T))) \ + ) \ ) \ + ) \ : \ - (char *) (T) \ + PointerGetDatum((char *) (T)) \ ) -/* att_align aligns the given offset as needed for a datum of length attlen +#endif /* SIZEOF_DATUM == 8 */ + +/* + * att_align aligns the given offset as needed for a datum of length attlen * and alignment requirement attalign. In practice we don't need the length. * The attalign cases are tested in what is hopefully something like their * frequency of occurrence. @@ -81,6 +110,10 @@ ))) \ ) +/* + * att_addlength increments the given offset by the length of the attribute. + * attval is only accessed if we are dealing with a varlena attribute. + */ #define att_addlength(cur_offset, attlen, attval) \ ( \ ((attlen) != -1) ? \ @@ -93,4 +126,60 @@ ) \ ) +/* + * store_att_byval is a partial inverse of fetch_att: store a given Datum + * value into a tuple data area at the specified address. However, it only + * handles the byval case, because in typical usage the caller needs to + * distinguish by-val and by-ref cases anyway, and so a do-it-all macro + * wouldn't be convenient. + */ +#if SIZEOF_DATUM == 8 + +#define store_att_byval(T,newdatum,attlen) \ + do { \ + switch (attlen) \ + { \ + case sizeof(char): \ + *(char *) (T) = DatumGetChar(newdatum); \ + break; \ + case sizeof(int16): \ + *(int16 *) (T) = DatumGetInt16(newdatum); \ + break; \ + case sizeof(int32): \ + *(int32 *) (T) = DatumGetInt32(newdatum); \ + break; \ + case sizeof(Datum): \ + *(Datum *) (T) = (newdatum); \ + break; \ + default: \ + elog(ERROR, "store_att_byval: unsupported byval length %d", \ + (int) (attlen)); \ + break; \ + } \ + } while (0) + +#else /* SIZEOF_DATUM != 8 */ + +#define store_att_byval(T,newdatum,attlen) \ + do { \ + switch (attlen) \ + { \ + case sizeof(char): \ + *(char *) (T) = DatumGetChar(newdatum); \ + break; \ + case sizeof(int16): \ + *(int16 *) (T) = DatumGetInt16(newdatum); \ + break; \ + case sizeof(int32): \ + *(int32 *) (T) = DatumGetInt32(newdatum); \ + break; \ + default: \ + elog(ERROR, "store_att_byval: unsupported byval length %d", \ + (int) (attlen)); \ + break; \ + } \ + } while (0) + +#endif /* SIZEOF_DATUM == 8 */ + #endif diff --git a/src/include/catalog/catalog.h b/src/include/catalog/catalog.h index b1d51d520de..4ebe9499ad8 100644 --- a/src/include/catalog/catalog.h +++ b/src/include/catalog/catalog.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: catalog.h,v 1.13 2000/10/16 14:52:26 vadim Exp $ + * $Id: catalog.h,v 1.14 2000/12/27 23:59:13 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -30,7 +30,7 @@ extern char *GetDatabasePath(Oid tblNode); extern bool IsSystemRelationName(const char *relname); extern bool IsSharedSystemRelationName(const char *relname); + extern Oid newoid(void); -extern void fillatt(TupleDesc att); #endif /* CATALOG_H */ diff --git a/src/include/catalog/pg_type.h b/src/include/catalog/pg_type.h index f9f7372fd78..d5e0c58dd19 100644 --- a/src/include/catalog/pg_type.h +++ b/src/include/catalog/pg_type.h @@ -8,7 +8,7 @@ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: pg_type.h,v 1.98 2000/11/30 18:38:47 tgl Exp $ + * $Id: pg_type.h,v 1.99 2000/12/27 23:59:13 tgl Exp $ * * NOTES * the genbki.sh script reads this file and generates .bki @@ -51,13 +51,11 @@ CATALOG(pg_type) BOOTSTRAP /* * typbyval determines whether internal Postgres routines pass a value - * of this type by value or by reference. Only char, short, and int- - * equivalent items can be passed by value, so if the type is not 1, - * 2, or 4 bytes long, Postgres does not have the option of passing by - * value and so typbyval had better be FALSE. Variable-length types - * are always passed by reference. Note that typbyval can be false - * even if the length would allow pass-by-value; this is currently - * true for type float4, for example. + * of this type by value or by reference. typbyval had better be FALSE + * if the length is not 1, 2, or 4 (or 8 on 8-byte-Datum machines). + * Variable-length types are always passed by reference. Note that + * typbyval can be false even if the length would allow pass-by-value; + * this is currently true for type float4, for example. */ bool typbyval; diff --git a/src/include/config.h.in b/src/include/config.h.in index 77a61e64106..8be472c3fec 100644 --- a/src/include/config.h.in +++ b/src/include/config.h.in @@ -8,7 +8,7 @@ * or in config.h afterwards. Of course, if you edit config.h, then your * changes will be overwritten the next time you run configure. * - * $Id: config.h.in,v 1.153 2000/12/02 18:16:40 tgl Exp $ + * $Id: config.h.in,v 1.154 2000/12/27 23:59:14 tgl Exp $ */ #ifndef CONFIG_H @@ -582,6 +582,11 @@ extern void srandom(unsigned int seed); #undef INT64_FORMAT /* + * We need a #define symbol for sizeof(Datum) for use in some #if tests. + */ +#undef SIZEOF_DATUM + +/* * These must be defined as the alignment requirement (NOT the size) of * each of the basic C data types (except char, which we assume has align 1). * MAXIMUM_ALIGNOF is the largest alignment requirement for any C data type. |