diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/catalog/objectaddress.c | 27 | ||||
-rw-r--r-- | src/backend/commands/alter.c | 9 | ||||
-rw-r--r-- | src/include/catalog/objectaddress.h | 4 | ||||
-rw-r--r-- | src/test/regress/expected/database.out | 6 | ||||
-rw-r--r-- | src/test/regress/sql/database.sql | 7 |
5 files changed, 51 insertions, 2 deletions
diff --git a/src/backend/catalog/objectaddress.c b/src/backend/catalog/objectaddress.c index 903879bc437..d85e9f8f78d 100644 --- a/src/backend/catalog/objectaddress.c +++ b/src/backend/catalog/objectaddress.c @@ -2855,13 +2855,34 @@ get_object_property_data(Oid class_id) HeapTuple get_catalog_object_by_oid(Relation catalog, AttrNumber oidcol, Oid objectId) { + return + get_catalog_object_by_oid_extended(catalog, oidcol, objectId, false); +} + +/* + * Same as get_catalog_object_by_oid(), but with an additional "locktup" + * argument controlling whether to acquire a LOCKTAG_TUPLE at mode + * InplaceUpdateTupleLock. See README.tuplock section "Locking to write + * inplace-updated tables". + */ +HeapTuple +get_catalog_object_by_oid_extended(Relation catalog, + AttrNumber oidcol, + Oid objectId, + bool locktup) +{ HeapTuple tuple; Oid classId = RelationGetRelid(catalog); int oidCacheId = get_object_catcache_oid(classId); if (oidCacheId > 0) { - tuple = SearchSysCacheCopy1(oidCacheId, ObjectIdGetDatum(objectId)); + if (locktup) + tuple = SearchSysCacheLockedCopy1(oidCacheId, + ObjectIdGetDatum(objectId)); + else + tuple = SearchSysCacheCopy1(oidCacheId, + ObjectIdGetDatum(objectId)); if (!HeapTupleIsValid(tuple)) /* should not happen */ return NULL; } @@ -2886,6 +2907,10 @@ get_catalog_object_by_oid(Relation catalog, AttrNumber oidcol, Oid objectId) systable_endscan(scan); return NULL; } + + if (locktup) + LockTuple(catalog, &tuple->t_self, InplaceUpdateTupleLock); + tuple = heap_copytuple(tuple); systable_endscan(scan); diff --git a/src/backend/commands/alter.c b/src/backend/commands/alter.c index 6f27a492d09..feb5517a288 100644 --- a/src/backend/commands/alter.c +++ b/src/backend/commands/alter.c @@ -60,6 +60,7 @@ #include "miscadmin.h" #include "parser/parse_func.h" #include "rewrite/rewriteDefine.h" +#include "storage/lmgr.h" #include "tcop/utility.h" #include "utils/builtins.h" #include "utils/fmgroids.h" @@ -947,7 +948,9 @@ AlterObjectOwner_internal(Relation rel, Oid objectId, Oid new_ownerId) Oid old_ownerId; Oid namespaceId = InvalidOid; - oldtup = get_catalog_object_by_oid(rel, Anum_oid, objectId); + /* Search tuple and lock it. */ + oldtup = + get_catalog_object_by_oid_extended(rel, Anum_oid, objectId, true); if (oldtup == NULL) elog(ERROR, "cache lookup failed for object %u of catalog \"%s\"", objectId, RelationGetRelationName(rel)); @@ -1046,6 +1049,8 @@ AlterObjectOwner_internal(Relation rel, Oid objectId, Oid new_ownerId) /* Perform actual update */ CatalogTupleUpdate(rel, &newtup->t_self, newtup); + UnlockTuple(rel, &oldtup->t_self, InplaceUpdateTupleLock); + /* * Update owner dependency reference. When working on a large object, * we have to translate back to the OID conventionally used for LOs' @@ -1063,6 +1068,8 @@ AlterObjectOwner_internal(Relation rel, Oid objectId, Oid new_ownerId) } else { + UnlockTuple(rel, &oldtup->t_self, InplaceUpdateTupleLock); + /* * No need to change anything. But when working on a large object, we * have to translate back to the OID conventionally used for LOs' diff --git a/src/include/catalog/objectaddress.h b/src/include/catalog/objectaddress.h index cf4d8b31077..3d956420995 100644 --- a/src/include/catalog/objectaddress.h +++ b/src/include/catalog/objectaddress.h @@ -69,6 +69,10 @@ extern bool get_object_namensp_unique(Oid class_id); extern HeapTuple get_catalog_object_by_oid(Relation catalog, AttrNumber oidcol, Oid objectId); +extern HeapTuple get_catalog_object_by_oid_extended(Relation catalog, + AttrNumber oidcol, + Oid objectId, + bool locktup); extern char *getObjectDescription(const ObjectAddress *object, bool missing_ok); diff --git a/src/test/regress/expected/database.out b/src/test/regress/expected/database.out index 6bc935c14ed..8c4bdc2d349 100644 --- a/src/test/regress/expected/database.out +++ b/src/test/regress/expected/database.out @@ -11,4 +11,10 @@ WHERE datname = 'regression_utf8'; -- load catcache entry, if nothing else does ALTER DATABASE regression_utf8 RESET TABLESPACE; ROLLBACK; +CREATE ROLE regress_datdba_before; +CREATE ROLE regress_datdba_after; +ALTER DATABASE regression_utf8 OWNER TO regress_datdba_before; +REASSIGN OWNED BY regress_datdba_before TO regress_datdba_after; DROP DATABASE regression_utf8; +DROP ROLE regress_datdba_before; +DROP ROLE regress_datdba_after; diff --git a/src/test/regress/sql/database.sql b/src/test/regress/sql/database.sql index dbb899c41ce..edd62128268 100644 --- a/src/test/regress/sql/database.sql +++ b/src/test/regress/sql/database.sql @@ -13,4 +13,11 @@ WHERE datname = 'regression_utf8'; ALTER DATABASE regression_utf8 RESET TABLESPACE; ROLLBACK; +CREATE ROLE regress_datdba_before; +CREATE ROLE regress_datdba_after; +ALTER DATABASE regression_utf8 OWNER TO regress_datdba_before; +REASSIGN OWNED BY regress_datdba_before TO regress_datdba_after; + DROP DATABASE regression_utf8; +DROP ROLE regress_datdba_before; +DROP ROLE regress_datdba_after; |