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_constraint check 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. - - - - reltoastrelid oid pg_class.oid --- 1470,1475 ---- *************** *** 1512,1517 **** --- 1490,1504 ---- + relntrans + tid + pg_class_nt.ctid + + CTID of this relation's pg_class_nt row. + + + + relhasindex bool *************** *** 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 ---- + + <structname>pg_class_nt</structname> + + + 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. + + + + <structname>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. + + + + + + + <structname>pg_constraint</structname> 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;