Code cleanup for REINDEX DATABASE/SCHEMA/SYSTEM.

Fix some minor infelicities.  Some of these things were introduced in
commit fe263d115a, and some are older.
This commit is contained in:
Tom Lane 2015-03-08 12:18:43 -04:00
parent ac0914285a
commit 90c35a9ed0
3 changed files with 34 additions and 56 deletions

View File

@ -1780,26 +1780,26 @@ ReindexTable(RangeVar *relation)
} }
/* /*
* ReindexObject * ReindexMultipleTables
* Recreate indexes of object whose type is defined by objectKind. * Recreate indexes of tables selected by objectName/objectKind.
* *
* To reduce the probability of deadlocks, each table is reindexed in a * To reduce the probability of deadlocks, each table is reindexed in a
* separate transaction, so we can release the lock on it right away. * separate transaction, so we can release the lock on it right away.
* That means this must not be called within a user transaction block! * That means this must not be called within a user transaction block!
*/ */
Oid void
ReindexObject(const char *objectName, ReindexObjectType objectKind) ReindexMultipleTables(const char *objectName, ReindexObjectType objectKind)
{ {
Oid objectOid; Oid objectOid;
Relation relationRelation; Relation relationRelation;
HeapScanDesc scan; HeapScanDesc scan;
ScanKeyData *scan_keys = NULL; ScanKeyData scan_keys[1];
HeapTuple tuple; HeapTuple tuple;
MemoryContext private_context; MemoryContext private_context;
MemoryContext old; MemoryContext old;
List *relids = NIL; List *relids = NIL;
ListCell *l; ListCell *l;
int num_keys; int num_keys;
AssertArg(objectName); AssertArg(objectName);
Assert(objectKind == REINDEX_OBJECT_SCHEMA || Assert(objectKind == REINDEX_OBJECT_SCHEMA ||
@ -1807,10 +1807,10 @@ ReindexObject(const char *objectName, ReindexObjectType objectKind)
objectKind == REINDEX_OBJECT_DATABASE); objectKind == REINDEX_OBJECT_DATABASE);
/* /*
* Get OID of object to reindex, being the database currently being * Get OID of object to reindex, being the database currently being used
* used by session for a database or for system catalogs, or the schema * by session for a database or for system catalogs, or the schema defined
* defined by caller. At the same time do permission checks that need * by caller. At the same time do permission checks that need different
* different processing depending on the object type. * processing depending on the object type.
*/ */
if (objectKind == REINDEX_OBJECT_SCHEMA) if (objectKind == REINDEX_OBJECT_SCHEMA)
{ {
@ -1824,11 +1824,11 @@ ReindexObject(const char *objectName, ReindexObjectType objectKind)
{ {
objectOid = MyDatabaseId; objectOid = MyDatabaseId;
if (strcmp(objectName, get_database_name(MyDatabaseId)) != 0) if (strcmp(objectName, get_database_name(objectOid)) != 0)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED), (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("can only reindex the currently open database"))); errmsg("can only reindex the currently open database")));
if (!pg_database_ownercheck(MyDatabaseId, GetUserId())) if (!pg_database_ownercheck(objectOid, GetUserId()))
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_DATABASE, aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_DATABASE,
objectName); objectName);
} }
@ -1840,42 +1840,19 @@ ReindexObject(const char *objectName, ReindexObjectType objectKind)
* abort cleanup logic. * abort cleanup logic.
*/ */
private_context = AllocSetContextCreate(PortalContext, private_context = AllocSetContextCreate(PortalContext,
(objectKind == REINDEX_OBJECT_SCHEMA) ? "ReindexMultipleTables",
"ReindexSchema" : "ReindexDatabase",
ALLOCSET_DEFAULT_MINSIZE, ALLOCSET_DEFAULT_MINSIZE,
ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_INITSIZE,
ALLOCSET_DEFAULT_MAXSIZE); ALLOCSET_DEFAULT_MAXSIZE);
/* /*
* We always want to reindex pg_class first when reindexing system * Define the search keys to find the objects to reindex. For a schema, we
* catalogs or a database. This ensures that if there is any corruption * select target relations using relnamespace, something not necessary for
* in pg_class' indexes, they will be fixed before we process any other * a database-wide operation.
* tables. This is critical because reindexing itself will try to
* update pg_class.
*/
if (objectKind == REINDEX_OBJECT_DATABASE ||
objectKind == REINDEX_OBJECT_SYSTEM ||
(objectKind == REINDEX_OBJECT_SCHEMA &&
IsSystemNamespace(objectOid)))
{
old = MemoryContextSwitchTo(private_context);
relids = lappend_oid(relids, RelationRelationId);
MemoryContextSwitchTo(old);
}
/*
* Define the search keys to find the objects to reindex. For a schema,
* we search target relations using relnamespace and relkind, something
* not necessary for a database-wide operation.
*/ */
if (objectKind == REINDEX_OBJECT_SCHEMA) if (objectKind == REINDEX_OBJECT_SCHEMA)
{ {
/*
* Return all objects in schema. We filter out
* inappropriate objects as we walk through results.
*/
num_keys = 1; num_keys = 1;
scan_keys = palloc(sizeof(ScanKeyData));
ScanKeyInit(&scan_keys[0], ScanKeyInit(&scan_keys[0],
Anum_pg_class_relnamespace, Anum_pg_class_relnamespace,
BTEqualStrategyNumber, F_OIDEQ, BTEqualStrategyNumber, F_OIDEQ,
@ -1898,8 +1875,8 @@ ReindexObject(const char *objectName, ReindexObjectType objectKind)
Oid relid = HeapTupleGetOid(tuple); Oid relid = HeapTupleGetOid(tuple);
/* /*
* Only regular tables and matviews can have indexes, * Only regular tables and matviews can have indexes, so ignore any
* so filter out any other kind of object. * other kind of relation.
*/ */
if (classtuple->relkind != RELKIND_RELATION && if (classtuple->relkind != RELKIND_RELATION &&
classtuple->relkind != RELKIND_MATVIEW) classtuple->relkind != RELKIND_MATVIEW)
@ -1911,20 +1888,25 @@ ReindexObject(const char *objectName, ReindexObjectType objectKind)
continue; continue;
/* Check user/system classification, and optionally skip */ /* Check user/system classification, and optionally skip */
if (!IsSystemClass(relid, classtuple) && if (objectKind == REINDEX_OBJECT_SYSTEM &&
objectKind == REINDEX_OBJECT_SYSTEM) !IsSystemClass(relid, classtuple))
continue; continue;
/* Save the list of relation OIDs in private context */
old = MemoryContextSwitchTo(private_context);
/* /*
* Already have it in the case of system catalogs being all * We always want to reindex pg_class first if it's selected to be
* reindexed, of a database or of a system catalog being reindexed * reindexed. This ensures that if there is any corruption in
* as a schema. * 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.
*/ */
if (HeapTupleGetOid(tuple) == RelationRelationId) if (relid == RelationRelationId)
continue; relids = lcons_oid(relid, relids);
else
relids = lappend_oid(relids, relid);
old = MemoryContextSwitchTo(private_context);
relids = lappend_oid(relids, relid);
MemoryContextSwitchTo(old); MemoryContextSwitchTo(old);
} }
heap_endscan(scan); heap_endscan(scan);
@ -1953,8 +1935,4 @@ ReindexObject(const char *objectName, ReindexObjectType objectKind)
StartTransactionCommand(); StartTransactionCommand();
MemoryContextDelete(private_context); MemoryContextDelete(private_context);
if (scan_keys)
pfree(scan_keys);
return objectOid;
} }

View File

@ -756,7 +756,7 @@ standard_ProcessUtility(Node *parsetree,
(stmt->kind == REINDEX_OBJECT_SCHEMA) ? "REINDEX SCHEMA" : (stmt->kind == REINDEX_OBJECT_SCHEMA) ? "REINDEX SCHEMA" :
(stmt->kind == REINDEX_OBJECT_SYSTEM) ? "REINDEX SYSTEM" : (stmt->kind == REINDEX_OBJECT_SYSTEM) ? "REINDEX SYSTEM" :
"REINDEX DATABASE"); "REINDEX DATABASE");
ReindexObject(stmt->name, stmt->kind); ReindexMultipleTables(stmt->name, stmt->kind);
break; break;
default: default:
elog(ERROR, "unrecognized object type: %d", elog(ERROR, "unrecognized object type: %d",

View File

@ -31,7 +31,7 @@ extern ObjectAddress DefineIndex(Oid relationId,
bool quiet); bool quiet);
extern Oid ReindexIndex(RangeVar *indexRelation); extern Oid ReindexIndex(RangeVar *indexRelation);
extern Oid ReindexTable(RangeVar *relation); extern Oid ReindexTable(RangeVar *relation);
extern Oid ReindexObject(const char *databaseName, ReindexObjectType kind); extern void ReindexMultipleTables(const char *objectName, ReindexObjectType objectKind);
extern char *makeObjectName(const char *name1, const char *name2, extern char *makeObjectName(const char *name1, const char *name2,
const char *label); const char *label);
extern char *ChooseRelationName(const char *name1, const char *name2, extern char *ChooseRelationName(const char *name1, const char *name2,