diff options
Diffstat (limited to 'src/backend/commands')
-rw-r--r-- | src/backend/commands/functioncmds.c | 21 | ||||
-rw-r--r-- | src/backend/commands/indexcmds.c | 171 | ||||
-rw-r--r-- | src/backend/commands/vacuum.c | 30 |
3 files changed, 86 insertions, 136 deletions
diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c index ea5ba103131..328643c171e 100644 --- a/src/backend/commands/functioncmds.c +++ b/src/backend/commands/functioncmds.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/functioncmds.c,v 1.34 2003/09/10 19:59:23 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/functioncmds.c,v 1.35 2003/09/24 18:54:01 tgl Exp $ * * DESCRIPTION * These routines take the parse tree and pick out the @@ -1095,24 +1095,25 @@ DropCast(DropCastStmt *stmt) void DropCastById(Oid castOid) { - Relation relation, - index; + Relation relation; ScanKeyData scankey; - IndexScanDesc scan; + SysScanDesc scan; HeapTuple tuple; relation = heap_openr(CastRelationName, RowExclusiveLock); - index = index_openr(CastOidIndex); ScanKeyEntryInitialize(&scankey, 0x0, - 1, F_OIDEQ, ObjectIdGetDatum(castOid)); - scan = index_beginscan(relation, index, SnapshotNow, 1, &scankey); - tuple = index_getnext(scan, ForwardScanDirection); + ObjectIdAttributeNumber, + F_OIDEQ, + ObjectIdGetDatum(castOid)); + scan = systable_beginscan(relation, CastOidIndex, true, + SnapshotNow, 1, &scankey); + + tuple = systable_getnext(scan); if (!HeapTupleIsValid(tuple)) elog(ERROR, "could not find tuple for cast %u", castOid); simple_heap_delete(relation, &tuple->t_self); - index_endscan(scan); - index_close(index); + systable_endscan(scan); heap_close(relation, RowExclusiveLock); } diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c index 4c2221263d7..c8ccab8d4e1 100644 --- a/src/backend/commands/indexcmds.c +++ b/src/backend/commands/indexcmds.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.108 2003/09/23 01:51:09 inoue Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.109 2003/09/24 18:54:01 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -112,14 +112,6 @@ DefineIndex(RangeVar *heapRelation, relationId = RelationGetRelid(rel); namespaceId = RelationGetNamespace(rel); - if (!IsBootstrapProcessingMode() && - IsSystemRelation(rel) && - !IndexesAreActive(rel)) - ereport(ERROR, - (errcode(ERRCODE_INDEXES_DEACTIVATED), - errmsg("existing indexes are inactive"), - errhint("REINDEX the table first."))); - heap_close(rel, NoLock); /* @@ -599,10 +591,6 @@ ReindexIndex(RangeVar *indexRelation, bool force /* currently unused */ ) { Oid indOid; HeapTuple tuple; - bool overwrite; - - /* Choose in-place-or-not mode */ - overwrite = IsIgnoringSystemIndexes(); indOid = RangeVarGetRelid(indexRelation, false); tuple = SearchSysCache(RELOID, @@ -617,37 +605,14 @@ ReindexIndex(RangeVar *indexRelation, bool force /* currently unused */ ) errmsg("relation \"%s\" is not an index", indexRelation->relname))); - if (IsSystemClass((Form_pg_class) GETSTRUCT(tuple)) && - !IsToastClass((Form_pg_class) GETSTRUCT(tuple))) - { - if (!allowSystemTableMods) - ereport(ERROR, - (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), - errmsg("permission denied: \"%s\" is a system index", - indexRelation->relname), - errhint("Do REINDEX in standalone postgres with -O -P options."))); - if (!IsIgnoringSystemIndexes()) - ereport(ERROR, - (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), - errmsg("permission denied: \"%s\" is a system index", - indexRelation->relname), - errhint("Do REINDEX in standalone postgres with -P -O options."))); - } + /* Check permissions */ + if (!pg_class_ownercheck(indOid, GetUserId())) + aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS, + indexRelation->relname); ReleaseSysCache(tuple); - /* - * In-place REINDEX within a transaction block is dangerous, because - * if the transaction is later rolled back we have no way to undo - * truncation of the index's physical file. Disallow it. - */ - if (overwrite) - PreventTransactionChain((void *) indexRelation, "REINDEX"); - - if (!reindex_index(indOid, force, overwrite)) - ereport(WARNING, - (errmsg("index \"%s\" wasn't reindexed", - indexRelation->relname))); + reindex_index(indOid); } /* @@ -655,54 +620,62 @@ ReindexIndex(RangeVar *indexRelation, bool force /* currently unused */ ) * Recreate indexes of a table. */ void -ReindexTable(RangeVar *relation, bool force) +ReindexTable(RangeVar *relation, bool force /* currently unused */ ) { Oid heapOid; - char relkind; + HeapTuple tuple; heapOid = RangeVarGetRelid(relation, false); - relkind = get_rel_relkind(heapOid); + tuple = SearchSysCache(RELOID, + ObjectIdGetDatum(heapOid), + 0, 0, 0); + if (!HeapTupleIsValid(tuple)) /* shouldn't happen */ + elog(ERROR, "cache lookup failed for relation %u", heapOid); - if (relkind != RELKIND_RELATION && relkind != RELKIND_TOASTVALUE) + if (((Form_pg_class) GETSTRUCT(tuple))->relkind != RELKIND_RELATION && + ((Form_pg_class) GETSTRUCT(tuple))->relkind != RELKIND_TOASTVALUE) ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), errmsg("relation \"%s\" is not a table", relation->relname))); - /* - * In-place REINDEX within a transaction block is dangerous, because - * if the transaction is later rolled back we have no way to undo - * truncation of the index's physical file. Disallow it. - * - * XXX we assume that in-place reindex will only be done if - * IsIgnoringSystemIndexes() is true. - */ - if (IsIgnoringSystemIndexes()) - PreventTransactionChain((void *) relation, "REINDEX"); + /* Check permissions */ + if (!pg_class_ownercheck(heapOid, GetUserId())) + aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS, + relation->relname); + + /* Can't reindex shared tables except in standalone mode */ + if (((Form_pg_class) GETSTRUCT(tuple))->relisshared && IsUnderPostmaster) + ereport(ERROR, + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), + errmsg("shared table \"%s\" can only be reindexed in standalone mode", + relation->relname))); + + ReleaseSysCache(tuple); - if (!reindex_relation(heapOid, force)) + if (!reindex_relation(heapOid)) ereport(WARNING, - (errmsg("table \"%s\" wasn't reindexed", + (errmsg("table \"%s\" has no indexes", relation->relname))); } /* * ReindexDatabase * Recreate indexes of a database. + * + * To reduce the probability of deadlocks, each table is reindexed in a + * separate transaction, so we can release the lock on it right away. */ void -ReindexDatabase(const char *dbname, bool force, bool all) +ReindexDatabase(const char *dbname, bool force /* currently unused */, + bool all) { Relation relationRelation; HeapScanDesc scan; HeapTuple tuple; MemoryContext private_context; MemoryContext old; - int relcnt, - relalc, - i, - oncealc = 200; - Oid *relids = (Oid *) NULL; + List *relids = NIL; AssertArg(dbname); @@ -715,21 +688,12 @@ ReindexDatabase(const char *dbname, bool force, bool all) aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_DATABASE, dbname); - if (!allowSystemTableMods) - ereport(ERROR, - (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), - errmsg("REINDEX DATABASE must be done in standalone postgres with -O -P options"))); - if (!IsIgnoringSystemIndexes()) - ereport(ERROR, - (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), - errmsg("REINDEX DATABASE must be done in standalone postgres with -P -O options"))); - /* * We cannot run inside a user transaction block; if we were inside a * transaction, then our commit- and start-transaction-command calls * would not have the intended effect! */ - PreventTransactionChain((void *) dbname, "REINDEX"); + PreventTransactionChain((void *) dbname, "REINDEX DATABASE"); /* * Create a memory context that will survive forced transaction @@ -744,54 +708,67 @@ ReindexDatabase(const char *dbname, bool force, bool all) ALLOCSET_DEFAULT_MAXSIZE); /* + * We always want to reindex pg_class first. This ensures that if + * there is any corruption in pg_class' indexes, they will be fixed + * before we process any other tables. This is critical because + * reindexing itself will try to update pg_class. + */ + old = MemoryContextSwitchTo(private_context); + relids = lappendo(relids, RelOid_pg_class); + MemoryContextSwitchTo(old); + + /* * Scan pg_class to build a list of the relations we need to reindex. + * + * We only consider plain relations here (toast rels will be processed + * indirectly by reindex_relation). */ relationRelation = heap_openr(RelationRelationName, AccessShareLock); scan = heap_beginscan(relationRelation, SnapshotNow, 0, NULL); - relcnt = relalc = 0; while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL) { - char relkind; + Form_pg_class classtuple = (Form_pg_class) GETSTRUCT(tuple); + + if (classtuple->relkind != RELKIND_RELATION) + continue; - if (!all) + if (!all) /* only system tables? */ { - if (!(IsSystemClass((Form_pg_class) GETSTRUCT(tuple)) && - !IsToastClass((Form_pg_class) GETSTRUCT(tuple)))) + if (!IsSystemClass(classtuple)) continue; } - relkind = ((Form_pg_class) GETSTRUCT(tuple))->relkind; - if (relkind == RELKIND_RELATION || relkind == RELKIND_TOASTVALUE) + + if (IsUnderPostmaster) /* silently ignore shared tables */ { - old = MemoryContextSwitchTo(private_context); - if (relcnt == 0) - { - relalc = oncealc; - relids = palloc(sizeof(Oid) * relalc); - } - else if (relcnt >= relalc) - { - relalc *= 2; - relids = repalloc(relids, sizeof(Oid) * relalc); - } - MemoryContextSwitchTo(old); - relids[relcnt] = HeapTupleGetOid(tuple); - relcnt++; + if (classtuple->relisshared) + continue; } + + if (HeapTupleGetOid(tuple) == RelOid_pg_class) + continue; /* got it already */ + + old = MemoryContextSwitchTo(private_context); + relids = lappendo(relids, HeapTupleGetOid(tuple)); + MemoryContextSwitchTo(old); } heap_endscan(scan); heap_close(relationRelation, AccessShareLock); /* Now reindex each rel in a separate transaction */ CommitTransactionCommand(); - for (i = 0; i < relcnt; i++) + while (relids) { + Oid relid = lfirsto(relids); + StartTransactionCommand(); SetQuerySnapshot(); /* might be needed for functions in * indexes */ - if (reindex_relation(relids[i], force)) + if (reindex_relation(relid)) ereport(NOTICE, - (errmsg("relation %u was reindexed", relids[i]))); + (errmsg("table \"%s\" was reindexed", + get_rel_name(relid)))); CommitTransactionCommand(); + relids = lnext(relids); } StartTransactionCommand(); diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c index f6331e8d214..e626848f12b 100644 --- a/src/backend/commands/vacuum.c +++ b/src/backend/commands/vacuum.c @@ -13,7 +13,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.259 2003/08/04 02:39:58 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.260 2003/09/24 18:54:01 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -904,11 +904,6 @@ full_vacuum_rel(Relation onerel, VacuumStmt *vacstmt) int nindexes, i; VRelStats *vacrelstats; - bool reindex = false; - - if (IsIgnoringSystemIndexes() && - IsSystemRelation(onerel)) - reindex = true; vacuum_set_xid_limits(vacstmt, onerel->rd_rel->relisshared, &OldestXmin, &FreezeLimit); @@ -927,27 +922,9 @@ full_vacuum_rel(Relation onerel, VacuumStmt *vacstmt) /* Now open all indexes of the relation */ vac_open_indexes(onerel, &nindexes, &Irel); - if (!Irel) - reindex = false; - else if (!RelationGetForm(onerel)->relhasindex) - reindex = true; if (nindexes > 0) vacrelstats->hasindex = true; -#ifdef NOT_USED - - /* - * reindex in VACUUM is dangerous under WAL. ifdef out until it - * becomes safe. - */ - if (reindex) - { - vac_close_indexes(nindexes, Irel); - Irel = (Relation *) NULL; - activate_indexes_of_a_table(onerel, false); - } -#endif /* NOT_USED */ - /* Clean/scan index relation(s) */ if (Irel != (Relation *) NULL) { @@ -994,11 +971,6 @@ full_vacuum_rel(Relation onerel, VacuumStmt *vacstmt) } } -#ifdef NOT_USED - if (reindex) - activate_indexes_of_a_table(onerel, true); -#endif /* NOT_USED */ - /* update shared free space map with final free space info */ vac_update_fsm(onerel, &fraged_pages, vacrelstats->rel_pages); |