Optional Oid - Mailing list pgsql-patches
From | Manfred Koizar |
---|---|
Subject | Optional Oid |
Date | |
Msg-id | t37aju841ba4qc6jaem23vhfhb8k5cmttg@4ax.com Whole thread Raw |
Responses |
Re: Optional Oid
Re: Optional Oid |
List | pgsql-patches |
Here is a preview of a patch which shall eventually further reduce heap tuple header size by four bytes for tables created WITHOUT OIDS. t_oid is eliminated from the start of struct HeapTupleHeader. If an 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. [Follow-up to -hackers?] Servus Manfred diff -ruN ../base/src/backend/access/common/heaptuple.c src/backend/access/common/heaptuple.c --- ../base/src/backend/access/common/heaptuple.c 2002-06-21 02:12:13.000000000 +0200 +++ src/backend/access/common/heaptuple.c 2002-07-16 19:58:01.000000000 +0200 @@ -436,7 +436,7 @@ 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 @@ 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 @@ 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 @@ * 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 @@ */ 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 @@ 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 -ruN ../base/src/backend/access/common/tupdesc.c src/backend/access/common/tupdesc.c --- ../base/src/backend/access/common/tupdesc.c 2002-06-21 02:12:13.000000000 +0200 +++ src/backend/access/common/tupdesc.c 2002-07-15 21:29:30.000000000 +0200 @@ -36,7 +36,7 @@ * ---------------------------------------------------------------- */ TupleDesc -CreateTemplateTupleDesc(int natts) +CreateTemplateTupleDesc(int natts, hasoid_t withoid) { uint32 size; TupleDesc desc; @@ -58,6 +58,7 @@ MemSet(desc->attrs, 0, size); desc->natts = natts; + desc->tdhasoid = withoid; return desc; } @@ -82,6 +83,7 @@ desc->attrs = attrs; desc->natts = natts; desc->constr = NULL; + desc->tdhasoid = UNDEFOID; return desc; } @@ -116,6 +118,7 @@ desc->attrs[i]->atthasdef = false; } desc->constr = NULL; + desc->tdhasoid = tupdesc->tdhasoid; return desc; } @@ -182,6 +185,7 @@ else desc->constr = NULL; + desc->tdhasoid = tupdesc->tdhasoid; return desc; } @@ -235,6 +239,8 @@ 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 @@ */ 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 @@ * 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 @@ /* OK, get the column alias */ attname = strVal(lfirst(colaliases)); - tupdesc = CreateTemplateTupleDesc(1); + tupdesc = CreateTemplateTupleDesc(1, WITHOUTOID); TupleDescInitEntry(tupdesc, (AttrNumber) 1, attname, diff -ruN ../base/src/backend/access/heap/heapam.c src/backend/access/heap/heapam.c --- ../base/src/backend/access/heap/heapam.c 2002-07-03 12:27:39.000000000 +0200 +++ src/backend/access/heap/heapam.c 2002-07-15 22:22:28.000000000 +0200 @@ -1116,10 +1116,11 @@ * 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 @@ 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 @@ 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 @@ */ 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 @@ } /* 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 -ruN ../base/src/backend/access/heap/tuptoaster.c src/backend/access/heap/tuptoaster.c --- ../base/src/backend/access/heap/tuptoaster.c 2002-05-27 23:52:41.000000000 +0200 +++ src/backend/access/heap/tuptoaster.c 2002-07-16 19:58:01.000000000 +0200 @@ -726,6 +726,8 @@ 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 -ruN ../base/src/backend/bootstrap/bootparse.y src/backend/bootstrap/bootparse.y --- ../base/src/backend/bootstrap/bootparse.y 2002-06-21 02:12:14.000000000 +0200 +++ src/backend/bootstrap/bootparse.y 2002-07-15 22:11:00.000000000 +0200 @@ -179,13 +179,13 @@ } 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 -ruN ../base/src/backend/bootstrap/bootstrap.c src/backend/bootstrap/bootstrap.c --- ../base/src/backend/bootstrap/bootstrap.c 2002-06-21 02:12:14.000000000 +0200 +++ src/backend/bootstrap/bootstrap.c 2002-07-15 21:31:23.000000000 +0200 @@ -495,7 +495,8 @@ 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 @@ 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 @@ 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 -ruN ../base/src/backend/catalog/aclchk.c src/backend/catalog/aclchk.c --- ../base/src/backend/catalog/aclchk.c 2002-06-21 02:12:14.000000000 +0200 +++ src/backend/catalog/aclchk.c 2002-07-15 20:26:36.000000000 +0200 @@ -591,7 +591,8 @@ 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 -ruN ../base/src/backend/catalog/heap.c src/backend/catalog/heap.c --- ../base/src/backend/catalog/heap.c 2002-06-21 02:12:14.000000000 +0200 +++ src/backend/catalog/heap.c 2002-07-16 19:35:34.000000000 +0200 @@ -66,7 +66,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 DeleteAttributeTuples(Relation rel); static void DeleteRelationTuple(Relation rel); static void DeleteTypeTuple(Relation rel); @@ -448,6 +448,7 @@ (*dpp)->attcacheoff = -1; tup = heap_addheader(Natts_pg_attribute, + false, ATTRIBUTE_TUPLE_SIZE, (void *) *dpp); @@ -473,6 +474,7 @@ Form_pg_attribute attStruct; tup = heap_addheader(Natts_pg_attribute, + false, ATTRIBUTE_TUPLE_SIZE, (void *) *dpp); @@ -519,8 +521,7 @@ 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; @@ -571,7 +572,6 @@ 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 @@ -579,11 +579,13 @@ * ---------------- */ 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. @@ -683,6 +685,8 @@ 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 @@ -715,8 +719,7 @@ 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 @@ -1109,7 +1112,8 @@ * the type of the relation we are deleteing then we have to disallow * the deletion. should talk to stonebraker about this. -cim 6/19/90 */ - typoid = tup->t_data->t_oid; + AssertTupleDescHasOid(pg_type_desc->rd_att); + typoid = HeapTupleGetOid(tup); pg_attribute_desc = heap_openr(AttributeRelationName, RowExclusiveLock); diff -ruN ../base/src/backend/catalog/index.c src/backend/catalog/index.c --- ../base/src/backend/catalog/index.c 2002-06-21 02:12:14.000000000 +0200 +++ src/backend/catalog/index.c 2002-07-16 19:35:34.000000000 +0200 @@ -110,7 +110,7 @@ /* * 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); @@ -198,7 +198,7 @@ * allocate the new tuple descriptor */ - indexTupDesc = CreateTemplateTupleDesc(numatts); + indexTupDesc = CreateTemplateTupleDesc(numatts, WITHOUTOID); /* ---------------- * for each attribute we are indexing, obtain its attribute @@ -319,6 +319,7 @@ /* 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); @@ -326,7 +327,8 @@ * 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); /* @@ -405,6 +407,7 @@ Assert(indexTupDesc->attrs[i]->attcacheoff == -1); new_tuple = heap_addheader(Natts_pg_attribute, + false, ATTRIBUTE_TUPLE_SIZE, (void *) indexTupDesc->attrs[i]); @@ -494,6 +497,7 @@ * form a tuple to insert into pg_index */ tuple = heap_addheader(Natts_pg_index, + false, itupLen, (void *) indexForm); @@ -596,6 +600,7 @@ indexInfo->ii_KeyAttrNumbers, classObjectId); + indexTupDesc->tdhasoid = WITHOUTOID; /* * create the index relation (but don't create storage yet) */ @@ -623,7 +628,7 @@ 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 -ruN ../base/src/backend/catalog/namespace.c src/backend/catalog/namespace.c --- ../base/src/backend/catalog/namespace.c 2002-06-21 02:12:15.000000000 +0200 +++ src/backend/catalog/namespace.c 2002-07-15 20:19:46.000000000 +0200 @@ -584,7 +584,7 @@ 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 */ } } @@ -597,7 +597,7 @@ 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)); @@ -831,7 +831,7 @@ 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 */ } } @@ -843,7 +843,7 @@ 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; @@ -1007,7 +1007,7 @@ /* 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; @@ -1022,7 +1022,7 @@ 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; @@ -1597,7 +1597,8 @@ case RELKIND_RELATION: case RELKIND_SEQUENCE: case RELKIND_VIEW: - tempRelList = lconsi(tuple->t_data->t_oid, tempRelList); + AssertTupleDescHasOid(pgclass->rd_att); + tempRelList = lconsi(HeapTupleGetOid(tuple), tempRelList); break; default: break; diff -ruN ../base/src/backend/catalog/pg_operator.c src/backend/catalog/pg_operator.c --- ../base/src/backend/catalog/pg_operator.c 2002-06-21 02:12:15.000000000 +0200 +++ src/backend/catalog/pg_operator.c 2002-07-15 16:52:05.000000000 +0200 @@ -141,7 +141,7 @@ { RegProcedure oprcode = ((Form_pg_operator) GETSTRUCT(tup))->oprcode; - operatorObjectId = tup->t_data->t_oid; + operatorObjectId = HeapTupleGetOid(tup); *defined = RegProcedureIsValid(oprcode); ReleaseSysCache(tup); } diff -ruN ../base/src/backend/catalog/pg_proc.c src/backend/catalog/pg_proc.c --- ../base/src/backend/catalog/pg_proc.c 2002-06-21 02:12:15.000000000 +0200 +++ src/backend/catalog/pg_proc.c 2002-07-15 20:28:36.000000000 +0200 @@ -235,6 +235,7 @@ /* 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); } @@ -249,7 +250,8 @@ CatalogCloseIndices(Num_pg_proc_indices, idescs); } - retval = tup->t_data->t_oid; + AssertTupleDescHasOid(tupDesc); + retval = HeapTupleGetOid(tup); heap_freetuple(tup); heap_close(rel, RowExclusiveLock); diff -ruN ../base/src/backend/catalog/pg_type.c src/backend/catalog/pg_type.c --- ../base/src/backend/catalog/pg_type.c 2002-06-21 02:12:15.000000000 +0200 +++ src/backend/catalog/pg_type.c 2002-07-15 20:30:03.000000000 +0200 @@ -272,7 +272,8 @@ 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 { @@ -283,7 +284,8 @@ 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 -ruN ../base/src/backend/commands/comment.c src/backend/commands/comment.c --- ../base/src/backend/commands/comment.c 2002-06-21 02:12:15.000000000 +0200 +++ src/backend/commands/comment.c 2002-07-15 20:33:21.000000000 +0200 @@ -424,7 +424,8 @@ 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 */ @@ -470,7 +471,8 @@ 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())) @@ -541,7 +543,8 @@ 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 { @@ -581,7 +584,8 @@ 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); } @@ -794,7 +798,8 @@ 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); diff -ruN ../base/src/backend/commands/copy.c src/backend/commands/copy.c --- ../base/src/backend/commands/copy.c 2002-06-21 02:12:15.000000000 +0200 +++ src/backend/commands/copy.c 2002-07-15 20:34:46.000000000 +0200 @@ -575,9 +575,13 @@ /* 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 @@ -585,8 +589,9 @@ /* 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; @@ -977,7 +982,7 @@ 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 -ruN ../base/src/backend/commands/dbcommands.c src/backend/commands/dbcommands.c --- ../base/src/backend/commands/dbcommands.c 2002-06-21 02:12:15.000000000 +0200 +++ src/backend/commands/dbcommands.c 2002-07-15 20:36:01.000000000 +0200 @@ -341,7 +341,8 @@ 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); @@ -611,7 +612,10 @@ /* 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 -ruN ../base/src/backend/commands/explain.c src/backend/commands/explain.c --- ../base/src/backend/commands/explain.c 2002-06-21 02:12:15.000000000 +0200 +++ src/backend/commands/explain.c 2002-07-15 20:19:46.000000000 +0200 @@ -855,7 +855,7 @@ 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 -ruN ../base/src/backend/commands/functioncmds.c src/backend/commands/functioncmds.c --- ../base/src/backend/commands/functioncmds.c 2002-06-21 02:12:15.000000000 +0200 +++ src/backend/commands/functioncmds.c 2002-07-15 18:41:59.000000000 +0200 @@ -439,7 +439,7 @@ 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 -ruN ../base/src/backend/commands/indexcmds.c src/backend/commands/indexcmds.c --- ../base/src/backend/commands/indexcmds.c 2002-07-01 19:50:36.000000000 +0200 +++ src/backend/commands/indexcmds.c 2002-07-15 17:46:58.000000000 +0200 @@ -139,7 +139,7 @@ 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) @@ -494,7 +494,7 @@ * 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)) @@ -754,7 +754,7 @@ relids = repalloc(relids, sizeof(Oid) * relalc); } MemoryContextSwitchTo(old); - relids[relcnt] = tuple->t_data->t_oid; + relids[relcnt] = HeapTupleGetOid(tuple); relcnt++; } } diff -ruN ../base/src/backend/commands/tablecmds.c src/backend/commands/tablecmds.c --- ../base/src/backend/commands/tablecmds.c 2002-07-09 14:00:55.000000000 +0200 +++ src/backend/commands/tablecmds.c 2002-07-16 19:35:34.000000000 +0200 @@ -141,6 +141,7 @@ * have to copy inherited constraints here.) */ descriptor = BuildDescForRelation(schema); + descriptor->tdhasoid = BoolToHasOid(stmt->hasoids || parentHasOids); if (old_constraints != NIL) { @@ -1597,6 +1598,7 @@ tform = (Form_pg_type) GETSTRUCT(typeTuple); attributeTuple = heap_addheader(Natts_pg_attribute, + false, ATTRIBUTE_TUPLE_SIZE, (void *) &attributeD); @@ -1604,7 +1606,7 @@ 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; @@ -1621,6 +1623,7 @@ ReleaseSysCache(typeTuple); + AssertTupleDescHasNoOid(attrdesc->rd_att); simple_heap_insert(attrdesc, attributeTuple); /* Update indexes on pg_attribute */ @@ -1641,6 +1644,7 @@ 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 */ @@ -2892,7 +2896,7 @@ 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 -ruN ../base/src/backend/commands/trigger.c src/backend/commands/trigger.c --- ../base/src/backend/commands/trigger.c 2002-06-21 02:12:15.000000000 +0200 +++ src/backend/commands/trigger.c 2002-07-15 22:22:28.000000000 +0200 @@ -364,7 +364,8 @@ if (namestrcmp(&(pg_trigger->tgname), trigname) == 0) { /* Delete any comments associated with this trigger */ - DeleteComments(tuple->t_data->t_oid, RelationGetRelid(tgrel)); + AssertTupleDescHasOid(tgrel->rd_att); + DeleteComments(HeapTupleGetOid(tuple), RelationGetRelid(tgrel)); simple_heap_delete(tgrel, &tuple->t_self); found++; @@ -430,7 +431,8 @@ while (HeapTupleIsValid(tup = systable_getnext(tgscan))) { /* Delete any comments associated with this trigger */ - DeleteComments(tup->t_data->t_oid, RelationGetRelid(tgrel)); + AssertTupleDescHasOid(tgrel->rd_att); + DeleteComments(HeapTupleGetOid(tup), RelationGetRelid(tgrel)); simple_heap_delete(tgrel, &tup->t_self); @@ -667,7 +669,8 @@ 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)))); @@ -1928,7 +1931,8 @@ 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 -ruN ../base/src/backend/commands/typecmds.c src/backend/commands/typecmds.c --- ../base/src/backend/commands/typecmds.c 2002-07-01 19:50:36.000000000 +0200 +++ src/backend/commands/typecmds.c 2002-07-15 16:52:05.000000000 +0200 @@ -474,7 +474,7 @@ * Note: Name is strictly for error message */ expr = cookDefault(pstate, colDef->raw_expr, - typeTup->t_data->t_oid, + HeapTupleGetOid(typeTup), stmt->typename->typmod, domainName); /* @@ -551,7 +551,7 @@ receiveProcedure, /* receive procedure */ sendProcedure, /* send procedure */ basetypelem, /* element type ID */ - typeTup->t_data->t_oid, /* base type ID */ + HeapTupleGetOid(typeTup), /* base type ID */ defaultValue, /* default type value (text) */ defaultValueBin, /* default type value (binary) */ byValue, /* passed by value */ diff -ruN ../base/src/backend/commands/vacuum.c src/backend/commands/vacuum.c --- ../base/src/backend/commands/vacuum.c 2002-06-21 02:12:15.000000000 +0200 +++ src/backend/commands/vacuum.c 2002-07-15 20:39:19.000000000 +0200 @@ -392,7 +392,8 @@ { /* 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 @@ /* * 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 -ruN ../base/src/backend/commands/vacuumlazy.c src/backend/commands/vacuumlazy.c --- ../base/src/backend/commands/vacuumlazy.c 2002-06-21 02:12:15.000000000 +0200 +++ src/backend/commands/vacuumlazy.c 2002-07-15 16:52:05.000000000 +0200 @@ -368,8 +368,8 @@ /* * 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 -ruN ../base/src/backend/executor/execJunk.c src/backend/executor/execJunk.c --- ../base/src/backend/executor/execJunk.c 2002-06-21 02:12:15.000000000 +0200 +++ src/backend/executor/execJunk.c 2002-07-15 21:41:28.000000000 +0200 @@ -170,7 +170,7 @@ * 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 @@ * 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 -ruN ../base/src/backend/executor/execMain.c src/backend/executor/execMain.c --- ../base/src/backend/executor/execMain.c 2002-06-27 13:58:04.000000000 +0200 +++ src/backend/executor/execMain.c 2002-07-15 21:46:35.000000000 +0200 @@ -717,6 +717,10 @@ } /* + * new "INTO" table is created WITH OIDS + */ + tupType->tdhasoid = WITHOID; + /* * have to copy tupType to get rid of constraints */ tupdesc = CreateTupleDescCopy(tupType); diff -ruN ../base/src/backend/executor/execQual.c src/backend/executor/execQual.c --- ../base/src/backend/executor/execQual.c 2002-07-09 14:00:55.000000000 +0200 +++ src/backend/executor/execQual.c 2002-07-15 20:19:46.000000000 +0200 @@ -1770,7 +1770,10 @@ * 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 -ruN ../base/src/backend/executor/execTuples.c src/backend/executor/execTuples.c --- ../base/src/backend/executor/execTuples.c 2002-06-21 02:12:16.000000000 +0200 +++ src/backend/executor/execTuples.c 2002-07-15 21:13:09.000000000 +0200 @@ -540,6 +540,7 @@ ExecSetSlotDescriptor(slot, tupType, false); + NullTupleDesc.tdhasoid = WITHOUTOID; nullTuple = heap_formtuple(&NullTupleDesc, values, nulls); return ExecStoreTuple(nullTuple, slot, InvalidBuffer, true); @@ -557,7 +558,7 @@ * ---------------------------------------------------------------- */ TupleDesc -ExecTypeFromTL(List *targetList) +ExecTypeFromTL(List *targetList, hasoid_t withoid) { List *tlitem; TupleDesc typeInfo; @@ -576,7 +577,7 @@ /* * allocate a new typeInfo */ - typeInfo = CreateTemplateTupleDesc(len); + typeInfo = CreateTemplateTupleDesc(len, withoid); /* * scan list, generate type info for each entry diff -ruN ../base/src/backend/executor/execUtils.c src/backend/executor/execUtils.c --- ../base/src/backend/executor/execUtils.c 2002-06-27 13:58:04.000000000 +0200 +++ src/backend/executor/execUtils.c 2002-07-15 21:21:39.000000000 +0200 @@ -290,9 +290,23 @@ 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 -ruN ../base/src/backend/executor/nodeFunctionscan.c src/backend/executor/nodeFunctionscan.c --- ../base/src/backend/executor/nodeFunctionscan.c 2002-06-21 02:12:16.000000000 +0200 +++ src/backend/executor/nodeFunctionscan.c 2002-07-15 20:19:46.000000000 +0200 @@ -234,7 +234,7 @@ */ char *attname = strVal(lfirst(rte->eref->colnames)); - tupdesc = CreateTemplateTupleDesc(1); + tupdesc = CreateTemplateTupleDesc(1, WITHOUTOID); TupleDescInitEntry(tupdesc, (AttrNumber) 1, attname, diff -ruN ../base/src/backend/executor/spi.c src/backend/executor/spi.c --- ../base/src/backend/executor/spi.c 2002-06-21 02:12:16.000000000 +0200 +++ src/backend/executor/spi.c 2002-07-15 16:52:05.000000000 +0200 @@ -435,11 +435,15 @@ { 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 -ruN ../base/src/backend/optimizer/util/clauses.c src/backend/optimizer/util/clauses.c --- ../base/src/backend/optimizer/util/clauses.c 2002-07-09 14:00:55.000000000 +0200 +++ src/backend/optimizer/util/clauses.c 2002-07-15 16:52:05.000000000 +0200 @@ -1071,7 +1071,7 @@ 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 -ruN ../base/src/backend/parser/parse_coerce.c src/backend/parser/parse_coerce.c --- ../base/src/backend/parser/parse_coerce.c 2002-07-09 14:00:55.000000000 +0200 +++ src/backend/parser/parse_coerce.c 2002-07-15 19:03:43.000000000 +0200 @@ -792,7 +792,7 @@ if (isExplicit || pform->proimplicit) { /* Okay to use it */ - funcid = ftup->t_data->t_oid; + funcid = HeapTupleGetOid(ftup); } } ReleaseSysCache(ftup); diff -ruN ../base/src/backend/parser/parse_oper.c src/backend/parser/parse_oper.c --- ../base/src/backend/parser/parse_oper.c 2002-06-21 02:12:19.000000000 +0200 +++ src/backend/parser/parse_oper.c 2002-07-15 18:44:09.000000000 +0200 @@ -150,7 +150,7 @@ Oid oprid(Operator op) { - return op->t_data->t_oid; + return HeapTupleGetOid(op); } /* given operator tuple, return the underlying function's OID */ diff -ruN ../base/src/backend/parser/parse_type.c src/backend/parser/parse_type.c --- ../base/src/backend/parser/parse_type.c 2002-07-09 14:00:55.000000000 +0200 +++ src/backend/parser/parse_type.c 2002-07-15 18:44:32.000000000 +0200 @@ -283,7 +283,7 @@ { 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 -ruN ../base/src/backend/postmaster/pgstat.c src/backend/postmaster/pgstat.c --- ../base/src/backend/postmaster/pgstat.c 2002-05-21 11:54:17.000000000 +0200 +++ src/backend/postmaster/pgstat.c 2002-07-15 20:40:20.000000000 +0200 @@ -628,7 +628,8 @@ 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 -ruN ../base/src/backend/rewrite/rewriteRemove.c src/backend/rewrite/rewriteRemove.c --- ../base/src/backend/rewrite/rewriteRemove.c 2002-06-21 02:12:20.000000000 +0200 +++ src/backend/rewrite/rewriteRemove.c 2002-07-15 20:41:32.000000000 +0200 @@ -67,7 +67,8 @@ * Save the OID of the rule (i.e. the tuple's OID) and the event * relation's OID */ - ruleId = tuple->t_data->t_oid; + AssertTupleDescHasOid(RewriteRelation->rd_att); + ruleId = HeapTupleGetOid(tuple); eventRelationOid = ((Form_pg_rewrite) GETSTRUCT(tuple))->ev_class; Assert(eventRelationOid == owningRel); @@ -157,7 +158,8 @@ while (HeapTupleIsValid(tuple = systable_getnext(scanDesc))) { /* Delete any comments associated with this rule */ - DeleteComments(tuple->t_data->t_oid, RelationGetRelid(RewriteRelation)); + AssertTupleDescHasOid(RewriteRelation->rd_att); + DeleteComments(HeapTupleGetOid(tuple), RelationGetRelid(RewriteRelation)); simple_heap_delete(RewriteRelation, &tuple->t_self); } diff -ruN ../base/src/backend/utils/adt/regproc.c src/backend/utils/adt/regproc.c --- ../base/src/backend/utils/adt/regproc.c 2002-06-21 02:12:22.000000000 +0200 +++ src/backend/utils/adt/regproc.c 2002-07-15 20:43:19.000000000 +0200 @@ -110,7 +110,8 @@ 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 @@ 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 @@ 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 @@ 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 -ruN ../base/src/backend/utils/adt/sets.c src/backend/utils/adt/sets.c --- ../base/src/backend/utils/adt/sets.c 2002-06-21 02:12:22.000000000 +0200 +++ src/backend/utils/adt/sets.c 2002-07-15 20:43:55.000000000 +0200 @@ -120,7 +120,8 @@ 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 -ruN ../base/src/backend/utils/cache/catcache.c src/backend/utils/cache/catcache.c --- ../base/src/backend/utils/cache/catcache.c 2002-06-21 02:12:22.000000000 +0200 +++ src/backend/utils/cache/catcache.c 2002-07-15 20:19:47.000000000 +0200 @@ -218,7 +218,7 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ continue; if (cache->cc_reloidattr == ObjectIdAttributeNumber) - tupRelid = ct->tuple.t_data->t_oid; + tupRelid = HeapTupleGetOid(&ct->tuple); else { bool isNull; @@ -907,6 +907,7 @@ * 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 @@ } 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 -ruN ../base/src/backend/utils/cache/inval.c src/backend/utils/cache/inval.c --- ../base/src/backend/utils/cache/inval.c 2002-06-21 02:12:22.000000000 +0200 +++ src/backend/utils/cache/inval.c 2002-07-15 20:44:46.000000000 +0200 @@ -525,7 +525,10 @@ 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 -ruN ../base/src/backend/utils/cache/relcache.c src/backend/utils/cache/relcache.c --- ../base/src/backend/utils/cache/relcache.c 2002-06-21 02:12:23.000000000 +0200 +++ src/backend/utils/cache/relcache.c 2002-07-15 22:22:28.000000000 +0200 @@ -440,7 +440,7 @@ 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 @@ 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 @@ /* * 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 @@ * 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 @@ * 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 @@ 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 @@ */ Assert(relation->rd_rel != NULL); memcpy((char *) relation->rd_rel, (char *) relp, CLASS_TUPLE_SIZE); + relation->rd_att->tdhasoid = BoolToHasOid(relp->relhasoids); ReleaseSysCache(htup); } @@ -2776,7 +2779,7 @@ 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 -ruN ../base/src/backend/utils/cache/syscache.c src/backend/utils/cache/syscache.c --- ../base/src/backend/utils/cache/syscache.c 2002-06-21 02:12:23.000000000 +0200 +++ src/backend/utils/cache/syscache.c 2002-07-15 18:47:21.000000000 +0200 @@ -574,7 +574,7 @@ 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 -ruN ../base/src/backend/utils/init/postinit.c src/backend/utils/init/postinit.c --- ../base/src/backend/utils/init/postinit.c 2002-06-21 02:12:23.000000000 +0200 +++ src/backend/utils/init/postinit.c 2002-07-15 20:46:54.000000000 +0200 @@ -98,8 +98,9 @@ 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 -ruN ../base/src/backend/utils/misc/database.c src/backend/utils/misc/database.c --- ../base/src/backend/utils/misc/database.c 2002-06-21 02:12:23.000000000 +0200 +++ src/backend/utils/misc/database.c 2002-07-15 18:48:11.000000000 +0200 @@ -220,7 +220,7 @@ 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 -ruN ../base/src/include/access/heapam.h src/include/access/heapam.h --- ../base/src/include/access/heapam.h 2002-06-21 02:12:26.000000000 +0200 +++ src/include/access/heapam.h 2002-07-16 19:35:34.000000000 +0200 @@ -200,6 +200,6 @@ 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 -ruN ../base/src/include/access/htup.h src/include/access/htup.h --- ../base/src/include/access/htup.h 2002-07-09 14:00:56.000000000 +0200 +++ src/include/access/htup.h 2002-07-16 19:58:01.000000000 +0200 @@ -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 @@ 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 @@ #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 @@ #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 -ruN ../base/src/include/access/tupdesc.h src/include/access/tupdesc.h --- ../base/src/include/access/tupdesc.h 2002-06-21 02:12:26.000000000 +0200 +++ src/include/access/tupdesc.h 2002-07-15 20:56:56.000000000 +0200 @@ -41,6 +41,11 @@ 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_relcheck) for a tuple. @@ -51,9 +56,27 @@ 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 -ruN ../base/src/include/executor/executor.h src/include/executor/executor.h --- ../base/src/include/executor/executor.h 2002-06-27 13:58:05.000000000 +0200 +++ src/include/executor/executor.h 2002-07-15 22:53:02.000000000 +0200 @@ -118,7 +118,7 @@ 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 -ruN ../base/src/include/pg_config.h.in src/include/pg_config.h.in --- ../base/src/include/pg_config.h.in 2002-05-05 02:03:29.000000000 +0200 +++ src/include/pg_config.h.in 2002-07-15 16:52:05.000000000 +0200 @@ -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 -ruN ../base/src/pl/plpython/plpython.c src/pl/plpython/plpython.c --- ../base/src/pl/plpython/plpython.c 2002-06-17 10:11:34.000000000 +0200 +++ src/pl/plpython/plpython.c 2002-07-15 16:52:05.000000000 +0200 @@ -2091,7 +2091,7 @@ 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 -ruN ../base/src/pl/tcl/pltcl.c src/pl/tcl/pltcl.c --- ../base/src/pl/tcl/pltcl.c 2002-06-17 10:11:34.000000000 +0200 +++ src/pl/tcl/pltcl.c 2002-07-15 16:52:05.000000000 +0200 @@ -1755,7 +1755,7 @@ { /* 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 -ruN ../base/src/test/regress/expected/without_oid.out src/test/regress/expected/without_oid.out --- ../base/src/test/regress/expected/without_oid.out 1970-01-01 01:00:00.000000000 +0100 +++ src/test/regress/expected/without_oid.out 2002-07-10 23:53:44.000000000 +0200 @@ -0,0 +1,38 @@ +-- +-- WITHOUT OID +-- +CREATE TABLE wi (i INT); +CREATE TABLE wo (i INT) WITHOUT OIDS; +INSERT INTO wi VALUES (1); -- 1 +INSERT INTO wo SELECT i FROM wi; -- 1 +INSERT INTO wo SELECT i+1 FROM wi; -- 1+1=2 +INSERT INTO wi SELECT i+1 FROM wo; -- 1+2=3 +INSERT INTO wi SELECT i+3 FROM wi; -- 3+3=6 +INSERT INTO wo SELECT i+2 FROM wi; -- 2+6=8 +INSERT INTO wo SELECT i+8 FROM wo; -- 8+8=16 +INSERT INTO wi SELECT i+6 FROM wo; -- 6+16=22 +INSERT INTO wi SELECT i+22 FROM wi; -- 22+22=44 +INSERT INTO wo SELECT i+16 FROM wi; -- 16+44=60 +INSERT INTO wo SELECT i+60 FROM wo; -- 60+60=120 +INSERT INTO wi SELECT i+44 FROM wo; -- 44+120=164 +INSERT INTO wi SELECT i+164 FROM wi; -- 164+164=328 +INSERT INTO wo SELECT i+120 FROM wi; -- 120+328=448 +INSERT INTO wo SELECT i+448 FROM wo; -- 448+448=896 +INSERT INTO wi SELECT i+328 FROM wo; -- 328+896=1224 +INSERT INTO wi SELECT i+1224 FROM wi; -- 1224+1224=2448 +INSERT INTO wo SELECT i+896 FROM wi; -- 896+2448=3344 +INSERT INTO wo SELECT i+3344 FROM wo; -- 3344+3344=6688 +INSERT INTO wi SELECT i+2448 FROM wo; -- 2448+6688=9136 +INSERT INTO wo SELECT i+6688 FROM wi WHERE i<=2448; -- 6688+2448=9136 +VACUUM ANALYZE wi; +VACUUM ANALYZE wo; +SELECT min(relpages) < max(relpages), min(reltuples) - max(reltuples) + FROM pg_class + WHERE relname IN ('wi', 'wo'); + ?column? | ?column? +----------+---------- + t | 0 +(1 row) + +DROP TABLE wi; +DROP TABLE wo; diff -ruN ../base/src/test/regress/parallel_schedule src/test/regress/parallel_schedule --- ../base/src/test/regress/parallel_schedule 2002-06-21 02:12:33.000000000 +0200 +++ src/test/regress/parallel_schedule 2002-07-10 23:29:32.000000000 +0200 @@ -75,3 +75,5 @@ # ---------- # "plpgsql" cannot run concurrently with "rules" test: limit plpgsql temp domain rangefuncs + +test: without_oid diff -ruN ../base/src/test/regress/serial_schedule src/test/regress/serial_schedule --- ../base/src/test/regress/serial_schedule 2002-06-21 02:12:33.000000000 +0200 +++ src/test/regress/serial_schedule 2002-07-10 23:31:16.000000000 +0200 @@ -83,3 +83,4 @@ test: temp test: domain test: rangefuncs +test: without_oid diff -ruN ../base/src/test/regress/sql/without_oid.sql src/test/regress/sql/without_oid.sql --- ../base/src/test/regress/sql/without_oid.sql 1970-01-01 01:00:00.000000000 +0100 +++ src/test/regress/sql/without_oid.sql 2002-07-10 23:54:13.000000000 +0200 @@ -0,0 +1,35 @@ +-- +-- WITHOUT OID +-- + +CREATE TABLE wi (i INT); +CREATE TABLE wo (i INT) WITHOUT OIDS; +INSERT INTO wi VALUES (1); -- 1 +INSERT INTO wo SELECT i FROM wi; -- 1 +INSERT INTO wo SELECT i+1 FROM wi; -- 1+1=2 +INSERT INTO wi SELECT i+1 FROM wo; -- 1+2=3 +INSERT INTO wi SELECT i+3 FROM wi; -- 3+3=6 +INSERT INTO wo SELECT i+2 FROM wi; -- 2+6=8 +INSERT INTO wo SELECT i+8 FROM wo; -- 8+8=16 +INSERT INTO wi SELECT i+6 FROM wo; -- 6+16=22 +INSERT INTO wi SELECT i+22 FROM wi; -- 22+22=44 +INSERT INTO wo SELECT i+16 FROM wi; -- 16+44=60 +INSERT INTO wo SELECT i+60 FROM wo; -- 60+60=120 +INSERT INTO wi SELECT i+44 FROM wo; -- 44+120=164 +INSERT INTO wi SELECT i+164 FROM wi; -- 164+164=328 +INSERT INTO wo SELECT i+120 FROM wi; -- 120+328=448 +INSERT INTO wo SELECT i+448 FROM wo; -- 448+448=896 +INSERT INTO wi SELECT i+328 FROM wo; -- 328+896=1224 +INSERT INTO wi SELECT i+1224 FROM wi; -- 1224+1224=2448 +INSERT INTO wo SELECT i+896 FROM wi; -- 896+2448=3344 +INSERT INTO wo SELECT i+3344 FROM wo; -- 3344+3344=6688 +INSERT INTO wi SELECT i+2448 FROM wo; -- 2448+6688=9136 +INSERT INTO wo SELECT i+6688 FROM wi WHERE i<=2448; -- 6688+2448=9136 +VACUUM ANALYZE wi; +VACUUM ANALYZE wo; +SELECT min(relpages) < max(relpages), min(reltuples) - max(reltuples) + FROM pg_class + WHERE relname IN ('wi', 'wo'); + +DROP TABLE wi; +DROP TABLE wo; diff -ruN ../base/contrib/dbsize/dbsize.c contrib/dbsize/dbsize.c --- ../base/contrib/dbsize/dbsize.c 2002-05-21 11:54:08.000000000 +0200 +++ contrib/dbsize/dbsize.c 2002-07-15 18:01:46.000000000 +0200 @@ -65,7 +65,7 @@ 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 -ruN ../base/contrib/fulltextindex/fti.c contrib/fulltextindex/fti.c --- ../base/contrib/fulltextindex/fti.c 2001-11-05 19:46:23.000000000 +0100 +++ contrib/fulltextindex/fti.c 2002-07-15 16:52:05.000000000 +0200 @@ -190,7 +190,7 @@ 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 -ruN ../base/contrib/rserv/rserv.c contrib/rserv/rserv.c --- ../base/contrib/rserv/rserv.c 2002-03-06 08:09:11.000000000 +0100 +++ contrib/rserv/rserv.c 2002-07-15 16:52:05.000000000 +0200 @@ -102,7 +102,9 @@ if (keynum == ObjectIdAttributeNumber) { - sprintf(oidbuf, "%u", tuple->t_data->t_oid); + sprintf(oidbuf, "%u", rel->rd_rel->relhasoids + ? HeapTupleGetOid(tuple) + : InvalidOid); key = oidbuf; } else
pgsql-patches by date: