diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c index 6563f2bb5b..1c1d0da448 100644 --- a/src/backend/commands/indexcmds.c +++ b/src/backend/commands/indexcmds.c @@ -1780,26 +1780,26 @@ ReindexTable(RangeVar *relation) } /* - * ReindexObject - * Recreate indexes of object whose type is defined by objectKind. + * ReindexMultipleTables + * Recreate indexes of tables selected by objectName/objectKind. * * To reduce the probability of deadlocks, each table is reindexed in a * separate transaction, so we can release the lock on it right away. * That means this must not be called within a user transaction block! */ -Oid -ReindexObject(const char *objectName, ReindexObjectType objectKind) +void +ReindexMultipleTables(const char *objectName, ReindexObjectType objectKind) { Oid objectOid; Relation relationRelation; HeapScanDesc scan; - ScanKeyData *scan_keys = NULL; + ScanKeyData scan_keys[1]; HeapTuple tuple; MemoryContext private_context; MemoryContext old; List *relids = NIL; ListCell *l; - int num_keys; + int num_keys; AssertArg(objectName); Assert(objectKind == REINDEX_OBJECT_SCHEMA || @@ -1807,10 +1807,10 @@ ReindexObject(const char *objectName, ReindexObjectType objectKind) objectKind == REINDEX_OBJECT_DATABASE); /* - * Get OID of object to reindex, being the database currently being - * used by session for a database or for system catalogs, or the schema - * defined by caller. At the same time do permission checks that need - * different processing depending on the object type. + * Get OID of object to reindex, being the database currently being used + * by session for a database or for system catalogs, or the schema defined + * by caller. At the same time do permission checks that need different + * processing depending on the object type. */ if (objectKind == REINDEX_OBJECT_SCHEMA) { @@ -1824,11 +1824,11 @@ ReindexObject(const char *objectName, ReindexObjectType objectKind) { objectOid = MyDatabaseId; - if (strcmp(objectName, get_database_name(MyDatabaseId)) != 0) + if (strcmp(objectName, get_database_name(objectOid)) != 0) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), 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, objectName); } @@ -1840,42 +1840,19 @@ ReindexObject(const char *objectName, ReindexObjectType objectKind) * abort cleanup logic. */ private_context = AllocSetContextCreate(PortalContext, - (objectKind == REINDEX_OBJECT_SCHEMA) ? - "ReindexSchema" : "ReindexDatabase", + "ReindexMultipleTables", ALLOCSET_DEFAULT_MINSIZE, ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE); /* - * We always want to reindex pg_class first when reindexing system - * catalogs or a database. 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. - */ - 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. + * Define the search keys to find the objects to reindex. For a schema, we + * select target relations using relnamespace, something not necessary for + * a database-wide operation. */ if (objectKind == REINDEX_OBJECT_SCHEMA) { - /* - * Return all objects in schema. We filter out - * inappropriate objects as we walk through results. - */ num_keys = 1; - scan_keys = palloc(sizeof(ScanKeyData)); ScanKeyInit(&scan_keys[0], Anum_pg_class_relnamespace, BTEqualStrategyNumber, F_OIDEQ, @@ -1898,8 +1875,8 @@ ReindexObject(const char *objectName, ReindexObjectType objectKind) Oid relid = HeapTupleGetOid(tuple); /* - * Only regular tables and matviews can have indexes, - * so filter out any other kind of object. + * Only regular tables and matviews can have indexes, so ignore any + * other kind of relation. */ if (classtuple->relkind != RELKIND_RELATION && classtuple->relkind != RELKIND_MATVIEW) @@ -1911,20 +1888,25 @@ ReindexObject(const char *objectName, ReindexObjectType objectKind) continue; /* Check user/system classification, and optionally skip */ - if (!IsSystemClass(relid, classtuple) && - objectKind == REINDEX_OBJECT_SYSTEM) + if (objectKind == REINDEX_OBJECT_SYSTEM && + !IsSystemClass(relid, classtuple)) 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 - * reindexed, of a database or of a system catalog being reindexed - * as a schema. + * We always want to reindex pg_class first if it's selected to be + * reindexed. 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. */ - if (HeapTupleGetOid(tuple) == RelationRelationId) - continue; + if (relid == RelationRelationId) + relids = lcons_oid(relid, relids); + else + relids = lappend_oid(relids, relid); - old = MemoryContextSwitchTo(private_context); - relids = lappend_oid(relids, relid); MemoryContextSwitchTo(old); } heap_endscan(scan); @@ -1953,8 +1935,4 @@ ReindexObject(const char *objectName, ReindexObjectType objectKind) StartTransactionCommand(); MemoryContextDelete(private_context); - if (scan_keys) - pfree(scan_keys); - - return objectOid; } diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c index e2e718e216..126e38d7f7 100644 --- a/src/backend/tcop/utility.c +++ b/src/backend/tcop/utility.c @@ -756,7 +756,7 @@ standard_ProcessUtility(Node *parsetree, (stmt->kind == REINDEX_OBJECT_SCHEMA) ? "REINDEX SCHEMA" : (stmt->kind == REINDEX_OBJECT_SYSTEM) ? "REINDEX SYSTEM" : "REINDEX DATABASE"); - ReindexObject(stmt->name, stmt->kind); + ReindexMultipleTables(stmt->name, stmt->kind); break; default: elog(ERROR, "unrecognized object type: %d", diff --git a/src/include/commands/defrem.h b/src/include/commands/defrem.h index 9e3e93b605..a9c67838a6 100644 --- a/src/include/commands/defrem.h +++ b/src/include/commands/defrem.h @@ -31,7 +31,7 @@ extern ObjectAddress DefineIndex(Oid relationId, bool quiet); extern Oid ReindexIndex(RangeVar *indexRelation); 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, const char *label); extern char *ChooseRelationName(const char *name1, const char *name2,