Skip to content

Commit ca8100f

Browse files
committed
Add ONLY support to LOCK and TRUNCATE. By default, these commands are now
recursive. => Note this incompatibility in the release notes.
1 parent b7b8f0b commit ca8100f

File tree

7 files changed

+287
-38
lines changed

7 files changed

+287
-38
lines changed

doc/src/sgml/ref/lock.sgml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<!--
2-
$PostgreSQL: pgsql/doc/src/sgml/ref/lock.sgml,v 1.51 2008/11/14 10:22:47 petere Exp $
2+
$PostgreSQL: pgsql/doc/src/sgml/ref/lock.sgml,v 1.52 2009/01/12 08:54:25 petere Exp $
33
PostgreSQL documentation
44
-->
55

@@ -21,7 +21,7 @@ PostgreSQL documentation
2121

2222
<refsynopsisdiv>
2323
<synopsis>
24-
LOCK [ TABLE ] <replaceable class="PARAMETER">name</replaceable> [, ...] [ IN <replaceable class="PARAMETER">lockmode</replaceable> MODE ] [ NOWAIT ]
24+
LOCK [ TABLE ] [ ONLY ] <replaceable class="PARAMETER">name</replaceable> [, ...] [ IN <replaceable class="PARAMETER">lockmode</replaceable> MODE ] [ NOWAIT ]
2525

2626
where <replaceable class="PARAMETER">lockmode</replaceable> is one of:
2727

@@ -109,7 +109,9 @@ where <replaceable class="PARAMETER">lockmode</replaceable> is one of:
109109
<listitem>
110110
<para>
111111
The name (optionally schema-qualified) of an existing table to
112-
lock.
112+
lock. If <literal>ONLY</> is specified, only that table is
113+
locked. If <literal>ONLY</> is not specified, the table and all
114+
its descendant tables (if any) are locked.
113115
</para>
114116

115117
<para>

doc/src/sgml/ref/truncate.sgml

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<!--
2-
$PostgreSQL: pgsql/doc/src/sgml/ref/truncate.sgml,v 1.31 2008/12/18 10:45:00 petere Exp $
2+
$PostgreSQL: pgsql/doc/src/sgml/ref/truncate.sgml,v 1.32 2009/01/12 08:54:25 petere Exp $
33
PostgreSQL documentation
44
-->
55

@@ -21,7 +21,7 @@ PostgreSQL documentation
2121

2222
<refsynopsisdiv>
2323
<synopsis>
24-
TRUNCATE [ TABLE ] <replaceable class="PARAMETER">name</replaceable> [, ... ]
24+
TRUNCATE [ TABLE ] [ ONLY ] <replaceable class="PARAMETER">name</replaceable> [, ... ]
2525
[ RESTART IDENTITY | CONTINUE IDENTITY ] [ CASCADE | RESTRICT ]
2626
</synopsis>
2727
</refsynopsisdiv>
@@ -47,7 +47,10 @@ TRUNCATE [ TABLE ] <replaceable class="PARAMETER">name</replaceable> [, ... ]
4747
<term><replaceable class="PARAMETER">name</replaceable></term>
4848
<listitem>
4949
<para>
50-
The name (optionally schema-qualified) of a table to be truncated.
50+
The name (optionally schema-qualified) of a table to be
51+
truncated. If <literal>ONLY</> is specified, only that table is
52+
truncated. If <literal>ONLY</> is not specified, the table and
53+
all its descendant tables (if any) are truncated.
5154
</para>
5255
</listitem>
5356
</varlistentry>

src/backend/commands/lockcmds.c

Lines changed: 38 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/commands/lockcmds.c,v 1.20 2009/01/01 17:23:38 momjian Exp $
11+
* $PostgreSQL: pgsql/src/backend/commands/lockcmds.c,v 1.21 2009/01/12 08:54:26 petere Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -18,6 +18,8 @@
1818
#include "catalog/namespace.h"
1919
#include "commands/lockcmds.h"
2020
#include "miscadmin.h"
21+
#include "optimizer/prep.h"
22+
#include "parser/parse_clause.h"
2123
#include "utils/acl.h"
2224
#include "utils/lsyscache.h"
2325
#include "utils/rel.h"
@@ -40,38 +42,48 @@ LockTableCommand(LockStmt *lockstmt)
4042
{
4143
RangeVar *relation = lfirst(p);
4244
Oid reloid;
43-
AclResult aclresult;
44-
Relation rel;
45+
bool recurse = interpretInhOption(relation->inhOpt);
46+
List *children_and_self;
47+
ListCell *child;
4548

46-
/*
47-
* We don't want to open the relation until we've checked privilege.
48-
* So, manually get the relation OID.
49-
*/
5049
reloid = RangeVarGetRelid(relation, false);
5150

52-
if (lockstmt->mode == AccessShareLock)
53-
aclresult = pg_class_aclcheck(reloid, GetUserId(),
54-
ACL_SELECT);
51+
if (recurse)
52+
children_and_self = find_all_inheritors(reloid);
5553
else
56-
aclresult = pg_class_aclcheck(reloid, GetUserId(),
57-
ACL_UPDATE | ACL_DELETE | ACL_TRUNCATE);
54+
children_and_self = list_make1_oid(reloid);
5855

59-
if (aclresult != ACLCHECK_OK)
60-
aclcheck_error(aclresult, ACL_KIND_CLASS,
61-
get_rel_name(reloid));
56+
foreach(child, children_and_self)
57+
{
58+
Oid childreloid = lfirst_oid(child);
59+
Relation rel;
60+
AclResult aclresult;
6261

63-
if (lockstmt->nowait)
64-
rel = relation_open_nowait(reloid, lockstmt->mode);
65-
else
66-
rel = relation_open(reloid, lockstmt->mode);
62+
/* We don't want to open the relation until we've checked privilege. */
63+
if (lockstmt->mode == AccessShareLock)
64+
aclresult = pg_class_aclcheck(childreloid, GetUserId(),
65+
ACL_SELECT);
66+
else
67+
aclresult = pg_class_aclcheck(childreloid, GetUserId(),
68+
ACL_UPDATE | ACL_DELETE | ACL_TRUNCATE);
69+
70+
if (aclresult != ACLCHECK_OK)
71+
aclcheck_error(aclresult, ACL_KIND_CLASS,
72+
get_rel_name(childreloid));
73+
74+
if (lockstmt->nowait)
75+
rel = relation_open_nowait(childreloid, lockstmt->mode);
76+
else
77+
rel = relation_open(childreloid, lockstmt->mode);
6778

68-
/* Currently, we only allow plain tables to be locked */
69-
if (rel->rd_rel->relkind != RELKIND_RELATION)
70-
ereport(ERROR,
71-
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
72-
errmsg("\"%s\" is not a table",
73-
relation->relname)));
79+
/* Currently, we only allow plain tables to be locked */
80+
if (rel->rd_rel->relkind != RELKIND_RELATION)
81+
ereport(ERROR,
82+
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
83+
errmsg("\"%s\" is not a table",
84+
get_rel_name(childreloid))));
7485

75-
relation_close(rel, NoLock); /* close rel, keep lock */
86+
relation_close(rel, NoLock); /* close rel, keep lock */
87+
}
7688
}
7789
}

src/backend/commands/tablecmds.c

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.276 2009/01/01 17:23:39 momjian Exp $
11+
* $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.277 2009/01/12 08:54:26 petere Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -772,17 +772,41 @@ ExecuteTruncate(TruncateStmt *stmt)
772772
{
773773
RangeVar *rv = lfirst(cell);
774774
Relation rel;
775+
bool recurse = interpretInhOption(rv->inhOpt);
776+
Oid myrelid;
775777

776778
rel = heap_openrv(rv, AccessExclusiveLock);
779+
myrelid = RelationGetRelid(rel);
777780
/* don't throw error for "TRUNCATE foo, foo" */
778-
if (list_member_oid(relids, RelationGetRelid(rel)))
781+
if (list_member_oid(relids, myrelid))
779782
{
780783
heap_close(rel, AccessExclusiveLock);
781784
continue;
782785
}
783786
truncate_check_rel(rel);
784787
rels = lappend(rels, rel);
785-
relids = lappend_oid(relids, RelationGetRelid(rel));
788+
relids = lappend_oid(relids, myrelid);
789+
790+
if (recurse)
791+
{
792+
ListCell *child;
793+
List *children;
794+
795+
children = find_all_inheritors(myrelid);
796+
797+
foreach(child, children)
798+
{
799+
Oid childrelid = lfirst_oid(child);
800+
801+
if (list_member_oid(relids, childrelid))
802+
continue;
803+
804+
rel = heap_open(childrelid, AccessExclusiveLock);
805+
truncate_check_rel(rel);
806+
rels = lappend(rels, rel);
807+
relids = lappend_oid(relids, childrelid);
808+
}
809+
}
786810
}
787811

788812
/*

src/backend/parser/gram.y

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
*
1212
*
1313
* IDENTIFICATION
14-
* $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.652 2009/01/07 22:54:45 momjian Exp $
14+
* $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.653 2009/01/12 08:54:26 petere Exp $
1515
*
1616
* HISTORY
1717
* AUTHOR DATE MAJOR EVENT
@@ -284,6 +284,7 @@ static TypeName *TableFuncTypeName(List *columns);
284284
execute_param_clause using_clause returning_clause
285285
enum_val_list table_func_column_list
286286
create_generic_options alter_generic_options
287+
relation_expr_list
287288

288289
%type <range> OptTempTableName
289290
%type <into> into_clause create_as_target
@@ -3794,7 +3795,7 @@ attrs: '.' attr_name
37943795
*****************************************************************************/
37953796

37963797
TruncateStmt:
3797-
TRUNCATE opt_table qualified_name_list opt_restart_seqs opt_drop_behavior
3798+
TRUNCATE opt_table relation_expr_list opt_restart_seqs opt_drop_behavior
37983799
{
37993800
TruncateStmt *n = makeNode(TruncateStmt);
38003801
n->relations = $3;
@@ -6558,7 +6559,15 @@ using_clause:
65586559
| /*EMPTY*/ { $$ = NIL; }
65596560
;
65606561

6561-
LockStmt: LOCK_P opt_table qualified_name_list opt_lock opt_nowait
6562+
6563+
/*****************************************************************************
6564+
*
6565+
* QUERY:
6566+
* LOCK TABLE
6567+
*
6568+
*****************************************************************************/
6569+
6570+
LockStmt: LOCK_P opt_table relation_expr_list opt_lock opt_nowait
65626571
{
65636572
LockStmt *n = makeNode(LockStmt);
65646573

@@ -7487,6 +7496,12 @@ relation_expr:
74877496
;
74887497

74897498

7499+
relation_expr_list:
7500+
relation_expr { $$ = list_make1($1); }
7501+
| relation_expr_list ',' relation_expr { $$ = lappend($1, $3); }
7502+
;
7503+
7504+
74907505
/*
74917506
* Given "UPDATE foo set set ...", we have to decide without looking any
74927507
* further ahead whether the first "set" is an alias or the UPDATE's SET

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy