aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/catalog/objectaddress.c27
-rw-r--r--src/backend/commands/alter.c9
-rw-r--r--src/include/catalog/objectaddress.h4
-rw-r--r--src/test/regress/expected/database.out6
-rw-r--r--src/test/regress/sql/database.sql7
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;