diff --git a/src/include/catalog/dependency.h b/src/include/catalog/dependency.h index 0cd6fcf027..5811d082b0 100644 --- a/src/include/catalog/dependency.h +++ b/src/include/catalog/dependency.h @@ -200,10 +200,10 @@ extern long changeDependencyFor(Oid classId, Oid objectId, Oid refClassId, Oid oldRefObjectId, Oid newRefObjectId); -extern long changeDependenciesOf(Oid classId, Oid oldObjectId, +extern long switchDependenciesOf(Oid classId, Oid oldObjectId, Oid newObjectId); -extern long changeDependenciesOn(Oid refClassId, Oid oldRefObjectId, +extern long switchDependenciesOn(Oid refClassId, Oid oldRefObjectId, Oid newRefObjectId); extern Oid getExtensionOfObject(Oid classId, Oid objectId); diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 1681f61727..fb9bb276bb 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -1675,14 +1675,10 @@ index_concurrently_swap(Oid newIndexId, Oid oldIndexId, const char *oldName) } /* - * Move all dependencies of and on the old index to the new one. First - * remove any dependencies that the new index may have to provide an - * initial clean state for the dependency switch, and then move all the - * dependencies from the old index to the new one. + * Switch all dependencies of and on the old and new indexes. */ - deleteDependencyRecordsFor(RelationRelationId, newIndexId, false); - changeDependenciesOf(RelationRelationId, oldIndexId, newIndexId); - changeDependenciesOn(RelationRelationId, oldIndexId, newIndexId); + switchDependenciesOf(RelationRelationId, oldIndexId, newIndexId); + switchDependenciesOn(RelationRelationId, oldIndexId, newIndexId); /* * Copy over statistics from old to new index diff --git a/src/backend/catalog/pg_depend.c b/src/backend/catalog/pg_depend.c index f9af245eec..11caa38083 100644 --- a/src/backend/catalog/pg_depend.c +++ b/src/backend/catalog/pg_depend.c @@ -396,7 +396,7 @@ changeDependencyFor(Oid classId, Oid objectId, } /* - * Adjust all dependency records to come from a different object of the same type + * Switch dependency records between two objects of the same type * * classId/oldObjectId specify the old referencing object. * newObjectId is the new referencing object (must be of class classId). @@ -404,38 +404,41 @@ changeDependencyFor(Oid classId, Oid objectId, * Returns the number of records updated. */ long -changeDependenciesOf(Oid classId, Oid oldObjectId, +switchDependenciesOf(Oid classId, Oid oldObjectId, Oid newObjectId) { long count = 0; Relation depRel; - ScanKeyData key[2]; + ScanKeyData key; SysScanDesc scan; HeapTuple tup; depRel = table_open(DependRelationId, RowExclusiveLock); - ScanKeyInit(&key[0], + ScanKeyInit(&key, Anum_pg_depend_classid, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(classId)); - ScanKeyInit(&key[1], - Anum_pg_depend_objid, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(oldObjectId)); scan = systable_beginscan(depRel, DependDependerIndexId, true, - NULL, 2, key); + NULL, 1, &key); while (HeapTupleIsValid((tup = systable_getnext(scan)))) { Form_pg_depend depform = (Form_pg_depend) GETSTRUCT(tup); + if (depform->objid != oldObjectId && + depform->objid != newObjectId) + continue; + /* make a modifiable copy */ tup = heap_copytuple(tup); depform = (Form_pg_depend) GETSTRUCT(tup); - depform->objid = newObjectId; + if (depform->objid == oldObjectId) + depform->objid = newObjectId; + else + depform->objid = oldObjectId; CatalogTupleUpdate(depRel, &tup->t_self, tup); @@ -452,7 +455,7 @@ changeDependenciesOf(Oid classId, Oid oldObjectId, } /* - * Adjust all dependency records to point to a different object of the same type + * Switch all dependency records between two objects of the same type. * * refClassId/oldRefObjectId specify the old referenced object. * newRefObjectId is the new referenced object (must be of class refClassId). @@ -460,74 +463,75 @@ changeDependenciesOf(Oid classId, Oid oldObjectId, * Returns the number of records updated. */ long -changeDependenciesOn(Oid refClassId, Oid oldRefObjectId, +switchDependenciesOn(Oid refClassId, Oid oldRefObjectId, Oid newRefObjectId) { long count = 0; Relation depRel; - ScanKeyData key[2]; + ScanKeyData key; SysScanDesc scan; HeapTuple tup; - ObjectAddress objAddr; - bool newIsPinned; + ObjectAddress newObjAddr; + ObjectAddress oldObjAddr; depRel = table_open(DependRelationId, RowExclusiveLock); /* - * If oldRefObjectId is pinned, there won't be any dependency entries on - * it --- we can't cope in that case. (This isn't really worth expending - * code to fix, in current usage; it just means you can't rename stuff out - * of pg_catalog, which would likely be a bad move anyway.) + * If oldRefObjectId or newRefObjectId are pinned, there won't be any + * dependency entries on it --- we can't cope in that case. (This + * isn't really worth expending code to fix, in current usage; it + * just means you can't rename stuff out of pg_catalog, which would + * likely be a bad move anyway.) */ - objAddr.classId = refClassId; - objAddr.objectId = oldRefObjectId; - objAddr.objectSubId = 0; + oldObjAddr.classId = refClassId; + oldObjAddr.objectId = oldRefObjectId; + oldObjAddr.objectSubId = 0; - if (isObjectPinned(&objAddr, depRel)) + if (isObjectPinned(&oldObjAddr, depRel)) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("cannot remove dependency on %s because it is a system object", - getObjectDescription(&objAddr)))); + getObjectDescription(&oldObjAddr)))); - /* - * We can handle adding a dependency on something pinned, though, since - * that just means deleting the dependency entry. - */ - objAddr.objectId = newRefObjectId; + newObjAddr.classId = refClassId; + newObjAddr.objectId = newRefObjectId; + newObjAddr.objectSubId = 0; - newIsPinned = isObjectPinned(&objAddr, depRel); + if (isObjectPinned(&newObjAddr, depRel)) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot remove dependency on %s because it is a system object", + getObjectDescription(&newObjAddr)))); /* Now search for dependency records */ - ScanKeyInit(&key[0], + ScanKeyInit(&key, Anum_pg_depend_refclassid, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(refClassId)); - ScanKeyInit(&key[1], - Anum_pg_depend_refobjid, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(oldRefObjectId)); scan = systable_beginscan(depRel, DependReferenceIndexId, true, - NULL, 2, key); + NULL, 1, &key); while (HeapTupleIsValid((tup = systable_getnext(scan)))) { Form_pg_depend depform = (Form_pg_depend) GETSTRUCT(tup); - if (newIsPinned) - CatalogTupleDelete(depRel, &tup->t_self); - else - { - /* make a modifiable copy */ - tup = heap_copytuple(tup); - depform = (Form_pg_depend) GETSTRUCT(tup); + if (depform->refobjid != oldRefObjectId && + depform->refobjid != newRefObjectId) + continue; + /* make a modifiable copy */ + tup = heap_copytuple(tup); + depform = (Form_pg_depend) GETSTRUCT(tup); + + if (depform->refobjid == oldRefObjectId) depform->refobjid = newRefObjectId; + else + depform->refobjid = oldRefObjectId; - CatalogTupleUpdate(depRel, &tup->t_self, tup); + CatalogTupleUpdate(depRel, &tup->t_self, tup); - heap_freetuple(tup); - } + heap_freetuple(tup); count++; }