Index: doc/src/sgml/catalogs.sgml
===================================================================
RCS file: /home/alvherre/cvs/pgsql/doc/src/sgml/catalogs.sgml,v
retrieving revision 2.124
diff -c -r2.124 catalogs.sgml
*** doc/src/sgml/catalogs.sgml 3 Jun 2006 02:53:04 -0000 2.124
--- doc/src/sgml/catalogs.sgml 12 Jun 2006 03:16:08 -0000
***************
*** 104,109 ****
--- 104,114 ----
+ pg_class_nt
+ non-transactional columns for pg_class
+
+
+ pg_constraintcheck constraints, unique constraints, primary key constraints, foreign key constraints
***************
*** 1465,1497 ****
- relpages
- int4
-
-
- Size of the on-disk representation of this table in pages (of size
- BLCKSZ).
- This is only an estimate used by the planner.
- It is updated by VACUUM,
- ANALYZE, and a few DDL commands
- such as CREATE INDEX.
-
-
-
-
- reltuples
- float4
-
-
- Number of rows in the table.
- This is only an estimate used by the planner.
- It is updated by VACUUM,
- ANALYZE, and a few DDL commands
- such as CREATE INDEX.
-
-
-
- reltoastrelidoidpg_class.oid
--- 1470,1475 ----
***************
*** 1512,1517 ****
--- 1490,1504 ----
+ relntrans
+ tid
+ pg_class_nt.ctid
+
+ CTID of this relation's pg_class_nt row.
+
+
+
+ relhasindexbool
***************
*** 1538,1547 ****
char
! r> = ordinary table, i> = index,
! S> = sequence, v> = view, c> =
! composite type, t> = TOAST
! table
--- 1525,1533 ----
char
! r> = ordinary table, i> = index, S> =
! sequence, v> = view, c> = composite type,
! t> = TOAST table, n> = non-transactional catalog
***************
*** 1648,1653 ****
--- 1634,1695 ----
+
+ pg_class_nt
+
+
+ pg_class_nt
+
+
+
+ The catalog pg_class_nt stores the non-transactional
+ information about pg_class entries, that is, the
+ information that is independent of the commit status of any particular
+ transaction.
+
+
+
+ pg_class_nt> Columns
+
+
+
+
+ Name
+ Type
+ References
+ Description
+
+
+
+
+
+ npages
+ int4
+
+
+ Size of the on-disk representation of this table in pages (of size
+ BLCKSZ). This is only an estimate used by the planner.
+ It is updated by VACUUM, ANALYZE,
+ and a few DDL commands such as CREATE INDEX.
+
+
+
+
+ ntuples
+ float4
+
+
+ Number of rows in the table. This is only an estimate used by the
+ planner. It is updated by VACUUM,
+ ANALYZE, and a few DDL commands such as
+ CREATE INDEX.
+
+
+
+
+
+
+
pg_constraint
Index: src/backend/access/heap/heapam.c
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/backend/access/heap/heapam.c,v
retrieving revision 1.213
diff -c -r1.213 heapam.c
*** src/backend/access/heap/heapam.c 28 May 2006 02:27:08 -0000 1.213
--- src/backend/access/heap/heapam.c 10 Jun 2006 23:17:47 -0000
***************
*** 1828,1833 ****
--- 1828,1839 ----
Assert(ItemPointerIsValid(otid));
+ if (relation->rd_rel->relkind == RELKIND_NON_TRANSACTIONAL)
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("can't update non-transactional catalog %s",
+ RelationGetRelationName(relation))));
+
buffer = ReadBuffer(relation, ItemPointerGetBlockNumber(otid));
LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
Index: src/backend/catalog/Makefile
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/backend/catalog/Makefile,v
retrieving revision 1.59
diff -c -r1.59 Makefile
*** src/backend/catalog/Makefile 12 Feb 2006 03:22:17 -0000 1.59
--- src/backend/catalog/Makefile 12 Jun 2006 16:39:21 -0000
***************
*** 24,33 ****
# Note: there are some undocumented dependencies on the ordering in which
# the catalog header files are assembled into postgres.bki. In particular,
! # indexing.h had better be last.
POSTGRES_BKI_SRCS := $(addprefix $(top_srcdir)/src/include/catalog/,\
! pg_proc.h pg_type.h pg_attribute.h pg_class.h pg_autovacuum.h \
pg_attrdef.h pg_constraint.h pg_inherits.h pg_index.h \
pg_operator.h pg_opclass.h pg_am.h pg_amop.h pg_amproc.h \
pg_language.h pg_largeobject.h pg_aggregate.h pg_statistic.h \
--- 24,34 ----
# Note: there are some undocumented dependencies on the ordering in which
# the catalog header files are assembled into postgres.bki. In particular,
! # indexing.h had better be last, and the bootstrapped catalogs must appear in
! # front.
POSTGRES_BKI_SRCS := $(addprefix $(top_srcdir)/src/include/catalog/,\
! pg_proc.h pg_type.h pg_attribute.h pg_class.h pg_class_nt.h pg_autovacuum.h \
pg_attrdef.h pg_constraint.h pg_inherits.h pg_index.h \
pg_operator.h pg_opclass.h pg_am.h pg_amop.h pg_amproc.h \
pg_language.h pg_largeobject.h pg_aggregate.h pg_statistic.h \
Index: src/backend/catalog/heap.c
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/backend/catalog/heap.c,v
retrieving revision 1.299
diff -c -r1.299 heap.c
*** src/backend/catalog/heap.c 10 May 2006 23:18:39 -0000 1.299
--- src/backend/catalog/heap.c 12 Jun 2006 03:56:23 -0000
***************
*** 37,42 ****
--- 37,43 ----
#include "catalog/index.h"
#include "catalog/indexing.h"
#include "catalog/pg_attrdef.h"
+ #include "catalog/pg_class_nt.h"
#include "catalog/pg_constraint.h"
#include "catalog/pg_inherits.h"
#include "catalog/pg_namespace.h"
***************
*** 66,71 ****
--- 67,73 ----
Relation new_rel_desc,
Oid new_rel_oid, Oid new_type_oid,
Oid relowner,
+ ItemPointerData nttid,
char relkind);
static Oid AddNewRelationType(const char *typeName,
Oid typeNamespace,
***************
*** 557,562 ****
--- 559,565 ----
Oid new_rel_oid,
Oid new_type_oid,
Oid relowner,
+ ItemPointerData nttid,
char relkind)
{
Form_pg_class new_rel_reltup;
***************
*** 568,597 ****
*/
new_rel_reltup = new_rel_desc->rd_rel;
- switch (relkind)
- {
- case RELKIND_RELATION:
- case RELKIND_INDEX:
- case RELKIND_TOASTVALUE:
- /* The relation is real, but as yet empty */
- new_rel_reltup->relpages = 0;
- new_rel_reltup->reltuples = 0;
- break;
- case RELKIND_SEQUENCE:
- /* Sequences always have a known size */
- new_rel_reltup->relpages = 1;
- new_rel_reltup->reltuples = 1;
- break;
- default:
- /* Views, etc, have no disk storage */
- new_rel_reltup->relpages = 0;
- new_rel_reltup->reltuples = 0;
- break;
- }
-
new_rel_reltup->relowner = relowner;
new_rel_reltup->reltype = new_type_oid;
new_rel_reltup->relkind = relkind;
new_rel_desc->rd_att->tdtypeid = new_type_oid;
--- 571,580 ----
*/
new_rel_reltup = new_rel_desc->rd_rel;
new_rel_reltup->relowner = relowner;
new_rel_reltup->reltype = new_type_oid;
new_rel_reltup->relkind = relkind;
+ new_rel_reltup->relntrans = nttid;
new_rel_desc->rd_att->tdtypeid = new_type_oid;
***************
*** 618,623 ****
--- 601,684 ----
heap_freetuple(tup);
}
+ /*
+ * AddNewNtClassTuple
+ *
+ * Insert a pg_class_nt tuple for the given relation, and return its
+ * TID.
+ */
+ ItemPointerData
+ AddNewNtClassTuple(Relation new_rel_desc, char relkind)
+ {
+ ItemPointerData tid;
+
+ /*
+ * We don't create pg_class_nt entries for sequences, views or composite
+ * types, because they don't have variable-size storage and thus they don't
+ * need it.
+ */
+ if (relkind == RELKIND_VIEW ||
+ relkind == RELKIND_COMPOSITE_TYPE ||
+ relkind == RELKIND_SEQUENCE)
+ {
+ ItemPointerSetInvalid(&tid);
+ }
+ else
+ {
+ Relation ntRel;
+ Form_pg_class_nt new_rel_nttup;
+ HeapTuple tup;
+
+ ntRel = heap_open(NtClassRelationId, RowExclusiveLock);
+
+ new_rel_nttup = (Form_pg_class_nt) palloc(sizeof(FormData_pg_class_nt));
+
+ /* choose the appropiate new values we want to insert */
+ switch (relkind)
+ {
+ case RELKIND_RELATION:
+ case RELKIND_INDEX:
+ case RELKIND_TOASTVALUE:
+ case RELKIND_NON_TRANSACTIONAL:
+ /* The relation is real, but as yet empty */
+ new_rel_nttup->npages = 0;
+ new_rel_nttup->ntuples = 0;
+ break;
+ default:
+ elog(ERROR, "can't create pg_class_nt entries for relkind '%c'",
+ relkind);
+ break;
+ }
+
+ /*
+ * now form a tuple to add to pg_class_nt
+ */
+ tup = heap_addheader(Natts_pg_class_nt,
+ false,
+ NTCLASS_TUPLE_SIZE,
+ (void *) new_rel_nttup);
+
+ /*
+ * finally insert the new tuple, update the indexes, and clean up.
+ */
+ simple_heap_insert(ntRel, tup);
+
+ /* Grab the newly inserted tuple's TID for saving it into pg_class */
+ tid = tup->t_self;
+
+ #ifdef NOT_USED
+ /* pg_class_nt does not have indexes */
+ CatalogUpdateIndexes(ntRel, tup);
+ #endif
+
+ heap_close(ntRel, RowExclusiveLock);
+
+ heap_freetuple(tup);
+ pfree(new_rel_nttup);
+ }
+
+ return tid;
+ }
/* --------------------------------
* AddNewRelationType -
***************
*** 679,684 ****
--- 740,747 ----
Relation pg_class_desc;
Relation new_rel_desc;
Oid new_type_oid;
+ ItemPointerData nttid;
+
pg_class_desc = heap_open(RelationRelationId, RowExclusiveLock);
***************
*** 733,738 ****
--- 796,806 ----
relkind);
/*
+ * Create a pg_class_nt entry for the relation.
+ */
+ nttid = AddNewNtClassTuple(new_rel_desc, relkind);
+
+ /*
* now create an entry in pg_class for the relation.
*
* NOTE: we could get a unique-index failure here, in case someone else is
***************
*** 744,749 ****
--- 812,818 ----
relid,
new_type_oid,
ownerid,
+ nttid,
relkind);
/*
***************
*** 872,877 ****
--- 941,962 ----
heap_close(pg_class_desc, RowExclusiveLock);
}
+ void
+ DeleteNtClassTuple(ItemPointer tid)
+ {
+ Relation pg_class_nt;
+
+ /* some relations don't have pg_class_nt tuples */
+ if (!ItemPointerIsValid(tid))
+ return;
+
+ pg_class_nt = heap_open(NtClassRelationId, RowExclusiveLock);
+
+ simple_heap_delete(pg_class_nt, tid);
+
+ heap_close(pg_class_nt, RowExclusiveLock);
+ }
+
/*
* DeleteAttributeTuples
*
***************
*** 1159,1164 ****
--- 1244,1252 ----
smgrscheduleunlink(rel->rd_smgr, rel->rd_istemp);
}
+ /* Delete the pg_class_nt tuple */
+ DeleteNtClassTuple(&(rel->rd_rel->relntrans));
+
/*
* Close relcache entry, but *keep* AccessExclusiveLock on the relation
* until transaction commit. This ensures no one else will try to do
***************
*** 2133,2135 ****
--- 2221,2293 ----
return result;
}
+
+ /*
+ * Return the number of tuples and pages for a given relation, as recorded in
+ * its pg_class_nt entry. ntuples and npages are output parameters, and can be
+ * NULL if the caller does not need them.
+ */
+ void
+ relation_get_ntups_npages(Relation relation, float4 *ntuples, int4 *npages)
+ {
+ HeapTuple tup;
+ Relation pg_class_nt;
+ Form_pg_class_nt ntForm;
+
+ pg_class_nt = heap_open(NtClassRelationId, AccessShareLock);
+
+ tup = get_class_nt_entry(pg_class_nt, relation);
+ ntForm = (Form_pg_class_nt) GETSTRUCT(tup);
+
+ if (ntuples != NULL)
+ *ntuples = ntForm->ntuples;
+ if (npages != NULL)
+ *npages = ntForm->npages;
+
+ heap_freetuple(tup);
+ heap_close(pg_class_nt, AccessShareLock);
+ }
+
+ /*
+ * get_class_nt_entry
+ * Return a copy of the pg_class_nt tuple for the given target relation.
+ *
+ * The first argument is the pg_class_nt relation, already open and suitably
+ * locked. If the caller is going to call update_class_nt_entry later, it
+ * must be locked with at least RowExclusiveLock.
+ */
+ HeapTuple
+ get_class_nt_entry(Relation pg_class_nt, Relation target)
+ {
+ HeapTupleData tuple;
+ HeapTuple retval;
+ Buffer buffer;
+
+ Assert(ItemPointerIsValid(&(target->rd_rel->relntrans)));
+
+ tuple.t_self = target->rd_rel->relntrans;
+
+ if (!heap_fetch(pg_class_nt, SnapshotNow, &tuple, &buffer, false, NULL))
+ elog(ERROR, "lookup failed for pg_class_nt entry for relation %s",
+ RelationGetRelationName(target));
+
+ retval = heap_copytuple(&tuple);
+ ReleaseBuffer(buffer);
+
+ return retval;
+ }
+
+ /*
+ * update_class_nt_entry
+ * Update a given pg_class_nt entry.
+ *
+ * The passed tuple should have been obtained by get_class_nt_entry.
+ */
+ void
+ update_class_nt_entry(Relation pg_class_nt, HeapTuple tuple)
+ {
+ elog(DEBUG2, "updating pg_class_nt entry (%u/%u)",
+ ItemPointerGetBlockNumber(&(tuple->t_self)),
+ ItemPointerGetOffsetNumber(&(tuple->t_self)));
+ heap_inplace_update(pg_class_nt, tuple);
+ }
Index: src/backend/catalog/index.c
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/backend/catalog/index.c,v
retrieving revision 1.266
diff -c -r1.266 index.c
*** src/backend/catalog/index.c 10 May 2006 23:18:39 -0000 1.266
--- src/backend/catalog/index.c 12 Jun 2006 16:30:11 -0000
***************
*** 31,36 ****
--- 31,37 ----
#include "catalog/heap.h"
#include "catalog/index.h"
#include "catalog/indexing.h"
+ #include "catalog/pg_class_nt.h"
#include "catalog/pg_constraint.h"
#include "catalog/pg_opclass.h"
#include "catalog/pg_type.h"
***************
*** 569,575 ****
/*
* Fill in fields of the index's pg_class entry that are not set correctly
! * by heap_create.
*
* XXX should have a cleaner way to create cataloged indexes
*/
--- 570,576 ----
/*
* Fill in fields of the index's pg_class entry that are not set correctly
! * by heap_create, and create the pg_class_nt entry.
*
* XXX should have a cleaner way to create cataloged indexes
*/
***************
*** 577,582 ****
--- 578,585 ----
indexRelation->rd_rel->relam = accessMethodObjectId;
indexRelation->rd_rel->relkind = RELKIND_INDEX;
indexRelation->rd_rel->relhasoids = false;
+ indexRelation->rd_rel->relntrans =
+ AddNewNtClassTuple(indexRelation, RELKIND_INDEX);
/*
* store index's pg_class entry
***************
*** 756,761 ****
--- 759,768 ----
}
else if (skip_build)
{
+ float4 ntuples;
+
+ relation_get_ntups_npages(heapRelation, &ntuples, NULL);
+
/*
* Caller is responsible for filling the index later on. However,
* we'd better make sure that the heap relation is correctly marked
***************
*** 765,771 ****
true,
isprimary,
InvalidOid,
! heapRelation->rd_rel->reltuples);
/* Make the above update visible */
CommandCounterIncrement();
}
--- 772,778 ----
true,
isprimary,
InvalidOid,
! ntuples);
/* Make the above update visible */
CommandCounterIncrement();
}
***************
*** 826,831 ****
--- 833,841 ----
smgrscheduleunlink(userIndexRelation->rd_smgr,
userIndexRelation->rd_istemp);
+ /* delete pg_class_nt tuple */
+ DeleteNtClassTuple(&(userIndexRelation->rd_rel->relntrans));
+
/*
* Close and flush the index's relcache entry, to ensure relcache doesn't
* try to rebuild it while we're deleting catalog entries. We keep the
***************
*** 1011,1027 ****
/*
* index_update_stats --- update pg_class entry after CREATE INDEX
*
! * This routine updates the pg_class row of either an index or its parent
! * relation after CREATE INDEX. Its rather bizarre API is designed to
! * ensure we can do all the necessary work in just one update.
*
* hasindex: set relhasindex to this value
* isprimary: if true, set relhaspkey true; else no change
* reltoastidxid: if not InvalidOid, set reltoastidxid to this value;
* else no change
! * reltuples: set reltuples to this value
*
! * relpages is also updated (using RelationGetNumberOfBlocks()).
*
* NOTE: an important side-effect of this operation is that an SI invalidation
* message is sent out to all backends --- including me --- causing relcache
--- 1021,1037 ----
/*
* index_update_stats --- update pg_class entry after CREATE INDEX
*
! * This routine updates the pg_class and pg_class_nt rows of either an index or
! * its parent relation after CREATE INDEX. Its rather bizarre API is designed
! * to ensure we can do all the necessary work in just one update.
*
* hasindex: set relhasindex to this value
* isprimary: if true, set relhaspkey true; else no change
* reltoastidxid: if not InvalidOid, set reltoastidxid to this value;
* else no change
! * pg_class_nt.ntuples: set reltuples to this value
*
! * pg_class_nt.npages is also updated (using RelationGetNumberOfBlocks()).
*
* NOTE: an important side-effect of this operation is that an SI invalidation
* message is sent out to all backends --- including me --- causing relcache
***************
*** 1038,1045 ****
--- 1048,1057 ----
BlockNumber relpages = RelationGetNumberOfBlocks(rel);
Oid relid = RelationGetRelid(rel);
Relation pg_class;
+ Relation pg_class_nt;
HeapTuple tuple;
Form_pg_class rd_rel;
+ Form_pg_class_nt ntForm;
bool in_place_upd;
bool dirty;
***************
*** 1112,1127 ****
dirty = true;
}
}
- if (rd_rel->reltuples != (float4) reltuples)
- {
- rd_rel->reltuples = (float4) reltuples;
- dirty = true;
- }
- if (rd_rel->relpages != (int32) relpages)
- {
- rd_rel->relpages = (int32) relpages;
- dirty = true;
- }
/*
* If anything changed, write out the tuple
--- 1124,1129 ----
***************
*** 1185,1190 ****
--- 1187,1216 ----
heap_freetuple(tuple);
heap_close(pg_class, RowExclusiveLock);
+
+ /* update the non-transactional (pg_class_nt) entry */
+ pg_class_nt = heap_open(NtClassRelationId, RowExclusiveLock);
+
+ tuple = get_class_nt_entry(pg_class_nt, rel);
+
+ ntForm = (Form_pg_class_nt) GETSTRUCT(tuple);
+
+ dirty = false;
+ if (ntForm->ntuples != (float4) reltuples)
+ {
+ ntForm->ntuples = (float4) reltuples;
+ dirty = true;
+ }
+ if (ntForm->npages != (int32) relpages)
+ {
+ ntForm->npages = (int32) relpages;
+ dirty = true;
+ }
+ if (dirty)
+ update_class_nt_entry(pg_class_nt, tuple);
+ heap_freetuple(tuple);
+
+ heap_close(pg_class_nt, RowExclusiveLock);
}
/*
***************
*** 1240,1249 ****
RelationOpenSmgr(relation);
smgrscheduleunlink(relation->rd_smgr, relation->rd_istemp);
! /* update the pg_class row */
rd_rel->relfilenode = newrelfilenode;
- rd_rel->relpages = 0; /* it's empty until further notice */
- rd_rel->reltuples = 0;
simple_heap_update(pg_class, &tuple->t_self, tuple);
CatalogUpdateIndexes(pg_class, tuple);
--- 1266,1278 ----
RelationOpenSmgr(relation);
smgrscheduleunlink(relation->rd_smgr, relation->rd_istemp);
! /*
! * Update the pg_class row. The caller is responsible for ensuring the
! * pg_class_nt entry is correct. While we could update it here, it's just
! * a waste of time to set the values to 0, because currently all callers
! * set them to the correct values sometime after calling us.
! */
rd_rel->relfilenode = newrelfilenode;
simple_heap_update(pg_class, &tuple->t_self, tuple);
CatalogUpdateIndexes(pg_class, tuple);
Index: src/backend/commands/analyze.c
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/backend/commands/analyze.c,v
retrieving revision 1.93
diff -c -r1.93 analyze.c
*** src/backend/commands/analyze.c 23 Mar 2006 00:19:28 -0000 1.93
--- src/backend/commands/analyze.c 12 Jun 2006 16:44:32 -0000
***************
*** 159,164 ****
--- 159,174 ----
}
/*
+ * We don't process RELKIND_NON_TRANSACTIONAL relations, but we don't
+ * complain since VACUUM processes them but we don't.
+ */
+ if (onerel->rd_rel->relkind == RELKIND_NON_TRANSACTIONAL)
+ {
+ relation_close(onerel, AccessShareLock);
+ return;
+ }
+
+ /*
* Check that it's a plain table; we used to do this in get_rel_oids() but
* seems safer to check after we've locked the relation.
*/
***************
*** 422,428 ****
*/
if (!vacstmt->vacuum)
{
! vac_update_relstats(RelationGetRelid(onerel),
RelationGetNumberOfBlocks(onerel),
totalrows,
hasindex);
--- 432,438 ----
*/
if (!vacstmt->vacuum)
{
! vac_update_relstats(onerel,
RelationGetNumberOfBlocks(onerel),
totalrows,
hasindex);
***************
*** 432,438 ****
double totalindexrows;
totalindexrows = ceil(thisdata->tupleFract * totalrows);
! vac_update_relstats(RelationGetRelid(Irel[ind]),
RelationGetNumberOfBlocks(Irel[ind]),
totalindexrows,
false);
--- 442,448 ----
double totalindexrows;
totalindexrows = ceil(thisdata->tupleFract * totalrows);
! vac_update_relstats(Irel[ind],
RelationGetNumberOfBlocks(Irel[ind]),
totalindexrows,
false);
Index: src/backend/commands/cluster.c
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/backend/commands/cluster.c,v
retrieving revision 1.147
diff -c -r1.147 cluster.c
*** src/backend/commands/cluster.c 2 May 2006 22:25:10 -0000 1.147
--- src/backend/commands/cluster.c 12 Jun 2006 03:48:28 -0000
***************
*** 728,733 ****
--- 728,734 ----
relform2;
Oid swaptemp;
CatalogIndexState indstate;
+ ItemPointerData swap_tid;
/* We need writable copies of both pg_class tuples. */
relRelation = heap_open(RelationRelationId, RowExclusiveLock);
***************
*** 763,781 ****
/* we should not swap reltoastidxid */
! /* swap size statistics too, since new rel has freshly-updated stats */
! {
! int4 swap_pages;
! float4 swap_tuples;
!
! swap_pages = relform1->relpages;
! relform1->relpages = relform2->relpages;
! relform2->relpages = swap_pages;
!
! swap_tuples = relform1->reltuples;
! relform1->reltuples = relform2->reltuples;
! relform2->reltuples = swap_tuples;
! }
/* Update the tuples in pg_class */
simple_heap_update(relRelation, &reltup1->t_self, reltup1);
--- 764,779 ----
/* we should not swap reltoastidxid */
! /*
! * Swap pg_class_nt rows too. This automatically updates the
! * size statistics.
! *
! * XXX make sure this is still correct when adding more rows to
! * pg_class_nt.
! */
! swap_tid = relform1->relntrans;
! relform1->relntrans = relform2->relntrans;
! relform2->relntrans = swap_tid;
/* Update the tuples in pg_class */
simple_heap_update(relRelation, &reltup1->t_self, reltup1);
Index: src/backend/commands/vacuum.c
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/backend/commands/vacuum.c,v
retrieving revision 1.330
diff -c -r1.330 vacuum.c
*** src/backend/commands/vacuum.c 10 May 2006 23:18:39 -0000 1.330
--- src/backend/commands/vacuum.c 12 Jun 2006 04:03:01 -0000
***************
*** 28,35 ****
--- 28,37 ----
#include "access/subtrans.h"
#include "access/xlog.h"
#include "catalog/catalog.h"
+ #include "catalog/heap.h"
#include "catalog/indexing.h"
#include "catalog/namespace.h"
+ #include "catalog/pg_class_nt.h"
#include "catalog/pg_database.h"
#include "catalog/pg_index.h"
#include "commands/dbcommands.h"
***************
*** 200,212 ****
/* non-export function prototypes */
static List *get_rel_oids(List *relids, const RangeVar *vacrel,
! const char *stmttype);
static void vac_update_dbstats(Oid dbid,
TransactionId vacuumXID,
TransactionId frozenXID);
static void vac_truncate_clog(TransactionId vacuumXID,
TransactionId frozenXID);
! static bool vacuum_rel(Oid relid, VacuumStmt *vacstmt, char expected_relkind);
static void full_vacuum_rel(Relation onerel, VacuumStmt *vacstmt);
static void scan_heap(VRelStats *vacrelstats, Relation onerel,
VacPageList vacuum_pages, VacPageList fraged_pages);
--- 202,214 ----
/* non-export function prototypes */
static List *get_rel_oids(List *relids, const RangeVar *vacrel,
! const char *stmttype, bool full);
static void vac_update_dbstats(Oid dbid,
TransactionId vacuumXID,
TransactionId frozenXID);
static void vac_truncate_clog(TransactionId vacuumXID,
TransactionId frozenXID);
! static bool vacuum_rel(Oid relid, VacuumStmt *vacstmt, bool allow_toast);
static void full_vacuum_rel(Relation onerel, VacuumStmt *vacstmt);
static void scan_heap(VRelStats *vacrelstats, Relation onerel,
VacPageList vacuum_pages, VacPageList fraged_pages);
***************
*** 350,356 ****
* Build list of relations to process, unless caller gave us one. (If we
* build one, we put it in vac_context for safekeeping.)
*/
! relations = get_rel_oids(relids, vacstmt->relation, stmttype);
if (vacstmt->vacuum && all_rels)
{
--- 352,359 ----
* Build list of relations to process, unless caller gave us one. (If we
* build one, we put it in vac_context for safekeeping.)
*/
! relations = get_rel_oids(relids, vacstmt->relation, stmttype,
! vacstmt->full);
if (vacstmt->vacuum && all_rels)
{
***************
*** 446,452 ****
if (vacstmt->vacuum)
{
! if (!vacuum_rel(relid, vacstmt, RELKIND_RELATION))
all_rels = false; /* forget about updating dbstats */
}
if (vacstmt->analyze)
--- 449,455 ----
if (vacstmt->vacuum)
{
! if (!vacuum_rel(relid, vacstmt, false))
all_rels = false; /* forget about updating dbstats */
}
if (vacstmt->analyze)
***************
*** 563,569 ****
* per-relation transactions.
*/
static List *
! get_rel_oids(List *relids, const RangeVar *vacrel, const char *stmttype)
{
List *oid_list = NIL;
MemoryContext oldcontext;
--- 566,573 ----
* per-relation transactions.
*/
static List *
! get_rel_oids(List *relids, const RangeVar *vacrel, const char *stmttype,
! bool full)
{
List *oid_list = NIL;
MemoryContext oldcontext;
***************
*** 590,608 ****
Relation pgclass;
HeapScanDesc scan;
HeapTuple tuple;
- ScanKeyData key;
-
- ScanKeyInit(&key,
- Anum_pg_class_relkind,
- BTEqualStrategyNumber, F_CHAREQ,
- CharGetDatum(RELKIND_RELATION));
pgclass = heap_open(RelationRelationId, AccessShareLock);
! scan = heap_beginscan(pgclass, SnapshotNow, 1, &key);
while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
{
/* Make a relation list entry for this guy */
oldcontext = MemoryContextSwitchTo(vac_context);
oid_list = lappend_oid(oid_list, HeapTupleGetOid(tuple));
--- 594,620 ----
Relation pgclass;
HeapScanDesc scan;
HeapTuple tuple;
pgclass = heap_open(RelationRelationId, AccessShareLock);
! scan = heap_beginscan(pgclass, SnapshotNow, 0, NULL);
while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
{
+ Form_pg_class classForm;
+ char relkind;
+
+ classForm = (Form_pg_class) GETSTRUCT(tuple);
+ relkind = classForm->relkind;
+
+ /* we only process plain and non-transactional tables */
+ if (relkind != RELKIND_RELATION &&
+ relkind != RELKIND_NON_TRANSACTIONAL)
+ continue;
+ /* we only process non-transactional catalogs on lazy vacuum */
+ if (relkind == RELKIND_NON_TRANSACTIONAL && full)
+ continue;
+
/* Make a relation list entry for this guy */
oldcontext = MemoryContextSwitchTo(vac_context);
oid_list = lappend_oid(oid_list, HeapTupleGetOid(tuple));
***************
*** 669,677 ****
* vac_update_relstats() -- update statistics for one relation
*
* Update the whole-relation statistics that are kept in its pg_class
! * row. There are additional stats that will be updated if we are
! * doing ANALYZE, but we always update these stats. This routine works
! * for both index and heap relation entries in pg_class.
*
* We violate transaction semantics here by overwriting the rel's
* existing pg_class tuple with the new values. This is reasonably
--- 681,689 ----
* vac_update_relstats() -- update statistics for one relation
*
* Update the whole-relation statistics that are kept in its pg_class
! * and pg_class_nt rows. There are additional stats that will be updated
! * if we are doing ANALYZE, but we always update these stats. This
! * routine works for both index and heap relation entries in pg_class.
*
* We violate transaction semantics here by overwriting the rel's
* existing pg_class tuple with the new values. This is reasonably
***************
*** 679,723 ****
* commits. The reason for this is that if we updated these tuples in
* the usual way, vacuuming pg_class itself wouldn't work very well ---
* by the time we got done with a vacuum cycle, most of the tuples in
! * pg_class would've been obsoleted. Of course, this only works for
! * fixed-size never-null columns, but these are.
*
* This routine is shared by full VACUUM, lazy VACUUM, and stand-alone
* ANALYZE.
*/
void
! vac_update_relstats(Oid relid, BlockNumber num_pages, double num_tuples,
bool hasindex)
{
Relation rd;
HeapTuple ctup;
Form_pg_class pgcform;
bool dirty;
rd = heap_open(RelationRelationId, RowExclusiveLock);
/* Fetch a copy of the tuple to scribble on */
ctup = SearchSysCacheCopy(RELOID,
! ObjectIdGetDatum(relid),
0, 0, 0);
if (!HeapTupleIsValid(ctup))
elog(ERROR, "pg_class entry for relid %u vanished during vacuuming",
! relid);
pgcform = (Form_pg_class) GETSTRUCT(ctup);
/* Apply required updates, if any, to copied tuple */
dirty = false;
- if (pgcform->relpages != (int32) num_pages)
- {
- pgcform->relpages = (int32) num_pages;
- dirty = true;
- }
- if (pgcform->reltuples != (float4) num_tuples)
- {
- pgcform->reltuples = (float4) num_tuples;
- dirty = true;
- }
if (pgcform->relhasindex != hasindex)
{
pgcform->relhasindex = hasindex;
--- 691,758 ----
* commits. The reason for this is that if we updated these tuples in
* the usual way, vacuuming pg_class itself wouldn't work very well ---
* by the time we got done with a vacuum cycle, most of the tuples in
! * them would've been obsoleted. Of course, this only works for
! * fixed-size never-null columns, but these are. Also, note this doesn't
! * apply to pg_class_nt, because by definition of non-transactional
! * catalog we must always update it in-place.
*
* This routine is shared by full VACUUM, lazy VACUUM, and stand-alone
* ANALYZE.
*/
void
! vac_update_relstats(Relation rel, BlockNumber num_pages, double num_tuples,
bool hasindex)
{
Relation rd;
HeapTuple ctup;
+ Form_pg_class_nt pgntform;
Form_pg_class pgcform;
bool dirty;
+ /* Process pg_class_nt first */
+ rd = heap_open(NtClassRelationId, RowExclusiveLock);
+
+ /* Fetch a copy of the pg_class_nt tuple to scribble on */
+ ctup = get_class_nt_entry(rd, rel);
+
+ pgntform = (Form_pg_class_nt) GETSTRUCT(ctup);
+
+ /* Apply required updates, if any, to copied tuple */
+
+ dirty = false;
+ if (pgntform->npages != (int32) num_pages)
+ {
+ pgntform->npages = (int32) num_pages;
+ dirty = true;
+ }
+ if (pgntform->ntuples != (float4) num_tuples)
+ {
+ pgntform->ntuples = (float4) num_tuples;
+ dirty = true;
+ }
+
+ /* If anything changed, write out the tuple */
+ if (dirty)
+ update_class_nt_entry(rd, ctup);
+ heap_freetuple(ctup);
+
+ heap_close(rd, RowExclusiveLock);
+
+ /* Now go for the pg_class tuple */
rd = heap_open(RelationRelationId, RowExclusiveLock);
/* Fetch a copy of the tuple to scribble on */
ctup = SearchSysCacheCopy(RELOID,
! ObjectIdGetDatum(RelationGetRelid(rel)),
0, 0, 0);
if (!HeapTupleIsValid(ctup))
elog(ERROR, "pg_class entry for relid %u vanished during vacuuming",
! RelationGetRelid(rel));
pgcform = (Form_pg_class) GETSTRUCT(ctup);
/* Apply required updates, if any, to copied tuple */
dirty = false;
if (pgcform->relhasindex != hasindex)
{
pgcform->relhasindex = hasindex;
***************
*** 934,940 ****
* At entry and exit, we are not inside a transaction.
*/
static bool
! vacuum_rel(Oid relid, VacuumStmt *vacstmt, char expected_relkind)
{
LOCKMODE lmode;
Relation onerel;
--- 969,975 ----
* At entry and exit, we are not inside a transaction.
*/
static bool
! vacuum_rel(Oid relid, VacuumStmt *vacstmt, bool allow_toast)
{
LOCKMODE lmode;
Relation onerel;
***************
*** 1005,1013 ****
/*
* Check that it's a plain table; we used to do this in get_rel_oids() but
! * seems safer to check after we've locked the relation.
*/
! if (onerel->rd_rel->relkind != expected_relkind)
{
ereport(WARNING,
(errmsg("skipping \"%s\" --- cannot vacuum indexes, views, or special system tables",
--- 1040,1051 ----
/*
* Check that it's a plain table; we used to do this in get_rel_oids() but
! * seems safer to check after we've locked the relation. We only accept
! * TOAST tables if the caller told us it's OK to do so.
*/
! if (!(onerel->rd_rel->relkind == RELKIND_RELATION ||
! onerel->rd_rel->relkind == RELKIND_NON_TRANSACTIONAL ||
! (onerel->rd_rel->relkind == RELKIND_TOASTVALUE && allow_toast)))
{
ereport(WARNING,
(errmsg("skipping \"%s\" --- cannot vacuum indexes, views, or special system tables",
***************
*** 1019,1024 ****
--- 1057,1078 ----
}
/*
+ * We only process non-transactional catalogs in lazy vacuum, because they
+ * are referenced by TID and applying VACUUM FULL to them would destroy the
+ * references.
+ */
+ if (onerel->rd_rel->relkind == RELKIND_NON_TRANSACTIONAL && vacstmt->full)
+ {
+ ereport(WARNING,
+ (errmsg("skipping \"%s\" --- cannot vacuum non-transactional catalogs in VACUUM FULL",
+ RelationGetRelationName(onerel))));
+ relation_close(onerel, lmode);
+ StrategyHintVacuum(false);
+ CommitTransactionCommand();
+ return false;
+ }
+
+ /*
* Silently ignore tables that are temp tables of other backends ---
* trying to vacuum these will lead to great unhappiness, since their
* contents are probably not up-to-date on disk. (We don't throw a
***************
*** 1079,1085 ****
*/
if (toast_relid != InvalidOid)
{
! if (!vacuum_rel(toast_relid, vacstmt, RELKIND_TOASTVALUE))
result = false; /* failed to vacuum the TOAST table? */
}
--- 1133,1139 ----
*/
if (toast_relid != InvalidOid)
{
! if (!vacuum_rel(toast_relid, vacstmt, true))
result = false; /* failed to vacuum the TOAST table? */
}
***************
*** 1179,1185 ****
vac_update_fsm(onerel, &fraged_pages, vacrelstats->rel_pages);
/* update statistics in pg_class */
! vac_update_relstats(RelationGetRelid(onerel), vacrelstats->rel_pages,
vacrelstats->rel_tuples, vacrelstats->hasindex);
/* report results to the stats collector, too */
--- 1233,1239 ----
vac_update_fsm(onerel, &fraged_pages, vacrelstats->rel_pages);
/* update statistics in pg_class */
! vac_update_relstats(onerel, vacrelstats->rel_pages,
vacrelstats->rel_tuples, vacrelstats->hasindex);
/* report results to the stats collector, too */
***************
*** 2938,2944 ****
return;
/* now update statistics in pg_class */
! vac_update_relstats(RelationGetRelid(indrel),
stats->num_pages, stats->num_index_tuples,
false);
--- 2992,2998 ----
return;
/* now update statistics in pg_class */
! vac_update_relstats(indrel,
stats->num_pages, stats->num_index_tuples,
false);
***************
*** 3007,3013 ****
return;
/* now update statistics in pg_class */
! vac_update_relstats(RelationGetRelid(indrel),
stats->num_pages, stats->num_index_tuples,
false);
--- 3061,3067 ----
return;
/* now update statistics in pg_class */
! vac_update_relstats(indrel,
stats->num_pages, stats->num_index_tuples,
false);
Index: src/backend/commands/vacuumlazy.c
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/backend/commands/vacuumlazy.c,v
retrieving revision 1.70
diff -c -r1.70 vacuumlazy.c
*** src/backend/commands/vacuumlazy.c 2 May 2006 22:25:10 -0000 1.70
--- src/backend/commands/vacuumlazy.c 10 Jun 2006 23:17:47 -0000
***************
*** 175,181 ****
lazy_update_fsm(onerel, vacrelstats);
/* Update statistics in pg_class */
! vac_update_relstats(RelationGetRelid(onerel),
vacrelstats->rel_pages,
vacrelstats->rel_tuples,
hasindex);
--- 175,181 ----
lazy_update_fsm(onerel, vacrelstats);
/* Update statistics in pg_class */
! vac_update_relstats(onerel,
vacrelstats->rel_pages,
vacrelstats->rel_tuples,
hasindex);
***************
*** 667,673 ****
return;
/* now update statistics in pg_class */
! vac_update_relstats(RelationGetRelid(indrel),
stats->num_pages,
stats->num_index_tuples,
false);
--- 667,673 ----
return;
/* now update statistics in pg_class */
! vac_update_relstats(indrel,
stats->num_pages,
stats->num_index_tuples,
false);
Index: src/backend/optimizer/util/plancat.c
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/backend/optimizer/util/plancat.c,v
retrieving revision 1.119
diff -c -r1.119 plancat.c
*** src/backend/optimizer/util/plancat.c 5 Mar 2006 15:58:31 -0000 1.119
--- src/backend/optimizer/util/plancat.c 10 Jun 2006 23:17:47 -0000
***************
*** 19,24 ****
--- 19,25 ----
#include "access/genam.h"
#include "access/heapam.h"
+ #include "catalog/heap.h"
#include "catalog/pg_amop.h"
#include "catalog/pg_inherits.h"
#include "catalog/pg_index.h"
***************
*** 235,240 ****
--- 236,243 ----
BlockNumber relpages;
double reltuples;
double density;
+ int4 npages;
+ float4 ntuples;
switch (rel->rd_rel->relkind)
{
***************
*** 263,269 ****
* world, and it shouldn't degrade the quality of the plan too
* much anyway to err in this direction.
*/
! if (curpages < 10 && rel->rd_rel->relpages == 0)
curpages = 10;
/* report estimated # pages */
--- 266,273 ----
* world, and it shouldn't degrade the quality of the plan too
* much anyway to err in this direction.
*/
! relation_get_ntups_npages(rel, &ntuples, &npages);
! if (curpages < 10 && ntuples == 0)
curpages = 10;
/* report estimated # pages */
***************
*** 275,282 ****
break;
}
/* coerce values in pg_class to more desirable types */
! relpages = (BlockNumber) rel->rd_rel->relpages;
! reltuples = (double) rel->rd_rel->reltuples;
/*
* If it's an index, discount the metapage. This is a kluge
--- 279,286 ----
break;
}
/* coerce values in pg_class to more desirable types */
! relpages = (BlockNumber) npages;
! reltuples = (double) ntuples;
/*
* If it's an index, discount the metapage. This is a kluge
Index: src/backend/postmaster/autovacuum.c
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/backend/postmaster/autovacuum.c,v
retrieving revision 1.19
diff -c -r1.19 autovacuum.c
*** src/backend/postmaster/autovacuum.c 19 May 2006 15:15:37 -0000 1.19
--- src/backend/postmaster/autovacuum.c 12 Jun 2006 03:51:26 -0000
***************
*** 24,29 ****
--- 24,30 ----
#include "access/genam.h"
#include "access/heapam.h"
#include "access/xlog.h"
+ #include "catalog/heap.h"
#include "catalog/indexing.h"
#include "catalog/namespace.h"
#include "catalog/pg_autovacuum.h"
***************
*** 615,623 ****
ScanKeyData entry[1];
Oid relid;
! /* Consider only regular and toast tables. */
if (classForm->relkind != RELKIND_RELATION &&
! classForm->relkind != RELKIND_TOASTVALUE)
continue;
/*
--- 616,625 ----
ScanKeyData entry[1];
Oid relid;
! /* Consider only regular, non-transactional and toast tables. */
if (classForm->relkind != RELKIND_RELATION &&
! classForm->relkind != RELKIND_TOASTVALUE &&
! classForm->relkind != RELKIND_NON_TRANSACTIONAL)
continue;
/*
***************
*** 734,740 ****
List **toast_table_ids)
{
Relation rel;
! float4 reltuples; /* pg_class.reltuples */
/* constants from pg_autovacuum or GUC variables */
int vac_base_thresh,
--- 736,742 ----
List **toast_table_ids)
{
Relation rel;
! float4 reltuples; /* pg_class_nt.ntuples */
/* constants from pg_autovacuum or GUC variables */
int vac_base_thresh,
***************
*** 773,779 ****
if (!PointerIsValid(rel))
return;
! reltuples = rel->rd_rel->reltuples;
vactuples = tabentry->n_dead_tuples;
anltuples = tabentry->n_live_tuples + tabentry->n_dead_tuples -
tabentry->last_anl_tuples;
--- 775,781 ----
if (!PointerIsValid(rel))
return;
! relation_get_ntups_npages(rel, &reltuples, NULL);
vactuples = tabentry->n_dead_tuples;
anltuples = tabentry->n_live_tuples + tabentry->n_dead_tuples -
tabentry->last_anl_tuples;
***************
*** 843,849 ****
Assert(CurrentMemoryContext == AutovacMemCxt);
! if (classForm->relkind == RELKIND_RELATION)
{
if (dovacuum || doanalyze)
elog(DEBUG2, "autovac: will%s%s %s",
--- 845,852 ----
Assert(CurrentMemoryContext == AutovacMemCxt);
! if (classForm->relkind == RELKIND_RELATION ||
! classForm->relkind == RELKIND_NON_TRANSACTIONAL)
{
if (dovacuum || doanalyze)
elog(DEBUG2, "autovac: will%s%s %s",
Index: src/backend/utils/cache/relcache.c
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/backend/utils/cache/relcache.c,v
retrieving revision 1.241
diff -c -r1.241 relcache.c
*** src/backend/utils/cache/relcache.c 6 May 2006 15:51:07 -0000 1.241
--- src/backend/utils/cache/relcache.c 12 Jun 2006 17:01:20 -0000
***************
*** 40,45 ****
--- 40,46 ----
#include "catalog/pg_attrdef.h"
#include "catalog/pg_attribute.h"
#include "catalog/pg_authid.h"
+ #include "catalog/pg_class_nt.h"
#include "catalog/pg_constraint.h"
#include "catalog/pg_index.h"
#include "catalog/pg_namespace.h"
***************
*** 71,77 ****
*/
#define RELCACHE_INIT_FILENAME "pg_internal.init"
! #define RELCACHE_INIT_FILEMAGIC 0x573262 /* version ID value */
/*
* hardcoded tuple descriptors. see include/catalog/pg_attribute.h
--- 72,78 ----
*/
#define RELCACHE_INIT_FILENAME "pg_internal.init"
! #define RELCACHE_INIT_FILEMAGIC 0x573263 /* version ID value */
/*
* hardcoded tuple descriptors. see include/catalog/pg_attribute.h
***************
*** 81,86 ****
--- 82,88 ----
static FormData_pg_attribute Desc_pg_proc[Natts_pg_proc] = {Schema_pg_proc};
static FormData_pg_attribute Desc_pg_type[Natts_pg_type] = {Schema_pg_type};
static FormData_pg_attribute Desc_pg_index[Natts_pg_index] = {Schema_pg_index};
+ static FormData_pg_attribute Desc_pg_class_nt[Natts_pg_class_nt] = {Schema_pg_class_nt};
/*
* Hash tables that index the relation cache
***************
*** 1163,1169 ****
* catalogs.
*
* formrdesc is currently used for: pg_class, pg_attribute, pg_proc,
! * and pg_type (see RelationCacheInitializePhase2).
*
* Note that these catalogs can't have constraints (except attnotnull),
* default values, rules, or triggers, since we don't cope with any of that.
--- 1165,1171 ----
* catalogs.
*
* formrdesc is currently used for: pg_class, pg_attribute, pg_proc,
! * pg_class_nt and pg_type (see RelationCacheInitializePhase2).
*
* Note that these catalogs can't have constraints (except attnotnull),
* default values, rules, or triggers, since we don't cope with any of that.
***************
*** 1220,1232 ****
*/
relation->rd_rel->relisshared = false;
- relation->rd_rel->relpages = 1;
- relation->rd_rel->reltuples = 1;
relation->rd_rel->relkind = RELKIND_RELATION;
relation->rd_rel->relhasoids = hasoids;
relation->rd_rel->relnatts = (int16) natts;
/*
* initialize attribute tuple form
*
* Unlike the case with the relation tuple, this data had better be right
--- 1222,1238 ----
*/
relation->rd_rel->relisshared = false;
relation->rd_rel->relkind = RELKIND_RELATION;
relation->rd_rel->relhasoids = hasoids;
relation->rd_rel->relnatts = (int16) natts;
/*
+ * We don't need relntrans at this point, so set it to invalid to make
+ * sure we will correct it later before trying to access it.
+ */
+ ItemPointerSetInvalid(&(relation->rd_rel->relntrans));
+
+ /*
* initialize attribute tuple form
*
* Unlike the case with the relation tuple, this data had better be right
***************
*** 2028,2033 ****
--- 2034,2040 ----
case AttributeRelationId:
case ProcedureRelationId:
case TypeRelationId:
+ case NtClassRelationId:
nailit = true;
break;
default:
***************
*** 2120,2125 ****
--- 2127,2146 ----
rel->rd_rel->relfilenode = relid;
rel->rd_rel->reltablespace = reltablespace;
+ /*
+ * Set relntrans to invalid for now. It'll be corrected later by the
+ * caller. However, in bootstrap mode we must create valid entries for
+ * bootstrap relations, because the bootstrap process creates those only
+ * with heap_create and cannot fix them later, because it doesn't have
+ * access to their true pg_class_nt TID. So we make them point to the
+ * dummy entry (0,1) to make sure the bootstrapper doesn't overwrite other
+ * relation's entry.
+ */
+ if (IsBootstrapProcessingMode() && nailit)
+ ItemPointerSet(&(rel->rd_rel->relntrans), 0, 1);
+ else
+ ItemPointerSetInvalid(&(rel->rd_rel->relntrans));
+
RelationInitLockInfo(rel); /* see lmgr.c */
RelationInitPhysicalAddr(rel);
***************
*** 2230,2237 ****
true, Natts_pg_proc, Desc_pg_proc);
formrdesc("pg_type", PG_TYPE_RELTYPE_OID,
true, Natts_pg_type, Desc_pg_type);
! #define NUM_CRITICAL_RELS 4 /* fix if you change list above */
}
MemoryContextSwitchTo(oldcxt);
--- 2251,2260 ----
true, Natts_pg_proc, Desc_pg_proc);
formrdesc("pg_type", PG_TYPE_RELTYPE_OID,
true, Natts_pg_type, Desc_pg_type);
+ formrdesc("pg_class_nt", PG_CLASS_NT_RELTYPE_OID,
+ true, Natts_pg_class_nt, Desc_pg_class_nt);
! #define NUM_CRITICAL_RELS 5 /* fix if you change list above */
}
MemoryContextSwitchTo(oldcxt);
Index: src/include/catalog/catversion.h
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/include/catalog/catversion.h,v
retrieving revision 1.334
diff -c -r1.334 catversion.h
*** src/include/catalog/catversion.h 24 May 2006 11:01:39 -0000 1.334
--- src/include/catalog/catversion.h 12 Jun 2006 03:33:27 -0000
***************
*** 53,58 ****
*/
/* yyyymmddN */
! #define CATALOG_VERSION_NO 200605241
#endif
--- 53,58 ----
*/
/* yyyymmddN */
! #define CATALOG_VERSION_NO 200606101
#endif
Index: src/include/catalog/heap.h
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/include/catalog/heap.h,v
retrieving revision 1.80
diff -c -r1.80 heap.h
*** src/include/catalog/heap.h 30 Apr 2006 01:08:07 -0000 1.80
--- src/include/catalog/heap.h 12 Jun 2006 03:39:27 -0000
***************
*** 43,48 ****
--- 43,50 ----
bool shared_relation,
bool allow_system_table_mods);
+ extern ItemPointerData AddNewNtClassTuple(Relation new_rel_desc, char relkind);
+
extern Oid heap_create_with_catalog(const char *relname,
Oid relnamespace,
Oid reltablespace,
***************
*** 86,91 ****
--- 88,94 ----
DropBehavior behavior, bool complain);
extern void RemoveAttrDefaultById(Oid attrdefId);
extern void RemoveStatistics(Oid relid, AttrNumber attnum);
+ extern void DeleteNtClassTuple(ItemPointer tid);
extern Form_pg_attribute SystemAttributeDefinition(AttrNumber attno,
bool relhasoids);
***************
*** 97,100 ****
--- 100,114 ----
extern void CheckAttributeType(const char *attname, Oid atttypid);
+ /*
+ * use "struct HeapTupleData *" here instead of HeapTuple to avoid including
+ * htup.h
+ */
+ extern void relation_get_ntups_npages(Relation relation, float4 *ntuples,
+ int4 *npages);
+ extern struct HeapTupleData *get_class_nt_entry(Relation pg_class_nt,
+ Relation target);
+ extern void update_class_nt_entry(Relation pg_class_nt,
+ struct HeapTupleData *tuple);
+
#endif /* HEAP_H */
Index: src/include/catalog/pg_attribute.h
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/include/catalog/pg_attribute.h,v
retrieving revision 1.120
diff -c -r1.120 pg_attribute.h
*** src/include/catalog/pg_attribute.h 5 Mar 2006 15:58:54 -0000 1.120
--- src/include/catalog/pg_attribute.h 12 Jun 2006 03:39:45 -0000
***************
*** 387,410 ****
{ 1259, {"relam"}, 26, -1, 4, 5, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
{ 1259, {"relfilenode"}, 26, -1, 4, 6, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
{ 1259, {"reltablespace"}, 26, -1, 4, 7, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
! { 1259, {"relpages"}, 23, -1, 4, 8, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
! { 1259, {"reltuples"}, 700, -1, 4, 9, 0, -1, -1, false, 'p', 'i', true, false, false, true, 0 }, \
! { 1259, {"reltoastrelid"}, 26, -1, 4, 10, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
! { 1259, {"reltoastidxid"}, 26, -1, 4, 11, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
! { 1259, {"relhasindex"}, 16, -1, 1, 12, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
! { 1259, {"relisshared"}, 16, -1, 1, 13, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
! { 1259, {"relkind"}, 18, -1, 1, 14, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
! { 1259, {"relnatts"}, 21, -1, 2, 15, 0, -1, -1, true, 'p', 's', true, false, false, true, 0 }, \
! { 1259, {"relchecks"}, 21, -1, 2, 16, 0, -1, -1, true, 'p', 's', true, false, false, true, 0 }, \
! { 1259, {"reltriggers"}, 21, -1, 2, 17, 0, -1, -1, true, 'p', 's', true, false, false, true, 0 }, \
! { 1259, {"relukeys"}, 21, -1, 2, 18, 0, -1, -1, true, 'p', 's', true, false, false, true, 0 }, \
! { 1259, {"relfkeys"}, 21, -1, 2, 19, 0, -1, -1, true, 'p', 's', true, false, false, true, 0 }, \
! { 1259, {"relrefs"}, 21, -1, 2, 20, 0, -1, -1, true, 'p', 's', true, false, false, true, 0 }, \
! { 1259, {"relhasoids"}, 16, -1, 1, 21, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
! { 1259, {"relhaspkey"}, 16, -1, 1, 22, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
! { 1259, {"relhasrules"}, 16, -1, 1, 23, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
! { 1259, {"relhassubclass"},16, -1, 1, 24, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
! { 1259, {"relacl"}, 1034, -1, -1, 25, 1, -1, -1, false, 'x', 'i', false, false, false, true, 0 }
DATA(insert ( 1259 relname 19 -1 NAMEDATALEN 1 0 -1 -1 f p i t f f t 0));
DATA(insert ( 1259 relnamespace 26 -1 4 2 0 -1 -1 t p i t f f t 0));
--- 387,409 ----
{ 1259, {"relam"}, 26, -1, 4, 5, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
{ 1259, {"relfilenode"}, 26, -1, 4, 6, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
{ 1259, {"reltablespace"}, 26, -1, 4, 7, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
! { 1259, {"reltoastrelid"}, 26, -1, 4, 8, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
! { 1259, {"reltoastidxid"}, 26, -1, 4, 9, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
! { 1259, {"relntrans"}, 27, -1, 6, 10, 0, -1, -1, false, 'p', 's', true, false, false, true, 0 }, \
! { 1259, {"relhasindex"}, 16, -1, 1, 11, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
! { 1259, {"relisshared"}, 16, -1, 1, 12, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
! { 1259, {"relkind"}, 18, -1, 1, 13, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
! { 1259, {"relnatts"}, 21, -1, 2, 14, 0, -1, -1, true, 'p', 's', true, false, false, true, 0 }, \
! { 1259, {"relchecks"}, 21, -1, 2, 15, 0, -1, -1, true, 'p', 's', true, false, false, true, 0 }, \
! { 1259, {"reltriggers"}, 21, -1, 2, 16, 0, -1, -1, true, 'p', 's', true, false, false, true, 0 }, \
! { 1259, {"relukeys"}, 21, -1, 2, 17, 0, -1, -1, true, 'p', 's', true, false, false, true, 0 }, \
! { 1259, {"relfkeys"}, 21, -1, 2, 18, 0, -1, -1, true, 'p', 's', true, false, false, true, 0 }, \
! { 1259, {"relrefs"}, 21, -1, 2, 19, 0, -1, -1, true, 'p', 's', true, false, false, true, 0 }, \
! { 1259, {"relhasoids"}, 16, -1, 1, 20, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
! { 1259, {"relhaspkey"}, 16, -1, 1, 21, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
! { 1259, {"relhasrules"}, 16, -1, 1, 22, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
! { 1259, {"relhassubclass"},16, -1, 1, 23, 0, -1, -1, true, 'p', 'c', true, false, false, true, 0 }, \
! { 1259, {"relacl"}, 1034, -1, -1, 24, 1, -1, -1, false, 'x', 'i', false, false, false, true, 0 }
DATA(insert ( 1259 relname 19 -1 NAMEDATALEN 1 0 -1 -1 f p i t f f t 0));
DATA(insert ( 1259 relnamespace 26 -1 4 2 0 -1 -1 t p i t f f t 0));
***************
*** 413,436 ****
DATA(insert ( 1259 relam 26 -1 4 5 0 -1 -1 t p i t f f t 0));
DATA(insert ( 1259 relfilenode 26 -1 4 6 0 -1 -1 t p i t f f t 0));
DATA(insert ( 1259 reltablespace 26 -1 4 7 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1259 relpages 23 -1 4 8 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1259 reltuples 700 -1 4 9 0 -1 -1 f p i t f f t 0));
! DATA(insert ( 1259 reltoastrelid 26 -1 4 10 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1259 reltoastidxid 26 -1 4 11 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1259 relhasindex 16 -1 1 12 0 -1 -1 t p c t f f t 0));
! DATA(insert ( 1259 relisshared 16 -1 1 13 0 -1 -1 t p c t f f t 0));
! DATA(insert ( 1259 relkind 18 -1 1 14 0 -1 -1 t p c t f f t 0));
! DATA(insert ( 1259 relnatts 21 -1 2 15 0 -1 -1 t p s t f f t 0));
! DATA(insert ( 1259 relchecks 21 -1 2 16 0 -1 -1 t p s t f f t 0));
! DATA(insert ( 1259 reltriggers 21 -1 2 17 0 -1 -1 t p s t f f t 0));
! DATA(insert ( 1259 relukeys 21 -1 2 18 0 -1 -1 t p s t f f t 0));
! DATA(insert ( 1259 relfkeys 21 -1 2 19 0 -1 -1 t p s t f f t 0));
! DATA(insert ( 1259 relrefs 21 -1 2 20 0 -1 -1 t p s t f f t 0));
! DATA(insert ( 1259 relhasoids 16 -1 1 21 0 -1 -1 t p c t f f t 0));
! DATA(insert ( 1259 relhaspkey 16 -1 1 22 0 -1 -1 t p c t f f t 0));
! DATA(insert ( 1259 relhasrules 16 -1 1 23 0 -1 -1 t p c t f f t 0));
! DATA(insert ( 1259 relhassubclass 16 -1 1 24 0 -1 -1 t p c t f f t 0));
! DATA(insert ( 1259 relacl 1034 -1 -1 25 1 -1 -1 f x i f f f t 0));
DATA(insert ( 1259 ctid 27 0 6 -1 0 -1 -1 f p s t f f t 0));
DATA(insert ( 1259 oid 26 0 4 -2 0 -1 -1 t p i t f f t 0));
DATA(insert ( 1259 xmin 28 0 4 -3 0 -1 -1 t p i t f f t 0));
--- 412,434 ----
DATA(insert ( 1259 relam 26 -1 4 5 0 -1 -1 t p i t f f t 0));
DATA(insert ( 1259 relfilenode 26 -1 4 6 0 -1 -1 t p i t f f t 0));
DATA(insert ( 1259 reltablespace 26 -1 4 7 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1259 reltoastrelid 26 -1 4 8 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1259 reltoastidxid 26 -1 4 9 0 -1 -1 t p i t f f t 0));
! DATA(insert ( 1259 relntrans 27 -1 6 10 0 -1 -1 f p s t f f t 0));
! DATA(insert ( 1259 relhasindex 16 -1 1 11 0 -1 -1 t p c t f f t 0));
! DATA(insert ( 1259 relisshared 16 -1 1 12 0 -1 -1 t p c t f f t 0));
! DATA(insert ( 1259 relkind 18 -1 1 13 0 -1 -1 t p c t f f t 0));
! DATA(insert ( 1259 relnatts 21 -1 2 14 0 -1 -1 t p s t f f t 0));
! DATA(insert ( 1259 relchecks 21 -1 2 15 0 -1 -1 t p s t f f t 0));
! DATA(insert ( 1259 reltriggers 21 -1 2 16 0 -1 -1 t p s t f f t 0));
! DATA(insert ( 1259 relukeys 21 -1 2 17 0 -1 -1 t p s t f f t 0));
! DATA(insert ( 1259 relfkeys 21 -1 2 18 0 -1 -1 t p s t f f t 0));
! DATA(insert ( 1259 relrefs 21 -1 2 19 0 -1 -1 t p s t f f t 0));
! DATA(insert ( 1259 relhasoids 16 -1 1 20 0 -1 -1 t p c t f f t 0));
! DATA(insert ( 1259 relhaspkey 16 -1 1 21 0 -1 -1 t p c t f f t 0));
! DATA(insert ( 1259 relhasrules 16 -1 1 22 0 -1 -1 t p c t f f t 0));
! DATA(insert ( 1259 relhassubclass 16 -1 1 23 0 -1 -1 t p c t f f t 0));
! DATA(insert ( 1259 relacl 1034 -1 -1 24 1 -1 -1 f x i f f f t 0));
DATA(insert ( 1259 ctid 27 0 6 -1 0 -1 -1 f p s t f f t 0));
DATA(insert ( 1259 oid 26 0 4 -2 0 -1 -1 t p i t f f t 0));
DATA(insert ( 1259 xmin 28 0 4 -3 0 -1 -1 t p i t f f t 0));
***************
*** 440,445 ****
--- 438,461 ----
DATA(insert ( 1259 tableoid 26 0 4 -7 0 -1 -1 t p i t f f t 0));
/* ----------------
+ * pg_class_nt
+ * ----------------
+ */
+ #define Schema_pg_class_nt \
+ { 1004, {"npages"}, 23, -1, 4, 1, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \
+ { 1004, {"ntuples"}, 700, -1, 4, 2, 0, -1, -1, false, 'p', 'i', true, false, false, true, 0 }
+
+ DATA(insert ( 1004 npages 23 -1 4 1 0 -1 -1 t p i t f f t 0));
+ DATA(insert ( 1004 ntuples 700 -1 4 2 0 -1 -1 f p i t f f t 0));
+ DATA(insert ( 1004 ctid 27 0 6 -1 0 -1 -1 f p s t f f t 0));
+ /* no OIDs in pg_class_nt */
+ DATA(insert ( 1004 xmin 28 0 4 -3 0 -1 -1 t p i t f f t 0));
+ DATA(insert ( 1004 cmin 29 0 4 -4 0 -1 -1 t p i t f f t 0));
+ DATA(insert ( 1004 xmax 28 0 4 -5 0 -1 -1 t p i t f f t 0));
+ DATA(insert ( 1004 cmax 29 0 4 -6 0 -1 -1 t p i t f f t 0));
+ DATA(insert ( 1004 tableoid 26 0 4 -7 0 -1 -1 t p i t f f t 0));
+
+ /* ----------------
* pg_index
*
* pg_index is not bootstrapped in the same way as the other relations that
Index: src/include/catalog/pg_class.h
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/include/catalog/pg_class.h,v
retrieving revision 1.92
diff -c -r1.92 pg_class.h
*** src/include/catalog/pg_class.h 28 May 2006 02:27:08 -0000 1.92
--- src/include/catalog/pg_class.h 12 Jun 2006 16:11:40 -0000
***************
*** 19,24 ****
--- 19,26 ----
#ifndef PG_CLASS_H
#define PG_CLASS_H
+ #include "storage/itemptr.h"
+
/* ----------------
* postgres.h contains the system type definitions and the
* CATALOG(), BKI_BOOTSTRAP and DATA() sugar words so this file
***************
*** 42,47 ****
--- 44,59 ----
*/
#define RelationRelationId 1259
+ /*
+ * This CATALOG() entry is used by genbki to create the initial bootstrap file,
+ * but the bootstrap type system only recognizes "tid" as a valid type.
+ * However, CPP also turns this definition into a C struct, but the C name of
+ * that type is actually ItemPointerData. So we put this definition here in
+ * order to have both systems understand that element. To limit the possible
+ * damage done, we #undef it right at the bottom.
+ */
+ #define tid ItemPointerData
+
CATALOG(pg_class,1259) BKI_BOOTSTRAP
{
NameData relname; /* class name */
***************
*** 51,60 ****
Oid relam; /* index access method; 0 if not an index */
Oid relfilenode; /* identifier of physical storage file */
Oid reltablespace; /* identifier of table space for relation */
- int4 relpages; /* # of blocks (not always up-to-date) */
- float4 reltuples; /* # of tuples (not always up-to-date) */
Oid reltoastrelid; /* OID of toast table; 0 if none */
Oid reltoastidxid; /* if toast table, OID of chunk_id index */
bool relhasindex; /* T if has (or has had) any indexes */
bool relisshared; /* T if shared across databases */
char relkind; /* see RELKIND_xxx constants below */
--- 63,71 ----
Oid relam; /* index access method; 0 if not an index */
Oid relfilenode; /* identifier of physical storage file */
Oid reltablespace; /* identifier of table space for relation */
Oid reltoastrelid; /* OID of toast table; 0 if none */
Oid reltoastidxid; /* if toast table, OID of chunk_id index */
+ tid relntrans; /* CTID of pg_class_nt entry */
bool relhasindex; /* T if has (or has had) any indexes */
bool relisshared; /* T if shared across databases */
char relkind; /* see RELKIND_xxx constants below */
***************
*** 80,85 ****
--- 91,97 ----
*/
aclitem relacl[1]; /* we declare this just for the catalog */
} FormData_pg_class;
+ #undef tid
/* Size of fixed part of pg_class tuples, not counting relacl or padding */
#define CLASS_TUPLE_SIZE \
***************
*** 103,110 ****
* relacl field. This is a kluge.
* ----------------
*/
! #define Natts_pg_class_fixed 24
! #define Natts_pg_class 25
#define Anum_pg_class_relname 1
#define Anum_pg_class_relnamespace 2
#define Anum_pg_class_reltype 3
--- 115,122 ----
* relacl field. This is a kluge.
* ----------------
*/
! #define Natts_pg_class_fixed 23
! #define Natts_pg_class 24
#define Anum_pg_class_relname 1
#define Anum_pg_class_relnamespace 2
#define Anum_pg_class_reltype 3
***************
*** 112,135 ****
#define Anum_pg_class_relam 5
#define Anum_pg_class_relfilenode 6
#define Anum_pg_class_reltablespace 7
! #define Anum_pg_class_relpages 8
! #define Anum_pg_class_reltuples 9
! #define Anum_pg_class_reltoastrelid 10
! #define Anum_pg_class_reltoastidxid 11
! #define Anum_pg_class_relhasindex 12
! #define Anum_pg_class_relisshared 13
! #define Anum_pg_class_relkind 14
! #define Anum_pg_class_relnatts 15
! #define Anum_pg_class_relchecks 16
! #define Anum_pg_class_reltriggers 17
! #define Anum_pg_class_relukeys 18
! #define Anum_pg_class_relfkeys 19
! #define Anum_pg_class_relrefs 20
! #define Anum_pg_class_relhasoids 21
! #define Anum_pg_class_relhaspkey 22
! #define Anum_pg_class_relhasrules 23
! #define Anum_pg_class_relhassubclass 24
! #define Anum_pg_class_relacl 25
/* ----------------
* initial contents of pg_class
--- 124,146 ----
#define Anum_pg_class_relam 5
#define Anum_pg_class_relfilenode 6
#define Anum_pg_class_reltablespace 7
! #define Anum_pg_class_reltoastrelid 8
! #define Anum_pg_class_reltoastidxid 9
! #define Anum_pg_class_relhasindex 10
! #define Anum_pg_class_relisshared 11
! #define Anum_pg_class_relkind 12
! #define Anum_pg_class_relnatts 13
! #define Anum_pg_class_relntrans 14
! #define Anum_pg_class_relchecks 15
! #define Anum_pg_class_reltriggers 16
! #define Anum_pg_class_relukeys 17
! #define Anum_pg_class_relfkeys 18
! #define Anum_pg_class_relrefs 19
! #define Anum_pg_class_relhasoids 20
! #define Anum_pg_class_relhaspkey 21
! #define Anum_pg_class_relhasrules 22
! #define Anum_pg_class_relhassubclass 23
! #define Anum_pg_class_relacl 24
/* ----------------
* initial contents of pg_class
***************
*** 139,151 ****
* ----------------
*/
! DATA(insert OID = 1247 ( pg_type PGNSP 71 PGUID 0 1247 0 0 0 0 0 f f r 23 0 0 0 0 0 t f f f _null_ ));
DESCR("");
! DATA(insert OID = 1249 ( pg_attribute PGNSP 75 PGUID 0 1249 0 0 0 0 0 f f r 17 0 0 0 0 0 f f f f _null_ ));
DESCR("");
! DATA(insert OID = 1255 ( pg_proc PGNSP 81 PGUID 0 1255 0 0 0 0 0 f f r 18 0 0 0 0 0 t f f f _null_ ));
DESCR("");
! DATA(insert OID = 1259 ( pg_class PGNSP 83 PGUID 0 1259 0 0 0 0 0 f f r 25 0 0 0 0 0 t f f f _null_ ));
DESCR("");
#define RELKIND_INDEX 'i' /* secondary index */
--- 150,164 ----
* ----------------
*/
! DATA(insert OID = 1247 ( pg_type PGNSP 71 PGUID 0 1247 0 0 0 "(0,2)" f f r 23 0 0 0 0 0 t f f f _null_ ));
! DESCR("");
! DATA(insert OID = 1249 ( pg_attribute PGNSP 75 PGUID 0 1249 0 0 0 "(0,3)" f f r 17 0 0 0 0 0 f f f f _null_ ));
DESCR("");
! DATA(insert OID = 1255 ( pg_proc PGNSP 81 PGUID 0 1255 0 0 0 "(0,4)" f f r 18 0 0 0 0 0 t f f f _null_ ));
DESCR("");
! DATA(insert OID = 1259 ( pg_class PGNSP 83 PGUID 0 1259 0 0 0 "(0,5)" f f r 24 0 0 0 0 0 t f f f _null_ ));
DESCR("");
! DATA(insert OID = 1004 ( pg_class_nt PGNSP 86 PGUID 0 1004 0 0 0 "(0,6)" f f n 2 0 0 0 0 0 f f f f _null_ ));
DESCR("");
#define RELKIND_INDEX 'i' /* secondary index */
***************
*** 155,159 ****
--- 168,173 ----
#define RELKIND_TOASTVALUE 't' /* moved off huge values */
#define RELKIND_VIEW 'v' /* view */
#define RELKIND_COMPOSITE_TYPE 'c' /* composite type */
+ #define RELKIND_NON_TRANSACTIONAL 'n' /* non-transactional heap */
#endif /* PG_CLASS_H */
Index: src/include/catalog/pg_type.h
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/include/catalog/pg_type.h,v
retrieving revision 1.171
diff -c -r1.171 pg_type.h
*** src/include/catalog/pg_type.h 5 Apr 2006 22:11:57 -0000 1.171
--- src/include/catalog/pg_type.h 12 Jun 2006 03:38:34 -0000
***************
*** 314,319 ****
--- 314,321 ----
#define PG_PROC_RELTYPE_OID 81
DATA(insert OID = 83 ( pg_class PGNSP PGUID -1 f c t \054 1259 0 record_in record_out record_recv record_send - d x f 0 -1 0 _null_ _null_ ));
#define PG_CLASS_RELTYPE_OID 83
+ DATA(insert OID = 86 ( pg_class_nt PGNSP PGUID -1 f c t \054 1004 0 record_in record_out record_recv record_send - d x f 0 -1 0 _null_ _null_ ));
+ #define PG_CLASS_NT_RELTYPE_OID 86
/* OIDS 100 - 199 */
Index: src/include/commands/vacuum.h
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/include/commands/vacuum.h,v
retrieving revision 1.63
diff -c -r1.63 vacuum.h
*** src/include/commands/vacuum.h 5 Mar 2006 15:58:55 -0000 1.63
--- src/include/commands/vacuum.h 5 Jun 2006 02:36:52 -0000
***************
*** 114,120 ****
extern void vac_open_indexes(Relation relation, LOCKMODE lockmode,
int *nindexes, Relation **Irel);
extern void vac_close_indexes(int nindexes, Relation *Irel, LOCKMODE lockmode);
! extern void vac_update_relstats(Oid relid,
BlockNumber num_pages,
double num_tuples,
bool hasindex);
--- 114,120 ----
extern void vac_open_indexes(Relation relation, LOCKMODE lockmode,
int *nindexes, Relation **Irel);
extern void vac_close_indexes(int nindexes, Relation *Irel, LOCKMODE lockmode);
! extern void vac_update_relstats(Relation rel,
BlockNumber num_pages,
double num_tuples,
bool hasindex);
Index: src/test/regress/expected/stats.out
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/test/regress/expected/stats.out,v
retrieving revision 1.7
diff -c -r1.7 stats.out
*** src/test/regress/expected/stats.out 11 Jan 2006 20:12:42 -0000 1.7
--- src/test/regress/expected/stats.out 12 Jun 2006 03:53:48 -0000
***************
*** 2,8 ****
-- Test Statistics Collector
--
-- Must be run after tenk2 has been created (by create_table),
! -- populated (by create_misc) and indexed (by create_index).
--
-- conditio sine qua non
SHOW stats_start_collector; -- must be on
--- 2,8 ----
-- Test Statistics Collector
--
-- Must be run after tenk2 has been created (by create_table),
! -- populated (by copy and create_misc) and indexed (by create_index).
--
-- conditio sine qua non
SHOW stats_start_collector; -- must be on
***************
*** 44,62 ****
-- check effects
SELECT st.seq_scan >= pr.seq_scan + 1,
! st.seq_tup_read >= pr.seq_tup_read + cl.reltuples,
st.idx_scan >= pr.idx_scan + 1,
st.idx_tup_fetch >= pr.idx_tup_fetch + 1
! FROM pg_stat_user_tables AS st, pg_class AS cl, prevstats AS pr
WHERE st.relname='tenk2' AND cl.relname='tenk2';
?column? | ?column? | ?column? | ?column?
----------+----------+----------+----------
t | t | t | t
(1 row)
! SELECT st.heap_blks_read + st.heap_blks_hit >= pr.heap_blks + cl.relpages,
st.idx_blks_read + st.idx_blks_hit >= pr.idx_blks + 1
! FROM pg_statio_user_tables AS st, pg_class AS cl, prevstats AS pr
WHERE st.relname='tenk2' AND cl.relname='tenk2';
?column? | ?column?
----------+----------
--- 44,66 ----
-- check effects
SELECT st.seq_scan >= pr.seq_scan + 1,
! st.seq_tup_read >= pr.seq_tup_read + nt.reltuples,
st.idx_scan >= pr.idx_scan + 1,
st.idx_tup_fetch >= pr.idx_tup_fetch + 1
! FROM pg_stat_user_tables AS st,
! pg_class AS cl JOIN pg_class_nt AS nt ON (nt.ctid = cl.relntrans),
! prevstats AS pr
WHERE st.relname='tenk2' AND cl.relname='tenk2';
?column? | ?column? | ?column? | ?column?
----------+----------+----------+----------
t | t | t | t
(1 row)
! SELECT st.heap_blks_read + st.heap_blks_hit >= pr.heap_blks + nt.relpages,
st.idx_blks_read + st.idx_blks_hit >= pr.idx_blks + 1
! FROM pg_statio_user_tables AS st,
! pg_class AS cl JOIN pg_class_nt AS nt ON (nt.ctid = cl.relntrans),
! prevstats AS pr
WHERE st.relname='tenk2' AND cl.relname='tenk2';
?column? | ?column?
----------+----------
Index: src/test/regress/expected/type_sanity.out
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/test/regress/expected/type_sanity.out,v
retrieving revision 1.27
diff -c -r1.27 type_sanity.out
*** src/test/regress/expected/type_sanity.out 10 Jul 2005 21:14:00 -0000 1.27
--- src/test/regress/expected/type_sanity.out 5 Jun 2006 02:36:52 -0000
***************
*** 216,222 ****
-- Look for illegal values in pg_class fields
SELECT p1.oid, p1.relname
FROM pg_class as p1
! WHERE p1.relkind NOT IN ('r', 'i', 's', 'S', 'c', 't', 'v');
oid | relname
-----+---------
(0 rows)
--- 216,222 ----
-- Look for illegal values in pg_class fields
SELECT p1.oid, p1.relname
FROM pg_class as p1
! WHERE p1.relkind NOT IN ('r', 'i', 's', 'S', 'c', 't', 'v', 'n');
oid | relname
-----+---------
(0 rows)
Index: src/test/regress/expected/without_oid.out
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/test/regress/expected/without_oid.out,v
retrieving revision 1.7
diff -c -r1.7 without_oid.out
*** src/test/regress/expected/without_oid.out 14 Mar 2006 22:48:25 -0000 1.7
--- src/test/regress/expected/without_oid.out 12 Jun 2006 03:54:15 -0000
***************
*** 48,54 ****
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?
----------+----------
--- 48,54 ----
VACUUM ANALYZE wi;
VACUUM ANALYZE wo;
SELECT min(relpages) < max(relpages), min(reltuples) - max(reltuples)
! FROM pg_class JOIN pg_class_nt ON (pg_class_nt.ctid = relntrans)
WHERE relname IN ('wi', 'wo');
?column? | ?column?
----------+----------
Index: src/test/regress/sql/stats.sql
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/test/regress/sql/stats.sql,v
retrieving revision 1.5
diff -c -r1.5 stats.sql
*** src/test/regress/sql/stats.sql 11 Jan 2006 20:12:43 -0000 1.5
--- src/test/regress/sql/stats.sql 12 Jun 2006 03:54:50 -0000
***************
*** 2,8 ****
-- Test Statistics Collector
--
-- Must be run after tenk2 has been created (by create_table),
! -- populated (by create_misc) and indexed (by create_index).
--
-- conditio sine qua non
--- 2,8 ----
-- Test Statistics Collector
--
-- Must be run after tenk2 has been created (by create_table),
! -- populated (by copy and create_misc) and indexed (by create_index).
--
-- conditio sine qua non
***************
*** 30,43 ****
-- check effects
SELECT st.seq_scan >= pr.seq_scan + 1,
! st.seq_tup_read >= pr.seq_tup_read + cl.reltuples,
st.idx_scan >= pr.idx_scan + 1,
st.idx_tup_fetch >= pr.idx_tup_fetch + 1
! FROM pg_stat_user_tables AS st, pg_class AS cl, prevstats AS pr
WHERE st.relname='tenk2' AND cl.relname='tenk2';
! SELECT st.heap_blks_read + st.heap_blks_hit >= pr.heap_blks + cl.relpages,
st.idx_blks_read + st.idx_blks_hit >= pr.idx_blks + 1
! FROM pg_statio_user_tables AS st, pg_class AS cl, prevstats AS pr
WHERE st.relname='tenk2' AND cl.relname='tenk2';
-- End of Stats Test
--- 30,47 ----
-- check effects
SELECT st.seq_scan >= pr.seq_scan + 1,
! st.seq_tup_read >= pr.seq_tup_read + nt.reltuples,
st.idx_scan >= pr.idx_scan + 1,
st.idx_tup_fetch >= pr.idx_tup_fetch + 1
! FROM pg_stat_user_tables AS st,
! pg_class AS cl JOIN pg_class_nt AS nt ON (nt.ctid = cl.relntrans),
! prevstats AS pr
WHERE st.relname='tenk2' AND cl.relname='tenk2';
! SELECT st.heap_blks_read + st.heap_blks_hit >= pr.heap_blks + nt.relpages,
st.idx_blks_read + st.idx_blks_hit >= pr.idx_blks + 1
! FROM pg_statio_user_tables AS st,
! pg_class AS cl JOIN pg_class_nt AS nt ON (nt.ctid = cl.relntrans),
! prevstats AS pr
WHERE st.relname='tenk2' AND cl.relname='tenk2';
-- End of Stats Test
Index: src/test/regress/sql/type_sanity.sql
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/test/regress/sql/type_sanity.sql,v
retrieving revision 1.27
diff -c -r1.27 type_sanity.sql
*** src/test/regress/sql/type_sanity.sql 10 Jul 2005 21:14:00 -0000 1.27
--- src/test/regress/sql/type_sanity.sql 5 Jun 2006 02:36:52 -0000
***************
*** 169,175 ****
SELECT p1.oid, p1.relname
FROM pg_class as p1
! WHERE p1.relkind NOT IN ('r', 'i', 's', 'S', 'c', 't', 'v');
-- Indexes should have an access method, others not.
--- 169,175 ----
SELECT p1.oid, p1.relname
FROM pg_class as p1
! WHERE p1.relkind NOT IN ('r', 'i', 's', 'S', 'c', 't', 'v', 'n');
-- Indexes should have an access method, others not.
Index: src/test/regress/sql/without_oid.sql
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/test/regress/sql/without_oid.sql,v
retrieving revision 1.6
diff -c -r1.6 without_oid.sql
*** src/test/regress/sql/without_oid.sql 19 Feb 2006 00:04:28 -0000 1.6
--- src/test/regress/sql/without_oid.sql 12 Jun 2006 03:55:11 -0000
***************
*** 45,51 ****
VACUUM ANALYZE wo;
SELECT min(relpages) < max(relpages), min(reltuples) - max(reltuples)
! FROM pg_class
WHERE relname IN ('wi', 'wo');
DROP TABLE wi;
--- 45,51 ----
VACUUM ANALYZE wo;
SELECT min(relpages) < max(relpages), min(reltuples) - max(reltuples)
! FROM pg_class JOIN pg_class_nt ON (pg_class_nt.ctid = relntrans)
WHERE relname IN ('wi', 'wo');
DROP TABLE wi;