7
7
* Portions Copyright (c) 1994, Regents of the University of California
8
8
*
9
9
* 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 $
11
11
*
12
12
*-------------------------------------------------------------------------
13
13
*/
@@ -50,8 +50,8 @@ static TargetEntry *process_matched_tle(TargetEntry *src_tle,
50
50
static Node * get_assignment_input (Node * node );
51
51
static void rewriteValuesRTE (RangeTblEntry * rte ,Relation target_relation ,
52
52
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 );
55
55
static List * matchLocks (CmdType event ,RuleLock * rulelocks ,
56
56
int varno ,Query * parsetree );
57
57
static Query * fireRIRrules (Query * parsetree ,List * activeRIRs );
@@ -1122,8 +1122,8 @@ ApplyRetrieveRule(Query *parsetree,
1122
1122
/*
1123
1123
* Set up the view's referenced tables as if FOR UPDATE/SHARE.
1124
1124
*/
1125
- markQueryForLocking (rule_action ,rc -> forUpdate ,
1126
- rc -> noWait , true );
1125
+ markQueryForLocking (rule_action ,( Node * ) rule_action -> jointree ,
1126
+ rc -> forUpdate , rc -> noWait );
1127
1127
}
1128
1128
1129
1129
return parsetree ;
@@ -1135,24 +1135,20 @@ ApplyRetrieveRule(Query *parsetree,
1135
1135
* This may generate an invalid query, eg if some sub-query uses an
1136
1136
* aggregate. We leave it to the planner to detect that.
1137
1137
*
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.
1139
1142
*/
1140
1143
static void
1141
- markQueryForLocking (Query * qry ,bool forUpdate ,bool noWait ,bool skipOldNew )
1144
+ markQueryForLocking (Query * qry ,Node * jtnode ,bool forUpdate ,bool noWait )
1142
1145
{
1143
- Index rti = 0 ;
1144
- ListCell * l ;
1145
-
1146
- foreach (l ,qry -> rtable )
1146
+ if (jtnode == NULL )
1147
+ return ;
1148
+ if (IsA (jtnode ,RangeTblRef ))
1147
1149
{
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 );
1156
1152
1157
1153
if (rte -> rtekind == RTE_RELATION )
1158
1154
{
@@ -1162,9 +1158,28 @@ markQueryForLocking(Query *qry, bool forUpdate, bool noWait, bool skipOldNew)
1162
1158
else if (rte -> rtekind == RTE_SUBQUERY )
1163
1159
{
1164
1160
/* 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 );
1166
1163
}
1167
1164
}
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 ));
1168
1183
}
1169
1184
1170
1185