+ (PageHeaderData). Its format is detailed in
linkend="pageheaderdata-table">. The first two fields deal with WAL
related stuff. This is followed by three 2-byte integer fields
- (lower, upper, and
- special). These represent byte offsets to the start
+ (pd_lower, pd_upper,
+ and pd_special). These represent byte offsets to
+ the start
of unallocated space, to the end of unallocated space, and to the start of
the special space.
|
pd_lsn
XLogRecPtr
- 6 bytes
+ 8 bytes
LSN: next byte after last byte of xlog
|
Offset to start of special space.
|
- pd_opaque
- OpaqueData
+ pd_pagesize_version
+ uint16
2 bytes
- AM-generic information. Currently just stores the page size.
+ Page size and layout version number information.
+ All the details may be found in src/include/storage/bufpage.h.
+
+
Special space is a region at the end of the page that is allocated at page
initialization time and contains information specific to an access method.
- The last 2 bytes of the page header, opaque,
- currently only stores the page size. Page size is stored in each page
- because frames in the buffer pool may be subdivided into equal sized pages
- on a frame by frame basis within a table (is this true? - mvo).
-
+ The last 2 bytes of the page header,
+ pd_pagesize_version, store both the page size
+ and a version indicator. Beginning with
+
PostgreSQL 7.3 the version number is 1; prior
+ releases used version number 0. (The basic page layout and header format
+ has not changed, but the layout of heap tuple headers has.) The page size
+ is basically only present as a cross-check; there is no support for having
+ more than one page size in an installation.
Following the page header are item identifiers
- (ItemIdData). New item identifiers are allocated
- from the first four bytes of unallocated space. Because an item
- identifier is never moved until it is freed, its index may be used to
- indicate the location of an item on a page. In fact, every pointer to an
- item (ItemPointer, also know as
- CTID) created by
-
PostgreSQL consists of a frame number and an
- index of an item identifier. An item identifier contains a byte-offset to
+ (ItemIdData), each requiring four bytes.
+ An item identifier contains a byte-offset to
the start of an item, its length in bytes, and a set of attribute bits
which affect its interpretation.
+ New item identifiers are allocated
+ as needed from the beginning of the unallocated space.
+ The number of item identifiers present can be determined by looking at
+ pd_lower>, which is increased to allocate a new identifier.
+ Because an item
+ identifier is never moved until it is freed, its index may be used on a
+ long-term basis to reference an item, even when the item itself is moved
+ around on the page to compact free space. In fact, every pointer to an
+ item (ItemPointer, also known as
+ CTID) created by
+
PostgreSQL consists of a page number and the
+ index of an item identifier.
The items themselves are stored in space allocated backwards from the end
of unallocated space. The exact structure varies depending on what the
- table is to contain. Sequences and tables both use a structure named
- <firstterm>HeapTupleHeaderData, describe below.
+ table is to contain. Tables and sequences both use a structure named
+ <type>HeapTupleHeaderData, described below.
The final section is the "special section" which may contain anything the
access method wishes to store. Ordinary tables do not use this at all
- (indicated by setting the offset to the pagesize).
+ (indicated by setting pd_special> to equal the pagesize).
- All tuples are structured the same way. A header of around 31 bytes
- followed by an optional null bitmask and the data. The header is detailed
- below in . The null bitmask is
- only present if the HEAP_HASNULL bit is set in the
- t_infomask. If it is present it takes up the space
- between the end of the header and the beginning of the data, as indicated
- by the t_hoff field. In this list of bits, a 1 bit
- indicates not-null, a 0 bit is a null.
+ All table tuples are structured the same way. There is a fixed-size
+ header (occupying 23 bytes on most machines), followed by an optional null
+ bitmap, an optional object ID field, and the user data. The header is
+ detailed
+ in . The actual user data
+ (fields of the tuple) begins at the offset indicated by
+ t_hoff>, which must always be a multiple of the MAXALIGN
+ distance for the platform.
+ The null bitmap is
+ only present if the HEAP_HASNULL bit is set in
+ t_infomask. If it is present it begins just after
+ the fixed header and occupies enough bytes to have one bit per data column
+ (that is, t_natts> bits altogether). In this list of bits, a
+ 1 bit indicates not-null, a 0 bit is a null. When the bitmap is not
+ present, all columns are assumed not-null.
+ The object ID is only present if the HEAP_HASOID bit
+ is set in t_infomask. If present, it appears just
+ before the t_hoff> boundary. Any padding needed to make
+ t_hoff> a MAXALIGN multiple will appear between the null
+ bitmap and the object ID. (This in turn ensures that the object ID is
+ suitably aligned.)
|
- t_oid
- Oid
+ t_xmin
+ TransactionId
4 bytes
- OID of this tuple
+ insert XID stamp
|
t_cmin
CommandId
4 bytes
- insert CID stamp
+ insert CID stamp (overlays with t_xmax)
|
- t_cmax
- CommandId
+ t_xmax
+ TransactionId
4 bytes
- delete CID stamp
+ delete XID stamp
|
- t_xmin
- TransactionId
+ t_cmax
+ CommandId
4 bytes
- insert XID stamp
+ delete CID stamp (overlays with t_xvac)
|
- t_xmax
+ t_xvac
TransactionId
4 bytes
- delete XID stamp
+ XID for VACUUM operation moving tuple
|
t_ctid
t_infomask
uint16
2 bytes
- Various flags
+ various flags
|
t_hoff
uint8
1 byte
- length of tuple header. Also offset of data.
+ offset to user data
-
- All the details may be found in src/include/storage/bufpage.h.
-
+ All the details may be found in src/include/access/htup.h.
Interpreting the actual data can only be done with information obtained
from other tables, mostly pg_attribute. The
- particular fields are <firstterm>attlen> and
- <firstterm>attalign>. There is no way to directly get a
+ particular fields are <structfield>attlen> and
+ <structfield>attalign>. There is no way to directly get a
particular attribute, except when there are only fixed width fields and no
NULLs. All this trickery is wrapped up in the functions
heap_getattr, fastgetattr
the next. Then make sure you have the right alignment. If the field is a
fixed width field, then all the bytes are simply placed. If it's a
variable length field (attlen == -1) then it's a bit more complicated,
- using the variable length structure <firstterm>varattrib>.
+ using the variable length structure <type>varattrib>.
Depending on the flags, the data may be either inline, compressed or in
another table (TOAST).
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/access/common/heaptuple.c,v 1.80 2002/08/25 17:20:00 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/access/common/heaptuple.c,v 1.81 2002/09/02 01:05:03 tgl Exp $
*
* NOTES
* The old interface functions have been converted to macros
bitmask = CSIGNBIT;
}
- *infomask &= HEAP_XACT_MASK;
+ *infomask &= ~(HEAP_HASNULL | HEAP_HASVARWIDTH | HEAP_HASEXTENDED);
for (i = 0; i < numberOfAttributes; i++)
{
elog(ERROR, "heap_formtuple: numberOfAttributes %d exceeds limit %d",
numberOfAttributes, MaxTupleAttributeNumber);
- AssertTupleDescHasOidIsValid(tupleDescriptor);
-
for (i = 0; i < numberOfAttributes; i++)
{
if (nulls[i] != ' ')
if (hasnull)
len += BITMAPLEN(numberOfAttributes);
- if (tupleDescriptor->tdhasoid == WITHOID)
+ if (tupleDescriptor->tdhasoid)
len += sizeof(Oid);
hoff = len = MAXALIGN(len); /* align user data safely */
&td->t_infomask,
(hasnull ? td->t_bits : NULL));
+ if (tupleDescriptor->tdhasoid)
+ td->t_infomask |= HEAP_HASOID;
+
td->t_infomask |= HEAP_XMAX_INVALID;
return tuple;
char *nulls;
bool isNull;
HeapTuple newTuple;
- uint8 infomask;
/*
* sanity checks
nulls);
/*
- * copy the header except for t_len, t_natts, t_hoff, t_bits,
- * t_infomask
+ * copy the identification info of the old tuple: t_ctid, t_self,
+ * and OID (if any)
*/
- infomask = newTuple->t_data->t_infomask;
- /*
- * 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_data->t_ctid = tuple->t_data->t_ctid;
newTuple->t_self = tuple->t_self;
newTuple->t_tableOid = tuple->t_tableOid;
if (relation->rd_rel->relhasoids)
tuple->t_datamcxt = CurrentMemoryContext;
tuple->t_data = td = (HeapTupleHeader) ((char *) tuple + HEAPTUPLESIZE);
- MemSet((char *) td, 0, len);
+ MemSet((char *) td, 0, hoff);
td->t_hoff = hoff;
td->t_natts = natts;
- td->t_infomask = HEAP_XMAX_INVALID; /* XXX sufficient? */
+ td->t_infomask = withoid ? (HEAP_XMAX_INVALID | HEAP_HASOID) : HEAP_XMAX_INVALID;
memcpy((char *) td + hoff, structure, structlen);
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/access/common/tupdesc.c,v 1.87 2002/08/30 19:23:18 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/access/common/tupdesc.c,v 1.88 2002/09/02 01:05:03 tgl Exp $
*
* NOTES
* some of the executor utility code such as "ExecTypeFromTL" should be
* ----------------------------------------------------------------
*/
TupleDesc
-CreateTemplateTupleDesc(int natts, hasoid_t withoid)
+CreateTemplateTupleDesc(int natts, bool hasoid)
{
uint32 size;
TupleDesc desc;
MemSet(desc->attrs, 0, size);
desc->natts = natts;
- desc->tdhasoid = withoid;
+ desc->tdhasoid = hasoid;
return desc;
}
/* ----------------------------------------------------------------
* CreateTupleDesc
*
- * This function allocates a new TupleDesc from Form_pg_attribute array
+ * This function allocates a new TupleDesc pointing to a given
+ * Form_pg_attribute array
* ----------------------------------------------------------------
*/
TupleDesc
-CreateTupleDesc(int natts, Form_pg_attribute *attrs)
+CreateTupleDesc(int natts, bool hasoid, Form_pg_attribute *attrs)
{
TupleDesc desc;
desc->attrs = attrs;
desc->natts = natts;
desc->constr = NULL;
- desc->tdhasoid = UNDEFOID;
+ desc->tdhasoid = hasoid;
return desc;
}
*
* This function creates a new TupleDesc by copying from an existing
* TupleDesc (with Constraints)
- *
* ----------------------------------------------------------------
*/
TupleDesc
* BuildDescForRelation
*
* Given a relation schema (list of ColumnDef nodes), build a TupleDesc.
+ *
+ * Note: the default assumption is no OIDs; caller may modify the returned
+ * TupleDesc if it wants OIDs.
*/
TupleDesc
BuildDescForRelation(List *schema)
* allocate a new tuple descriptor
*/
natts = length(schema);
- desc = CreateTemplateTupleDesc(natts, UNDEFOID);
+ desc = CreateTemplateTupleDesc(natts, false);
constr->has_not_null = false;
attnum = 0;
/* OK, get the column alias */
attname = strVal(lfirst(colaliases));
- tupdesc = CreateTemplateTupleDesc(1, WITHOUTOID);
+ tupdesc = CreateTemplateTupleDesc(1, false);
TupleDescInitEntry(tupdesc,
(AttrNumber) 1,
attname,
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.146 2002/08/29 00:17:02 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.147 2002/09/02 01:05:03 tgl Exp $
*
*
* INTERFACE ROUTINES
if (relation->rd_rel->relhasoids)
{
+#ifdef NOT_USED
+ /* this is redundant with an Assert in HeapTupleSetOid */
+ Assert(tup->t_data->t_infomask & HEAP_HASOID);
+#endif
/*
* If the object id of this tuple has already been assigned, trust
* the caller. There are a couple of ways this can happen. At
* to support a persistent object store (objects need to contain
* pointers to one another).
*/
- AssertTupleDescHasOid(relation->rd_att);
if (!OidIsValid(HeapTupleGetOid(tup)))
HeapTupleSetOid(tup, newoid());
else
CheckMaxObjectId(HeapTupleGetOid(tup));
}
+ else
+ {
+ /* check there is not space for an OID */
+ Assert(!(tup->t_data->t_infomask & HEAP_HASOID));
+ }
tup->t_data->t_infomask &= ~(HEAP_XACT_MASK);
+ tup->t_data->t_infomask |= HEAP_XMAX_INVALID;
HeapTupleHeaderSetXmin(tup->t_data, GetCurrentTransactionId());
HeapTupleHeaderSetCmin(tup->t_data, cid);
- HeapTupleHeaderSetXmaxInvalid(tup->t_data);
- /*
- * Do *not* set Cmax! This would overwrite Cmin.
- */
- /* HeapTupleHeaderSetCmax(tup->t_data, FirstCommandId); */
- tup->t_data->t_infomask |= HEAP_XMAX_INVALID;
tup->t_tableOid = relation->rd_id;
#ifdef TUPLE_TOASTER_ACTIVE
rdata[0].len = SizeOfHeapInsert;
rdata[0].next = &(rdata[1]);
- if (relation->rd_rel->relhasoids)
- {
- AssertTupleDescHasOid(relation->rd_att);
- xlhdr.t_oid = HeapTupleGetOid(tup);
- }
- else
- xlhdr.t_oid = InvalidOid;
+ xlhdr.t_oid = HeapTupleGetOid(tup);
xlhdr.t_natts = tup->t_data->t_natts;
xlhdr.t_hoff = tup->t_data->t_hoff;
xlhdr.mask = tup->t_data->t_infomask;
*/
CacheInvalidateHeapTuple(relation, tup);
- if (!relation->rd_rel->relhasoids)
- return InvalidOid;
-
- AssertTupleDescHasOid(relation->rd_att);
return HeapTupleGetOid(tup);
}
/* store transaction information of xact deleting the tuple */
tp.t_data->t_infomask &= ~(HEAP_XMAX_COMMITTED |
- HEAP_XMAX_INVALID | HEAP_MARKED_FOR_UPDATE);
+ HEAP_XMAX_INVALID |
+ HEAP_MARKED_FOR_UPDATE |
+ HEAP_MOVED);
HeapTupleHeaderSetXmax(tp.t_data, GetCurrentTransactionId());
HeapTupleHeaderSetCmax(tp.t_data, cid);
/* Make sure there is no forward chain link in t_ctid */
/* Fill in OID and transaction status data for newtup */
if (relation->rd_rel->relhasoids)
{
- AssertTupleDescHasOid(relation->rd_att);
+#ifdef NOT_USED
+ /* this is redundant with an Assert in HeapTupleSetOid */
+ Assert(newtup->t_data->t_infomask & HEAP_HASOID);
+#endif
HeapTupleSetOid(newtup, HeapTupleGetOid(&oldtup));
}
+ else
+ {
+ /* check there is not space for an OID */
+ Assert(!(newtup->t_data->t_infomask & HEAP_HASOID));
+ }
+
newtup->t_data->t_infomask &= ~(HEAP_XACT_MASK);
newtup->t_data->t_infomask |= (HEAP_XMAX_INVALID | HEAP_UPDATED);
HeapTupleHeaderSetXmin(newtup->t_data, GetCurrentTransactionId());
HeapTupleHeaderSetCmin(newtup->t_data, cid);
- HeapTupleHeaderSetXmaxInvalid(newtup->t_data);
/*
* If the toaster needs to be activated, OR if the new tuple will not
oldtup.t_data->t_infomask &= ~(HEAP_XMAX_COMMITTED |
HEAP_XMAX_INVALID |
- HEAP_MARKED_FOR_UPDATE);
+ HEAP_MARKED_FOR_UPDATE |
+ HEAP_MOVED);
oldtup.t_data->t_infomask |= HEAP_XMAX_UNLOGGED;
HeapTupleHeaderSetXmax(oldtup.t_data, GetCurrentTransactionId());
HeapTupleHeaderSetCmax(oldtup.t_data, cid);
{
oldtup.t_data->t_infomask &= ~(HEAP_XMAX_COMMITTED |
HEAP_XMAX_INVALID |
- HEAP_MARKED_FOR_UPDATE);
+ HEAP_MARKED_FOR_UPDATE |
+ HEAP_MOVED);
HeapTupleHeaderSetXmax(oldtup.t_data, GetCurrentTransactionId());
HeapTupleHeaderSetCmax(oldtup.t_data, cid);
}
((PageHeader) BufferGetPage(*buffer))->pd_sui = ThisStartUpID;
/* store transaction information of xact marking the tuple */
- tuple->t_data->t_infomask &= ~(HEAP_XMAX_COMMITTED | HEAP_XMAX_INVALID);
+ tuple->t_data->t_infomask &= ~(HEAP_XMAX_COMMITTED |
+ HEAP_XMAX_INVALID |
+ HEAP_MOVED);
tuple->t_data->t_infomask |= HEAP_MARKED_FOR_UPDATE;
HeapTupleHeaderSetXmax(tuple->t_data, GetCurrentTransactionId());
HeapTupleHeaderSetCmax(tuple->t_data, cid);
rdata[1].len = 0;
rdata[1].next = &(rdata[2]);
- if (reln->rd_rel->relhasoids)
- {
- AssertTupleDescHasOid(reln->rd_att);
- xlhdr.hdr.t_oid = HeapTupleGetOid(newtup);
- }
- else
- xlhdr.hdr.t_oid = InvalidOid;
+ xlhdr.hdr.t_oid = HeapTupleGetOid(newtup);
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 (redo)
{
- /*
- * On redo from WAL we cannot rely on a tqual-routine
- * to have reset HEAP_MOVED.
- */
- htup->t_infomask &= ~(HEAP_MOVED | HEAP_XMAX_COMMITTED |
- HEAP_XMAX_INVALID | HEAP_MARKED_FOR_UPDATE);
+ htup->t_infomask &= ~(HEAP_XMAX_COMMITTED |
+ HEAP_XMAX_INVALID |
+ HEAP_MARKED_FOR_UPDATE |
+ HEAP_MOVED);
HeapTupleHeaderSetXmax(htup, record->xl_xid);
HeapTupleHeaderSetCmax(htup, FirstCommandId);
/* Make sure there is no forward chain link in t_ctid */
htup->t_infomask = HEAP_XMAX_INVALID | xlhdr.mask;
HeapTupleHeaderSetXmin(htup, record->xl_xid);
HeapTupleHeaderSetCmin(htup, FirstCommandId);
- HeapTupleHeaderSetXmaxInvalid(htup);
- HeapTupleHeaderSetCmax(htup, FirstCommandId);
htup->t_ctid = xlrec->target.tid;
if (reln->rd_rel->relhasoids)
- {
- AssertTupleDescHasOid(reln->rd_att);
HeapTupleHeaderSetOid(htup, xlhdr.t_oid);
- }
offnum = PageAddItem(page, (Item) htup, newlen, offnum,
LP_USED | OverwritePageMode);
{
if (move)
{
- htup->t_infomask &=
- ~(HEAP_XMIN_COMMITTED | HEAP_XMIN_INVALID | HEAP_MOVED_IN);
+ htup->t_infomask &= ~(HEAP_XMIN_COMMITTED |
+ HEAP_XMIN_INVALID |
+ HEAP_MOVED_IN);
htup->t_infomask |= HEAP_MOVED_OFF;
HeapTupleHeaderSetXvac(htup, record->xl_xid);
/* Make sure there is no forward chain link in t_ctid */
}
else
{
- /*
- * On redo from WAL we cannot rely on a tqual-routine
- * to have reset HEAP_MOVED.
- */
- htup->t_infomask &= ~(HEAP_MOVED | HEAP_XMAX_COMMITTED |
- HEAP_XMAX_INVALID | HEAP_MARKED_FOR_UPDATE);
+ htup->t_infomask &= ~(HEAP_XMAX_COMMITTED |
+ HEAP_XMAX_INVALID |
+ HEAP_MARKED_FOR_UPDATE |
+ HEAP_MOVED);
HeapTupleHeaderSetXmax(htup, record->xl_xid);
HeapTupleHeaderSetCmax(htup, FirstCommandId);
/* Set forward chain link in t_ctid */
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 xid[2]; /* xmax, xmin */
(char *) xlrec + hsize, 2 * sizeof(TransactionId));
htup->t_infomask = xlhdr.mask;
htup->t_infomask &= ~(HEAP_XMIN_COMMITTED |
- HEAP_XMIN_INVALID | HEAP_MOVED_OFF);
+ HEAP_XMIN_INVALID |
+ HEAP_MOVED_OFF);
htup->t_infomask |= HEAP_MOVED_IN;
HeapTupleHeaderSetXmin(htup, xid[1]);
HeapTupleHeaderSetXmax(htup, xid[0]);
htup->t_infomask = HEAP_XMAX_INVALID | xlhdr.mask;
HeapTupleHeaderSetXmin(htup, record->xl_xid);
HeapTupleHeaderSetCmin(htup, FirstCommandId);
- HeapTupleHeaderSetXmaxInvalid(htup);
- HeapTupleHeaderSetCmax(htup, FirstCommandId);
}
/* Make sure there is no forward chain link in t_ctid */
htup->t_ctid = xlrec->newtid;
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/access/heap/tuptoaster.c,v 1.34 2002/08/06 02:36:33 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/access/heap/tuptoaster.c,v 1.35 2002/09/02 01:05:03 tgl Exp $
*
*
* INTERFACE ROUTINES
new_len = offsetof(HeapTupleHeaderData, t_bits);
if (has_nulls)
new_len += BITMAPLEN(numAttrs);
- if (rel->rd_rel->relhasoids)
+ if (olddata->t_infomask & HEAP_HASOID)
new_len += sizeof(Oid);
new_len = MAXALIGN(new_len);
Assert(new_len == olddata->t_hoff);
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/bootstrap/bootparse.y,v 1.51 2002/08/30 22:18:05 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/bootstrap/bootparse.y,v 1.52 2002/09/02 01:05:03 tgl Exp $
*
*-------------------------------------------------------------------------
*/
}
RPAREN
{
+ TupleDesc tupdesc;
+
do_start();
+ tupdesc = CreateTupleDesc(numattr, !($4), attrtypes);
+
if ($2)
{
- TupleDesc tupdesc;
-
if (boot_reldesc)
{
elog(DEBUG3, "create bootstrap: warning, open relation exists, closing first");
closerel(NULL);
}
- tupdesc = CreateTupleDesc(numattr, attrtypes);
- tupdesc->tdhasoid = BoolToHasOid(! ($4));
boot_reldesc = heap_create(LexIDStr($5),
PG_CATALOG_NAMESPACE,
tupdesc,
else
{
Oid id;
- TupleDesc tupdesc;
- tupdesc = CreateTupleDesc(numattr,attrtypes);
id = heap_create_with_catalog(LexIDStr($5),
PG_CATALOG_NAMESPACE,
tupdesc,
RELKIND_RELATION,
$3,
- ! ($4),
true);
elog(DEBUG3, "relation created with oid %u", id);
}
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/bootstrap/bootstrap.c,v 1.139 2002/08/30 22:18:05 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/bootstrap/bootstrap.c,v 1.140 2002/09/02 01:05:03 tgl Exp $
*
*-------------------------------------------------------------------------
*/
app = Typ;
while ((tup = heap_getnext(scan, ForwardScanDirection)) != NULL)
{
- AssertTupleDescHasOid(rel->rd_att);
(*app)->am_oid = HeapTupleGetOid(tup);
memcpy((char *) &(*app)->am_typ,
(char *) GETSTRUCT(tup),
elog(DEBUG3, "inserting row oid %u, %d columns", objectid, numattr);
- tupDesc = CreateTupleDesc(numattr, attrtypes);
- tupDesc->tdhasoid = BoolToHasOid(RelationGetForm(boot_reldesc)->relhasoids);
+ tupDesc = CreateTupleDesc(numattr,
+ RelationGetForm(boot_reldesc)->relhasoids,
+ attrtypes);
tuple = heap_formtuple(tupDesc, values, Blanks);
-
if (objectid != (Oid) 0)
- {
- 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");
app = Typ;
while ((tup = heap_getnext(scan, ForwardScanDirection)) != NULL)
{
- AssertTupleDescHasOid(rel->rd_att);
(*app)->am_oid = HeapTupleGetOid(tup);
memmove((char *) &(*app++)->am_typ,
(char *) GETSTRUCT(tup),
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/catalog/aclchk.c,v 1.75 2002/08/22 00:01:41 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/catalog/aclchk.c,v 1.76 2002/09/02 01:05:03 tgl Exp $
*
* NOTES
* See acl.h.
elog(ERROR, "namespace \"%s\" not found", nspname);
pg_namespace_tuple = (Form_pg_namespace) GETSTRUCT(tuple);
- AssertTupleDescHasOid(relation->rd_att);
if (!pg_namespace_ownercheck(HeapTupleGetOid(tuple), GetUserId()))
aclcheck_error(ACLCHECK_NOT_OWNER, nspname);
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.223 2002/08/29 04:38:04 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.224 2002/09/02 01:05:03 tgl Exp $
*
*
* INTERFACE ROUTINES
* --------------------------------
*/
static void
-CheckAttributeNames(TupleDesc tupdesc, bool relhasoids, char relkind)
+CheckAttributeNames(TupleDesc tupdesc, char relkind)
{
int i;
int j;
for (i = 0; i < natts; i++)
{
if (SystemAttributeByName(NameStr(tupdesc->attrs[i]->attname),
- relhasoids) != NULL)
+ tupdesc->tdhasoid) != NULL)
elog(ERROR, "name of column \"%s\" conflicts with an existing system column",
NameStr(tupdesc->attrs[i]->attname));
}
static void
AddNewAttributeTuples(Oid new_rel_oid,
TupleDesc tupdesc,
- bool relhasoids,
char relkind)
{
Form_pg_attribute *dpp;
dpp = SysAtt;
for (i = 0; i < -1 - FirstLowInvalidHeapAttributeNumber; i++)
{
- if (relhasoids || (*dpp)->attnum != ObjectIdAttributeNumber)
+ if (tupdesc->tdhasoid ||
+ (*dpp)->attnum != ObjectIdAttributeNumber)
{
Form_pg_attribute attStruct;
(void *) new_rel_reltup);
/* force tuple to have the desired OID */
- AssertTupleDescHasOid(pg_class_desc->rd_att);
HeapTupleSetOid(tup, new_rel_oid);
/*
TupleDesc tupdesc,
char relkind,
bool shared_relation,
- bool relhasoids,
bool allow_system_table_mods)
{
Relation pg_class_desc;
elog(ERROR, "Number of columns is out of range (1 to %d)",
MaxHeapAttributeNumber);
- CheckAttributeNames(tupdesc, relhasoids, relkind);
+ CheckAttributeNames(tupdesc, relkind);
if (get_relname_relid(relname, relnamespace))
elog(ERROR, "Relation '%s' already exists", relname);
-
- tupdesc->tdhasoid = BoolToHasOid(relhasoids);
/*
* Create the relcache entry (mostly dummy at this point) and the
* now add tuples to pg_attribute for the attributes in our new
* relation.
*/
- AddNewAttributeTuples(new_rel_oid, new_rel_desc->rd_att,
- relhasoids, relkind);
+ AddNewAttributeTuples(new_rel_oid, new_rel_desc->rd_att, relkind);
/*
* make a dependency link to force the relation to be deleted if
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)))
{
conscan = systable_beginscan(conrel, ConstraintRelidIndex, true,
SnapshotNow, 1, key);
- AssertTupleDescHasOid(conrel->rd_att);
/*
* Scan over the result set, removing any matching entries.
*/
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.192 2002/08/30 19:23:18 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.193 2002/09/02 01:05:04 tgl Exp $
*
*
* INTERFACE ROUTINES
/*
* Allocate and zero a tuple descriptor for a one-column tuple.
*/
- funcTupDesc = CreateTemplateTupleDesc(1, UNDEFOID);
+ funcTupDesc = CreateTemplateTupleDesc(1, false);
funcTupDesc->attrs[0] = (Form_pg_attribute) palloc(ATTRIBUTE_TUPLE_SIZE);
MemSet(funcTupDesc->attrs[0], 0, ATTRIBUTE_TUPLE_SIZE);
* allocate the new tuple descriptor
*/
- indexTupDesc = CreateTemplateTupleDesc(numatts, WITHOUTOID);
+ indexTupDesc = CreateTemplateTupleDesc(numatts, false);
/* ----------------
* for each attribute we are indexing, obtain its attribute
* 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.
*/
- AssertTupleDescHasOid(pg_class->rd_att);
HeapTupleSetOid(tuple, RelationGetRelid(indexRelation));
simple_heap_insert(pg_class, tuple);
indexInfo->ii_KeyAttrNumbers,
classObjectId);
- indexTupDesc->tdhasoid = WITHOUTOID;
+ indexTupDesc->tdhasoid = false;
/*
* create the index relation's relcache entry and physical disk file.
* (If we fail further down, it's the smgr's responsibility to remove
indexRelation->rd_rel->relowner = GetUserId();
indexRelation->rd_rel->relam = accessMethodObjectId;
indexRelation->rd_rel->relkind = RELKIND_INDEX;
- indexRelation->rd_rel->relhasoids = false; /* WITHOUTOID! */
+ indexRelation->rd_rel->relhasoids = false;
/*
* store index's pg_class entry
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/catalog/namespace.c,v 1.33 2002/08/30 22:18:05 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/catalog/namespace.c,v 1.34 2002/09/02 01:05:04 tgl Exp $
*
*-------------------------------------------------------------------------
*/
case RELKIND_RELATION:
case RELKIND_SEQUENCE:
case RELKIND_VIEW:
- AssertTupleDescHasOid(pgclass->rd_att);
object.classId = RelOid_pg_class;
object.objectId = HeapTupleGetOid(tuple);
object.objectSubId = 0;
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.91 2002/08/29 00:17:03 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.92 2002/09/02 01:05:04 tgl Exp $
*
*-------------------------------------------------------------------------
*/
/* 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;
/* Need to update indexes for either the insert or update case */
CatalogUpdateIndexes(rel, tup);
- AssertTupleDescHasOid(tupDesc);
retval = HeapTupleGetOid(tup);
/*
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/catalog/pg_type.c,v 1.80 2002/08/29 00:17:03 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/catalog/pg_type.c,v 1.81 2002/09/02 01:05:04 tgl Exp $
*
*-------------------------------------------------------------------------
*/
simple_heap_update(pg_type_desc, &tup->t_self, tup);
- AssertTupleDescHasOid(pg_type_desc->rd_att);
typeObjectId = HeapTupleGetOid(tup);
}
else
nulls);
/* preassign tuple Oid, if one was given */
- AssertTupleDescHasOid(tupDesc);
HeapTupleSetOid(tup, assignedTypeOid);
typeObjectId = simple_heap_insert(pg_type_desc, tup);
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/cluster.c,v 1.87 2002/08/27 03:38:27 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/cluster.c,v 1.88 2002/09/02 01:05:04 tgl Exp $
*
*-------------------------------------------------------------------------
*/
tupdesc,
OldHeap->rd_rel->relkind,
OldHeap->rd_rel->relisshared,
- OldHeap->rd_rel->relhasoids,
allowSystemTableMods);
/*
* Copyright (c) 1996-2001, PostgreSQL Global Development Group
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/comment.c,v 1.58 2002/08/29 00:17:03 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/comment.c,v 1.59 2002/09/02 01:05:04 tgl Exp $
*
*-------------------------------------------------------------------------
*/
if (HeapTupleIsValid(tuple))
{
reloid = ((Form_pg_rewrite) GETSTRUCT(tuple))->ev_class;
- AssertTupleDescHasOid(RewriteRelation->rd_att);
ruleoid = HeapTupleGetOid(tuple);
}
else
if (!HeapTupleIsValid(tuple))
elog(ERROR, "rule \"%s\" does not exist", rulename);
Assert(reloid == ((Form_pg_rewrite) GETSTRUCT(tuple))->ev_class);
- AssertTupleDescHasOid(relation->rd_att);
ruleoid = HeapTupleGetOid(tuple);
ReleaseSysCache(tuple);
}
elog(ERROR, "trigger \"%s\" for relation \"%s\" does not exist",
trigname, RelationGetRelationName(relation));
- AssertTupleDescHasOid(pg_trigger->rd_att);
oid = HeapTupleGetOid(triggertuple);
systable_endscan(scan);
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.169 2002/08/29 07:22:21 ishii Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.170 2002/09/02 01:05:04 tgl Exp $
*
*-------------------------------------------------------------------------
*/
/* Send OID if wanted --- note fld_count doesn't include it */
if (oids)
{
- Oid oid;
-
- AssertTupleDescHasOid(tupDesc);
- oid = HeapTupleGetOid(tuple);
+ Oid oid = HeapTupleGetOid(tuple);
+
fld_size = sizeof(Oid);
CopySendData(&fld_size, sizeof(int16), fp);
CopySendData(&oid, sizeof(Oid), fp);
/* Text format has no per-tuple header, but send OID if wanted */
if (oids)
{
- AssertTupleDescHasOid(tupDesc);
string = DatumGetCString(DirectFunctionCall1(oidout,
ObjectIdGetDatum(HeapTupleGetOid(tuple))));
CopySendString(string, fp);
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/dbcommands.c,v 1.100 2002/08/29 07:22:21 ishii Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/dbcommands.c,v 1.101 2002/09/02 01:05:04 tgl Exp $
*
*-------------------------------------------------------------------------
*/
tuple = heap_formtuple(pg_database_dsc, new_record, new_record_nulls);
- AssertTupleDescHasOid(pg_database_dsc);
HeapTupleSetOid(tuple, dboid); /* override heap_insert's OID
* selection */
/* oid of the database */
if (dbIdP)
- {
- AssertTupleDescHasOid(relation->rd_att);
*dbIdP = HeapTupleGetOid(tuple);
- }
/* sysid of the owner */
if (ownerIdP)
*ownerIdP = dbform->datdba;
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994-5, Regents of the University of California
*
- * $Header: /cvsroot/pgsql/src/backend/commands/explain.c,v 1.85 2002/08/29 00:17:03 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/explain.c,v 1.86 2002/09/02 01:05:04 tgl Exp $
*
*/
List *l;
/* need a tuple descriptor representing a single TEXT column */
- tupdesc = CreateTemplateTupleDesc(1, WITHOUTOID);
+ tupdesc = CreateTemplateTupleDesc(1, false);
TupleDescInitEntry(tupdesc, (AttrNumber) 1, "QUERY PLAN",
TEXTOID, -1, 0, false);
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.37 2002/08/30 19:23:19 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.38 2002/09/02 01:05:04 tgl Exp $
*
*-------------------------------------------------------------------------
*/
* have to copy inherited constraints here.)
*/
descriptor = BuildDescForRelation(schema);
- descriptor->tdhasoid = BoolToHasOid(stmt->hasoids || parentHasOids);
+
+ descriptor->tdhasoid = (stmt->hasoids || parentHasOids);
if (old_constraints != NIL)
{
descriptor,
relkind,
false,
- stmt->hasoids || parentHasOids,
allowSystemTableMods);
StoreCatalogInheritance(relationId, inheritOids);
ReleaseSysCache(typeTuple);
- AssertTupleDescHasNoOid(attrdesc->rd_att);
simple_heap_insert(attrdesc, attributeTuple);
/* Update indexes on pg_attribute */
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 indexes current */
snprintf(toast_idxname, NAMEDATALEN, "pg_toast_%u_index", relOid);
/* this is pretty painful... need a tuple descriptor */
- tupdesc = CreateTemplateTupleDesc(3, WITHOUTOID);
+ tupdesc = CreateTemplateTupleDesc(3, false);
TupleDescInitEntry(tupdesc, (AttrNumber) 1,
"chunk_id",
OIDOID,
tupdesc,
RELKIND_TOASTVALUE,
shared_relation,
- false,
true);
/* make the toast relation visible, else index creation will fail */
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.129 2002/08/25 17:20:00 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.130 2002/09/02 01:05:04 tgl Exp $
*
*-------------------------------------------------------------------------
*/
tuple = heap_formtuple(tgrel->rd_att, values, nulls);
/* force tuple to have the desired OID */
- AssertTupleDescHasOid(tgrel->rd_att);
HeapTupleSetOid(tuple, trigoid);
/*
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 = HeapTupleGetOid(tup);
object.objectSubId = 0;
RelationGetRelationName(relation));
build = &(triggers[found]);
- AssertTupleDescHasOid(tgrel->rd_att);
build->tgoid = HeapTupleGetOid(htup);
build->tgname = MemoryContextStrdup(CacheMemoryContext,
DatumGetCString(DirectFunctionCall1(nameout,
elog(ERROR, "Constraint '%s' is not deferrable",
cname);
- AssertTupleDescHasOid(tgrel->rd_att);
constr_oid = HeapTupleGetOid(htup);
loid = lappendi(loid, constr_oid);
found = true;
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.235 2002/08/30 22:18:05 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.236 2002/09/02 01:05:04 tgl Exp $
*
*-------------------------------------------------------------------------
*/
{
/* Make a relation list entry for this guy */
oldcontext = MemoryContextSwitchTo(vac_context);
- AssertTupleDescHasOid(pgclass->rd_att);
vrl = lappendi(vrl, HeapTupleGetOid(tuple));
MemoryContextSwitchTo(oldcontext);
}
/* NO ELOG(ERROR) TILL CHANGES ARE LOGGED */
START_CRIT_SECTION();
- tuple.t_data->t_infomask &=
- ~(HEAP_XMIN_COMMITTED | HEAP_XMIN_INVALID | HEAP_MOVED_IN);
+ tuple.t_data->t_infomask &= ~(HEAP_XMIN_COMMITTED |
+ HEAP_XMIN_INVALID |
+ HEAP_MOVED_IN);
tuple.t_data->t_infomask |= HEAP_MOVED_OFF;
HeapTupleHeaderSetXvac(tuple.t_data, myXID);
* Update the state of the copied tuple, and store it
* on the destination page.
*/
- newtup.t_data->t_infomask &=
- ~(HEAP_XMIN_COMMITTED | HEAP_XMIN_INVALID | HEAP_MOVED_OFF);
+ newtup.t_data->t_infomask &= ~(HEAP_XMIN_COMMITTED |
+ HEAP_XMIN_INVALID |
+ HEAP_MOVED_OFF);
newtup.t_data->t_infomask |= HEAP_MOVED_IN;
HeapTupleHeaderSetXvac(newtup.t_data, myXID);
- newoff = PageAddItem(ToPage, (Item) newtup.t_data, tuple_len,
- InvalidOffsetNumber, LP_USED);
+ newoff = PageAddItem(ToPage,
+ (Item) newtup.t_data,
+ tuple_len,
+ InvalidOffsetNumber,
+ LP_USED);
if (newoff == InvalidOffsetNumber)
{
elog(PANIC, "moving chain: failed to add item with len = %lu to page %u",
START_CRIT_SECTION();
/*
- * Mark new tuple as moved_in by vacuum and store vacuum XID
- * in t_cid !!!
+ * Mark new tuple as MOVED_IN by me.
*/
- newtup.t_data->t_infomask &=
- ~(HEAP_XMIN_COMMITTED | HEAP_XMIN_INVALID | HEAP_MOVED_OFF);
+ newtup.t_data->t_infomask &= ~(HEAP_XMIN_COMMITTED |
+ HEAP_XMIN_INVALID |
+ HEAP_MOVED_OFF);
newtup.t_data->t_infomask |= HEAP_MOVED_IN;
HeapTupleHeaderSetXvac(newtup.t_data, myXID);
newtup.t_self = newtup.t_data->t_ctid;
/*
- * Mark old tuple as moved_off by vacuum and store vacuum XID
- * in t_cid !!!
+ * Mark old tuple as MOVED_OFF by me.
*/
- tuple.t_data->t_infomask &=
- ~(HEAP_XMIN_COMMITTED | HEAP_XMIN_INVALID | HEAP_MOVED_IN);
+ tuple.t_data->t_infomask &= ~(HEAP_XMIN_COMMITTED |
+ HEAP_XMIN_INVALID |
+ HEAP_MOVED_IN);
tuple.t_data->t_infomask |= HEAP_MOVED_OFF;
HeapTupleHeaderSetXvac(tuple.t_data, myXID);
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.176 2002/08/29 00:17:03 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.177 2002/09/02 01:05:05 tgl Exp $
*
*-------------------------------------------------------------------------
*/
aclcheck_error(aclresult,
get_namespace_name(namespaceId));
- /*
- * new "INTO" table is created WITH OIDS
- */
- tupType->tdhasoid = WITHOID;
/*
* have to copy tupType to get rid of constraints
*/
tupdesc = CreateTupleDescCopy(tupType);
+ /*
+ * Formerly we forced the output table to have OIDs, but
+ * as of 7.3 it will not have OIDs, because it's too late
+ * here to change the tupdescs of the already-initialized
+ * plan tree. (Perhaps we could recurse and change them
+ * all, but it's not really worth the trouble IMHO...)
+ */
+
intoRelationId =
heap_create_with_catalog(intoName,
namespaceId,
tupdesc,
RELKIND_RELATION,
false,
- true,
allowSystemTableMods);
FreeTupleDesc(tupdesc);
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.106 2002/08/31 22:10:43 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.107 2002/09/02 01:05:05 tgl Exp $
*
*-------------------------------------------------------------------------
*/
/*
* Scalar type, so make a single-column descriptor
*/
- tupdesc = CreateTemplateTupleDesc(1, WITHOUTOID);
+ tupdesc = CreateTemplateTupleDesc(1, false);
TupleDescInitEntry(tupdesc,
(AttrNumber) 1,
"column",
* 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
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/executor/execTuples.c,v 1.57 2002/08/29 00:17:03 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/executor/execTuples.c,v 1.58 2002/09/02 01:05:05 tgl Exp $
*
*-------------------------------------------------------------------------
*/
ExecSetSlotDescriptor(slot, tupType, false);
- NullTupleDesc.tdhasoid = WITHOUTOID;
nullTuple = heap_formtuple(&NullTupleDesc, values, nulls);
return ExecStoreTuple(nullTuple, slot, InvalidBuffer, true);
* ----------------------------------------------------------------
*/
TupleDesc
-ExecTypeFromTL(List *targetList, hasoid_t withoid)
+ExecTypeFromTL(List *targetList, bool hasoid)
{
List *tlitem;
TupleDesc typeInfo;
/*
* allocate a new typeInfo
*/
- typeInfo = CreateTemplateTupleDesc(len, withoid);
+ typeInfo = CreateTemplateTupleDesc(len, hasoid);
/*
* scan list, generate type info for each entry
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/executor/execUtils.c,v 1.88 2002/08/06 02:36:34 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/executor/execUtils.c,v 1.89 2002/09/02 01:05:05 tgl Exp $
*
*-------------------------------------------------------------------------
*/
ExecAssignResultTypeFromTL(Plan *node, CommonState *commonstate)
{
ResultRelInfo *ri;
- Relation rel;
- hasoid_t withoid;
+ bool hasoid = false;
TupleDesc tupDesc;
+ /*
+ * This is pretty grotty: we need to ensure that result tuples have
+ * space for an OID iff they are going to be stored into a relation
+ * that has OIDs. We assume that estate->es_result_relation_info
+ * is already set up to describe the target relation. One reason
+ * this is ugly is that all plan nodes in the plan tree will emit
+ * tuples with space for an OID, though we really only need the topmost
+ * plan to do so.
+ *
+ * It would be better to have InitPlan adjust the topmost plan node's
+ * output descriptor after plan tree initialization. However, that
+ * doesn't quite work because in an UPDATE that spans an inheritance
+ * tree, some of the target relations may have OIDs and some not.
+ * We have to make the decision on a per-relation basis as we initialize
+ * each of the child plans of the topmost Append plan. So, this is ugly
+ * but it works, for now ...
+ */
ri = node->state->es_result_relation_info;
if (ri != NULL)
- rel = ri->ri_RelationDesc;
- else
- rel = node->state->es_into_relation_descriptor;
+ {
+ Relation rel = ri->ri_RelationDesc;
- if (rel != NULL)
- withoid = BoolToHasOid(rel->rd_rel->relhasoids);
- else
- withoid = WITHOUTOID;
+ if (rel != NULL)
+ hasoid = rel->rd_rel->relhasoids;
+ }
- tupDesc = ExecTypeFromTL(node->targetlist, withoid);
+ tupDesc = ExecTypeFromTL(node->targetlist, hasoid);
ExecAssignResultType(commonstate, tupDesc, true);
}
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/executor/nodeAppend.c,v 1.45 2002/06/20 20:29:28 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/executor/nodeAppend.c,v 1.46 2002/09/02 01:05:05 tgl Exp $
*
*-------------------------------------------------------------------------
*/
/*
* call ExecInitNode on each of the plans to be executed and save the
- * results into the array "initialized"
+ * results into the array "initialized". Note we *must* set
+ * estate->es_result_relation_info correctly while we initialize each
+ * sub-plan; ExecAssignResultTypeFromTL depends on that!
*/
for (i = appendstate->as_firstplan; i <= appendstate->as_lastplan; i++)
{
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/executor/nodeFunctionscan.c,v 1.10 2002/08/31 19:09:27 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/executor/nodeFunctionscan.c,v 1.11 2002/09/02 01:05:05 tgl Exp $
*
*-------------------------------------------------------------------------
*/
*/
char *attname = strVal(lfirst(rte->eref->colnames));
- tupdesc = CreateTemplateTupleDesc(1, WITHOUTOID);
+ tupdesc = CreateTemplateTupleDesc(1, false);
TupleDescInitEntry(tupdesc,
(AttrNumber) 1,
attname,
/*
* Must be a pseudo type, i.e. record
*/
- List *coldeflist = rte->coldeflist;
-
- tupdesc = BuildDescForRelation(coldeflist);
- tupdesc->tdhasoid = WITHOUTOID;
+ tupdesc = BuildDescForRelation(rte->coldeflist);
}
else
elog(ERROR, "Unknown kind of return type specified for function");
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/executor/spi.c,v 1.72 2002/07/20 05:16:58 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/executor/spi.c,v 1.73 2002/09/02 01:05:05 tgl Exp $
*
*-------------------------------------------------------------------------
*/
MemoryContext oldcxt = NULL;
HeapTuple mtuple;
int numberOfAttributes;
- uint8 infomask;
Datum *v;
char *n;
bool isnull;
if (i == natts) /* no errors in *attnum */
{
mtuple = heap_formtuple(rel->rd_att, v, n);
- infomask = mtuple->t_data->t_infomask;
/*
- * copy t_xmin, t_cid, t_xmax, t_ctid, t_natts, t_infomask
+ * copy the identification info of the old tuple: t_ctid, t_self,
+ * and OID (if any)
*/
- 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;
+ mtuple->t_data->t_ctid = tuple->t_data->t_ctid;
+ mtuple->t_self = tuple->t_self;
+ mtuple->t_tableOid = tuple->t_tableOid;
if (rel->rd_rel->relhasoids)
HeapTupleSetOid(mtuple, HeapTupleGetOid(tuple));
}
*
* Copyright (c) 2001, PostgreSQL Global Development Group
*
- * $Header: /cvsroot/pgsql/src/backend/postmaster/pgstat.c,v 1.24 2002/08/29 07:22:23 ishii Exp $
+ * $Header: /cvsroot/pgsql/src/backend/postmaster/pgstat.c,v 1.25 2002/09/02 01:05:05 tgl Exp $
* ----------
*/
#include "postgres.h"
dbidlist = (Oid *) repalloc((char *) dbidlist,
sizeof(Oid) * dbidalloc);
}
- AssertTupleDescHasOid(dbrel->rd_att);
dbidlist[dbidused++] = HeapTupleGetOid(dbtup);
}
heap_endscan(dbscan);
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/storage/page/bufpage.c,v 1.47 2002/08/06 19:41:23 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/storage/page/bufpage.c,v 1.48 2002/09/02 01:05:05 tgl Exp $
*
*-------------------------------------------------------------------------
*/
p->pd_lower = SizeOfPageHeaderData;
p->pd_upper = pageSize - specialSize;
p->pd_special = pageSize - specialSize;
- PageSetPageSize(page, pageSize);
+ PageSetPageSizeAndVersion(page, pageSize, PG_PAGE_LAYOUT_VERSION);
}
* Copyright (c) 2002, PostgreSQL Global Development Group
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/lockfuncs.c,v 1.5 2002/08/31 17:14:28 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/lockfuncs.c,v 1.6 2002/09/02 01:05:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
/* build tupdesc for result tuples */
/* this had better match pg_locks view in initdb.sh */
- tupdesc = CreateTemplateTupleDesc(6, WITHOUTOID);
+ tupdesc = CreateTemplateTupleDesc(6, false);
TupleDescInitEntry(tupdesc, (AttrNumber) 1, "relation",
OIDOID, -1, 0, false);
TupleDescInitEntry(tupdesc, (AttrNumber) 2, "database",
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/regproc.c,v 1.73 2002/08/22 00:01:43 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/regproc.c,v 1.74 2002/09/02 01:05:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
while (HeapTupleIsValid(tuple = systable_getnext(sysscan)))
{
- AssertTupleDescHasOid(hdesc->rd_att);
result = (RegProcedure) HeapTupleGetOid(tuple);
if (++matches > 1)
break;
while (HeapTupleIsValid(tuple = systable_getnext(sysscan)))
{
- AssertTupleDescHasOid(hdesc->rd_att);
result = HeapTupleGetOid(tuple);
if (++matches > 1)
break;
SnapshotNow, 1, skey);
if (HeapTupleIsValid(tuple = systable_getnext(sysscan)))
- {
- AssertTupleDescHasOid(hdesc->rd_att);
result = HeapTupleGetOid(tuple);
- }
else
elog(ERROR, "No class with name %s", class_name_or_oid);
SnapshotNow, 1, skey);
if (HeapTupleIsValid(tuple = systable_getnext(sysscan)))
- {
- AssertTupleDescHasOid(hdesc->rd_att);
result = HeapTupleGetOid(tuple);
- }
else
elog(ERROR, "No type with name %s", typ_name_or_oid);
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/sets.c,v 1.52 2002/08/27 03:56:35 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/sets.c,v 1.53 2002/09/02 01:05:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
simple_heap_update(procrel, &newtup->t_self, newtup);
- AssertTupleDescHasOid(procrel->rd_att);
setoid = HeapTupleGetOid(newtup);
CatalogUpdateIndexes(procrel, newtup);
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/cache/catcache.c,v 1.97 2002/07/20 05:16:58 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/cache/catcache.c,v 1.98 2002/09/02 01:05:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
* 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
ntp = heap_formtuple(tupDesc, values, nulls);
if (tupOid != InvalidOid)
- {
- AssertTupleDescHasOid(tupDesc);
HeapTupleSetOid(ntp, tupOid);
- }
pfree(values);
pfree(nulls);
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/cache/inval.c,v 1.53 2002/07/20 05:16:58 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/cache/inval.c,v 1.54 2002/09/02 01:05:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
tupleRelId = RelationGetRelid(relation);
if (tupleRelId == RelOid_pg_class)
- {
- AssertTupleDescHasOid(relation->rd_att);
relationId = HeapTupleGetOid(tuple);
- }
else if (tupleRelId == RelOid_pg_attribute)
relationId = ((Form_pg_attribute) GETSTRUCT(tuple))->attrelid;
else
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.172 2002/08/11 21:17:35 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.173 2002/09/02 01:05:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
relation->rd_rel = relationForm;
/* and allocate attribute tuple form storage */
- relation->rd_att = CreateTemplateTupleDesc(relationForm->relnatts, BoolToHasOid(relationForm->relhasoids));
+ relation->rd_att = CreateTemplateTupleDesc(relationForm->relnatts,
+ relationForm->relhasoids);
MemoryContextSwitchTo(oldcxt);
AttrDefault *attrdef = NULL;
int ndef = 0;
+ relation->rd_att->tdhasoid = RelationGetForm(relation)->relhasoids;
+
constr = (TupleConstr *) MemoryContextAlloc(CacheMemoryContext,
sizeof(TupleConstr));
constr->has_not_null = false;
rule = (RewriteRule *) MemoryContextAlloc(rulescxt,
sizeof(RewriteRule));
- AssertTupleDescHasOid(rewrite_tupdesc);
rule->ruleId = HeapTupleGetOid(rewrite_tuple);
rule->event = rewrite_form->ev_type - '0';
* 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
* 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, BoolToHasOid(relation->rd_rel->relhasoids));
+ relation->rd_att = CreateTemplateTupleDesc(natts,
+ relation->rd_rel->relhasoids);
/*
* initialize tuple desc info
rel->rd_rel->relnamespace = relnamespace;
rel->rd_rel->relkind = RELKIND_UNCATALOGED;
- rel->rd_rel->relhasoids = (rel->rd_att->tdhasoid == WITHOID);
+ rel->rd_rel->relhasoids = rel->rd_att->tdhasoid;
rel->rd_rel->relnatts = natts;
rel->rd_rel->reltype = InvalidOid;
*/
Assert(relation->rd_rel != NULL);
memcpy((char *) relation->rd_rel, (char *) relp, CLASS_TUPLE_SIZE);
- relation->rd_att->tdhasoid = BoolToHasOid(relp->relhasoids);
+ relation->rd_att->tdhasoid = relp->relhasoids;
ReleaseSysCache(htup);
}
rel->rd_rel = relform;
/* initialize attribute tuple forms */
- rel->rd_att = CreateTemplateTupleDesc(relform->relnatts, BoolToHasOid(relform->relhasoids));
+ rel->rd_att = CreateTemplateTupleDesc(relform->relnatts,
+ relform->relhasoids);
/* next read all the attribute tuple form data entries */
for (i = 0; i < relform->relnatts; i++)
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/init/postinit.c,v 1.112 2002/08/30 22:18:06 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/init/postinit.c,v 1.113 2002/09/02 01:05:06 tgl Exp $
*
*
*-------------------------------------------------------------------------
pgdbscan = heap_beginscan(pgdbrel, SnapshotNow, 1, &key);
tup = heap_getnext(pgdbscan, ForwardScanDirection);
- AssertTupleDescHasOid(pgdbrel->rd_att);
if (!HeapTupleIsValid(tup) ||
HeapTupleGetOid(tup) != MyDatabaseId)
{
* command, configuration file, and command line options.
* See src/backend/utils/misc/README for more information.
*
- * $Header: /cvsroot/pgsql/src/backend/utils/misc/guc.c,v 1.90 2002/09/01 23:26:06 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/misc/guc.c,v 1.91 2002/09/02 01:05:06 tgl Exp $
*
* Copyright 2000 by PostgreSQL Global Development Group
* Written by Peter Eisentraut
.
value = GetConfigOptionByName(name, &varname);
/* need a tuple descriptor representing a single TEXT column */
- tupdesc = CreateTemplateTupleDesc(1, WITHOUTOID);
+ tupdesc = CreateTemplateTupleDesc(1, false);
TupleDescInitEntry(tupdesc, (AttrNumber) 1, (char *) varname,
TEXTOID, -1, 0, false);
char *values[2];
/* need a tuple descriptor representing two TEXT columns */
- tupdesc = CreateTemplateTupleDesc(2, WITHOUTOID);
+ tupdesc = CreateTemplateTupleDesc(2, false);
TupleDescInitEntry(tupdesc, (AttrNumber) 1, "name",
TEXTOID, -1, 0, false);
TupleDescInitEntry(tupdesc, (AttrNumber) 2, "setting",
oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
/* need a tuple descriptor representing two TEXT columns */
- tupdesc = CreateTemplateTupleDesc(2, WITHOUTOID);
+ tupdesc = CreateTemplateTupleDesc(2, false);
TupleDescInitEntry(tupdesc, (AttrNumber) 1, "name",
TEXTOID, -1, 0, false);
TupleDescInitEntry(tupdesc, (AttrNumber) 2, "setting",
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/time/tqual.c,v 1.58 2002/07/30 16:08:33 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/time/tqual.c,v 1.59 2002/09/02 01:05:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
return false;
}
tuple->t_infomask |= HEAP_XMIN_COMMITTED;
- tuple->t_infomask &= ~HEAP_MOVED;
}
}
else if (tuple->t_infomask & HEAP_MOVED_IN)
if (TransactionIdIsInProgress(HeapTupleHeaderGetXvac(tuple)))
return false;
if (TransactionIdDidCommit(HeapTupleHeaderGetXvac(tuple)))
- {
tuple->t_infomask |= HEAP_XMIN_COMMITTED;
- tuple->t_infomask &= ~HEAP_MOVED;
- }
else
{
tuple->t_infomask |= HEAP_XMIN_INVALID;
return false;
}
tuple->t_infomask |= HEAP_XMIN_COMMITTED;
- tuple->t_infomask &= ~HEAP_MOVED;
}
}
else if (tuple->t_infomask & HEAP_MOVED_IN)
if (TransactionIdIsInProgress(HeapTupleHeaderGetXvac(tuple)))
return false;
if (TransactionIdDidCommit(HeapTupleHeaderGetXvac(tuple)))
- {
tuple->t_infomask |= HEAP_XMIN_COMMITTED;
- tuple->t_infomask &= ~HEAP_MOVED;
- }
else
{
tuple->t_infomask |= HEAP_XMIN_INVALID;
return false;
}
tuple->t_infomask |= HEAP_XMIN_COMMITTED;
- tuple->t_infomask &= ~HEAP_MOVED;
}
}
else if (tuple->t_infomask & HEAP_MOVED_IN)
if (TransactionIdIsInProgress(HeapTupleHeaderGetXvac(tuple)))
return false;
if (TransactionIdDidCommit(HeapTupleHeaderGetXvac(tuple)))
- {
tuple->t_infomask |= HEAP_XMIN_COMMITTED;
- tuple->t_infomask &= ~HEAP_MOVED;
- }
else
{
tuple->t_infomask |= HEAP_XMIN_INVALID;
return HeapTupleInvisible;
}
tuple->t_infomask |= HEAP_XMIN_COMMITTED;
- tuple->t_infomask &= ~HEAP_MOVED;
}
}
else if (tuple->t_infomask & HEAP_MOVED_IN)
if (TransactionIdIsInProgress(HeapTupleHeaderGetXvac(tuple)))
return HeapTupleInvisible;
if (TransactionIdDidCommit(HeapTupleHeaderGetXvac(tuple)))
- {
tuple->t_infomask |= HEAP_XMIN_COMMITTED;
- tuple->t_infomask &= ~HEAP_MOVED;
- }
else
{
tuple->t_infomask |= HEAP_XMIN_INVALID;
return false;
}
tuple->t_infomask |= HEAP_XMIN_COMMITTED;
- tuple->t_infomask &= ~HEAP_MOVED;
}
}
else if (tuple->t_infomask & HEAP_MOVED_IN)
if (TransactionIdIsInProgress(HeapTupleHeaderGetXvac(tuple)))
return false;
if (TransactionIdDidCommit(HeapTupleHeaderGetXvac(tuple)))
- {
tuple->t_infomask |= HEAP_XMIN_COMMITTED;
- tuple->t_infomask &= ~HEAP_MOVED;
- }
else
{
tuple->t_infomask |= HEAP_XMIN_INVALID;
return false;
}
tuple->t_infomask |= HEAP_XMIN_COMMITTED;
- tuple->t_infomask &= ~HEAP_MOVED;
}
}
else if (tuple->t_infomask & HEAP_MOVED_IN)
if (TransactionIdIsInProgress(HeapTupleHeaderGetXvac(tuple)))
return false;
if (TransactionIdDidCommit(HeapTupleHeaderGetXvac(tuple)))
- {
tuple->t_infomask |= HEAP_XMIN_COMMITTED;
- tuple->t_infomask &= ~HEAP_MOVED;
- }
else
{
tuple->t_infomask |= HEAP_XMIN_INVALID;
return HEAPTUPLE_DEAD;
}
tuple->t_infomask |= HEAP_XMIN_COMMITTED;
- tuple->t_infomask &= ~HEAP_MOVED;
}
else if (tuple->t_infomask & HEAP_MOVED_IN)
{
if (TransactionIdIsInProgress(HeapTupleHeaderGetXvac(tuple)))
return HEAPTUPLE_INSERT_IN_PROGRESS;
if (TransactionIdDidCommit(HeapTupleHeaderGetXvac(tuple)))
- {
tuple->t_infomask |= HEAP_XMIN_COMMITTED;
- tuple->t_infomask &= ~HEAP_MOVED;
- }
else
{
tuple->t_infomask |= HEAP_XMIN_INVALID;
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: htup.h,v 1.58 2002/08/25 17:20:01 tgl Exp $
+ * $Id: htup.h,v 1.59 2002/09/02 01:05:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
*/
#define MaxHeapAttributeNumber 1600 /* 8 * 200 */
-/*
+/*----------
* On-disk heap tuple header. Currently this is also used as the header
* format for tuples formed in memory, although in principle they could
- * be different.
+ * be different. To avoid wasting space, the fields should be layed out
+ * in such a way to avoid structure padding.
+ *
+ * The overall structure of a heap tuple looks like:
+ * fixed fields (HeapTupleHeaderData struct)
+ * nulls bitmap (if HEAP_HASNULL is set in t_infomask)
+ * alignment padding (as needed to make user data MAXALIGN'd)
+ * object ID (if HEAP_HASOID is set in t_infomask)
+ * user data fields
+ *
+ * We store five "virtual" fields Xmin, Cmin, Xmax, Cmax, and Xvac
+ * in just three physical fields. Xmin is always really stored, but
+ * Cmin and Xmax share a field, as do Cmax and Xvac. This works because
+ * we know that there are only a limited number of states that a tuple can
+ * be in, and that Cmin and Cmax are only interesting for the lifetime of
+ * the inserting and deleting transactions respectively. We have the
+ * following possible states of a tuple:
+ *
+ * XMIN CMIN XMAX CMAX XVAC
+ *
+ * NEW (never deleted, not moved by vacuum):
+ * valid valid invalid invalid invalid
*
- * To avoid wasting space, the attributes should be layed out in such a
- * way to reduce structure padding. Note that t_hoff is the offset to
- * the start of the user data, and so must be a multiple of MAXALIGN.
- * Also note that we omit the nulls bitmap if t_infomask shows that there
- * are no nulls in the tuple.
+ * DELETED BY CREATING XACT:
+ * valid valid = XMIN valid invalid
+ *
+ * DELETED BY OTHER XACT:
+ * valid unneeded valid valid invalid
+ *
+ * MOVED BY VACUUM FULL:
+ * valid unneeded maybe-valid unneeded valid
+ *
+ * This assumes that VACUUM FULL never tries to move a tuple whose Cmin or
+ * Cmax is still interesting (ie, insert-in-progress or delete-in-progress).
+ *
+ * This table shows that if we use an infomask bit to handle the case
+ * XMAX=XMIN specially, we never need to store Cmin and Xmax at the same
+ * time. Nor do we need to store Cmax and Xvac at the same time.
+ *
+ * Following the fixed header fields, the nulls bitmap is stored (beginning
+ * at t_bits). The bitmap is *not* stored if t_infomask shows that there
+ * are no nulls in the tuple. If an OID field is present (as indicated by
+ * t_infomask), then it is stored just before the user data, which begins at
+ * the offset shown by t_hoff. Note that t_hoff must be a multiple of
+ * MAXALIGN.
+ *----------
*/
-/*
-** We store five "virtual" fields Xmin, Cmin, Xmax, Cmax, and Xvac
-** in three physical fields t_xmin, t_cid, t_xmax:
-** CommandId Cmin; insert CID stamp
-** CommandId Cmax; delete CommandId stamp
-** TransactionId Xmin; insert XID stamp
-** TransactionId Xmax; delete XID stamp
-** TransactionId Xvac; used by VACCUUM
-**
-** This assumes, that a CommandId can be stored in a TransactionId.
-*/
typedef struct HeapTupleHeaderData
{
- TransactionId t_xmin; /* Xmin -- 4 bytes each */
- TransactionId t_cid; /* Cmin, Cmax, Xvac */
- TransactionId t_xmax; /* Xmax, Cmax */
+ TransactionId t_xmin; /* inserting xact ID */
+
+ union {
+ CommandId t_cmin; /* inserting command ID */
+ TransactionId t_xmax; /* deleting xact ID */
+ } t_field2;
+
+ union {
+ CommandId t_cmax; /* deleting command ID */
+ TransactionId t_xvac; /* VACUUM FULL xact ID */
+ } t_field3;
ItemPointerData t_ctid; /* current TID of this or newer tuple */
#define HEAP_HASCOMPRESSED 0x0008 /* has compressed stored
* attribute(s) */
#define HEAP_HASEXTENDED 0x000C /* the two above combined */
-
-#define HEAP_XMIN_IS_XMAX 0x0040 /* created and deleted in the */
- /* same transaction */
-#define HEAP_XMAX_UNLOGGED 0x0080 /* to lock tuple for update */
- /* without logging */
+#define HEAP_HASOID 0x0010 /* has an object-id field */
+/* bit 0x0020 is presently unused */
+#define HEAP_XMAX_IS_XMIN 0x0040 /* created and deleted in the
+ * same transaction */
+#define HEAP_XMAX_UNLOGGED 0x0080 /* to lock tuple for update
+ * without logging */
#define HEAP_XMIN_COMMITTED 0x0100 /* t_xmin committed */
#define HEAP_XMIN_INVALID 0x0200 /* t_xmin invalid/aborted */
#define HEAP_XMAX_COMMITTED 0x0400 /* t_xmax committed */
#define HEAP_MARKED_FOR_UPDATE 0x1000 /* marked for UPDATE */
#define HEAP_UPDATED 0x2000 /* this is UPDATEd version of row */
#define HEAP_MOVED_OFF 0x4000 /* moved to another place by
- * vacuum */
+ * VACUUM FULL */
#define HEAP_MOVED_IN 0x8000 /* moved from another place by
- * vacuum */
+ * VACUUM FULL */
#define HEAP_MOVED (HEAP_MOVED_OFF | HEAP_MOVED_IN)
-#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 */
-
+#define HEAP_XACT_MASK 0xFFC0 /* visibility-related bits */
-/* 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) \
-)
-
+/*
+ * HeapTupleHeader accessor macros
+ *
+ * Note: beware of multiple evaluations of "tup" argument. But the Set
+ * macros evaluate their other argument only once.
+ */
#define HeapTupleHeaderGetXmin(tup) \
( \
(tup)->t_xmin \
)
-#define HeapTupleHeaderGetXmax(tup) \
-( \
- ((tup)->t_infomask & HEAP_XMIN_IS_XMAX) ? \
- (tup)->t_xmin \
- : \
- (tup)->t_xmax \
-)
-
-/* no AssertMacro, because this is read as a system-defined attribute */
-#define HeapTupleHeaderGetCmin(tup) \
+#define HeapTupleHeaderSetXmin(tup, xid) \
( \
- ((tup)->t_infomask & HEAP_MOVED) ? \
- FirstCommandId \
- : \
- ( \
- ((tup)->t_infomask & (HEAP_XMIN_IS_XMAX | HEAP_XMAX_INVALID)) ? \
- (CommandId) (tup)->t_cid \
- : \
- FirstCommandId \
- ) \
+ TransactionIdStore((xid), &(tup)->t_xmin) \
)
-#define HeapTupleHeaderGetCmax(tup) \
+#define HeapTupleHeaderGetXmax(tup) \
( \
- ((tup)->t_infomask & HEAP_MOVED) ? \
- FirstCommandId \
+ ((tup)->t_infomask & HEAP_XMAX_IS_XMIN) ? \
+ (tup)->t_xmin \
: \
- ( \
- ((tup)->t_infomask & (HEAP_XMIN_IS_XMAX | HEAP_XMAX_INVALID)) ? \
- (CommandId) (tup)->t_xmax \
- : \
- (CommandId) (tup)->t_cid \
- ) \
-)
-
-#define HeapTupleHeaderGetXvac(tup) \
-( \
- AssertMacro((tup)->t_infomask & HEAP_MOVED), \
- (tup)->t_cid \
-)
-
-
-#define HeapTupleHeaderSetXmin(tup, xid) \
-( \
- TransactionIdStore((xid), &(tup)->t_xmin) \
+ (tup)->t_field2.t_xmax \
)
-#define HeapTupleHeaderSetXminInvalid(tup) \
-do { \
- (tup)->t_infomask &= ~HEAP_XMIN_IS_XMAX; \
- StoreInvalidTransactionId(&(tup)->t_xmin); \
-} while (0)
-
#define HeapTupleHeaderSetXmax(tup, xid) \
do { \
- if (TransactionIdEquals((tup)->t_xmin, (xid))) \
- (tup)->t_infomask |= HEAP_XMIN_IS_XMAX; \
+ TransactionId _newxid = (xid); \
+ if (TransactionIdEquals((tup)->t_xmin, _newxid)) \
+ (tup)->t_infomask |= HEAP_XMAX_IS_XMIN; \
else \
{ \
- (tup)->t_infomask &= ~HEAP_XMIN_IS_XMAX; \
- TransactionIdStore((xid), &(tup)->t_xmax); \
+ (tup)->t_infomask &= ~HEAP_XMAX_IS_XMIN; \
+ TransactionIdStore(_newxid, &(tup)->t_field2.t_xmax); \
} \
} while (0)
-#define HeapTupleHeaderSetXmaxInvalid(tup) \
-do { \
- (tup)->t_infomask &= ~HEAP_XMIN_IS_XMAX; \
- StoreInvalidTransactionId(&(tup)->t_xmax); \
-} while (0)
+/*
+ * Note: GetCmin will produce wrong answers after SetXmax has been executed
+ * by a transaction other than the inserting one. We could check
+ * HEAP_XMAX_INVALID and return FirstCommandId if it's clear, but since that
+ * bit will be set again if the deleting transaction aborts, there'd be no
+ * real gain in safety from the extra test. So, just rely on the caller not
+ * to trust the value unless it's meaningful.
+ */
+#define HeapTupleHeaderGetCmin(tup) \
+( \
+ (tup)->t_field2.t_cmin \
+)
#define HeapTupleHeaderSetCmin(tup, cid) \
do { \
- Assert(!((tup)->t_infomask & HEAP_MOVED)); \
- TransactionIdStore((TransactionId) (cid), &(tup)->t_cid); \
+ Assert((tup)->t_infomask & HEAP_XMAX_INVALID); \
+ (tup)->t_field2.t_cmin = (cid); \
} while (0)
+/*
+ * As with GetCmin, we can't completely ensure that GetCmax can detect whether
+ * a valid command ID is available, and there's little point in a partial test.
+ */
+#define HeapTupleHeaderGetCmax(tup) \
+( \
+ (tup)->t_field3.t_cmax \
+)
+
#define HeapTupleHeaderSetCmax(tup, cid) \
do { \
Assert(!((tup)->t_infomask & HEAP_MOVED)); \
- if ((tup)->t_infomask & HEAP_XMIN_IS_XMAX) \
- TransactionIdStore((TransactionId) (cid), &(tup)->t_xmax); \
- else \
- TransactionIdStore((TransactionId) (cid), &(tup)->t_cid); \
+ (tup)->t_field3.t_cmax = (cid); \
} while (0)
+#define HeapTupleHeaderGetXvac(tup) \
+( \
+ ((tup)->t_infomask & HEAP_MOVED) ? \
+ (tup)->t_field3.t_xvac \
+ : \
+ InvalidTransactionId \
+)
+
#define HeapTupleHeaderSetXvac(tup, xid) \
do { \
Assert((tup)->t_infomask & HEAP_MOVED); \
- TransactionIdStore((xid), &(tup)->t_cid); \
+ TransactionIdStore((xid), &(tup)->t_field3.t_xvac); \
+} while (0)
+
+#define HeapTupleHeaderGetOid(tup) \
+( \
+ ((tup)->t_infomask & HEAP_HASOID) ? \
+ *((Oid *) ((char *)(tup) + (tup)->t_hoff - sizeof(Oid))) \
+ : \
+ InvalidOid \
+)
+
+#define HeapTupleHeaderSetOid(tup, oid) \
+do { \
+ Assert((tup)->t_infomask & HEAP_HASOID); \
+ *((Oid *) ((char *)(tup) + (tup)->t_hoff - sizeof(Oid))) = (oid); \
} while (0)
#define HEAPTUPLESIZE MAXALIGN(sizeof(HeapTupleData))
-/* ----------------
- * support macros
- * ----------------
+/*
+ * GETSTRUCT - given a HeapTuple pointer, return address of the user data
*/
-#define GETSTRUCT(TUP) (((char *)((HeapTuple)(TUP))->t_data) + \
- ((HeapTuple)(TUP))->t_data->t_hoff)
+#define GETSTRUCT(TUP) ((char *) ((TUP)->t_data) + (TUP)->t_data->t_hoff)
/*
#define HeapTupleIsValid(tuple) PointerIsValid(tuple)
#define HeapTupleNoNulls(tuple) \
- (!(((HeapTuple) (tuple))->t_data->t_infomask & HEAP_HASNULL))
+ (!((tuple)->t_data->t_infomask & HEAP_HASNULL))
#define HeapTupleAllFixed(tuple) \
- (!(((HeapTuple) (tuple))->t_data->t_infomask & HEAP_HASVARWIDTH))
+ (!((tuple)->t_data->t_infomask & HEAP_HASVARWIDTH))
#define HeapTupleHasExternal(tuple) \
- ((((HeapTuple)(tuple))->t_data->t_infomask & HEAP_HASEXTERNAL) != 0)
+ (((tuple)->t_data->t_infomask & HEAP_HASEXTERNAL) != 0)
#define HeapTupleHasCompressed(tuple) \
- ((((HeapTuple)(tuple))->t_data->t_infomask & HEAP_HASCOMPRESSED) != 0)
+ (((tuple)->t_data->t_infomask & HEAP_HASCOMPRESSED) != 0)
#define HeapTupleHasExtended(tuple) \
- ((((HeapTuple)(tuple))->t_data->t_infomask & HEAP_HASEXTENDED) != 0)
+ (((tuple)->t_data->t_infomask & HEAP_HASEXTENDED) != 0)
#define HeapTupleGetOid(tuple) \
- HeapTupleHeaderGetOid(((HeapTuple)(tuple))->t_data)
+ HeapTupleHeaderGetOid((tuple)->t_data)
#define HeapTupleSetOid(tuple, oid) \
- HeapTupleHeaderSetOid(((HeapTuple)(tuple))->t_data, (oid))
+ HeapTupleHeaderSetOid((tuple)->t_data, (oid))
#endif /* HTUP_H */
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: tupdesc.h,v 1.37 2002/07/20 05:16:59 momjian Exp $
+ * $Id: tupdesc.h,v 1.38 2002/09/02 01:05:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
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.
+ * pg_attribute, pg_attrdef, pg_constraint) for the structure of a tuple.
*/
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 */
+ bool tdhasoid; /* Tuple has oid attribute in its header */
} *TupleDesc;
-#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)
+extern TupleDesc CreateTemplateTupleDesc(int natts, bool hasoid);
-#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);
+extern TupleDesc CreateTupleDesc(int natts, bool hasoid,
+ Form_pg_attribute *attrs);
extern TupleDesc CreateTupleDescCopy(TupleDesc tupdesc);
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: catversion.h,v 1.156 2002/08/31 17:14:28 tgl Exp $
+ * $Id: catversion.h,v 1.157 2002/09/02 01:05:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
*/
/* yyyymmddN */
-#define CATALOG_VERSION_NO 200208311
+#define CATALOG_VERSION_NO 200209011
#endif
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: heap.h,v 1.55 2002/08/02 18:15:09 tgl Exp $
+ * $Id: heap.h,v 1.56 2002/09/02 01:05:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
TupleDesc tupdesc,
char relkind,
bool shared_relation,
- bool relhasoids,
bool allow_system_table_mods);
extern void heap_drop_with_catalog(Oid rid);
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: executor.h,v 1.76 2002/08/30 23:59:46 tgl Exp $
+ * $Id: executor.h,v 1.77 2002/09/02 01:05:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
extern TupleTableSlot *ExecInitExtraTupleSlot(EState *estate);
extern TupleTableSlot *ExecInitNullTupleSlot(EState *estate,
TupleDesc tupType);
-extern TupleDesc ExecTypeFromTL(List *targetList, hasoid_t withoid);
+extern TupleDesc ExecTypeFromTL(List *targetList, bool hasoid);
extern void SetChangedParamList(Plan *node, List *newchg);
typedef struct TupOutputState
* or in pg_config.h afterwards. Of course, if you edit pg_config.h, then your
* changes will be overwritten the next time you run configure.
*
- * $Id: pg_config.h.in,v 1.29 2002/08/29 08:03:22 ishii Exp $
+ * $Id: pg_config.h.in,v 1.30 2002/09/02 01:05:06 tgl Exp $
*/
#ifndef PG_CONFIG_H
/* #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
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: bufpage.h,v 1.51 2002/08/06 19:37:10 tgl Exp $
+ * $Id: bufpage.h,v 1.52 2002/09/02 01:05:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
* pd_lower - offset to start of free space.
* pd_upper - offset to end of free space.
* pd_special - offset to start of special space.
- * pd_pagesize - size in bytes.
- * Minimum possible page size is perhaps 64B to fit
- * page header, opaque space and a minimal tuple;
- * of course, in reality you want it much bigger.
- * On the high end, we can only support pages up
- * to 32KB because lp_off/lp_len are 15 bits.
+ * pd_pagesize_version - size in bytes and page layout version number.
+ *
+ * The page version number and page size are packed together into a single
+ * uint16 field. This is for historical reasons: before PostgreSQL 7.3,
+ * there was no concept of a page version number, and doing it this way
+ * lets us pretend that pre-7.3 databases have page version number zero.
+ * We constrain page sizes to be multiples of 256, leaving the low eight
+ * bytes available for a version number.
+ *
+ * Minimum possible page size is perhaps 64B to fit page header, opaque space
+ * and a minimal tuple; of course, in reality you want it much bigger, so
+ * the constraint on pagesize mod 256 is not an important restriction.
+ * On the high end, we can only support pages up to 32KB because lp_off/lp_len
+ * are 15 bits.
*/
typedef struct PageHeaderData
{
LocationIndex pd_lower; /* offset to start of free space */
LocationIndex pd_upper; /* offset to end of free space */
LocationIndex pd_special; /* offset to start of special space */
- uint16 pd_pagesize;
+ uint16 pd_pagesize_version;
ItemIdData pd_linp[1]; /* beginning of line pointer array */
} PageHeaderData;
typedef PageHeaderData *PageHeader;
+/*
+ * Page layout version number 0 is for pre-7.3 Postgres releases. The
+ * current version number is 1, denoting a new HeapTupleHeader layout.
+ */
+#define PG_PAGE_LAYOUT_VERSION 1
+
/* ----------------------------------------------------------------
* page support macros
((char *) (&((PageHeader) (page))->pd_linp[0]))
/* ----------------
- * macros to access opaque space
+ * macros to access page size info
* ----------------
*/
* however, it can be called on a page for which there is no buffer.
*/
#define PageGetPageSize(page) \
- ((Size) ((PageHeader) (page))->pd_pagesize)
+ ((Size) (((PageHeader) (page))->pd_pagesize_version & (uint16) 0xFF00))
/*
- * PageSetPageSize
- * Sets the page size of a page.
+ * PageGetPageLayoutVersion
+ * Returns the page layout version of a page.
+ *
+ * this can only be called on a formatted page (unlike
+ * BufferGetPageSize, which can be called on an unformatted page).
+ * however, it can be called on a page for which there is no buffer.
*/
-#define PageSetPageSize(page, size) \
- (((PageHeader) (page))->pd_pagesize = (size))
+#define PageGetPageLayoutVersion(page) \
+ (((PageHeader) (page))->pd_pagesize_version & 0x00FF)
+
+/*
+ * PageSetPageSizeAndVersion
+ * Sets the page size and page layout version number of a page.
+ *
+ * We could support setting these two values separately, but there's
+ * no real need for it at the moment.
+ */
+#define PageSetPageSizeAndVersion(page, size, version) \
+( \
+ AssertMacro(((size) & 0xFF00) == (size)), \
+ AssertMacro(((version) & 0x00FF) == (version)), \
+ ((PageHeader) (page))->pd_pagesize_version = (size) | (version) \
+)
/* ----------------
* page special data macros