@@ -31,7 +31,7 @@ static void LockTableRecurse(Oid reloid, LOCKMODE lockmode, bool nowait, Oid use
3131static AclResult LockTableAclCheck (Oid relid , LOCKMODE lockmode , Oid userid );
3232static void RangeVarCallbackForLockTable (const RangeVar * rv , Oid relid ,
3333 Oid oldrelid , void * arg );
34- static void LockViewRecurse (Oid reloid , Oid root_reloid , LOCKMODE lockmode , bool nowait );
34+ static void LockViewRecurse (Oid reloid , LOCKMODE lockmode , bool nowait , 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 else if (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
179178typedef struct
180179{
181- Oid root_reloid ;
182- LOCKMODE lockmode ;
183- bool nowait ;
184- Oid viewowner ;
185- Oid viewoid ;
180+ LOCKMODE lockmode ; /* lock mode to use */
181+ bool nowait ; /* no wait mode */
182+ Oid viewowner ; /* view owner for checking the privilege */
183+ Oid viewoid ; /* OID of the view to be locked */
184+ List * ancestor_views ; /* OIDs of ancestor views */
186185} LockViewRecurse_context ;
187186
188187static bool
@@ -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- AclResult aclresult ;
200+ RangeTblEntry * rte = lfirst (rtable );
201+ AclResult aclresult ;
203202
204- Oid relid = rte -> relid ;
205- char relkind = rte -> relkind ;
206- char * relname = get_rel_name (relid );
203+ Oid relid = rte -> relid ;
204+ char relkind = 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 else if (!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 else if (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
256258static void
257- LockViewRecurse (Oid reloid , Oid root_reloid , LOCKMODE lockmode , bool nowait )
259+ LockViewRecurse (Oid reloid , LOCKMODE lockmode , bool nowait , List * ancestor_views )
258260{
259261 LockViewRecurse_context context ;
260262
261- Relation view ;
262- Query * viewquery ;
263+ Relation view ;
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
0 commit comments