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 /01 19:10:27 momjian Exp $
10+ * $PostgreSQL: pgsql/src/backend/rewrite/rewriteHandler.c,v 1.171 2007/03 /01 18: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 ,
5252 List * 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 ,
5656 int 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
11291129 return 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
11571153 if (rte -> rtekind == RTE_RELATION )
11581154 {
@@ -1162,9 +1158,28 @@ markQueryForLocking(Query *qry, bool forUpdate, bool noWait, bool skipOldNew)
11621158 else 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
0 commit comments