postgresql/src/backend/commands/lockcmds.c

90 lines
2.3 KiB
C
Raw Normal View History

/*-------------------------------------------------------------------------
*
* lockcmds.c
* Lock command support code
*
2009-01-01 18:24:05 +01:00
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/lockcmds.c,v 1.22 2009/05/12 00:56:05 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
#include "access/heapam.h"
#include "catalog/namespace.h"
#include "catalog/pg_inherits.h"
#include "commands/lockcmds.h"
#include "miscadmin.h"
#include "parser/parse_clause.h"
#include "utils/acl.h"
#include "utils/lsyscache.h"
#include "utils/rel.h"
/*
* LOCK TABLE
*/
void
LockTableCommand(LockStmt *lockstmt)
{
ListCell *p;
/*
2005-10-15 04:49:52 +02:00
* Iterate over the list and open, lock, and close the relations one at a
* time
*/
foreach(p, lockstmt->relations)
{
RangeVar *relation = lfirst(p);
Oid reloid;
bool recurse = interpretInhOption(relation->inhOpt);
List *children_and_self;
ListCell *child;
reloid = RangeVarGetRelid(relation, false);
if (recurse)
children_and_self = find_all_inheritors(reloid);
else
children_and_self = list_make1_oid(reloid);
foreach(child, children_and_self)
{
Oid childreloid = lfirst_oid(child);
Relation rel;
AclResult aclresult;
/* We don't want to open the relation until we've checked privilege. */
if (lockstmt->mode == AccessShareLock)
aclresult = pg_class_aclcheck(childreloid, GetUserId(),
ACL_SELECT);
else
aclresult = pg_class_aclcheck(childreloid, GetUserId(),
ACL_UPDATE | ACL_DELETE | ACL_TRUNCATE);
if (aclresult != ACLCHECK_OK)
aclcheck_error(aclresult, ACL_KIND_CLASS,
get_rel_name(childreloid));
if (lockstmt->nowait)
rel = relation_open_nowait(childreloid, lockstmt->mode);
else
rel = relation_open(childreloid, lockstmt->mode);
/* Currently, we only allow plain tables to be locked */
if (rel->rd_rel->relkind != RELKIND_RELATION)
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("\"%s\" is not a table",
get_rel_name(childreloid))));
relation_close(rel, NoLock); /* close rel, keep lock */
}
}
}