-
Notifications
You must be signed in to change notification settings - Fork 183
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Make infer role configurable and fix double parse bug #533
Changes from 4 commits
43e2ebb
ecad6e6
82fa4a7
fbc5f87
68be7eb
e01da80
3c578ef
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -372,6 +372,10 @@ impl QueryRouter { | |
|
||
/// 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.infer_role_from_query { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Wouldn't it be better to check for this in the client code than here? I think it's confusing to return nothing from a function based on a setting vs. just not calling the function in the first place. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think there's arguments for both approaches, I kinda like abstracting away things the client has to do so that's why I went this way. Though if you feel we should put that control on the client then happy to change. |
||
return Ok(()); // Nothing to do | ||
} | ||
|
||
debug!("Inferring role"); | ||
|
||
if ast.is_empty() { | ||
|
@@ -433,6 +437,10 @@ impl QueryRouter { | |
/// N.B.: Only supports anonymous prepared statements since we don't | ||
/// keep a cache of them in PgCat. | ||
pub fn infer_shard_from_bind(&mut self, message: &BytesMut) -> bool { | ||
if !self.pool_settings.infer_role_from_query { | ||
return false; // Nothing to do | ||
} | ||
|
||
debug!("Parsing bind message"); | ||
|
||
let mut message_cursor = Cursor::new(message); | ||
|
@@ -910,6 +918,7 @@ mod test { | |
fn test_infer_replica() { | ||
QueryRouter::setup(); | ||
let mut qr = QueryRouter::new(); | ||
qr.pool_settings.infer_role_from_query = true; | ||
assert!(qr.try_execute_command(&simple_query("SET SERVER ROLE TO 'auto'")) != None); | ||
assert!(qr.query_parser_enabled()); | ||
|
||
|
@@ -934,6 +943,7 @@ mod test { | |
fn test_infer_primary() { | ||
QueryRouter::setup(); | ||
let mut qr = QueryRouter::new(); | ||
qr.pool_settings.infer_role_from_query = true; | ||
|
||
let queries = vec![ | ||
simple_query("UPDATE items SET name = 'pumpkin' WHERE id = 5"), | ||
|
@@ -964,6 +974,8 @@ mod test { | |
fn test_infer_parse_prepared() { | ||
QueryRouter::setup(); | ||
let mut qr = QueryRouter::new(); | ||
qr.pool_settings.infer_role_from_query = true; | ||
|
||
qr.try_execute_command(&simple_query("SET SERVER ROLE TO 'auto'")); | ||
assert!(qr.try_execute_command(&simple_query("SET PRIMARY READS TO off")) != None); | ||
|
||
|
@@ -1132,6 +1144,8 @@ mod test { | |
fn test_enable_query_parser() { | ||
QueryRouter::setup(); | ||
let mut qr = QueryRouter::new(); | ||
qr.pool_settings.infer_role_from_query = true; | ||
|
||
let query = simple_query("SET SERVER ROLE TO 'auto'"); | ||
assert!(qr.try_execute_command(&simple_query("SET PRIMARY READS TO off")) != None); | ||
|
||
|
@@ -1164,6 +1178,7 @@ mod test { | |
user: crate::config::User::default(), | ||
default_role: Some(Role::Replica), | ||
query_parser_enabled: true, | ||
infer_role_from_query: true, | ||
primary_reads_enabled: false, | ||
sharding_function: ShardingFunction::PgBigintHash, | ||
automatic_sharding_key: Some(String::from("test.id")), | ||
|
@@ -1239,6 +1254,7 @@ mod test { | |
user: crate::config::User::default(), | ||
default_role: Some(Role::Replica), | ||
query_parser_enabled: true, | ||
infer_role_from_query: true, | ||
primary_reads_enabled: false, | ||
sharding_function: ShardingFunction::PgBigintHash, | ||
automatic_sharding_key: None, | ||
|
@@ -1284,6 +1300,7 @@ mod test { | |
let mut qr = QueryRouter::new(); | ||
qr.pool_settings.automatic_sharding_key = Some("data.id".to_string()); | ||
qr.pool_settings.shards = 3; | ||
qr.pool_settings.infer_role_from_query = true; | ||
|
||
assert!(qr | ||
.infer(&QueryRouter::parse(&simple_query("SELECT * FROM data WHERE id = 5")).unwrap()) | ||
|
@@ -1385,6 +1402,7 @@ mod test { | |
let mut qr = QueryRouter::new(); | ||
qr.pool_settings.automatic_sharding_key = Some("data.id".to_string()); | ||
qr.pool_settings.shards = 3; | ||
qr.pool_settings.infer_role_from_query = true; | ||
|
||
assert!(qr | ||
.infer(&QueryRouter::parse(&simple_query(stmt)).unwrap()) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we call it something better like
query_parser_read_write_splitting
or something less "pgcat"-internals specific and more end-user oriented? I'm open to ideas.