提交 16365ac7 编写于 作者: B Bruce Momjian

Add LOCK A,B,C functionality as LOCK A;LOCK B;LOCK C; as agreed.

Neil Padgett
上级 0bfc64b3
<!--
$Header: /cvsroot/pgsql/doc/src/sgml/ref/lock.sgml,v 1.24 2001/07/09 22:18:33 tgl Exp $
$Header: /cvsroot/pgsql/doc/src/sgml/ref/lock.sgml,v 1.25 2001/08/04 19:38:59 momjian Exp $
Postgres documentation
-->
......@@ -15,7 +15,7 @@ Postgres documentation
LOCK
</refname>
<refpurpose>
Explicitly lock a table inside a transaction
Explicitly lock a table / tables inside a transaction
</refpurpose>
</refnamediv>
<refsynopsisdiv>
......@@ -23,8 +23,8 @@ Postgres documentation
<date>2001-07-09</date>
</refsynopsisdivinfo>
<synopsis>
LOCK [ TABLE ] <replaceable class="PARAMETER">name</replaceable>
LOCK [ TABLE ] <replaceable class="PARAMETER">name</replaceable> IN <replaceable class="PARAMETER">lockmode</replaceable> MODE
LOCK [ TABLE ] <replaceable class="PARAMETER">name</replaceable> [,...]
LOCK [ TABLE ] <replaceable class="PARAMETER">name</replaceable> [,...] IN <replaceable class="PARAMETER">lockmode</replaceable> MODE
where <replaceable class="PARAMETER">lockmode</replaceable> is one of:
......@@ -373,6 +373,7 @@ ERROR <replaceable class="PARAMETER">name</replaceable>: Table does not exist.
An example for this rule was given previously when discussing the
use of SHARE ROW EXCLUSIVE mode rather than SHARE mode.
</para>
</listitem>
</itemizedlist>
......@@ -383,6 +384,12 @@ ERROR <replaceable class="PARAMETER">name</replaceable>: Table does not exist.
</para>
</note>
<para>
When locking multiple tables, the command LOCK a, b; is equivalent to LOCK
a; LOCK b;. The tables are locked one-by-one in the order specified in the
<command>LOCK</command> command.
</para>
<refsect2 id="R2-SQL-LOCK-3">
<refsect2info>
<date>1999-06-08</date>
......@@ -406,6 +413,7 @@ ERROR <replaceable class="PARAMETER">name</replaceable>: Table does not exist.
<para>
<command>LOCK</command> works only inside transactions.
</para>
</refsect2>
</refsect1>
......
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.136 2001/07/16 05:06:57 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.137 2001/08/04 19:38:59 momjian Exp $
*
* NOTES
* The PerformAddAttribute() code, like most of the relation
......@@ -1984,8 +1984,7 @@ needs_toast_table(Relation rel)
MAXALIGN(data_length);
return (tuple_length > TOAST_TUPLE_THRESHOLD);
}
/*
*
* LOCK TABLE
......@@ -1994,26 +1993,104 @@ needs_toast_table(Relation rel)
void
LockTableCommand(LockStmt *lockstmt)
{
Relation rel;
int aclresult;
int relCnt;
rel = heap_openr(lockstmt->relname, NoLock);
relCnt = length(lockstmt -> rellist);
if (rel->rd_rel->relkind != RELKIND_RELATION)
elog(ERROR, "LOCK TABLE: %s is not a table", lockstmt->relname);
/* Handle a single relation lock specially to avoid overhead on likely the
most common case */
if (lockstmt->mode == AccessShareLock)
aclresult = pg_aclcheck(lockstmt->relname, GetUserId(), ACL_SELECT);
else
aclresult = pg_aclcheck(lockstmt->relname, GetUserId(),
ACL_UPDATE | ACL_DELETE);
if(relCnt == 1)
{
/* Locking a single table */
Relation rel;
int aclresult;
char *relname;
relname = strVal(lfirst(lockstmt->rellist));
freeList(lockstmt->rellist);
rel = heap_openr(relname, NoLock);
if (rel->rd_rel->relkind != RELKIND_RELATION)
elog(ERROR, "LOCK TABLE: %s is not a table", relname);
if (lockstmt->mode == AccessShareLock)
aclresult = pg_aclcheck(relname, GetUserId(),
ACL_SELECT);
else
aclresult = pg_aclcheck(relname, GetUserId(),
ACL_UPDATE | ACL_DELETE);
if (aclresult != ACLCHECK_OK)
elog(ERROR, "LOCK TABLE: permission denied");
LockRelation(rel, lockstmt->mode);
pfree(relname);
heap_close(rel, NoLock); /* close rel, keep lock */
}
else
{
List *p;
Relation *RelationArray;
Relation *pRel;
if (aclresult != ACLCHECK_OK)
elog(ERROR, "LOCK TABLE: permission denied");
/* Locking multiple tables */
LockRelation(rel, lockstmt->mode);
/* Create an array of relations */
heap_close(rel, NoLock); /* close rel, keep lock */
RelationArray = palloc(relCnt * sizeof(Relation));
pRel = RelationArray;
/* Iterate over the list and populate the relation array */
foreach(p, lockstmt->rellist)
{
char* relname = strVal(lfirst(p));
int aclresult;
*pRel = heap_openr(relname, NoLock);
if ((*pRel)->rd_rel->relkind != RELKIND_RELATION)
elog(ERROR, "LOCK TABLE: %s is not a table",
relname);
if (lockstmt->mode == AccessShareLock)
aclresult = pg_aclcheck(relname, GetUserId(),
ACL_SELECT);
else
aclresult = pg_aclcheck(relname, GetUserId(),
ACL_UPDATE | ACL_DELETE);
if (aclresult != ACLCHECK_OK)
elog(ERROR, "LOCK TABLE: permission denied");
pRel++;
pfree(relname);
}
/* Now, lock all the relations, closing each after it is locked
(Keeping the locks)
*/
for(pRel = RelationArray;
pRel < RelationArray + relCnt;
pRel++)
{
LockRelation(*pRel, lockstmt->mode);
heap_close(*pRel, NoLock);
}
/* Free the relation array */
pfree(RelationArray);
}
}
......
......@@ -15,7 +15,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.148 2001/07/16 19:07:37 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.149 2001/08/04 19:38:59 momjian Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -2425,8 +2425,8 @@ _copyLockStmt(LockStmt *from)
{
LockStmt *newnode = makeNode(LockStmt);
if (from->relname)
newnode->relname = pstrdup(from->relname);
Node_Copy(from, newnode, rellist);
newnode->mode = from->mode;
return newnode;
......
......@@ -20,7 +20,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.96 2001/07/16 19:07:38 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.97 2001/08/04 19:38:59 momjian Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -1283,7 +1283,7 @@ _equalDropUserStmt(DropUserStmt *a, DropUserStmt *b)
static bool
_equalLockStmt(LockStmt *a, LockStmt *b)
{
if (!equalstr(a->relname, b->relname))
if (!equal(a->rellist, b->rellist))
return false;
if (a->mode != b->mode)
return false;
......
......@@ -11,7 +11,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.238 2001/07/16 19:07:40 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.239 2001/08/04 19:38:59 momjian Exp $
*
* HISTORY
* AUTHOR DATE MAJOR EVENT
......@@ -3280,11 +3280,11 @@ DeleteStmt: DELETE FROM relation_expr where_clause
}
;
LockStmt: LOCK_P opt_table relation_name opt_lock
LockStmt: LOCK_P opt_table relation_name_list opt_lock
{
LockStmt *n = makeNode(LockStmt);
n->relname = $3;
n->rellist = $3;
n->mode = $4;
$$ = (Node *)n;
}
......
......@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: parsenodes.h,v 1.136 2001/07/16 19:07:40 momjian Exp $
* $Id: parsenodes.h,v 1.137 2001/08/04 19:38:59 momjian Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -760,7 +760,7 @@ typedef struct VariableResetStmt
typedef struct LockStmt
{
NodeTag type;
char *relname; /* relation to lock */
List *rellist; /* relations to lock */
int mode; /* lock mode */
} LockStmt;
......
......@@ -2421,7 +2421,7 @@ DeleteStmt: DELETE FROM relation_expr where_clause
}
;
LockStmt: LOCK_P opt_table relation_name opt_lock
LockStmt: LOCK_P opt_table relation_name_list opt_lock
{
$$ = cat_str(4, make_str("lock"), $2, $3, $4);
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册