#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);
}
1.7.1