@@ -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 ,
3333Oid 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
6969if (get_rel_relkind (reloid )== RELKIND_VIEW )
70- LockViewRecurse (reloid ,reloid , lockstmt -> mode ,lockstmt -> nowait );
70+ LockViewRecurse (reloid ,lockstmt -> mode ,lockstmt -> nowait , NIL );
7171else if (recurse )
7272LockTableRecurse (reloid ,lockstmt -> mode ,lockstmt -> nowait ,GetUserId ());
7373}
@@ -92,7 +92,6 @@ RangeVarCallbackForLockTable(const RangeVar *rv, Oid relid, Oid oldrelid,
9292return ;/* woops, concurrently dropped; no permissions
9393 * check */
9494
95-
9695/* Currently, we only allow plain tables or views to be locked */
9796if (relkind != RELKIND_RELATION && relkind != RELKIND_PARTITIONED_TABLE &&
9897relkind != 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
194193if (IsA (node ,Query ))
195194{
196- Query * query = (Query * )node ;
197- ListCell * rtable ;
195+ Query * query = (Query * )node ;
196+ ListCell * rtable ;
198197
199198foreach (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+ */
209211if (relid == context -> viewoid &&
210212(!strcmp (rte -> eref -> aliasname ,"old" )|| !strcmp (rte -> eref -> aliasname ,"new" )))
211213continue ;
@@ -216,11 +218,11 @@ LockViewRecurse_walker(Node *node, LockViewRecurse_context *context)
216218continue ;
217219
218220/* Check infinite recursion in the view definition. */
219- if (relid == context -> root_reloid )
221+ if (list_member_oid ( context -> ancestor_views , relid ) )
220222ereport (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. */
226228aclresult = LockTableAclCheck (relid ,context -> lockmode ,context -> viewowner );
@@ -233,11 +235,11 @@ LockViewRecurse_walker(Node *node, LockViewRecurse_context *context)
233235else if (!ConditionalLockRelationOid (relid ,context -> lockmode ))
234236ereport (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\"" ,
237239relname )));
238240
239241if (relkind == RELKIND_VIEW )
240- LockViewRecurse (relid ,context -> root_reloid ,context -> lockmode ,context -> nowait );
242+ LockViewRecurse (relid ,context -> lockmode ,context -> nowait ,context -> ancestor_views );
241243else if (rte -> inh )
242244LockTableRecurse (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{
259261LockViewRecurse_context context ;
260262
261- Relation view ;
262- Query * viewquery ;
263+ Relation view ;
264+ Query * viewquery ;
263265
264266view = heap_open (reloid ,NoLock );
265267viewquery = get_view_query (view );
266268
267- context .root_reloid = root_reloid ;
268269context .lockmode = lockmode ;
269270context .nowait = nowait ;
270271context .viewowner = view -> rd_rel -> relowner ;
271272context .viewoid = reloid ;
273+ context .ancestor_views = lcons_oid (reloid ,ancestor_views );
272274
273275LockViewRecurse_walker ((Node * )viewquery ,& context );
274276
277+ ancestor_views = list_delete_oid (ancestor_views ,reloid );
278+
275279heap_close (view ,NoLock );
276280}
277281