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/backend/access/common/tupdesc.c | |
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/backend/access/common/tupdesc.c')
-rw-r--r-- | src/backend/access/common/tupdesc.c | 86 |
1 files changed, 52 insertions, 34 deletions
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; |