From ff1dfbb0df6d86acb5d4d6dabee623d74df17ab7 Mon Sep 17 00:00:00 2001 From: Amit Langote Date: Mon, 25 Sep 2023 11:52:02 +0900 Subject: [PATCH v48 5/8] Assert that relations needing their permissions checked are locked --- src/backend/executor/execMain.c | 11 +++++++ src/backend/storage/lmgr/lmgr.c | 45 +++++++++++++++++++++++++++++ src/backend/utils/cache/lsyscache.c | 21 ++++++++++++++ src/include/storage/lmgr.h | 1 + src/include/utils/lsyscache.h | 1 + 5 files changed, 79 insertions(+) diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c index 5755336abd..ffc62e379a 100644 --- a/src/backend/executor/execMain.c +++ b/src/backend/executor/execMain.c @@ -626,6 +626,17 @@ ExecCheckPermissions(List *rangeTable, List *rteperminfos, (rte->rtekind == RTE_SUBQUERY && rte->relkind == RELKIND_VIEW)); + /* + * Relations whose permissions need to be checked must already + * have been locked by the parser or by GetCachedPlan() if a + * cached plan is being executed. + * + * XXX Maybe we should we skip calling ExecCheckPermissions from + * InitPlan in a parallel worker. + */ + Assert(IsParallelWorker() || + CheckRelLockedByMe(rte->relid, AccessShareLock, true)); + (void) getRTEPermissionInfo(rteperminfos, rte); /* Many-to-one mapping not allowed */ Assert(!bms_is_member(rte->perminfoindex, indexset)); diff --git a/src/backend/storage/lmgr/lmgr.c b/src/backend/storage/lmgr/lmgr.c index ee9b89a672..c807e9cdcc 100644 --- a/src/backend/storage/lmgr/lmgr.c +++ b/src/backend/storage/lmgr/lmgr.c @@ -27,6 +27,7 @@ #include "storage/procarray.h" #include "storage/sinvaladt.h" #include "utils/inval.h" +#include "utils/lsyscache.h" /* @@ -364,6 +365,50 @@ CheckRelationLockedByMe(Relation relation, LOCKMODE lockmode, bool orstronger) return false; } +/* + * CheckRelLockedByMe + * + * Returns true if current transaction holds a lock on the given relation of + * mode 'lockmode'. If 'orstronger' is true, a stronger lockmode is also OK. + * ("Stronger" is defined as "numerically higher", which is a bit + * semantically dubious but is OK for the purposes we use this for.) + */ +bool +CheckRelLockedByMe(Oid relid, LOCKMODE lockmode, bool orstronger) +{ + Oid dbId = get_rel_relisshared(relid) ? InvalidOid : MyDatabaseId; + LOCKTAG tag; + + SET_LOCKTAG_RELATION(tag, dbId, relid); + + if (LockHeldByMe(&tag, lockmode)) + return true; + + if (orstronger) + { + LOCKMODE slockmode; + + for (slockmode = lockmode + 1; + slockmode <= MaxLockMode; + slockmode++) + { + if (LockHeldByMe(&tag, slockmode)) + { +#ifdef NOT_USED + /* Sometimes this might be useful for debugging purposes */ + elog(WARNING, "lock mode %s substituted for %s on relation %s", + GetLockmodeName(tag.locktag_lockmethodid, slockmode), + GetLockmodeName(tag.locktag_lockmethodid, lockmode), + RelationGetRelationName(relation)); +#endif + return true; + } + } + } + + return false; +} + /* * LockHasWaitersRelation * diff --git a/src/backend/utils/cache/lsyscache.c b/src/backend/utils/cache/lsyscache.c index fc6d267e44..2725d02312 100644 --- a/src/backend/utils/cache/lsyscache.c +++ b/src/backend/utils/cache/lsyscache.c @@ -2095,6 +2095,27 @@ get_rel_persistence(Oid relid) return result; } +/* + * get_rel_relisshared + * + * Returns if the given relation is shared or not + */ +bool +get_rel_relisshared(Oid relid) +{ + HeapTuple tp; + Form_pg_class reltup; + bool result; + + tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid)); + if (!HeapTupleIsValid(tp)) + elog(ERROR, "cache lookup failed for relation %u", relid); + reltup = (Form_pg_class) GETSTRUCT(tp); + result = reltup->relisshared; + ReleaseSysCache(tp); + + return result; +} /* ---------- TRANSFORM CACHE ---------- */ diff --git a/src/include/storage/lmgr.h b/src/include/storage/lmgr.h index 4ee91e3cf9..598bf2688a 100644 --- a/src/include/storage/lmgr.h +++ b/src/include/storage/lmgr.h @@ -48,6 +48,7 @@ extern bool ConditionalLockRelation(Relation relation, LOCKMODE lockmode); extern void UnlockRelation(Relation relation, LOCKMODE lockmode); extern bool CheckRelationLockedByMe(Relation relation, LOCKMODE lockmode, bool orstronger); +extern bool CheckRelLockedByMe(Oid relid, LOCKMODE lockmode, bool orstronger); extern bool LockHasWaitersRelation(Relation relation, LOCKMODE lockmode); extern void LockRelationIdForSession(LockRelId *relid, LOCKMODE lockmode); diff --git a/src/include/utils/lsyscache.h b/src/include/utils/lsyscache.h index f5fdbfe116..a024e5dcd0 100644 --- a/src/include/utils/lsyscache.h +++ b/src/include/utils/lsyscache.h @@ -140,6 +140,7 @@ extern char get_rel_relkind(Oid relid); extern bool get_rel_relispartition(Oid relid); extern Oid get_rel_tablespace(Oid relid); extern char get_rel_persistence(Oid relid); +extern bool get_rel_relisshared(Oid relid); extern Oid get_transform_fromsql(Oid typid, Oid langid, List *trftypes); extern Oid get_transform_tosql(Oid typid, Oid langid, List *trftypes); extern bool get_typisdefined(Oid typid); -- 2.35.3