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 9 Jun 2006 22:52:50 -0000 *************** *** 104,109 **** --- 104,114 ---- + pg_ntclass + 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_ntclass.ctid + + CTID of this relation's pg_ntclass 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_ntclass</structname> + + + pg_ntclass + + + + The catalog pg_ntclass 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_ntclass</> Columns + + + + + Name + Type + References + Description + + + + + + 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. + + + + + + + <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 10 Jun 2006 23:17:47 -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 it's better if the bootstrapped catalogs ! # 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_ntclass.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 11 Jun 2006 06:46:03 -0000 *************** *** 40,45 **** --- 40,46 ---- #include "catalog/pg_constraint.h" #include "catalog/pg_inherits.h" #include "catalog/pg_namespace.h" + #include "catalog/pg_ntclass.h" #include "catalog/pg_statistic.h" #include "catalog/pg_type.h" #include "commands/tablecmds.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_ntclass tuple for the given relation, and return its + * TID. + */ + ItemPointerData + AddNewNtclassTuple(Relation new_rel_desc, char relkind) + { + ItemPointerData tid; + + /* + * We don't create pg_ntclass 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_ntclass new_rel_nttup; + HeapTuple tup; + + ntRel = heap_open(NtClassRelationId, RowExclusiveLock); + + new_rel_nttup = (Form_pg_ntclass) palloc(sizeof(FormData_pg_ntclass)); + + /* 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->relpages = 0; + new_rel_nttup->reltuples = 0; + break; + default: + elog(ERROR, "can't create pg_ntclass entries for relkind '%c'", + relkind); + break; + } + + /* + * now form a tuple to add to pg_ntclass + */ + tup = heap_addheader(Natts_pg_ntclass, + 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_ntclass 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_ntclass 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_ntclass; + + /* some relations don't have pg_ntclass tuples */ + if (!ItemPointerIsValid(tid)) + return; + + pg_ntclass = heap_open(NtClassRelationId, RowExclusiveLock); + + simple_heap_delete(pg_ntclass, tid); + + heap_close(pg_ntclass, RowExclusiveLock); + } + /* * DeleteAttributeTuples * *************** *** 1160,1165 **** --- 1245,1255 ---- } /* + * Delete the pg_ntclass 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 * something with the doomed relation. *************** *** 2133,2135 **** --- 2223,2284 ---- return result; } + + /* + * Return the number of tuples and pages for a given relation, as recorded in + * its pg_ntclass 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_ntclass; + Form_pg_ntclass ntForm; + + pg_ntclass = heap_open(NtClassRelationId, AccessShareLock); + + tup = get_ntclass_entry(pg_ntclass, relation); + ntForm = (Form_pg_ntclass) GETSTRUCT(tup); + + if (ntuples != NULL) + *ntuples = ntForm->reltuples; + if (npages != NULL) + *npages = ntForm->relpages; + + heap_freetuple(tup); + heap_close(pg_ntclass, AccessShareLock); + } + + /* + * Return a copy of the pg_ntclass tuple for the given target relation. + */ + HeapTuple + get_ntclass_entry(Relation pg_ntclass, 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_ntclass, SnapshotNow, &tuple, &buffer, false, NULL)) + elog(ERROR, "lookup failed for pg_ntclass entry for relation %s", + RelationGetRelationName(target)); + + retval = heap_copytuple(&tuple); + ReleaseBuffer(buffer); + + return retval; + } + + void + update_ntclass_entry(Relation pg_ntclass, HeapTuple tuple) + { + elog(DEBUG2, "updating pg_ntclass entry (%u/%u)", + ItemPointerGetBlockNumber(&(tuple->t_self)), + ItemPointerGetOffsetNumber(&(tuple->t_self))); + heap_inplace_update(pg_ntclass, 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 10 Jun 2006 23:17:47 -0000 *************** *** 32,37 **** --- 32,38 ---- #include "catalog/index.h" #include "catalog/indexing.h" #include "catalog/pg_constraint.h" + #include "catalog/pg_ntclass.h" #include "catalog/pg_opclass.h" #include "catalog/pg_type.h" #include "executor/executor.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_ntclass 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_ntclass 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 *************** *** 1038,1045 **** --- 1048,1057 ---- BlockNumber relpages = RelationGetNumberOfBlocks(rel); Oid relid = RelationGetRelid(rel); Relation pg_class; + Relation pg_ntclass; HeapTuple tuple; Form_pg_class rd_rel; + Form_pg_ntclass 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_ntclass) entry */ + pg_ntclass = heap_open(NtClassRelationId, RowExclusiveLock); + + tuple = get_ntclass_entry(pg_ntclass, rel); + + ntForm = (Form_pg_ntclass) GETSTRUCT(tuple); + + dirty = false; + if (ntForm->reltuples != (float4) reltuples) + { + ntForm->reltuples = (float4) reltuples; + dirty = true; + } + if (ntForm->relpages != (int32) relpages) + { + ntForm->relpages = (int32) relpages; + dirty = true; + } + if (dirty) + update_ntclass_entry(pg_ntclass, tuple); + heap_freetuple(tuple); + + heap_close(pg_ntclass, 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_ntclass 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 10 Jun 2006 23:17:47 -0000 *************** *** 164,171 **** */ if (onerel->rd_rel->relkind != RELKIND_RELATION) { ! /* No need for a WARNING if we already complained during VACUUM */ ! if (!vacstmt->vacuum) ereport(WARNING, (errmsg("skipping \"%s\" --- cannot analyze indexes, views, or special system tables", RelationGetRelationName(onerel)))); --- 164,176 ---- */ if (onerel->rd_rel->relkind != RELKIND_RELATION) { ! /* ! * No need for a WARNING if we already complained during VACUUM. Also ! * don't complain if this is a non-transactional catalog, because ! * VACUUM processes it but we don't. ! */ ! if (!vacstmt->vacuum && ! (onerel->rd_rel->relkind != RELKIND_NON_TRANSACTIONAL)) ereport(WARNING, (errmsg("skipping \"%s\" --- cannot analyze indexes, views, or special system tables", RelationGetRelationName(onerel)))); *************** *** 422,428 **** */ if (!vacstmt->vacuum) { ! vac_update_relstats(RelationGetRelid(onerel), RelationGetNumberOfBlocks(onerel), totalrows, hasindex); --- 427,433 ---- */ 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); --- 437,443 ---- 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 10 Jun 2006 23:17:47 -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_ntclass rows too. This automatically updates the ! * size statistics. ! * ! * XXX make sure this is still correct when adding more rows to ! * pg_ntclass. ! */ ! 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 10 Jun 2006 23:17:47 -0000 *************** *** 28,37 **** --- 28,39 ---- #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_database.h" #include "catalog/pg_index.h" + #include "catalog/pg_ntclass.h" #include "commands/dbcommands.h" #include "commands/vacuum.h" #include "executor/executor.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_ntclass 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_ntclass, 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_ntclass pgntform; Form_pg_class pgcform; bool dirty; + /* Process pg_ntclass first */ + rd = heap_open(NtClassRelationId, RowExclusiveLock); + + /* Fetch a copy of the pg_ntclass tuple to scribble on */ + ctup = get_ntclass_entry(rd, rel); + + pgntform = (Form_pg_ntclass) GETSTRUCT(ctup); + + /* Apply required updates, if any, to copied tuple */ + + dirty = false; + if (pgntform->relpages != (int32) num_pages) + { + pgntform->relpages = (int32) num_pages; + dirty = true; + } + if (pgntform->reltuples != (float4) num_tuples) + { + pgntform->reltuples = (float4) num_tuples; + dirty = true; + } + + /* If anything changed, write out the tuple */ + if (dirty) + update_ntclass_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 10 Jun 2006 23:17:47 -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_ntclass.reltuples */ /* 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 11 Jun 2006 06:49:10 -0000 *************** *** 43,48 **** --- 43,49 ---- #include "catalog/pg_constraint.h" #include "catalog/pg_index.h" #include "catalog/pg_namespace.h" + #include "catalog/pg_ntclass.h" #include "catalog/pg_opclass.h" #include "catalog/pg_proc.h" #include "catalog/pg_rewrite.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_ntclass[Natts_pg_ntclass] = {Schema_pg_ntclass}; /* * 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_ntclass 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,2143 ---- rel->rd_rel->relfilenode = relid; rel->rd_rel->reltablespace = reltablespace; + /* + * Initialize pg_ntclass tuple. NOTE -- during bootstrap, we need to + * insert a pseudo-valid entry for nailed relations. Do the minimal work + * needed to allow the system to continue operating in this case; it will + * get fixed when we read the real pg_class 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); --- 2248,2257 ---- true, Natts_pg_proc, Desc_pg_proc); formrdesc("pg_type", PG_TYPE_RELTYPE_OID, true, Natts_pg_type, Desc_pg_type); + formrdesc("pg_ntclass", PG_NTCLASS_RELTYPE_OID, + true, Natts_pg_ntclass, Desc_pg_ntclass); ! #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 10 Jun 2006 23:22:07 -0000 *************** *** 37,43 **** * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * ! * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.334 2006/05/24 11:01:39 teodor Exp $ * *------------------------------------------------------------------------- */ --- 37,43 ---- * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * ! * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.334 2006-05-24 11:01:39 teodor Exp $ * *------------------------------------------------------------------------- */ *************** *** 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 5 Jun 2006 02:36:52 -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,112 ---- extern void CheckAttributeType(const char *attname, Oid atttypid); + /* + * use "struct HeapTupleData *" here instead of HeapTuple to avoid including + * htup.h + */ + extern struct HeapTupleData *get_ntclass_entry(Relation pg_ntclass, Relation target); + extern void relation_get_ntups_npages(Relation relation, float4 *ntuples, + int4 *npages); + extern void update_ntclass_entry(Relation pg_ntclass, 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 9 Jun 2006 22:47:58 -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_ntclass + * ---------------- + */ + #define Schema_pg_ntclass \ + { 1004, {"relpages"}, 23, -1, 4, 1, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0 }, \ + { 1004, {"reltuples"}, 700, -1, 4, 2, 0, -1, -1, false, 'p', 'i', true, false, false, true, 0 } + + DATA(insert ( 1004 relpages 23 -1 4 1 0 -1 -1 t p i t f f t 0)); + DATA(insert ( 1004 reltuples 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_ntclass */ + 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 10 Jun 2006 22:10:25 -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 *************** *** 32,37 **** --- 34,41 ---- * ---------------- */ + typedef ItemPointerData tid; + /* ---------------- * This structure is actually variable-length (the last attribute is * a POSTGRES array). Hence, sizeof(FormData_pg_class) does not *************** *** 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 */ --- 55,63 ---- 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_ntclass 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 */ *************** *** 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 --- 106,113 ---- * 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 --- 115,137 ---- #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 */ --- 141,155 ---- * ---------------- */ ! DATA(insert OID = 1247 ( pg_type PGNSP 71 PGUID 0 1247 0 0 0 "(0,1)" 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,2)" 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,3)" 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,4)" f f r 24 0 0 0 0 0 t f f f _null_ )); DESCR(""); ! DATA(insert OID = 1004 ( pg_ntclass PGNSP 86 PGUID 0 1004 0 0 0 "(0,5)" f f n 2 0 0 0 0 0 f f f f _null_ )); DESCR(""); #define RELKIND_INDEX 'i' /* secondary index */ *************** *** 155,159 **** --- 159,164 ---- #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 5 Jun 2006 02:36:52 -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_ntclass 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_NTCLASS_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 5 Jun 2006 02:36:52 -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_ntclass 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_ntclass 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 5 Jun 2006 02:36:52 -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_ntclass ON (pg_ntclass.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 5 Jun 2006 02:36:52 -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_ntclass 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_ntclass 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 5 Jun 2006 02:36:52 -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_ntclass ON (pg_ntclass.ctid = relntrans) WHERE relname IN ('wi', 'wo'); DROP TABLE wi;