diff options
author | Bruce Momjian | 2002-07-20 05:16:59 +0000 |
---|---|---|
committer | Bruce Momjian | 2002-07-20 05:16:59 +0000 |
commit | 9f9f550ed9e2408c8b00eb93659719df8055a30c (patch) | |
tree | 052357b394a959c33520fd32afbae6f9bb307c5d | |
parent | 94527489d17bde3d2e08095de3ee4cc23cc01157 (diff) |
oid is needed, it is added at the end of the struct (after the null
bitmap, if present).
Per Tom Lane's suggestion the information whether a tuple has an oid
or not is carried in the tuple descriptor. For debugging reasons
tdhasoid is of type char, not bool. There are predefined values for
WITHOID, WITHOUTOID and UNDEFOID.
This patch has been generated against a cvs snapshot from last week
and I don't expect it to apply cleanly to current sources. While I
post it here for public review, I'm working on a new version against a
current snapshot. (There's been heavy activity recently; hope to
catch up some day ...)
This is a long patch; if it is too hard to swallow, I can provide it
in smaller pieces:
Part 1: Accessor macros
Part 2: tdhasoid in TupDesc
Part 3: Regression test
Part 4: Parameter withoid to heap_addheader
Part 5: Eliminate t_oid from HeapTupleHeader
Part 2 is the most hairy part because of changes in the executor and
even in the parser; the other parts are straightforward.
Up to part 4 the patched postmaster stays binary compatible to
databases created with an unpatched version. Part 5 is small (100
lines) and finally breaks compatibility.
Manfred Koizar
57 files changed, 361 insertions, 145 deletions
diff --git a/contrib/dbsize/dbsize.c b/contrib/dbsize/dbsize.c index b072a86912..44699aa693 100644 --- a/contrib/dbsize/dbsize.c +++ b/contrib/dbsize/dbsize.c @@ -65,7 +65,7 @@ database_size(PG_FUNCTION_ARGS) if (!HeapTupleIsValid(tuple)) elog(ERROR, "database %s does not exist", NameStr(*dbname)); - dbid = tuple->t_data->t_oid; + dbid = HeapTupleGetOid(tuple); if (dbid == InvalidOid) elog(ERROR, "invalid database id"); diff --git a/contrib/fulltextindex/fti.c b/contrib/fulltextindex/fti.c index aabb2caf9f..8050f2a9d7 100644 --- a/contrib/fulltextindex/fti.c +++ b/contrib/fulltextindex/fti.c @@ -190,7 +190,7 @@ fti(PG_FUNCTION_ARGS) tupdesc = rel->rd_att; /* what the tuple looks like (?) */ /* get oid of current tuple, needed by all, so place here */ - oid = rettuple->t_data->t_oid; + oid = rel->rd_rel->relhasoids ? HeapTupleGetOid(rettuple) : InvalidOid; if (!OidIsValid(oid)) elog(ERROR, "Full Text Indexing: Oid of current tuple is invalid"); diff --git a/contrib/rserv/rserv.c b/contrib/rserv/rserv.c index 401cc5fd9c..54da14a696 100644 --- a/contrib/rserv/rserv.c +++ b/contrib/rserv/rserv.c @@ -102,7 +102,9 @@ _rserv_log_() if (keynum == ObjectIdAttributeNumber) { - sprintf(oidbuf, "%u", tuple->t_data->t_oid); + sprintf(oidbuf, "%u", rel->rd_rel->relhasoids + ? HeapTupleGetOid(tuple) + : InvalidOid); key = oidbuf; } else diff --git a/src/backend/access/common/heaptuple.c b/src/backend/access/common/heaptuple.c index 6d807fa93c..95b1e5feb2 100644 --- a/src/backend/access/common/heaptuple.c +++ b/src/backend/access/common/heaptuple.c @@ -436,7 +436,7 @@ heap_getsysattr(HeapTuple tup, int attnum, bool *isnull) result = PointerGetDatum(&(tup->t_self)); break; case ObjectIdAttributeNumber: - result = ObjectIdGetDatum(tup->t_data->t_oid); + result = ObjectIdGetDatum(HeapTupleGetOid(tup)); break; case MinTransactionIdAttributeNumber: result = TransactionIdGetDatum(HeapTupleHeaderGetXmin(tup->t_data)); @@ -581,6 +581,8 @@ heap_formtuple(TupleDesc tupleDescriptor, elog(ERROR, "heap_formtuple: numberOfAttributes %d exceeds limit %d", numberOfAttributes, MaxTupleAttributeNumber); + AssertTupleDescHasOidIsValid(tupleDescriptor); + for (i = 0; i < numberOfAttributes; i++) { if (nulls[i] != ' ') @@ -595,6 +597,9 @@ heap_formtuple(TupleDesc tupleDescriptor, if (hasnull) len += BITMAPLEN(numberOfAttributes); + if (tupleDescriptor->tdhasoid == WITHOID) + len += sizeof(Oid); + hoff = len = MAXALIGN(len); /* align user data safely */ len += ComputeDataSize(tupleDescriptor, value, nulls); @@ -698,14 +703,18 @@ heap_modifytuple(HeapTuple tuple, * t_infomask */ infomask = newTuple->t_data->t_infomask; - memmove((char *) &newTuple->t_data->t_oid, /* XXX */ - (char *) &tuple->t_data->t_oid, - ((char *) &tuple->t_data->t_hoff - - (char *) &tuple->t_data->t_oid)); /* XXX */ + /* + * copy t_xmin, t_cid, t_xmax, t_ctid, t_natts, t_infomask + */ + memmove((char *) newTuple->t_data, /* XXX */ + (char *) tuple->t_data, + offsetof(HeapTupleHeaderData, t_hoff)); /* XXX */ newTuple->t_data->t_infomask = infomask; newTuple->t_data->t_natts = numberOfAttributes; newTuple->t_self = tuple->t_self; newTuple->t_tableOid = tuple->t_tableOid; + if (relation->rd_rel->relhasoids) + HeapTupleSetOid(newTuple, HeapTupleGetOid(tuple)); return newTuple; } @@ -738,6 +747,7 @@ heap_freetuple(HeapTuple htup) */ HeapTuple heap_addheader(int natts, /* max domain index */ + bool withoid, /* reserve space for oid */ Size structlen, /* its length */ void *structure) /* pointer to the struct */ { @@ -749,7 +759,10 @@ heap_addheader(int natts, /* max domain index */ AssertArg(natts > 0); /* header needs no null bitmap */ - hoff = MAXALIGN(offsetof(HeapTupleHeaderData, t_bits)); + hoff = offsetof(HeapTupleHeaderData, t_bits); + if (withoid) + hoff += sizeof(Oid); + hoff = MAXALIGN(hoff); len = hoff + structlen; tuple = (HeapTuple) palloc(HEAPTUPLESIZE + len); diff --git a/src/backend/access/common/tupdesc.c b/src/backend/access/common/tupdesc.c index 5dece2cc1c..8b325a11a9 100644 --- a/src/backend/access/common/tupdesc.c +++ b/src/backend/access/common/tupdesc.c @@ -36,7 +36,7 @@ * ---------------------------------------------------------------- */ TupleDesc -CreateTemplateTupleDesc(int natts) +CreateTemplateTupleDesc(int natts, hasoid_t withoid) { uint32 size; TupleDesc desc; @@ -58,6 +58,7 @@ CreateTemplateTupleDesc(int natts) MemSet(desc->attrs, 0, size); desc->natts = natts; + desc->tdhasoid = withoid; return desc; } @@ -82,6 +83,7 @@ CreateTupleDesc(int natts, Form_pg_attribute *attrs) desc->attrs = attrs; desc->natts = natts; desc->constr = NULL; + desc->tdhasoid = UNDEFOID; return desc; } @@ -116,6 +118,7 @@ CreateTupleDescCopy(TupleDesc tupdesc) desc->attrs[i]->atthasdef = false; } desc->constr = NULL; + desc->tdhasoid = tupdesc->tdhasoid; return desc; } @@ -182,6 +185,7 @@ CreateTupleDescCopyConstr(TupleDesc tupdesc) else desc->constr = NULL; + desc->tdhasoid = tupdesc->tdhasoid; return desc; } @@ -235,6 +239,8 @@ equalTupleDescs(TupleDesc tupdesc1, TupleDesc tupdesc2) if (tupdesc1->natts != tupdesc2->natts) return false; + if (tupdesc1->tdhasoid != tupdesc2->tdhasoid) + return false; for (i = 0; i < tupdesc1->natts; i++) { Form_pg_attribute attr1 = tupdesc1->attrs[i]; @@ -392,7 +398,7 @@ TupleDescInitEntry(TupleDesc desc, */ typeForm = (Form_pg_type) GETSTRUCT(tuple); - att->atttypid = tuple->t_data->t_oid; + att->atttypid = HeapTupleGetOid(tuple); /* * There are a couple of cases where we must override the information @@ -479,7 +485,7 @@ BuildDescForRelation(List *schema) * allocate a new tuple descriptor */ natts = length(schema); - desc = CreateTemplateTupleDesc(natts); + desc = CreateTemplateTupleDesc(natts, UNDEFOID); constr->has_not_null = false; attnum = 0; @@ -646,7 +652,7 @@ TypeGetTupleDesc(Oid typeoid, List *colaliases) /* OK, get the column alias */ attname = strVal(lfirst(colaliases)); - tupdesc = CreateTemplateTupleDesc(1); + tupdesc = CreateTemplateTupleDesc(1, WITHOUTOID); TupleDescInitEntry(tupdesc, (AttrNumber) 1, attname, diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c index 837cc9d68b..1504609fd2 100644 --- a/src/backend/access/heap/heapam.c +++ b/src/backend/access/heap/heapam.c @@ -1116,10 +1116,11 @@ heap_insert(Relation relation, HeapTuple tup, CommandId cid) * to support a persistent object store (objects need to contain * pointers to one another). */ - if (!OidIsValid(tup->t_data->t_oid)) - tup->t_data->t_oid = newoid(); + AssertTupleDescHasOid(relation->rd_att); + if (!OidIsValid(HeapTupleGetOid(tup))) + HeapTupleSetOid(tup, newoid()); else - CheckMaxObjectId(tup->t_data->t_oid); + CheckMaxObjectId(HeapTupleGetOid(tup)); } HeapTupleHeaderSetXmin(tup->t_data, GetCurrentTransactionId()); @@ -1166,7 +1167,13 @@ heap_insert(Relation relation, HeapTuple tup, CommandId cid) rdata[0].len = SizeOfHeapInsert; rdata[0].next = &(rdata[1]); - xlhdr.t_oid = tup->t_data->t_oid; + if (relation->rd_rel->relhasoids) + { + AssertTupleDescHasOid(relation->rd_att); + xlhdr.t_oid = HeapTupleGetOid(tup); + } + else + xlhdr.t_oid = InvalidOid; xlhdr.t_natts = tup->t_data->t_natts; xlhdr.t_hoff = tup->t_data->t_hoff; xlhdr.mask = tup->t_data->t_infomask; @@ -1176,6 +1183,7 @@ heap_insert(Relation relation, HeapTuple tup, CommandId cid) rdata[1].next = &(rdata[2]); rdata[2].buffer = buffer; + /* PG73FORMAT: write bitmap [+ padding] [+ oid] + data */ rdata[2].data = (char *) tup->t_data + offsetof(HeapTupleHeaderData, t_bits); rdata[2].len = tup->t_len - offsetof(HeapTupleHeaderData, t_bits); rdata[2].next = NULL; @@ -1206,7 +1214,11 @@ heap_insert(Relation relation, HeapTuple tup, CommandId cid) */ CacheInvalidateHeapTuple(relation, tup); - return tup->t_data->t_oid; + if (!relation->rd_rel->relhasoids) + return InvalidOid; + + AssertTupleDescHasOid(relation->rd_att); + return HeapTupleGetOid(tup); } /* @@ -1499,7 +1511,11 @@ l2: } /* Fill in OID and transaction status data for newtup */ - newtup->t_data->t_oid = oldtup.t_data->t_oid; + if (relation->rd_rel->relhasoids) + { + AssertTupleDescHasOid(relation->rd_att); + HeapTupleSetOid(newtup, HeapTupleGetOid(&oldtup)); + } newtup->t_data->t_infomask &= ~(HEAP_XACT_MASK); newtup->t_data->t_infomask |= (HEAP_XMAX_INVALID | HEAP_UPDATED); HeapTupleHeaderSetXmin(newtup->t_data, GetCurrentTransactionId()); @@ -1972,24 +1988,28 @@ log_heap_update(Relation reln, Buffer oldbuf, ItemPointerData from, rdata[1].len = 0; rdata[1].next = &(rdata[2]); - xlhdr.hdr.t_oid = newtup->t_data->t_oid; + if (reln->rd_rel->relhasoids) + { + AssertTupleDescHasOid(reln->rd_att); + xlhdr.hdr.t_oid = HeapTupleGetOid(newtup); + } + else + xlhdr.hdr.t_oid = InvalidOid; xlhdr.hdr.t_natts = newtup->t_data->t_natts; xlhdr.hdr.t_hoff = newtup->t_data->t_hoff; xlhdr.hdr.mask = newtup->t_data->t_infomask; if (move) /* remember xmin & xmax */ { - TransactionId xmax; - TransactionId xmin; + TransactionId xid[2]; /* xmax, xmin */ - if (newtup->t_data->t_infomask & HEAP_XMAX_INVALID || - newtup->t_data->t_infomask & HEAP_MARKED_FOR_UPDATE) - xmax = InvalidTransactionId; + if (newtup->t_data->t_infomask & (HEAP_XMAX_INVALID | + HEAP_MARKED_FOR_UPDATE)) + xid[0] = InvalidTransactionId; else - xmax = HeapTupleHeaderGetXmax(newtup->t_data); - xmin = HeapTupleHeaderGetXmin(newtup->t_data); - memcpy((char *) &xlhdr + hsize, &xmax, sizeof(TransactionId)); - memcpy((char *) &xlhdr + hsize + sizeof(TransactionId), - &xmin, sizeof(TransactionId)); + xid[0] = HeapTupleHeaderGetXmax(newtup->t_data); + xid[1] = HeapTupleHeaderGetXmin(newtup->t_data); + memcpy((char *) &xlhdr + hsize, + (char *) xid, 2 * sizeof(TransactionId)); hsize += 2 * sizeof(TransactionId); } rdata[2].buffer = newbuf; @@ -1998,6 +2018,7 @@ log_heap_update(Relation reln, Buffer oldbuf, ItemPointerData from, rdata[2].next = &(rdata[3]); rdata[3].buffer = newbuf; + /* PG73FORMAT: write bitmap [+ padding] [+ oid] + data */ rdata[3].data = (char *) newtup->t_data + offsetof(HeapTupleHeaderData, t_bits); rdata[3].len = newtup->t_len - offsetof(HeapTupleHeaderData, t_bits); rdata[3].next = NULL; @@ -2193,12 +2214,13 @@ heap_xlog_insert(bool redo, XLogRecPtr lsn, XLogRecord *record) memcpy((char *) &xlhdr, (char *) xlrec + SizeOfHeapInsert, SizeOfHeapHeader); + htup = &tbuf.hdr; + MemSet((char *) htup, 0, sizeof(HeapTupleHeaderData)); + /* PG73FORMAT: get bitmap [+ padding] [+ oid] + data */ memcpy((char *) &tbuf + offsetof(HeapTupleHeaderData, t_bits), (char *) xlrec + SizeOfHeapInsert + SizeOfHeapHeader, newlen); newlen += offsetof(HeapTupleHeaderData, t_bits); - htup = &tbuf.hdr; - htup->t_oid = xlhdr.t_oid; htup->t_natts = xlhdr.t_natts; htup->t_hoff = xlhdr.t_hoff; htup->t_infomask = HEAP_XMAX_INVALID | xlhdr.mask; @@ -2206,6 +2228,11 @@ heap_xlog_insert(bool redo, XLogRecPtr lsn, XLogRecord *record) HeapTupleHeaderSetCmin(htup, FirstCommandId); HeapTupleHeaderSetXmaxInvalid(htup); HeapTupleHeaderSetCmax(htup, FirstCommandId); + if (reln->rd_rel->relhasoids) + { + AssertTupleDescHasOid(reln->rd_att); + HeapTupleHeaderSetOid(htup, xlhdr.t_oid); + } offnum = PageAddItem(page, (Item) htup, newlen, offnum, LP_USED | OverwritePageMode); @@ -2362,28 +2389,33 @@ newsame:; memcpy((char *) &xlhdr, (char *) xlrec + SizeOfHeapUpdate, SizeOfHeapHeader); + htup = &tbuf.hdr; + MemSet((char *) htup, 0, sizeof(HeapTupleHeaderData)); + /* PG73FORMAT: get bitmap [+ padding] [+ oid] + data */ memcpy((char *) &tbuf + offsetof(HeapTupleHeaderData, t_bits), (char *) xlrec + hsize, newlen); newlen += offsetof(HeapTupleHeaderData, t_bits); - htup = &tbuf.hdr; - htup->t_oid = xlhdr.t_oid; htup->t_natts = xlhdr.t_natts; htup->t_hoff = xlhdr.t_hoff; + if (reln->rd_rel->relhasoids) + { + AssertTupleDescHasOid(reln->rd_att); + HeapTupleHeaderSetOid(htup, xlhdr.t_oid); + } if (move) { - TransactionId xmax; - TransactionId xmin; + TransactionId xid[2]; /* xmax, xmin */ hsize = SizeOfHeapUpdate + SizeOfHeapHeader; - memcpy(&xmax, (char *) xlrec + hsize, sizeof(TransactionId)); - memcpy(&xmin, (char *) xlrec + hsize + sizeof(TransactionId), sizeof(TransactionId)); + memcpy((char *) xid, + (char *) xlrec + hsize, 2 * sizeof(TransactionId)); htup->t_infomask = xlhdr.mask; htup->t_infomask &= ~(HEAP_XMIN_COMMITTED | HEAP_XMIN_INVALID | HEAP_MOVED_OFF); htup->t_infomask |= HEAP_MOVED_IN; - HeapTupleHeaderSetXmin(htup, xmin); - HeapTupleHeaderSetXmax(htup, xmax); + HeapTupleHeaderSetXmin(htup, xid[1]); + HeapTupleHeaderSetXmax(htup, xid[0]); HeapTupleHeaderSetXvac(htup, record->xl_xid); } else diff --git a/src/backend/access/heap/tuptoaster.c b/src/backend/access/heap/tuptoaster.c index 83949aff1e..9ef4845cc7 100644 --- a/src/backend/access/heap/tuptoaster.c +++ b/src/backend/access/heap/tuptoaster.c @@ -726,6 +726,8 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup) new_len = offsetof(HeapTupleHeaderData, t_bits); if (has_nulls) new_len += BITMAPLEN(numAttrs); + if (rel->rd_rel->relhasoids) + new_len += sizeof(Oid); new_len = MAXALIGN(new_len); Assert(new_len == olddata->t_hoff); new_len += ComputeDataSize(tupleDesc, toast_values, toast_nulls); diff --git a/src/backend/bootstrap/bootparse.y b/src/backend/bootstrap/bootparse.y index 933a0f2f15..5935e238b2 100644 --- a/src/backend/bootstrap/bootparse.y +++ b/src/backend/bootstrap/bootparse.y @@ -179,13 +179,13 @@ Boot_CreateStmt: } tupdesc = CreateTupleDesc(numattr, attrtypes); + tupdesc->tdhasoid = BoolToHasOid(! ($4)); boot_reldesc = heap_create(LexIDStr($5), PG_CATALOG_NAMESPACE, tupdesc, $3, true, true); - boot_reldesc->rd_rel->relhasoids = ! ($4); elog(DEBUG3, "bootstrap relation created"); } else diff --git a/src/backend/bootstrap/bootstrap.c b/src/backend/bootstrap/bootstrap.c index 583600e113..cfb026ff68 100644 --- a/src/backend/bootstrap/bootstrap.c +++ b/src/backend/bootstrap/bootstrap.c @@ -495,7 +495,8 @@ boot_openrel(char *relname) app = Typ; while ((tup = heap_getnext(scan, ForwardScanDirection)) != NULL) { - (*app)->am_oid = tup->t_data->t_oid; + AssertTupleDescHasOid(rel->rd_att); + (*app)->am_oid = HeapTupleGetOid(tup); memcpy((char *) &(*app)->am_typ, (char *) GETSTRUCT(tup), sizeof((*app)->am_typ)); @@ -675,11 +676,15 @@ InsertOneTuple(Oid objectid) elog(DEBUG3, "inserting row oid %u, %d columns", objectid, numattr); tupDesc = CreateTupleDesc(numattr, attrtypes); + tupDesc->tdhasoid = BoolToHasOid(RelationGetForm(boot_reldesc)->relhasoids); tuple = heap_formtuple(tupDesc, values, Blanks); - pfree(tupDesc); /* just free's tupDesc, not the attrtypes */ if (objectid != (Oid) 0) - tuple->t_data->t_oid = objectid; + { + AssertTupleDescHasOid(tupDesc); + HeapTupleSetOid(tuple, objectid); + } + pfree(tupDesc); /* just free's tupDesc, not the attrtypes */ simple_heap_insert(boot_reldesc, tuple); heap_freetuple(tuple); elog(DEBUG3, "row inserted"); @@ -871,7 +876,8 @@ gettype(char *type) app = Typ; while ((tup = heap_getnext(scan, ForwardScanDirection)) != NULL) { - (*app)->am_oid = tup->t_data->t_oid; + AssertTupleDescHasOid(rel->rd_att); + (*app)->am_oid = HeapTupleGetOid(tup); memmove((char *) &(*app++)->am_typ, (char *) GETSTRUCT(tup), sizeof((*app)->am_typ)); diff --git a/src/backend/catalog/aclchk.c b/src/backend/catalog/aclchk.c index d67ebfb648..5fd1d99003 100644 --- a/src/backend/catalog/aclchk.c +++ b/src/backend/catalog/aclchk.c @@ -592,7 +592,8 @@ ExecuteGrantStmt_Namespace(GrantStmt *stmt) elog(ERROR, "namespace \"%s\" not found", nspname); pg_namespace_tuple = (Form_pg_namespace) GETSTRUCT(tuple); - if (!pg_namespace_ownercheck(tuple->t_data->t_oid, GetUserId())) + AssertTupleDescHasOid(relation->rd_att); + if (!pg_namespace_ownercheck(HeapTupleGetOid(tuple), GetUserId())) aclcheck_error(ACLCHECK_NOT_OWNER, nspname); /* diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c index 97da2d43af..52522bed5f 100644 --- a/src/backend/catalog/heap.c +++ b/src/backend/catalog/heap.c @@ -65,7 +65,7 @@ static void AddNewRelationTuple(Relation pg_class_desc, Relation new_rel_desc, Oid new_rel_oid, Oid new_type_oid, - char relkind, bool relhasoids); + char relkind); static void AddNewRelationType(const char *typeName, Oid typeNamespace, Oid new_rel_oid, @@ -445,6 +445,7 @@ AddNewAttributeTuples(Oid new_rel_oid, (*dpp)->attcacheoff = -1; tup = heap_addheader(Natts_pg_attribute, + false, ATTRIBUTE_TUPLE_SIZE, (void *) *dpp); @@ -481,6 +482,7 @@ AddNewAttributeTuples(Oid new_rel_oid, Form_pg_attribute attStruct; tup = heap_addheader(Natts_pg_attribute, + false, ATTRIBUTE_TUPLE_SIZE, (void *) *dpp); @@ -527,8 +529,7 @@ AddNewRelationTuple(Relation pg_class_desc, Relation new_rel_desc, Oid new_rel_oid, Oid new_type_oid, - char relkind, - bool relhasoids) + char relkind) { Form_pg_class new_rel_reltup; HeapTuple tup; @@ -579,7 +580,6 @@ AddNewRelationTuple(Relation pg_class_desc, new_rel_reltup->relowner = GetUserId(); new_rel_reltup->reltype = new_type_oid; new_rel_reltup->relkind = relkind; - new_rel_reltup->relhasoids = relhasoids; /* ---------------- * now form a tuple to add to pg_class @@ -587,11 +587,13 @@ AddNewRelationTuple(Relation pg_class_desc, * ---------------- */ tup = heap_addheader(Natts_pg_class_fixed, + true, CLASS_TUPLE_SIZE, (void *) new_rel_reltup); /* force tuple to have the desired OID */ - tup->t_data->t_oid = new_rel_oid; + AssertTupleDescHasOid(pg_class_desc->rd_att); + HeapTupleSetOid(tup, new_rel_oid); /* * finally insert the new tuple and free it. @@ -691,6 +693,8 @@ heap_create_with_catalog(const char *relname, if (get_relname_relid(relname, relnamespace)) elog(ERROR, "Relation '%s' already exists", relname); + tupdesc->tdhasoid = BoolToHasOid(relhasoids); + /* * Tell heap_create not to create a physical file; we'll do that below * after all our catalog updates are done. (This isn't really @@ -723,8 +727,7 @@ heap_create_with_catalog(const char *relname, new_rel_desc, new_rel_oid, new_type_oid, - relkind, - relhasoids); + relkind); /* * since defining a relation also defines a complex type, we add a new @@ -920,13 +923,14 @@ RemoveAttrDefault(Oid relid, AttrNumber attnum, scan = systable_beginscan(attrdef_rel, AttrDefaultIndex, true, SnapshotNow, 2, scankeys); + AssertTupleDescHasOid(attrdef_rel->rd_att); /* There should be at most one matching tuple, but we loop anyway */ while (HeapTupleIsValid(tuple = systable_getnext(scan))) { ObjectAddress object; object.classId = RelationGetRelid(attrdef_rel); - object.objectId = tuple->t_data->t_oid; + object.objectId = HeapTupleGetOid(tuple); object.objectSubId = 0; performDeletion(&object, behavior); @@ -1711,6 +1715,7 @@ RemoveRelConstraints(Relation rel, const char *constrName, conscan = systable_beginscan(conrel, ConstraintRelidIndex, true, SnapshotNow, 1, key); + AssertTupleDescHasOid(conrel->rd_att); /* * Scan over the result set, removing any matching entries. */ @@ -1723,7 +1728,7 @@ RemoveRelConstraints(Relation rel, const char *constrName, ObjectAddress conobj; conobj.classId = RelationGetRelid(conrel); - conobj.objectId = contup->t_data->t_oid; + conobj.objectId = HeapTupleGetOid(contup); conobj.objectSubId = 0; performDeletion(&conobj, behavior); diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 4d367559f9..009d14131d 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -111,7 +111,7 @@ BuildFuncTupleDesc(Oid funcOid, /* * Allocate and zero a tuple descriptor for a one-column tuple. */ - funcTupDesc = CreateTemplateTupleDesc(1); + funcTupDesc = CreateTemplateTupleDesc(1, UNDEFOID); funcTupDesc->attrs[0] = (Form_pg_attribute) palloc(ATTRIBUTE_TUPLE_SIZE); MemSet(funcTupDesc->attrs[0], 0, ATTRIBUTE_TUPLE_SIZE); @@ -199,7 +199,7 @@ ConstructTupleDescriptor(Relation heapRelation, * allocate the new tuple descriptor */ - indexTupDesc = CreateTemplateTupleDesc(numatts); + indexTupDesc = CreateTemplateTupleDesc(numatts, WITHOUTOID); /* ---------------- * for each attribute we are indexing, obtain its attribute @@ -320,6 +320,7 @@ UpdateRelationRelation(Relation indexRelation) /* XXX Natts_pg_class_fixed is a hack - see pg_class.h */ tuple = heap_addheader(Natts_pg_class_fixed, + true, CLASS_TUPLE_SIZE, (void *) indexRelation->rd_rel); @@ -327,7 +328,8 @@ UpdateRelationRelation(Relation indexRelation) * the new tuple must have the oid already chosen for the index. * sure would be embarrassing to do this sort of thing in polite company. */ - tuple->t_data->t_oid = RelationGetRelid(indexRelation); + AssertTupleDescHasOid(pg_class->rd_att); + HeapTupleSetOid(tuple, RelationGetRelid(indexRelation)); simple_heap_insert(pg_class, tuple); /* @@ -406,6 +408,7 @@ AppendAttributeTuples(Relation indexRelation, int numatts) Assert(indexTupDesc->attrs[i]->attcacheoff == -1); new_tuple = heap_addheader(Natts_pg_attribute, + false, ATTRIBUTE_TUPLE_SIZE, (void *) indexTupDesc->attrs[i]); @@ -495,6 +498,7 @@ UpdateIndexRelation(Oid indexoid, * form a tuple to insert into pg_index */ tuple = heap_addheader(Natts_pg_index, + false, itupLen, (void *) indexForm); @@ -599,6 +603,7 @@ index_create(Oid heapRelationId, indexInfo->ii_KeyAttrNumbers, classObjectId); + indexTupDesc->tdhasoid = WITHOUTOID; /* * create the index relation (but don't create storage yet) */ @@ -626,7 +631,7 @@ index_create(Oid heapRelationId, indexRelation->rd_rel->relowner = GetUserId(); indexRelation->rd_rel->relam = accessMethodObjectId; indexRelation->rd_rel->relkind = RELKIND_INDEX; - indexRelation->rd_rel->relhasoids = false; + indexRelation->rd_rel->relhasoids = false; /* WITHOUTOID! */ /* * store index's pg_class entry diff --git a/src/backend/catalog/namespace.c b/src/backend/catalog/namespace.c index 907032305a..25aadba5f0 100644 --- a/src/backend/catalog/namespace.c +++ b/src/backend/catalog/namespace.c @@ -571,7 +571,7 @@ FuncnameGetCandidates(List *names, int nargs) continue; /* keep previous result */ /* replace previous result */ prevResult->pathpos = pathpos; - prevResult->oid = proctup->t_data->t_oid; + prevResult->oid = HeapTupleGetOid(proctup); continue; /* args are same, of course */ } } @@ -584,7 +584,7 @@ FuncnameGetCandidates(List *names, int nargs) palloc(sizeof(struct _FuncCandidateList) - sizeof(Oid) + nargs * sizeof(Oid)); newResult->pathpos = pathpos; - newResult->oid = proctup->t_data->t_oid; + newResult->oid = HeapTupleGetOid(proctup); newResult->nargs = nargs; memcpy(newResult->args, procform->proargtypes, nargs * sizeof(Oid)); @@ -818,7 +818,7 @@ OpernameGetCandidates(List *names, char oprkind) continue; /* keep previous result */ /* replace previous result */ prevResult->pathpos = pathpos; - prevResult->oid = opertup->t_data->t_oid; + prevResult->oid = HeapTupleGetOid(opertup); continue; /* args are same, of course */ } } @@ -830,7 +830,7 @@ OpernameGetCandidates(List *names, char oprkind) newResult = (FuncCandidateList) palloc(sizeof(struct _FuncCandidateList) + sizeof(Oid)); newResult->pathpos = pathpos; - newResult->oid = opertup->t_data->t_oid; + newResult->oid = HeapTupleGetOid(opertup); newResult->nargs = 2; newResult->args[0] = operform->oprleft; newResult->args[1] = operform->oprright; @@ -994,7 +994,7 @@ OpclassGetCandidates(Oid amid) /* replace previous result */ prevResult->opcname_tmp = NameStr(opcform->opcname); prevResult->pathpos = pathpos; - prevResult->oid = opctup->t_data->t_oid; + prevResult->oid = HeapTupleGetOid(opctup); prevResult->opcintype = opcform->opcintype; prevResult->opcdefault = opcform->opcdefault; prevResult->opckeytype = opcform->opckeytype; @@ -1009,7 +1009,7 @@ OpclassGetCandidates(Oid amid) palloc(sizeof(struct _OpclassCandidateList)); newResult->opcname_tmp = NameStr(opcform->opcname); newResult->pathpos = pathpos; - newResult->oid = opctup->t_data->t_oid; + newResult->oid = HeapTupleGetOid(opctup); newResult->opcintype = opcform->opcintype; newResult->opcdefault = opcform->opcdefault; newResult->opckeytype = opcform->opckeytype; @@ -1572,8 +1572,9 @@ RemoveTempRelations(Oid tempNamespaceId) case RELKIND_RELATION: case RELKIND_SEQUENCE: case RELKIND_VIEW: + AssertTupleDescHasOid(pgclass->rd_att); object.classId = RelOid_pg_class; - object.objectId = tuple->t_data->t_oid; + object.objectId = HeapTupleGetOid(tuple); object.objectSubId = 0; performDeletion(&object, DROP_CASCADE); break; diff --git a/src/backend/catalog/pg_operator.c b/src/backend/catalog/pg_operator.c index 6354f1f786..31b8fcfc23 100644 --- a/src/backend/catalog/pg_operator.c +++ b/src/backend/catalog/pg_operator.c @@ -144,7 +144,7 @@ OperatorGet(const char *operatorName, { RegProcedure oprcode = ((Form_pg_operator) GETSTRUCT(tup))->oprcode; - operatorObjectId = tup->t_data->t_oid; + operatorObjectId = HeapTupleGetOid(tup); *defined = RegProcedureIsValid(oprcode); ReleaseSysCache(tup); } @@ -918,7 +918,7 @@ makeOperatorDependencies(HeapTuple tuple, Oid pg_operator_relid) referenced; myself.classId = pg_operator_relid; - myself.objectId = tuple->t_data->t_oid; + myself.objectId = HeapTupleGetOid(tuple); myself.objectSubId = 0; /* In case we are updating a shell, delete any existing entries */ diff --git a/src/backend/catalog/pg_proc.c b/src/backend/catalog/pg_proc.c index d3cd9efb47..4b59d2087d 100644 --- a/src/backend/catalog/pg_proc.c +++ b/src/backend/catalog/pg_proc.c @@ -239,6 +239,7 @@ ProcedureCreate(const char *procedureName, /* start out with empty permissions */ nulls[Anum_pg_proc_proacl-1] = 'n'; + AssertTupleDescHasOid(tupDesc); tup = heap_formtuple(tupDesc, values, nulls); simple_heap_insert(rel, tup); is_update = false; @@ -254,7 +255,8 @@ ProcedureCreate(const char *procedureName, CatalogCloseIndices(Num_pg_proc_indices, idescs); } - retval = tup->t_data->t_oid; + AssertTupleDescHasOid(tupDesc); + retval = HeapTupleGetOid(tup); /* * Create dependencies for the new function. If we are updating an diff --git a/src/backend/catalog/pg_type.c b/src/backend/catalog/pg_type.c index 48736a05c7..37288b1327 100644 --- a/src/backend/catalog/pg_type.c +++ b/src/backend/catalog/pg_type.c @@ -274,7 +274,8 @@ TypeCreate(const char *typeName, simple_heap_update(pg_type_desc, &tup->t_self, tup); - typeObjectId = tup->t_data->t_oid; + AssertTupleDescHasOid(pg_type_desc->rd_att); + typeObjectId = HeapTupleGetOid(tup); } else { @@ -285,7 +286,8 @@ TypeCreate(const char *typeName, nulls); /* preassign tuple Oid, if one was given */ - tup->t_data->t_oid = assignedTypeOid; + AssertTupleDescHasOid(tupDesc); + HeapTupleSetOid(tup, assignedTypeOid); typeObjectId = simple_heap_insert(pg_type_desc, tup); } diff --git a/src/backend/commands/comment.c b/src/backend/commands/comment.c index 33c763d039..fe75305210 100644 --- a/src/backend/commands/comment.c +++ b/src/backend/commands/comment.c @@ -435,7 +435,8 @@ CommentDatabase(List *qualname, char *comment) if (!HeapTupleIsValid(dbtuple)) elog(ERROR, "database \"%s\" does not exist", database); - oid = dbtuple->t_data->t_oid; + AssertTupleDescHasOid(pg_database->rd_att); + oid = HeapTupleGetOid(dbtuple); /* Allow if the user matches the database dba or is a superuser */ @@ -481,7 +482,8 @@ CommentNamespace(List *qualname, char *comment) elog(ERROR, "CommentSchema: Schema \"%s\" could not be found", namespace); - oid = tp->t_data->t_oid; + /* no TupleDesc here to Assert(...->tdhasoid); */ + oid = HeapTupleGetOid(tp); /* Check object security */ if (!pg_namespace_ownercheck(oid, GetUserId())) @@ -552,7 +554,8 @@ CommentRule(List *qualname, char *comment) if (HeapTupleIsValid(tuple)) { reloid = ((Form_pg_rewrite) GETSTRUCT(tuple))->ev_class; - ruleoid = tuple->t_data->t_oid; + AssertTupleDescHasOid(RewriteRelation->rd_att); + ruleoid = HeapTupleGetOid(tuple); } else { @@ -592,7 +595,8 @@ CommentRule(List *qualname, char *comment) if (!HeapTupleIsValid(tuple)) elog(ERROR, "rule \"%s\" does not exist", rulename); Assert(reloid == ((Form_pg_rewrite) GETSTRUCT(tuple))->ev_class); - ruleoid = tuple->t_data->t_oid; + AssertTupleDescHasOid(relation->rd_att); + ruleoid = HeapTupleGetOid(tuple); ReleaseSysCache(tuple); } @@ -805,7 +809,8 @@ CommentTrigger(List *qualname, char *comment) elog(ERROR, "trigger \"%s\" for relation \"%s\" does not exist", trigname, RelationGetRelationName(relation)); - oid = triggertuple->t_data->t_oid; + AssertTupleDescHasOid(pg_trigger->rd_att); + oid = HeapTupleGetOid(triggertuple); systable_endscan(scan); @@ -880,7 +885,7 @@ CommentConstraint(List *qualname, char *comment) if (OidIsValid(conOid)) elog(ERROR, "Relation \"%s\" has multiple constraints named \"%s\"", RelationGetRelationName(relation), conName); - conOid = tuple->t_data->t_oid; + conOid = HeapTupleGetOid(tuple); } } diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c index 521c27440f..8b98ae31d6 100644 --- a/src/backend/commands/copy.c +++ b/src/backend/commands/copy.c @@ -614,9 +614,13 @@ CopyTo(Relation rel, List *attlist, bool binary, bool oids, /* Send OID if wanted --- note fld_count doesn't include it */ if (oids) { + Oid oid; + + AssertTupleDescHasOid(tupDesc); + oid = HeapTupleGetOid(tuple); fld_size = sizeof(Oid); CopySendData(&fld_size, sizeof(int16), fp); - CopySendData(&tuple->t_data->t_oid, sizeof(Oid), fp); + CopySendData(&oid, sizeof(Oid), fp); } } else @@ -624,8 +628,9 @@ CopyTo(Relation rel, List *attlist, bool binary, bool oids, /* Text format has no per-tuple header, but send OID if wanted */ if (oids) { + AssertTupleDescHasOid(tupDesc); string = DatumGetCString(DirectFunctionCall1(oidout, - ObjectIdGetDatum(tuple->t_data->t_oid))); + ObjectIdGetDatum(HeapTupleGetOid(tuple)))); CopySendString(string, fp); pfree(string); need_delim = true; @@ -1069,7 +1074,7 @@ CopyFrom(Relation rel, List *attlist, bool binary, bool oids, tuple = heap_formtuple(tupDesc, values, nulls); if (oids && file_has_oids) - tuple->t_data->t_oid = loaded_oid; + HeapTupleSetOid(tuple, loaded_oid); skip_tuple = false; diff --git a/src/backend/commands/dbcommands.c b/src/backend/commands/dbcommands.c index e56816883c..fe1509a8a5 100644 --- a/src/backend/commands/dbcommands.c +++ b/src/backend/commands/dbcommands.c @@ -341,7 +341,8 @@ createdb(const CreatedbStmt *stmt) tuple = heap_formtuple(pg_database_dsc, new_record, new_record_nulls); - tuple->t_data->t_oid = dboid; /* override heap_insert's OID + AssertTupleDescHasOid(pg_database_dsc); + HeapTupleSetOid(tuple, dboid); /* override heap_insert's OID * selection */ simple_heap_insert(pg_database_rel, tuple); @@ -616,7 +617,10 @@ get_db_info(const char *name, Oid *dbIdP, int4 *ownerIdP, /* oid of the database */ if (dbIdP) - *dbIdP = tuple->t_data->t_oid; + { + AssertTupleDescHasOid(relation->rd_att); + *dbIdP = HeapTupleGetOid(tuple); + } /* sysid of the owner */ if (ownerIdP) *ownerIdP = dbform->datdba; diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c index e5765b48a3..866b6b3434 100644 --- a/src/backend/commands/explain.c +++ b/src/backend/commands/explain.c @@ -855,7 +855,7 @@ begin_text_output(CommandDest dest, char *title) tstate = (TextOutputState *) palloc(sizeof(TextOutputState)); /* need a tuple descriptor representing a single TEXT column */ - tupdesc = CreateTemplateTupleDesc(1); + tupdesc = CreateTemplateTupleDesc(1, WITHOUTOID); TupleDescInitEntry(tupdesc, (AttrNumber) 1, title, TEXTOID, -1, 0, false); diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c index bc0d602785..57657089a2 100644 --- a/src/backend/commands/functioncmds.c +++ b/src/backend/commands/functioncmds.c @@ -425,7 +425,7 @@ CreateFunction(CreateFunctionStmt *stmt) if (!HeapTupleIsValid(languageTuple)) elog(ERROR, "language \"%s\" does not exist", languageName); - languageOid = languageTuple->t_data->t_oid; + languageOid = HeapTupleGetOid(languageTuple); languageStruct = (Form_pg_language) GETSTRUCT(languageTuple); if (languageStruct->lanpltrusted) diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c index 2339be3998..4201ff035f 100644 --- a/src/backend/commands/indexcmds.c +++ b/src/backend/commands/indexcmds.c @@ -141,7 +141,7 @@ DefineIndex(RangeVar *heapRelation, if (!HeapTupleIsValid(tuple)) elog(ERROR, "DefineIndex: access method \"%s\" not found", accessMethodName); - accessMethodId = tuple->t_data->t_oid; + accessMethodId = HeapTupleGetOid(tuple); accessMethodForm = (Form_pg_am) GETSTRUCT(tuple); if (unique && !accessMethodForm->amcanunique) @@ -496,7 +496,7 @@ GetAttrOpClass(IndexElem *attribute, Oid attrType, * Verify that the index operator class accepts this * datatype. Note we will accept binary compatibility. */ - opClassId = tuple->t_data->t_oid; + opClassId = HeapTupleGetOid(tuple); opInputType = ((Form_pg_opclass) GETSTRUCT(tuple))->opcintype; if (!IsBinaryCompatible(attrType, opInputType)) @@ -761,7 +761,7 @@ ReindexDatabase(const char *dbname, bool force, bool all) relids = repalloc(relids, sizeof(Oid) * relalc); } MemoryContextSwitchTo(old); - relids[relcnt] = tuple->t_data->t_oid; + relids[relcnt] = HeapTupleGetOid(tuple); relcnt++; } } diff --git a/src/backend/commands/proclang.c b/src/backend/commands/proclang.c index c8e57f0169..cfe94992b7 100644 --- a/src/backend/commands/proclang.c +++ b/src/backend/commands/proclang.c @@ -134,7 +134,7 @@ CreateProceduralLanguage(CreatePLangStmt *stmt) * Create dependencies for language */ myself.classId = RelationGetRelid(rel); - myself.objectId = tup->t_data->t_oid; + myself.objectId = HeapTupleGetOid(tup); myself.objectSubId = 0; /* dependency on the PL handler function */ @@ -191,7 +191,7 @@ DropProceduralLanguage(DropPLangStmt *stmt) languageName); object.classId = get_system_catalog_relid(LanguageRelationName); - object.objectId = langTup->t_data->t_oid; + object.objectId = HeapTupleGetOid(langTup); object.objectSubId = 0; ReleaseSysCache(langTup); diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index 19f3c4e2e7..5250cc9c21 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -149,6 +149,7 @@ DefineRelation(CreateStmt *stmt, char relkind) * have to copy inherited constraints here.) */ descriptor = BuildDescForRelation(schema); + descriptor->tdhasoid = BoolToHasOid(stmt->hasoids || parentHasOids); if (old_constraints != NIL) { @@ -1658,6 +1659,7 @@ AlterTableAddColumn(Oid myrelid, tform = (Form_pg_type) GETSTRUCT(typeTuple); attributeTuple = heap_addheader(Natts_pg_attribute, + false, ATTRIBUTE_TUPLE_SIZE, (void *) &attributeD); @@ -1665,7 +1667,7 @@ AlterTableAddColumn(Oid myrelid, attribute->attrelid = myrelid; namestrcpy(&(attribute->attname), colDef->colname); - attribute->atttypid = typeTuple->t_data->t_oid; + attribute->atttypid = HeapTupleGetOid(typeTuple); attribute->attstattarget = DEFAULT_ATTSTATTARGET; attribute->attlen = tform->typlen; attribute->attcacheoff = -1; @@ -1682,6 +1684,7 @@ AlterTableAddColumn(Oid myrelid, ReleaseSysCache(typeTuple); + AssertTupleDescHasNoOid(attrdesc->rd_att); simple_heap_insert(attrdesc, attributeTuple); /* Update indexes on pg_attribute */ @@ -1702,6 +1705,7 @@ AlterTableAddColumn(Oid myrelid, newreltup = heap_copytuple(reltup); ((Form_pg_class) GETSTRUCT(newreltup))->relnatts = maxatts; + AssertTupleDescHasOid(pgclass->rd_att); simple_heap_update(pgclass, &newreltup->t_self, newreltup); /* keep catalog indices current */ @@ -3299,7 +3303,7 @@ AlterTableCreateToastTable(Oid relOid, bool silent) sprintf(toast_idxname, "pg_toast_%u_index", relOid); /* this is pretty painful... need a tuple descriptor */ - tupdesc = CreateTemplateTupleDesc(3); + tupdesc = CreateTemplateTupleDesc(3, WITHOUTOID); TupleDescInitEntry(tupdesc, (AttrNumber) 1, "chunk_id", OIDOID, diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c index 4dbab70127..58047cac5e 100644 --- a/src/backend/commands/trigger.c +++ b/src/backend/commands/trigger.c @@ -400,8 +400,9 @@ DropTrigger(Oid relid, const char *trigname, DropBehavior behavior) if (!pg_class_ownercheck(relid, GetUserId())) aclcheck_error(ACLCHECK_NOT_OWNER, get_rel_name(relid)); + AssertTupleDescHasOid(tgrel->rd_att); object.classId = RelationGetRelid(tgrel); - object.objectId = tup->t_data->t_oid; + object.objectId = HeapTupleGetOid(tup); object.objectSubId = 0; systable_endscan(tgscan); @@ -671,7 +672,8 @@ RelationBuildTriggers(Relation relation) RelationGetRelationName(relation)); build = &(triggers[found]); - build->tgoid = htup->t_data->t_oid; + AssertTupleDescHasOid(tgrel->rd_att); + build->tgoid = HeapTupleGetOid(htup); build->tgname = MemoryContextStrdup(CacheMemoryContext, DatumGetCString(DirectFunctionCall1(nameout, NameGetDatum(&pg_trigger->tgname)))); @@ -1932,7 +1934,8 @@ DeferredTriggerSetState(ConstraintsSetStmt *stmt) elog(ERROR, "Constraint '%s' is not deferrable", cname); - constr_oid = htup->t_data->t_oid; + AssertTupleDescHasOid(tgrel->rd_att); + constr_oid = HeapTupleGetOid(htup); loid = lappendi(loid, constr_oid); found = true; } diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c index 5553b72fbc..b137ce9d87 100644 --- a/src/backend/commands/typecmds.c +++ b/src/backend/commands/typecmds.c @@ -396,7 +396,7 @@ DefineDomain(CreateDomainStmt *stmt) typeTup = typenameType(stmt->typename); baseType = (Form_pg_type) GETSTRUCT(typeTup); - basetypeoid = typeTup->t_data->t_oid; + basetypeoid = HeapTupleGetOid(typeTup); /* * What we really don't want is domains of domains. This could cause all sorts diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c index df8d2466c0..f0e9beb182 100644 --- a/src/backend/commands/vacuum.c +++ b/src/backend/commands/vacuum.c @@ -392,7 +392,8 @@ getrels(const RangeVar *vacrel, const char *stmttype) { /* Make a relation list entry for this guy */ oldcontext = MemoryContextSwitchTo(vac_context); - vrl = lappendi(vrl, tuple->t_data->t_oid); + AssertTupleDescHasOid(pgclass->rd_att); + vrl = lappendi(vrl, HeapTupleGetOid(tuple)); MemoryContextSwitchTo(oldcontext); } @@ -1172,8 +1173,8 @@ scan_heap(VRelStats *vacrelstats, Relation onerel, /* * Other checks... */ - if (!OidIsValid(tuple.t_data->t_oid) && - onerel->rd_rel->relhasoids) + if (onerel->rd_rel->relhasoids && + !OidIsValid(HeapTupleGetOid(&tuple))) elog(WARNING, "Rel %s: TID %u/%u: OID IS INVALID. TUPGONE %d.", relname, blkno, offnum, (int) tupgone); diff --git a/src/backend/commands/vacuumlazy.c b/src/backend/commands/vacuumlazy.c index c6fb6af81d..8eeacdde6f 100644 --- a/src/backend/commands/vacuumlazy.c +++ b/src/backend/commands/vacuumlazy.c @@ -368,8 +368,8 @@ lazy_scan_heap(Relation onerel, LVRelStats *vacrelstats, /* * Other checks... */ - if (!OidIsValid(tuple.t_data->t_oid) && - onerel->rd_rel->relhasoids) + if (onerel->rd_rel->relhasoids && + !OidIsValid(HeapTupleGetOid(&tuple))) elog(WARNING, "Rel %s: TID %u/%u: OID IS INVALID. TUPGONE %d.", relname, blkno, offnum, (int) tupgone); diff --git a/src/backend/executor/execJunk.c b/src/backend/executor/execJunk.c index bed703c0cd..9b8e2f3bed 100644 --- a/src/backend/executor/execJunk.c +++ b/src/backend/executor/execJunk.c @@ -170,7 +170,7 @@ ExecInitJunkFilter(List *targetList, TupleDesc tupType, * Now calculate the tuple type for the cleaned tuple (we were already * given the type for the original targetlist). */ - cleanTupType = ExecTypeFromTL(cleanTargetList); + cleanTupType = ExecTypeFromTL(cleanTargetList, tupType->tdhasoid); len = ExecTargetListLength(targetList); cleanLength = ExecTargetListLength(cleanTargetList); @@ -383,8 +383,8 @@ ExecRemoveJunk(JunkFilter *junkfilter, TupleTableSlot *slot) * information for the new "clean" tuple. * * Note: we use memory on the stack to optimize things when we are - * dealing with a small number of tuples. for large tuples we just use - * palloc. + * dealing with a small number of attributes. for large tuples we + * just use palloc. */ if (cleanLength > 64) { diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c index 6460efcf72..7e575f81b7 100644 --- a/src/backend/executor/execMain.c +++ b/src/backend/executor/execMain.c @@ -717,6 +717,10 @@ InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate) } /* + * new "INTO" table is created WITH OIDS + */ + tupType->tdhasoid = WITHOID; + /* * have to copy tupType to get rid of constraints */ tupdesc = CreateTupleDescCopy(tupType); diff --git a/src/backend/executor/execQual.c b/src/backend/executor/execQual.c index 6efa7b6ecc..fa23489441 100644 --- a/src/backend/executor/execQual.c +++ b/src/backend/executor/execQual.c @@ -1770,7 +1770,10 @@ ExecTargetList(List *targetlist, * natts = 0 to deal with it. */ if (targettype == NULL) + { targettype = &NullTupleDesc; + targettype->tdhasoid = WITHOUTOID; + } /* * allocate an array of char's to hold the "null" information only if diff --git a/src/backend/executor/execTuples.c b/src/backend/executor/execTuples.c index 2d0c91681b..eaf1b724ea 100644 --- a/src/backend/executor/execTuples.c +++ b/src/backend/executor/execTuples.c @@ -540,6 +540,7 @@ ExecInitNullTupleSlot(EState *estate, TupleDesc tupType) ExecSetSlotDescriptor(slot, tupType, false); + NullTupleDesc.tdhasoid = WITHOUTOID; nullTuple = heap_formtuple(&NullTupleDesc, values, nulls); return ExecStoreTuple(nullTuple, slot, InvalidBuffer, true); @@ -557,7 +558,7 @@ ExecInitNullTupleSlot(EState *estate, TupleDesc tupType) * ---------------------------------------------------------------- */ TupleDesc -ExecTypeFromTL(List *targetList) +ExecTypeFromTL(List *targetList, hasoid_t withoid) { List *tlitem; TupleDesc typeInfo; @@ -576,7 +577,7 @@ ExecTypeFromTL(List *targetList) /* * allocate a new typeInfo */ - typeInfo = CreateTemplateTupleDesc(len); + typeInfo = CreateTemplateTupleDesc(len, withoid); /* * scan list, generate type info for each entry diff --git a/src/backend/executor/execUtils.c b/src/backend/executor/execUtils.c index e5197f7580..92440ab79b 100644 --- a/src/backend/executor/execUtils.c +++ b/src/backend/executor/execUtils.c @@ -290,9 +290,23 @@ ExecAssignResultTypeFromOuterPlan(Plan *node, CommonState *commonstate) void ExecAssignResultTypeFromTL(Plan *node, CommonState *commonstate) { + ResultRelInfo *ri; + Relation rel; + hasoid_t withoid; TupleDesc tupDesc; - tupDesc = ExecTypeFromTL(node->targetlist); + ri = node->state->es_result_relation_info; + if (ri != NULL) + rel = ri->ri_RelationDesc; + else + rel = node->state->es_into_relation_descriptor; + + if (rel != NULL) + withoid = BoolToHasOid(rel->rd_rel->relhasoids); + else + withoid = WITHOUTOID; + + tupDesc = ExecTypeFromTL(node->targetlist, withoid); ExecAssignResultType(commonstate, tupDesc, true); } diff --git a/src/backend/executor/nodeFunctionscan.c b/src/backend/executor/nodeFunctionscan.c index 98a24aeaef..21dd52c711 100644 --- a/src/backend/executor/nodeFunctionscan.c +++ b/src/backend/executor/nodeFunctionscan.c @@ -234,7 +234,7 @@ ExecInitFunctionScan(FunctionScan *node, EState *estate, Plan *parent) */ char *attname = strVal(lfirst(rte->eref->colnames)); - tupdesc = CreateTemplateTupleDesc(1); + tupdesc = CreateTemplateTupleDesc(1, WITHOUTOID); TupleDescInitEntry(tupdesc, (AttrNumber) 1, attname, diff --git a/src/backend/executor/spi.c b/src/backend/executor/spi.c index f2b4fb06df..9f0ae3716b 100644 --- a/src/backend/executor/spi.c +++ b/src/backend/executor/spi.c @@ -435,11 +435,15 @@ SPI_modifytuple(Relation rel, HeapTuple tuple, int natts, int *attnum, { mtuple = heap_formtuple(rel->rd_att, v, n); infomask = mtuple->t_data->t_infomask; - memmove(&(mtuple->t_data->t_oid), &(tuple->t_data->t_oid), - ((char *) &(tuple->t_data->t_hoff) - - (char *) &(tuple->t_data->t_oid))); + /* + * copy t_xmin, t_cid, t_xmax, t_ctid, t_natts, t_infomask + */ + memmove((char *)mtuple->t_data, (char *)tuple->t_data, + offsetof(HeapTupleHeaderData, t_hoff)); mtuple->t_data->t_infomask = infomask; mtuple->t_data->t_natts = numberOfAttributes; + if (rel->rd_rel->relhasoids) + HeapTupleSetOid(mtuple, HeapTupleGetOid(tuple)); } else { diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c index 42012fdcbe..709d0d3d31 100644 --- a/src/backend/optimizer/util/clauses.c +++ b/src/backend/optimizer/util/clauses.c @@ -1071,7 +1071,7 @@ CommuteClause(Expr *clause) commuTup = (Form_pg_operator) GETSTRUCT(optup); - commu = makeOper(optup->t_data->t_oid, + commu = makeOper(HeapTupleGetOid(optup), commuTup->oprcode, commuTup->oprresult, ((Oper *) clause->oper)->opretset); diff --git a/src/backend/parser/parse_oper.c b/src/backend/parser/parse_oper.c index c1fc9ec83d..302c5c14b0 100644 --- a/src/backend/parser/parse_oper.c +++ b/src/backend/parser/parse_oper.c @@ -150,7 +150,7 @@ any_ordering_op(Oid argtype) Oid oprid(Operator op) { - return op->t_data->t_oid; + return HeapTupleGetOid(op); } /* given operator tuple, return the underlying function's OID */ diff --git a/src/backend/parser/parse_type.c b/src/backend/parser/parse_type.c index 6792f0234b..583151c2e3 100644 --- a/src/backend/parser/parse_type.c +++ b/src/backend/parser/parse_type.c @@ -283,7 +283,7 @@ typeTypeId(Type tp) { if (tp == NULL) elog(ERROR, "typeTypeId() called with NULL type struct"); - return tp->t_data->t_oid; + return HeapTupleGetOid(tp); } /* given type (as type struct), return the length of type */ diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c index e40a1f88c0..b021782466 100644 --- a/src/backend/postmaster/pgstat.c +++ b/src/backend/postmaster/pgstat.c @@ -628,7 +628,8 @@ pgstat_vacuum_tabstat(void) dbidlist = (Oid *) repalloc((char *) dbidlist, sizeof(Oid) * dbidalloc); } - dbidlist[dbidused++] = dbtup->t_data->t_oid; + AssertTupleDescHasOid(dbrel->rd_att); + dbidlist[dbidused++] = HeapTupleGetOid(dbtup); } heap_endscan(dbscan); heap_close(dbrel, AccessShareLock); diff --git a/src/backend/rewrite/rewriteRemove.c b/src/backend/rewrite/rewriteRemove.c index 5d01c9fdfc..0e2b2e8d55 100644 --- a/src/backend/rewrite/rewriteRemove.c +++ b/src/backend/rewrite/rewriteRemove.c @@ -69,7 +69,7 @@ RemoveRewriteRule(Oid owningRel, const char *ruleName, DropBehavior behavior) * Do the deletion */ object.classId = get_system_catalog_relid(RewriteRelationName); - object.objectId = tuple->t_data->t_oid; + object.objectId = HeapTupleGetOid(tuple); object.objectSubId = 0; ReleaseSysCache(tuple); diff --git a/src/backend/utils/adt/regproc.c b/src/backend/utils/adt/regproc.c index c6f0f2387c..97a5c7a755 100644 --- a/src/backend/utils/adt/regproc.c +++ b/src/backend/utils/adt/regproc.c @@ -110,7 +110,8 @@ regprocin(PG_FUNCTION_ARGS) while (HeapTupleIsValid(tuple = systable_getnext(sysscan))) { - result = (RegProcedure) tuple->t_data->t_oid; + AssertTupleDescHasOid(hdesc->rd_att); + result = (RegProcedure) HeapTupleGetOid(tuple); if (++matches > 1) break; } @@ -414,7 +415,8 @@ regoperin(PG_FUNCTION_ARGS) while (HeapTupleIsValid(tuple = systable_getnext(sysscan))) { - result = tuple->t_data->t_oid; + AssertTupleDescHasOid(hdesc->rd_att); + result = HeapTupleGetOid(tuple); if (++matches > 1) break; } @@ -731,7 +733,10 @@ regclassin(PG_FUNCTION_ARGS) SnapshotNow, 1, skey); if (HeapTupleIsValid(tuple = systable_getnext(sysscan))) - result = tuple->t_data->t_oid; + { + AssertTupleDescHasOid(hdesc->rd_att); + result = HeapTupleGetOid(tuple); + } else elog(ERROR, "No class with name %s", class_name_or_oid); @@ -884,7 +889,10 @@ regtypein(PG_FUNCTION_ARGS) SnapshotNow, 1, skey); if (HeapTupleIsValid(tuple = systable_getnext(sysscan))) - result = tuple->t_data->t_oid; + { + AssertTupleDescHasOid(hdesc->rd_att); + result = HeapTupleGetOid(tuple); + } else elog(ERROR, "No type with name %s", typ_name_or_oid); diff --git a/src/backend/utils/adt/sets.c b/src/backend/utils/adt/sets.c index 8bb97fa632..6358db6dca 100644 --- a/src/backend/utils/adt/sets.c +++ b/src/backend/utils/adt/sets.c @@ -119,7 +119,8 @@ SetDefine(char *querystr, Oid elemType) simple_heap_update(procrel, &newtup->t_self, newtup); - setoid = newtup->t_data->t_oid; + AssertTupleDescHasOid(procrel->rd_att); + setoid = HeapTupleGetOid(newtup); if (RelationGetForm(procrel)->relhasindex) { diff --git a/src/backend/utils/cache/catcache.c b/src/backend/utils/cache/catcache.c index 04a294cae7..6969fc66f2 100644 --- a/src/backend/utils/cache/catcache.c +++ b/src/backend/utils/cache/catcache.c @@ -218,7 +218,7 @@ CatalogCacheComputeTupleHashValue(CatCache *cache, HeapTuple tuple) case 4: cur_skey[3].sk_argument = (cache->cc_key[3] == ObjectIdAttributeNumber) - ? ObjectIdGetDatum(tuple->t_data->t_oid) + ? ObjectIdGetDatum(HeapTupleGetOid(tuple)) : fastgetattr(tuple, cache->cc_key[3], cache->cc_tupdesc, @@ -228,7 +228,7 @@ CatalogCacheComputeTupleHashValue(CatCache *cache, HeapTuple tuple) case 3: cur_skey[2].sk_argument = (cache->cc_key[2] == ObjectIdAttributeNumber) - ? ObjectIdGetDatum(tuple->t_data->t_oid) + ? ObjectIdGetDatum(HeapTupleGetOid(tuple)) : fastgetattr(tuple, cache->cc_key[2], cache->cc_tupdesc, @@ -238,7 +238,7 @@ CatalogCacheComputeTupleHashValue(CatCache *cache, HeapTuple tuple) case 2: cur_skey[1].sk_argument = (cache->cc_key[1] == ObjectIdAttributeNumber) - ? ObjectIdGetDatum(tuple->t_data->t_oid) + ? ObjectIdGetDatum(HeapTupleGetOid(tuple)) : fastgetattr(tuple, cache->cc_key[1], cache->cc_tupdesc, @@ -248,7 +248,7 @@ CatalogCacheComputeTupleHashValue(CatCache *cache, HeapTuple tuple) case 1: cur_skey[0].sk_argument = (cache->cc_key[0] == ObjectIdAttributeNumber) - ? ObjectIdGetDatum(tuple->t_data->t_oid) + ? ObjectIdGetDatum(HeapTupleGetOid(tuple)) : fastgetattr(tuple, cache->cc_key[0], cache->cc_tupdesc, @@ -572,7 +572,7 @@ AtEOXact_CatCache(bool isCommit) if (isCommit) elog(WARNING, "Cache reference leak: cache %s (%d), tuple %u has count %d", ct->my_cache->cc_relname, ct->my_cache->id, - ct->tuple.t_data->t_oid, + HeapTupleGetOid(&ct->tuple), ct->refcount); ct->refcount = 0; } @@ -717,7 +717,7 @@ CatalogCacheFlushRelation(Oid relId) continue; if (cache->cc_reloidattr == ObjectIdAttributeNumber) - tupRelid = ct->tuple.t_data->t_oid; + tupRelid = HeapTupleGetOid(&ct->tuple); else { bool isNull; @@ -907,6 +907,7 @@ CatalogCacheInitializeCache(CatCache *cache) * copy the relcache's tuple descriptor to permanent cache storage */ tupdesc = CreateTupleDescCopyConstr(RelationGetDescr(relation)); + AssertTupleDescHasOidIsValid(tupdesc); /* * get the relation's OID and relisshared flag, too @@ -1685,7 +1686,11 @@ build_dummy_tuple(CatCache *cache, int nkeys, ScanKey skeys) } ntp = heap_formtuple(tupDesc, values, nulls); - ntp->t_data->t_oid = tupOid; + if (tupOid != InvalidOid) + { + AssertTupleDescHasOid(tupDesc); + HeapTupleSetOid(ntp, tupOid); + } pfree(values); pfree(nulls); diff --git a/src/backend/utils/cache/inval.c b/src/backend/utils/cache/inval.c index 0347ff6917..eb621674bc 100644 --- a/src/backend/utils/cache/inval.c +++ b/src/backend/utils/cache/inval.c @@ -525,7 +525,10 @@ PrepareForTupleInvalidation(Relation relation, HeapTuple tuple, tupleRelId = RelationGetRelid(relation); if (tupleRelId == RelOid_pg_class) - relationId = tuple->t_data->t_oid; + { + AssertTupleDescHasOid(relation->rd_att); + relationId = HeapTupleGetOid(tuple); + } else if (tupleRelId == RelOid_pg_attribute) relationId = ((Form_pg_attribute) GETSTRUCT(tuple))->attrelid; else diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index db49e2350f..9bbc0b60de 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -440,7 +440,7 @@ AllocateRelationDesc(Relation relation, Form_pg_class relp) relation->rd_rel = relationForm; /* and allocate attribute tuple form storage */ - relation->rd_att = CreateTemplateTupleDesc(relationForm->relnatts); + relation->rd_att = CreateTemplateTupleDesc(relationForm->relnatts, BoolToHasOid(relationForm->relhasoids)); MemoryContextSwitchTo(oldcxt); @@ -701,7 +701,8 @@ RelationBuildRuleLock(Relation relation) rule = (RewriteRule *) MemoryContextAlloc(rulescxt, sizeof(RewriteRule)); - rule->ruleId = rewrite_tuple->t_data->t_oid; + AssertTupleDescHasOid(rewrite_tupdesc); + rule->ruleId = HeapTupleGetOid(rewrite_tuple); rule->event = rewrite_form->ev_type - '0'; rule->attrno = rewrite_form->ev_attr; @@ -839,7 +840,7 @@ RelationBuildDesc(RelationBuildDescInfo buildinfo, /* * get information from the pg_class_tuple */ - relid = pg_class_tuple->t_data->t_oid; + relid = HeapTupleGetOid(pg_class_tuple); relp = (Form_pg_class) GETSTRUCT(pg_class_tuple); /* @@ -872,6 +873,7 @@ RelationBuildDesc(RelationBuildDescInfo buildinfo, * initialize the tuple descriptor (relation->rd_att). */ RelationBuildTupleDesc(buildinfo, relation); + RelationGetDescr(relation)->tdhasoid = BoolToHasOid(RelationGetForm(relation)->relhasoids); /* * Fetch rules and triggers that affect this relation @@ -1395,7 +1397,7 @@ formrdesc(const char *relationName, * right because it will never be replaced. The input values must be * correctly defined by macros in src/include/catalog/ headers. */ - relation->rd_att = CreateTemplateTupleDesc(natts); + relation->rd_att = CreateTemplateTupleDesc(natts, BoolToHasOid(relation->rd_rel->relhasoids)); /* * initialize tuple desc info @@ -2067,7 +2069,7 @@ RelationBuildLocalRelation(const char *relname, rel->rd_rel->relnamespace = relnamespace; rel->rd_rel->relkind = RELKIND_UNCATALOGED; - rel->rd_rel->relhasoids = true; + rel->rd_rel->relhasoids = (rel->rd_att->tdhasoid == WITHOID); rel->rd_rel->relnatts = natts; rel->rd_rel->reltype = InvalidOid; @@ -2313,6 +2315,7 @@ RelationCacheInitializePhase2(void) */ Assert(relation->rd_rel != NULL); memcpy((char *) relation->rd_rel, (char *) relp, CLASS_TUPLE_SIZE); + relation->rd_att->tdhasoid = BoolToHasOid(relp->relhasoids); ReleaseSysCache(htup); } @@ -2774,7 +2777,7 @@ load_relcache_init_file(void) rel->rd_rel = relform; /* initialize attribute tuple forms */ - rel->rd_att = CreateTemplateTupleDesc(relform->relnatts); + rel->rd_att = CreateTemplateTupleDesc(relform->relnatts, BoolToHasOid(relform->relhasoids)); /* next read all the attribute tuple form data entries */ for (i = 0; i < relform->relnatts; i++) diff --git a/src/backend/utils/cache/syscache.c b/src/backend/utils/cache/syscache.c index ab04d8993d..a222f160bf 100644 --- a/src/backend/utils/cache/syscache.c +++ b/src/backend/utils/cache/syscache.c @@ -597,7 +597,7 @@ GetSysCacheOid(int cacheId, tuple = SearchSysCache(cacheId, key1, key2, key3, key4); if (!HeapTupleIsValid(tuple)) return InvalidOid; - result = tuple->t_data->t_oid; + result = HeapTupleGetOid(tuple); ReleaseSysCache(tuple); return result; } diff --git a/src/backend/utils/init/postinit.c b/src/backend/utils/init/postinit.c index 996019eb57..2069ba356e 100644 --- a/src/backend/utils/init/postinit.c +++ b/src/backend/utils/init/postinit.c @@ -98,8 +98,9 @@ ReverifyMyDatabase(const char *name) pgdbscan = heap_beginscan(pgdbrel, SnapshotNow, 1, &key); tup = heap_getnext(pgdbscan, ForwardScanDirection); + AssertTupleDescHasOid(pgdbrel->rd_att); if (!HeapTupleIsValid(tup) || - tup->t_data->t_oid != MyDatabaseId) + HeapTupleGetOid(tup) != MyDatabaseId) { /* OOPS */ heap_close(pgdbrel, AccessShareLock); diff --git a/src/backend/utils/misc/database.c b/src/backend/utils/misc/database.c index 107031b8df..99111e203d 100644 --- a/src/backend/utils/misc/database.c +++ b/src/backend/utils/misc/database.c @@ -220,7 +220,7 @@ GetRawDatabaseInfo(const char *name, Oid *db_id, char *path) if (strcmp(name, NameStr(tup_db->datname)) == 0) { /* Found it; extract the OID and the database path. */ - *db_id = tup.t_data->t_oid; + *db_id = HeapTupleGetOid(&tup); pathlen = VARSIZE(&(tup_db->datpath)) - VARHDRSZ; if (pathlen < 0) pathlen = 0; /* pure paranoia */ diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h index 6ac5a778c2..449b632f55 100644 --- a/src/include/access/heapam.h +++ b/src/include/access/heapam.h @@ -200,6 +200,6 @@ extern HeapTuple heap_formtuple(TupleDesc tupleDescriptor, extern HeapTuple heap_modifytuple(HeapTuple tuple, Relation relation, Datum *replValue, char *replNull, char *repl); extern void heap_freetuple(HeapTuple tuple); -extern HeapTuple heap_addheader(int natts, Size structlen, void *structure); +extern HeapTuple heap_addheader(int natts, bool withoid, Size structlen, void *structure); #endif /* HEAPAM_H */ diff --git a/src/include/access/htup.h b/src/include/access/htup.h index ad0ccb36a2..72c9815057 100644 --- a/src/include/access/htup.h +++ b/src/include/access/htup.h @@ -70,8 +70,6 @@ */ typedef struct HeapTupleHeaderData { - Oid t_oid; /* OID of this tuple -- 4 bytes */ - TransactionId t_xmin; /* Xmin -- 4 bytes each */ TransactionId t_cid; /* Cmin, Cmax, Xvac */ TransactionId t_xmax; /* Xmax, Cmax */ @@ -84,7 +82,7 @@ typedef struct HeapTupleHeaderData uint8 t_hoff; /* sizeof header incl. bitmap, padding */ - /* ^ - 27 bytes - ^ */ + /* ^ - 23 bytes - ^ */ bits8 t_bits[1]; /* bitmap of NULLs -- VARIABLE LENGTH */ @@ -123,10 +121,42 @@ typedef HeapTupleHeaderData *HeapTupleHeader; #define HEAP_XACT_MASK 0xFFF0 /* visibility-related bits */ +/* paranoid checking */ + +#ifdef DEBUG_TUPLE_ACCESS + +#define HeapTupleHeaderExpectedLen(tup, withoid) \ + MAXALIGN(offsetof(HeapTupleHeaderData, t_bits) + \ + (((tup)->t_infomask & HEAP_HASNULL) \ + ? BITMAPLEN((tup)->t_natts) : 0) + \ + ((withoid) ? sizeof(Oid) : 0) \ + ) + +#define AssertHeapTupleHeaderHoffIsValid(tup, withoid) \ + AssertMacro((tup)->t_hoff == HeapTupleHeaderExpectedLen(tup, withoid)) + +#else + +#define AssertHeapTupleHeaderHoffIsValid(tup, withoid) ((void)true) + +#endif /* DEBUG_TUPLE_ACCESS */ /* HeapTupleHeader accessor macros */ +#define HeapTupleHeaderGetOid(tup) \ +( \ + AssertHeapTupleHeaderHoffIsValid(tup, true), \ + *((Oid *)((char *)(tup) + (tup)->t_hoff - sizeof(Oid))) \ +) + +#define HeapTupleHeaderSetOid(tup, oid) \ +( \ + AssertHeapTupleHeaderHoffIsValid(tup, true), \ + *((Oid *)((char *)(tup) + (tup)->t_hoff - sizeof(Oid))) = (oid) \ +) + + #define HeapTupleHeaderGetXmin(tup) \ ( \ (tup)->t_xmin \ @@ -406,4 +436,10 @@ typedef HeapTupleData *HeapTuple; #define HeapTupleHasExtended(tuple) \ ((((HeapTuple)(tuple))->t_data->t_infomask & HEAP_HASEXTENDED) != 0) +#define HeapTupleGetOid(tuple) \ + HeapTupleHeaderGetOid(((HeapTuple)(tuple))->t_data) + +#define HeapTupleSetOid(tuple, oid) \ + HeapTupleHeaderSetOid(((HeapTuple)(tuple))->t_data, (oid)) + #endif /* HTUP_H */ diff --git a/src/include/access/tupdesc.h b/src/include/access/tupdesc.h index bab2bc7e7c..4f3236a25c 100644 --- a/src/include/access/tupdesc.h +++ b/src/include/access/tupdesc.h @@ -41,6 +41,11 @@ typedef struct tupleConstr bool has_not_null; } TupleConstr; +typedef char hasoid_t; +#define WITHOID 'C' +#define WITHOUTOID 'S' +#define UNDEFOID '?' +#define BoolToHasOid(b) ((b) ? WITHOID : WITHOUTOID) /* * This structure contains all information (i.e. from Classes * pg_attribute, pg_attrdef, pg_constraint) for a tuple. @@ -51,9 +56,27 @@ typedef struct tupleDesc Form_pg_attribute *attrs; /* attrs[N] is a pointer to the description of Attribute Number N+1. */ TupleConstr *constr; + hasoid_t tdhasoid; /* Tuple has an oid attribute in its header */ } *TupleDesc; -extern TupleDesc CreateTemplateTupleDesc(int natts); +#ifdef DEBUG_TUPLE_ACCESS + +#define AssertTupleDescHasOidIsValid(td) \ + Assert(((td)->tdhasoid == WITHOID) || ((td)->tdhasoid == WITHOUTOID)) +#define AssertTupleDescHasOid(td) \ + Assert((td)->tdhasoid == WITHOID) +#define AssertTupleDescHasNoOid(td) \ + Assert((td)->tdhasoid == WITHOUTOID) + +#else + +#define AssertTupleDescHasOidIsValid(td) +#define AssertTupleDescHasOid(td) +#define AssertTupleDescHasNoOid(td) + +#endif + +extern TupleDesc CreateTemplateTupleDesc(int natts, hasoid_t withoid); extern TupleDesc CreateTupleDesc(int natts, Form_pg_attribute *attrs); diff --git a/src/include/executor/executor.h b/src/include/executor/executor.h index eb0646f1fa..7c2067a644 100644 --- a/src/include/executor/executor.h +++ b/src/include/executor/executor.h @@ -118,7 +118,7 @@ extern void ExecInitScanTupleSlot(EState *estate, extern TupleTableSlot *ExecInitExtraTupleSlot(EState *estate); extern TupleTableSlot *ExecInitNullTupleSlot(EState *estate, TupleDesc tupType); -extern TupleDesc ExecTypeFromTL(List *targetList); +extern TupleDesc ExecTypeFromTL(List *targetList, hasoid_t withoid); extern void SetChangedParamList(Plan *node, List *newchg); /* diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in index fcbf455123..6186906834 100644 --- a/src/include/pg_config.h.in +++ b/src/include/pg_config.h.in @@ -311,6 +311,12 @@ /* #define ACLDEBUG */ /* #define RTDEBUG */ /* #define GISTDEBUG */ +/* + * DEBUG_TUPLE_ACCESS enables paranoid assertions during + * elimination of oids from the fixed sized part of HeapTupleHeader. + * This is expected to be undef'd after v7.3 release at the latest. + */ +#define DEBUG_TUPLE_ACCESS /* * defining unsafe floats will make float4 and float8 ops faster diff --git a/src/pl/plpython/plpython.c b/src/pl/plpython/plpython.c index 092d205d67..e809f0c8e5 100644 --- a/src/pl/plpython/plpython.c +++ b/src/pl/plpython/plpython.c @@ -2091,7 +2091,7 @@ PLy_spi_prepare(PyObject * self, PyObject * args) Py_DECREF(optr); optr = NULL; /* this is important */ - plan->types[i] = typeTup->t_data->t_oid; + plan->types[i] = HeapTupleGetOid(typeTup); typeStruct = (Form_pg_type) GETSTRUCT(typeTup); if (typeStruct->typrelid == InvalidOid) PLy_output_datum_func(&plan->args[i], typeStruct); diff --git a/src/pl/tcl/pltcl.c b/src/pl/tcl/pltcl.c index 7bd1e1ee7a..7cc56977eb 100644 --- a/src/pl/tcl/pltcl.c +++ b/src/pl/tcl/pltcl.c @@ -1743,7 +1743,7 @@ pltcl_SPI_prepare(ClientData cdata, Tcl_Interp *interp, { /* XXX should extend this to allow qualified type names */ typeTup = typenameType(makeTypeName(args[i])); - qdesc->argtypes[i] = typeTup->t_data->t_oid; + qdesc->argtypes[i] = HeapTupleGetOid(typeTup); perm_fmgr_info(((Form_pg_type) GETSTRUCT(typeTup))->typinput, &(qdesc->arginfuncs[i])); qdesc->argtypelems[i] = ((Form_pg_type) GETSTRUCT(typeTup))->typelem; diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index 218a5bd14d..fd9ae6c89a 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -75,3 +75,6 @@ test: select_views alter_table portals_p2 rules foreign_key # ---------- # "plpgsql" cannot run concurrently with "rules" test: limit plpgsql temp domain rangefuncs copy2 + +test: without_oid + diff --git a/src/test/regress/serial_schedule b/src/test/regress/serial_schedule index 24b0f8bed4..0efa4b0d74 100644 --- a/src/test/regress/serial_schedule +++ b/src/test/regress/serial_schedule @@ -85,3 +85,4 @@ test: copy2 test: temp test: domain test: rangefuncs +test: without_oid |