Skip to content

Commit 29a476e

Browse files
authored
QueryRouter: route to primary when locks exists (select for update) (#782)
Authored-by: Javier Goday <[email protected]>
1 parent 81933b9 commit 29a476e

File tree

1 file changed

+29
-2
lines changed

1 file changed

+29
-2
lines changed

src/query_router.rs

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -427,8 +427,12 @@ impl QueryRouter {
427427
None => (),
428428
};
429429

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.
432436
self.active_role = match self.primary_reads_enabled() {
433437
false => Some(Role::Replica), // If primary should not be receiving reads, use a replica.
434438
true => None, // Any server role is fine in this case.
@@ -1158,6 +1162,29 @@ mod test {
11581162
}
11591163
}
11601164

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+
11611188
#[test]
11621189
fn test_infer_primary_reads_enabled() {
11631190
QueryRouter::setup();

0 commit comments

Comments
 (0)