OSDN Git Service

Add LOCK A,B,C functionality as LOCK A;LOCK B;LOCK C; as agreed.
authorBruce Momjian <bruce@momjian.us>
Sat, 4 Aug 2001 19:39:00 +0000 (19:39 +0000)
committerBruce Momjian <bruce@momjian.us>
Sat, 4 Aug 2001 19:39:00 +0000 (19:39 +0000)
Neil Padgett

doc/src/sgml/ref/lock.sgml
src/backend/commands/command.c
src/backend/nodes/copyfuncs.c
src/backend/nodes/equalfuncs.c
src/backend/parser/gram.y
src/include/nodes/parsenodes.h
src/interfaces/ecpg/preproc/preproc.y

index d576890..58e5337 100644 (file)
@@ -1,5 +1,5 @@
 <!--
-$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>
   
index 744129f..8276083 100644 (file)
@@ -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);
+       }
 }
 
 
index 2ea063f..65bd5f2 100644 (file)
@@ -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;
index eb194f6..3a9629c 100644 (file)
@@ -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;
index 00c6624..130d259 100644 (file)
@@ -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;
                                }
index 9fa7034..ed379ab 100644 (file)
@@ -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;
 
index 88330ad..09180f8 100644 (file)
@@ -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);
                                }