<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>
</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>
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;
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
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
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
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;
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
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