77 * Portions Copyright (c) 1994, Regents of the University of California
88 *
99 * IDENTIFICATION
10- * $PostgreSQL: pgsql/src/backend/rewrite/rewriteHandler.c,v 1.170 2007/02 /0119:10:27 momjian Exp $
10+ * $PostgreSQL: pgsql/src/backend/rewrite/rewriteHandler.c,v 1.171 2007/03 /0118:50:28 tgl Exp $
1111 *
1212 *-------------------------------------------------------------------------
1313 */
@@ -50,8 +50,8 @@ static TargetEntry *process_matched_tle(TargetEntry *src_tle,
5050static Node * get_assignment_input (Node * node );
5151static void rewriteValuesRTE (RangeTblEntry * rte ,Relation target_relation ,
5252List * attrnos );
53- static void markQueryForLocking (Query * qry ,bool forUpdate , bool noWait ,
54- bool skipOldNew );
53+ static void markQueryForLocking (Query * qry ,Node * jtnode ,
54+ bool forUpdate , bool noWait );
5555static List * matchLocks (CmdType event ,RuleLock * rulelocks ,
5656int varno ,Query * parsetree );
5757static Query * fireRIRrules (Query * parsetree ,List * activeRIRs );
@@ -1122,8 +1122,8 @@ ApplyRetrieveRule(Query *parsetree,
11221122/*
11231123 * Set up the view's referenced tables as if FOR UPDATE/SHARE.
11241124 */
1125- markQueryForLocking (rule_action ,rc -> forUpdate ,
1126- rc -> noWait , true );
1125+ markQueryForLocking (rule_action ,( Node * ) rule_action -> jointree ,
1126+ rc -> forUpdate , rc -> noWait );
11271127}
11281128
11291129return parsetree ;
@@ -1135,24 +1135,20 @@ ApplyRetrieveRule(Query *parsetree,
11351135 * This may generate an invalid query, eg if some sub-query uses an
11361136 * aggregate. We leave it to the planner to detect that.
11371137 *
1138- * NB: this must agree with the parser's transformLocking() routine.
1138+ * NB: this must agree with the parser's transformLockingClause() routine.
1139+ * However, unlike the parser we have to be careful not to mark a view's
1140+ * OLD and NEW rels for updating. The best way to handle that seems to be
1141+ * to scan the jointree to determine which rels are used.
11391142 */
11401143static void
1141- markQueryForLocking (Query * qry ,bool forUpdate ,bool noWait ,bool skipOldNew )
1144+ markQueryForLocking (Query * qry ,Node * jtnode ,bool forUpdate ,bool noWait )
11421145{
1143- Index rti = 0 ;
1144- ListCell * l ;
1145-
1146- foreach (l ,qry -> rtable )
1146+ if (jtnode == NULL )
1147+ return ;
1148+ if (IsA (jtnode ,RangeTblRef ))
11471149{
1148- RangeTblEntry * rte = (RangeTblEntry * )lfirst (l );
1149-
1150- rti ++ ;
1151-
1152- /* Ignore OLD and NEW entries if we are at top level of view */
1153- if (skipOldNew &&
1154- (rti == PRS2_OLD_VARNO || rti == PRS2_NEW_VARNO ))
1155- continue ;
1150+ int rti = ((RangeTblRef * )jtnode )-> rtindex ;
1151+ RangeTblEntry * rte = rt_fetch (rti ,qry -> rtable );
11561152
11571153if (rte -> rtekind == RTE_RELATION )
11581154{
@@ -1162,9 +1158,28 @@ markQueryForLocking(Query *qry, bool forUpdate, bool noWait, bool skipOldNew)
11621158else if (rte -> rtekind == RTE_SUBQUERY )
11631159{
11641160/* FOR UPDATE/SHARE of subquery is propagated to subquery's rels */
1165- markQueryForLocking (rte -> subquery ,forUpdate ,noWait , false);
1161+ markQueryForLocking (rte -> subquery , (Node * )rte -> subquery -> jointree ,
1162+ forUpdate ,noWait );
11661163}
11671164}
1165+ else if (IsA (jtnode ,FromExpr ))
1166+ {
1167+ FromExpr * f = (FromExpr * )jtnode ;
1168+ ListCell * l ;
1169+
1170+ foreach (l ,f -> fromlist )
1171+ markQueryForLocking (qry ,lfirst (l ),forUpdate ,noWait );
1172+ }
1173+ else if (IsA (jtnode ,JoinExpr ))
1174+ {
1175+ JoinExpr * j = (JoinExpr * )jtnode ;
1176+
1177+ markQueryForLocking (qry ,j -> larg ,forUpdate ,noWait );
1178+ markQueryForLocking (qry ,j -> rarg ,forUpdate ,noWait );
1179+ }
1180+ else
1181+ elog (ERROR ,"unrecognized node type: %d" ,
1182+ (int )nodeTag (jtnode ));
11681183}
11691184
11701185