Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
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)