@@ -427,8 +427,12 @@ impl QueryRouter {
427
427
None => ( ) ,
428
428
} ;
429
429
430
- // If we already visited a write statement, we should be going to the primary.
431
- if !visited_write_statement {
430
+ let has_locks = !query. locks . is_empty ( ) ;
431
+
432
+ if has_locks {
433
+ self . active_role = Some ( Role :: Primary ) ;
434
+ } else if !visited_write_statement {
435
+ // If we already visited a write statement, we should be going to the primary.
432
436
self . active_role = match self . primary_reads_enabled ( ) {
433
437
false => Some ( Role :: Replica ) , // If primary should not be receiving reads, use a replica.
434
438
true => None , // Any server role is fine in this case.
@@ -1158,6 +1162,29 @@ mod test {
1158
1162
}
1159
1163
}
1160
1164
1165
+ #[ test]
1166
+ fn test_select_for_update ( ) {
1167
+ QueryRouter :: setup ( ) ;
1168
+ let mut qr = QueryRouter :: new ( ) ;
1169
+ qr. pool_settings . query_parser_read_write_splitting = true ;
1170
+
1171
+ let queries_in_primary_role = vec ! [
1172
+ simple_query( "BEGIN" ) , // Transaction start
1173
+ simple_query( "SELECT * FROM items WHERE id = 5 FOR UPDATE" ) ,
1174
+ simple_query( "UPDATE items SET name = 'pumpkin' WHERE id = 5" ) ,
1175
+ ] ;
1176
+
1177
+ for query in queries_in_primary_role {
1178
+ assert ! ( qr. infer( & qr. parse( & query) . unwrap( ) ) . is_ok( ) ) ;
1179
+ assert_eq ! ( qr. role( ) , Some ( Role :: Primary ) ) ;
1180
+ }
1181
+
1182
+ // query without lock do not change role
1183
+ let query = simple_query ( "SELECT * FROM items WHERE id = 5" ) ;
1184
+ assert ! ( qr. infer( & qr. parse( & query) . unwrap( ) ) . is_ok( ) ) ;
1185
+ assert_eq ! ( qr. role( ) , None ) ;
1186
+ }
1187
+
1161
1188
#[ test]
1162
1189
fn test_infer_primary_reads_enabled ( ) {
1163
1190
QueryRouter :: setup ( ) ;
0 commit comments