diff options
Diffstat (limited to 'src/backend/commands/indexcmds.c')
-rw-r--r-- | src/backend/commands/indexcmds.c | 171 |
1 files changed, 74 insertions, 97 deletions
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(); |