]> granicus.if.org Git - postgresql/commitdiff
Disallow LOCK TABLE outside a transaction block (or function), since this case
authorTom Lane <tgl@sss.pgh.pa.us>
Tue, 4 Nov 2008 00:57:19 +0000 (00:57 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Tue, 4 Nov 2008 00:57:19 +0000 (00:57 +0000)
almost certainly represents user error.  Per a gripe from Sebastian Böhm
and subsequent discussion.

doc/src/sgml/ref/declare.sgml
doc/src/sgml/ref/lock.sgml
src/backend/tcop/utility.c
src/test/regress/expected/privileges.out
src/test/regress/sql/privileges.sql

index 269d2c101c4ce9ca18c50df6be5069d613505f60..744cda77726de5c8a6c011086b77451d6c44a716 100644 (file)
@@ -1,5 +1,5 @@
 <!--
-$PostgreSQL: pgsql/doc/src/sgml/ref/declare.sgml,v 1.42 2007/10/24 23:27:07 tgl Exp $
+$PostgreSQL: pgsql/doc/src/sgml/ref/declare.sgml,v 1.43 2008/11/04 00:57:19 tgl Exp $
 PostgreSQL documentation
 -->
 
@@ -175,10 +175,9 @@ DECLARE <replaceable class="parameter">name</replaceable> [ BINARY ] [ INSENSITI
     <productname>PostgreSQL</productname> reports an error if such a
     command is used outside a transaction block.
     Use
-    <xref linkend="sql-begin" endterm="sql-begin-title">,
+    <xref linkend="sql-begin" endterm="sql-begin-title"> and
     <xref linkend="sql-commit" endterm="sql-commit-title">
-    and
-    <xref linkend="sql-rollback" endterm="sql-rollback-title">
+    (or <xref linkend="sql-rollback" endterm="sql-rollback-title">)
     to define a transaction block.
    </para>
 
index d32e6d364c8a39fa3258251999e5dc0872f0b725..701c2a19a48f85ea8cbb8f7bc2346a76e20e37de 100644 (file)
@@ -1,5 +1,5 @@
 <!--
-$PostgreSQL: pgsql/doc/src/sgml/ref/lock.sgml,v 1.49 2008/09/08 00:47:40 tgl Exp $
+$PostgreSQL: pgsql/doc/src/sgml/ref/lock.sgml,v 1.50 2008/11/04 00:57:19 tgl Exp $
 PostgreSQL documentation
 -->
 
@@ -160,12 +160,15 @@ where <replaceable class="PARAMETER">lockmode</replaceable> is one of:
    </para>
 
    <para>
-    <command>LOCK TABLE</command> is useful only inside a transaction
-    block (<command>BEGIN</>/<command>COMMIT</> pair), since the lock
-    is dropped as soon as the transaction ends.  A <command>LOCK
-    TABLE</> command appearing outside any transaction block forms a
-    self-contained transaction, so the lock will be dropped as soon as
-    it is obtained.
+    <command>LOCK TABLE</> is useless outside a transaction block: the lock
+    would remain held only to the completion of the statement.  Therefore
+    <productname>PostgreSQL</productname> reports an error if <command>LOCK</>
+    is used outside a transaction block.
+    Use
+    <xref linkend="sql-begin" endterm="sql-begin-title"> and
+    <xref linkend="sql-commit" endterm="sql-commit-title">
+    (or <xref linkend="sql-rollback" endterm="sql-rollback-title">)
+    to define a transaction block.
    </para>
 
   <para>
index b1a0fe28ca5512220d3f12a0a1ea2fcf07654cb6..1218e7cb9b86846ccb7911f9f999d77c62c41ff8 100644 (file)
@@ -10,7 +10,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/tcop/utility.c,v 1.299 2008/10/10 13:48:05 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/tcop/utility.c,v 1.300 2008/11/04 00:57:19 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -938,6 +938,11 @@ ProcessUtility(Node *parsetree,
                        break;
 
                case T_LockStmt:
+                       /*
+                        * Since the lock would just get dropped immediately, LOCK TABLE
+                        * outside a transaction block is presumed to be user error.
+                        */
+                       RequireTransactionChain(isTopLevel, "LOCK TABLE");
                        LockTableCommand((LockStmt *) parsetree);
                        break;
 
index 21f9fc26fd9128ab374cd60e6fa77f7d681500e6..d1767e95ad4cdab702466aaf5e18e3d5842246d4 100644 (file)
@@ -45,7 +45,9 @@ INSERT INTO atest1 VALUES (1, 'one');
 DELETE FROM atest1;
 UPDATE atest1 SET a = 1 WHERE b = 'blech';
 TRUNCATE atest1;
+BEGIN;
 LOCK atest1 IN ACCESS EXCLUSIVE MODE;
+COMMIT;
 REVOKE ALL ON atest1 FROM PUBLIC;
 SELECT * FROM atest1;
  a | b 
@@ -102,8 +104,10 @@ DELETE FROM atest2; -- fail
 ERROR:  permission denied for relation atest2
 TRUNCATE atest2; -- fail
 ERROR:  permission denied for relation atest2
+BEGIN;
 LOCK atest2 IN ACCESS EXCLUSIVE MODE; -- fail
 ERROR:  permission denied for relation atest2
+COMMIT;
 COPY atest2 FROM stdin; -- fail
 ERROR:  permission denied for relation atest2
 GRANT ALL ON atest1 TO PUBLIC; -- fail
@@ -155,7 +159,9 @@ DELETE FROM atest2; -- fail
 ERROR:  permission denied for relation atest2
 TRUNCATE atest2; -- fail
 ERROR:  permission denied for relation atest2
+BEGIN;
 LOCK atest2 IN ACCESS EXCLUSIVE MODE; -- ok
+COMMIT;
 COPY atest2 FROM stdin; -- fail
 ERROR:  permission denied for relation atest2
 -- checks in subquery, both fail
index 450d5d9d68da1102b3355c25f78d91129e6794c4..63532f7e095702e7d6df93e0bc962dd53003544d 100644 (file)
@@ -48,7 +48,9 @@ INSERT INTO atest1 VALUES (1, 'one');
 DELETE FROM atest1;
 UPDATE atest1 SET a = 1 WHERE b = 'blech';
 TRUNCATE atest1;
+BEGIN;
 LOCK atest1 IN ACCESS EXCLUSIVE MODE;
+COMMIT;
 
 REVOKE ALL ON atest1 FROM PUBLIC;
 SELECT * FROM atest1;
@@ -80,7 +82,9 @@ SELECT * FROM atest1 FOR UPDATE; -- ok
 SELECT * FROM atest2 FOR UPDATE; -- fail
 DELETE FROM atest2; -- fail
 TRUNCATE atest2; -- fail
+BEGIN;
 LOCK atest2 IN ACCESS EXCLUSIVE MODE; -- fail
+COMMIT;
 COPY atest2 FROM stdin; -- fail
 GRANT ALL ON atest1 TO PUBLIC; -- fail
 
@@ -105,7 +109,9 @@ SELECT * FROM atest1 FOR UPDATE; -- fail
 SELECT * FROM atest2 FOR UPDATE; -- fail
 DELETE FROM atest2; -- fail
 TRUNCATE atest2; -- fail
+BEGIN;
 LOCK atest2 IN ACCESS EXCLUSIVE MODE; -- ok
+COMMIT;
 COPY atest2 FROM stdin; -- fail
 
 -- checks in subquery, both fail