Skip to content

Commit

Permalink
#829: read/write splitting on CTE mutable statements (#835)
Browse files Browse the repository at this point in the history
  • Loading branch information
jgoday authored Oct 23, 2024
1 parent 3935366 commit 186e722
Showing 1 changed file with 34 additions and 1 deletion.
35 changes: 34 additions & 1 deletion src/query_router.rs
Original file line number Diff line number Diff line change
Expand Up @@ -386,6 +386,18 @@ impl QueryRouter {
}
}

/// Determines if a query is mutable or not.
fn query_is_mutable_statement(q: &sqlparser::ast::Query) -> bool {
use sqlparser::ast::*;

match q.body.as_ref() {
SetExpr::Insert(_) => true,
SetExpr::Update(_) => true,
SetExpr::Query(q) => Self::query_is_mutable_statement(q),
_ => false,
}
}

/// Try to infer which server to connect to based on the contents of the query.
pub fn infer(&mut self, ast: &Vec<sqlparser::ast::Statement>) -> Result<(), Error> {
if !self.pool_settings.query_parser_read_write_splitting {
Expand Down Expand Up @@ -428,8 +440,9 @@ impl QueryRouter {
};

let has_locks = !query.locks.is_empty();
let is_mutable_statement = Self::query_is_mutable_statement(query);

if has_locks {
if has_locks || is_mutable_statement {
self.active_role = Some(Role::Primary);
} else if !visited_write_statement {
// If we already visited a write statement, we should be going to the primary.
Expand Down Expand Up @@ -1113,6 +1126,26 @@ mod test {
assert_eq!(qr.role(), None);
}

#[test]
fn test_split_cte_queries() {
QueryRouter::setup();
let mut qr = QueryRouter::new();
qr.pool_settings.query_parser_read_write_splitting = true;
qr.pool_settings.query_parser_enabled = true;

let query = simple_query(
"WITH t AS (
SELECT id FROM users WHERE name ILIKE '%ja%'
)
UPDATE user_languages
SET settings = '{}'
FROM t WHERE t.id = user_id;",
);
let ast = qr.parse(&query).unwrap();
assert!(qr.infer(&ast).is_ok());
assert_eq!(qr.role(), Some(Role::Primary));
}

#[test]
fn test_infer_replica() {
QueryRouter::setup();
Expand Down

0 comments on commit 186e722

Please sign in to comment.