Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit0303051

Browse files
committed
Add more infinite recursion detection while locking a view.
Also add regression test cases for detecting infinite recursion inlocking view tests. Some document enhancements. Patch by Yugo Nagata.
1 parent47c91b5 commit0303051

File tree

4 files changed

+63
-31
lines changed

4 files changed

+63
-31
lines changed

‎doc/src/sgml/ref/lock.sgml

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,8 @@ LOCK [ TABLE ] [ ONLY ] <replaceable class="parameter">name</replaceable> [ * ]
4646
</para>
4747

4848
<para>
49-
When a view isspecified to belocked, all relations appearing in the view
50-
definitionquery are also locked recursively with the same lock mode.
49+
When a view is locked, all relations appearing in the view definition
50+
query are also locked recursively with the same lock mode.
5151
</para>
5252

5353
<para>
@@ -173,6 +173,13 @@ LOCK [ TABLE ] [ ONLY ] <replaceable class="parameter">name</replaceable> [ * ]
173173
or <literal>TRUNCATE</literal> privileges.
174174
</para>
175175

176+
<para>
177+
The user performing the lock on the view must have the corresponding privilege
178+
on the view. In addition the view's owner must have the relevant privileges on
179+
the underlying base relations, but the user performing the lock does
180+
not need any permissions on the underlying base relations.
181+
</para>
182+
176183
<para>
177184
<command>LOCK TABLE</command> is useless outside a transaction block: the lock
178185
would remain held only to the completion of the statement. Therefore

‎src/backend/commands/lockcmds.c

Lines changed: 29 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ static void LockTableRecurse(Oid reloid, LOCKMODE lockmode, bool nowait, Oid use
3131
staticAclResultLockTableAclCheck(Oidrelid,LOCKMODElockmode,Oiduserid);
3232
staticvoidRangeVarCallbackForLockTable(constRangeVar*rv,Oidrelid,
3333
Oidoldrelid,void*arg);
34-
staticvoidLockViewRecurse(Oidreloid,Oidroot_reloid,LOCKMODElockmode,boolnowait);
34+
staticvoidLockViewRecurse(Oidreloid,LOCKMODElockmode,boolnowait,List*ancestor_views);
3535

3636
/*
3737
* LOCK TABLE
@@ -67,7 +67,7 @@ LockTableCommand(LockStmt *lockstmt)
6767
(void*)&lockstmt->mode);
6868

6969
if (get_rel_relkind(reloid)==RELKIND_VIEW)
70-
LockViewRecurse(reloid,reloid,lockstmt->mode,lockstmt->nowait);
70+
LockViewRecurse(reloid,lockstmt->mode,lockstmt->nowait,NIL);
7171
elseif (recurse)
7272
LockTableRecurse(reloid,lockstmt->mode,lockstmt->nowait,GetUserId());
7373
}
@@ -92,7 +92,6 @@ RangeVarCallbackForLockTable(const RangeVar *rv, Oid relid, Oid oldrelid,
9292
return;/* woops, concurrently dropped; no permissions
9393
* check */
9494

95-
9695
/* Currently, we only allow plain tables or views to be locked */
9796
if (relkind!=RELKIND_RELATION&&relkind!=RELKIND_PARTITIONED_TABLE&&
9897
relkind!=RELKIND_VIEW)
@@ -178,11 +177,11 @@ LockTableRecurse(Oid reloid, LOCKMODE lockmode, bool nowait, Oid userid)
178177

179178
typedefstruct
180179
{
181-
Oidroot_reloid;
182-
LOCKMODElockmode;
183-
boolnowait;
184-
Oidviewowner;
185-
Oidviewoid;
180+
LOCKMODElockmode;/* lock mode to use */
181+
boolnowait;/* no wait mode */
182+
Oidviewowner;/* view owner for checking the privilege */
183+
Oidviewoid;/* OID of the view to be locked */
184+
List*ancestor_views;/* OIDs of ancestor views */
186185
}LockViewRecurse_context;
187186

188187
staticbool
@@ -193,19 +192,22 @@ LockViewRecurse_walker(Node *node, LockViewRecurse_context *context)
193192

194193
if (IsA(node,Query))
195194
{
196-
Query*query= (Query*)node;
197-
ListCell*rtable;
195+
Query*query= (Query*)node;
196+
ListCell*rtable;
198197

199198
foreach(rtable,query->rtable)
200199
{
201-
RangeTblEntry*rte=lfirst(rtable);
202-
AclResultaclresult;
200+
RangeTblEntry*rte=lfirst(rtable);
201+
AclResultaclresult;
203202

204-
Oidrelid=rte->relid;
205-
charrelkind=rte->relkind;
206-
char*relname=get_rel_name(relid);
203+
Oidrelid=rte->relid;
204+
charrelkind=rte->relkind;
205+
char*relname=get_rel_name(relid);
207206

208-
/* The OLD and NEW placeholder entries in the view's rtable are skipped. */
207+
/*
208+
* The OLD and NEW placeholder entries in the view's rtable are
209+
* skipped.
210+
*/
209211
if (relid==context->viewoid&&
210212
(!strcmp(rte->eref->aliasname,"old")|| !strcmp(rte->eref->aliasname,"new")))
211213
continue;
@@ -216,11 +218,11 @@ LockViewRecurse_walker(Node *node, LockViewRecurse_context *context)
216218
continue;
217219

218220
/* Check infinite recursion in the view definition. */
219-
if (relid==context->root_reloid)
221+
if (list_member_oid(context->ancestor_views,relid))
220222
ereport(ERROR,
221223
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
222-
errmsg("infinite recursion detected in rules for relation \"%s\"",
223-
get_rel_name(context->root_reloid))));
224+
errmsg("infinite recursion detected in rules for relation \"%s\"",
225+
get_rel_name(relid))));
224226

225227
/* Check permissions with the view owner's privilege. */
226228
aclresult=LockTableAclCheck(relid,context->lockmode,context->viewowner);
@@ -233,11 +235,11 @@ LockViewRecurse_walker(Node *node, LockViewRecurse_context *context)
233235
elseif (!ConditionalLockRelationOid(relid,context->lockmode))
234236
ereport(ERROR,
235237
(errcode(ERRCODE_LOCK_NOT_AVAILABLE),
236-
errmsg("could not obtain lock on relation \"%s\"",
238+
errmsg("could not obtain lock on relation \"%s\"",
237239
relname)));
238240

239241
if (relkind==RELKIND_VIEW)
240-
LockViewRecurse(relid,context->root_reloid,context->lockmode,context->nowait);
242+
LockViewRecurse(relid,context->lockmode,context->nowait,context->ancestor_views);
241243
elseif (rte->inh)
242244
LockTableRecurse(relid,context->lockmode,context->nowait,context->viewowner);
243245
}
@@ -254,24 +256,26 @@ LockViewRecurse_walker(Node *node, LockViewRecurse_context *context)
254256
}
255257

256258
staticvoid
257-
LockViewRecurse(Oidreloid,Oidroot_reloid,LOCKMODElockmode,boolnowait)
259+
LockViewRecurse(Oidreloid,LOCKMODElockmode,boolnowait,List*ancestor_views)
258260
{
259261
LockViewRecurse_contextcontext;
260262

261-
Relationview;
262-
Query*viewquery;
263+
Relationview;
264+
Query*viewquery;
263265

264266
view=heap_open(reloid,NoLock);
265267
viewquery=get_view_query(view);
266268

267-
context.root_reloid=root_reloid;
268269
context.lockmode=lockmode;
269270
context.nowait=nowait;
270271
context.viewowner=view->rd_rel->relowner;
271272
context.viewoid=reloid;
273+
context.ancestor_views=lcons_oid(reloid,ancestor_views);
272274

273275
LockViewRecurse_walker((Node*)viewquery,&context);
274276

277+
ancestor_views=list_delete_oid(ancestor_views,reloid);
278+
275279
heap_close(view,NoLock);
276280
}
277281

‎src/test/regress/expected/lock.out

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,17 @@ select relname from pg_locks l, pg_class c
120120
lock_view6
121121
(2 rows)
122122

123+
ROLLBACK;
124+
-- detecting infinite recursions in view definitions
125+
CREATE OR REPLACE VIEW lock_view2 AS SELECT * from lock_view3;
126+
BEGIN TRANSACTION;
127+
LOCK TABLE lock_view2 IN EXCLUSIVE MODE;
128+
ERROR: infinite recursion detected in rules for relation "lock_view2"
129+
ROLLBACK;
130+
CREATE VIEW lock_view7 AS SELECT * from lock_view2;
131+
BEGIN TRANSACTION;
132+
LOCK TABLE lock_view7 IN EXCLUSIVE MODE;
133+
ERROR: infinite recursion detected in rules for relation "lock_view2"
123134
ROLLBACK;
124135
-- Verify that we can lock a table with inheritance children.
125136
CREATE TABLE lock_tbl2 (b BIGINT) INHERITS (lock_tbl1);
@@ -142,11 +153,12 @@ RESET ROLE;
142153
--
143154
-- Clean up
144155
--
156+
DROP VIEW lock_view7;
145157
DROP VIEW lock_view6;
146158
DROP VIEW lock_view5;
147159
DROP VIEW lock_view4;
148-
DROP VIEW lock_view3;
149-
DROP VIEWlock_view2;
160+
DROP VIEW lock_view3 CASCADE;
161+
NOTICE: drop cascades to viewlock_view2
150162
DROP VIEW lock_view1;
151163
DROP TABLE lock_tbl3;
152164
DROP TABLE lock_tbl2;

‎src/test/regress/sql/lock.sql

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,15 @@ select relname from pg_locks l, pg_class c
8484
wherel.relation=c.oidand relnamelike'%lock_%'and mode='ExclusiveLock'
8585
order by relname;
8686
ROLLBACK;
87+
-- detecting infinite recursions in view definitions
88+
CREATE OR REPLACEVIEWlock_view2ASSELECT*from lock_view3;
89+
BEGIN TRANSACTION;
90+
LOCK TABLE lock_view2IN EXCLUSIVE MODE;
91+
ROLLBACK;
92+
CREATEVIEWlock_view7ASSELECT*from lock_view2;
93+
BEGIN TRANSACTION;
94+
LOCK TABLE lock_view7IN EXCLUSIVE MODE;
95+
ROLLBACK;
8796

8897
-- Verify that we can lock a table with inheritance children.
8998
CREATETABLElock_tbl2 (bBIGINT) INHERITS (lock_tbl1);
@@ -107,11 +116,11 @@ RESET ROLE;
107116
--
108117
-- Clean up
109118
--
119+
DROPVIEW lock_view7;
110120
DROPVIEW lock_view6;
111121
DROPVIEW lock_view5;
112122
DROPVIEW lock_view4;
113-
DROPVIEW lock_view3;
114-
DROPVIEW lock_view2;
123+
DROPVIEW lock_view3 CASCADE;
115124
DROPVIEW lock_view1;
116125
DROPTABLE lock_tbl3;
117126
DROPTABLE lock_tbl2;

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp