#include "postgres.h"
#include "access/heapam.h"
#include "catalog/namespace.h"
#include "catalog/pg_inherits_fn.h"
#include "commands/lockcmds.h"
#include "miscadmin.h"
#include "parser/parse_clause.h"
#include "storage/lmgr.h"
#include "utils/acl.h"
#include "utils/lsyscache.h"
#include "utils/syscache.h"
Go to the source code of this file.
Functions | |
static void | LockTableRecurse (Oid reloid, LOCKMODE lockmode, bool nowait) |
static AclResult | LockTableAclCheck (Oid relid, LOCKMODE lockmode) |
static void | RangeVarCallbackForLockTable (const RangeVar *rv, Oid relid, Oid oldrelid, void *arg) |
void | LockTableCommand (LockStmt *lockstmt) |
Definition at line 169 of file lockcmds.c.
References AccessShareLock, ACL_DELETE, ACL_SELECT, ACL_TRUNCATE, ACL_UPDATE, GetUserId(), and pg_class_aclcheck().
Referenced by LockTableRecurse(), and RangeVarCallbackForLockTable().
{ AclResult aclresult; /* Verify adequate privilege */ if (lockmode == AccessShareLock) aclresult = pg_class_aclcheck(reloid, GetUserId(), ACL_SELECT); else aclresult = pg_class_aclcheck(reloid, GetUserId(), ACL_UPDATE | ACL_DELETE | ACL_TRUNCATE); return aclresult; }
void LockTableCommand | ( | LockStmt * | lockstmt | ) |
Definition at line 37 of file lockcmds.c.
References RangeVar::inhOpt, interpretInhOption(), lfirst, LockTableRecurse(), LockStmt::mode, LockStmt::nowait, PreventCommandDuringRecovery(), RangeVarCallbackForLockTable(), RangeVarGetRelidExtended(), LockStmt::relations, and RowExclusiveLock.
Referenced by standard_ProcessUtility().
{ ListCell *p; /*--------- * During recovery we only accept these variations: * LOCK TABLE foo IN ACCESS SHARE MODE * LOCK TABLE foo IN ROW SHARE MODE * LOCK TABLE foo IN ROW EXCLUSIVE MODE * This test must match the restrictions defined in LockAcquireExtended() *--------- */ if (lockstmt->mode > RowExclusiveLock) PreventCommandDuringRecovery("LOCK TABLE"); /* * Iterate over the list and process the named relations one at a time */ foreach(p, lockstmt->relations) { RangeVar *rv = (RangeVar *) lfirst(p); bool recurse = interpretInhOption(rv->inhOpt); Oid reloid; reloid = RangeVarGetRelidExtended(rv, lockstmt->mode, false, lockstmt->nowait, RangeVarCallbackForLockTable, (void *) &lockstmt->mode); if (recurse) LockTableRecurse(reloid, lockstmt->mode, lockstmt->nowait); } }
Definition at line 111 of file lockcmds.c.
References ACL_KIND_CLASS, aclcheck_error(), ACLCHECK_OK, ConditionalLockRelationOid(), ereport, errcode(), errmsg(), ERROR, find_inheritance_children(), get_rel_name(), lfirst_oid, LockRelationOid(), LockTableAclCheck(), NoLock, ObjectIdGetDatum, RELOID, SearchSysCacheExists1, and UnlockRelationOid().
Referenced by LockTableCommand().
{ List *children; ListCell *lc; children = find_inheritance_children(reloid, NoLock); foreach(lc, children) { Oid childreloid = lfirst_oid(lc); AclResult aclresult; /* Check permissions before acquiring the lock. */ aclresult = LockTableAclCheck(childreloid, lockmode); if (aclresult != ACLCHECK_OK) { char *relname = get_rel_name(childreloid); if (!relname) continue; /* child concurrently dropped, just skip it */ aclcheck_error(aclresult, ACL_KIND_CLASS, relname); } /* We have enough rights to lock the relation; do so. */ if (!nowait) LockRelationOid(childreloid, lockmode); else if (!ConditionalLockRelationOid(childreloid, lockmode)) { /* try to throw error by name; relation could be deleted... */ char *relname = get_rel_name(childreloid); if (!relname) continue; /* child concurrently dropped, just skip it */ ereport(ERROR, (errcode(ERRCODE_LOCK_NOT_AVAILABLE), errmsg("could not obtain lock on relation \"%s\"", relname))); } /* * Even if we got the lock, child might have been concurrently * dropped. If so, we can skip it. */ if (!SearchSysCacheExists1(RELOID, ObjectIdGetDatum(childreloid))) { /* Release useless lock */ UnlockRelationOid(childreloid, lockmode); continue; } LockTableRecurse(childreloid, lockmode, nowait); } }
static void RangeVarCallbackForLockTable | ( | const RangeVar * | rv, | |
Oid | relid, | |||
Oid | oldrelid, | |||
void * | arg | |||
) | [static] |
Definition at line 76 of file lockcmds.c.
References ACL_KIND_CLASS, aclcheck_error(), ACLCHECK_OK, ereport, errcode(), errmsg(), ERROR, get_rel_relkind(), LockTableAclCheck(), OidIsValid, RELKIND_RELATION, and RangeVar::relname.
Referenced by LockTableCommand().
{ LOCKMODE lockmode = *(LOCKMODE *) arg; char relkind; AclResult aclresult; if (!OidIsValid(relid)) return; /* doesn't exist, so no permissions check */ relkind = get_rel_relkind(relid); if (!relkind) return; /* woops, concurrently dropped; no permissions * check */ /* Currently, we only allow plain tables to be locked */ if (relkind != RELKIND_RELATION) ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), errmsg("\"%s\" is not a table", rv->relname))); /* Check permissions. */ aclresult = LockTableAclCheck(relid, lockmode); if (aclresult != ACLCHECK_OK) aclcheck_error(aclresult, ACL_KIND_CLASS, rv->relname); }