-
Notifications
You must be signed in to change notification settings - Fork 227
Don't send discard all when state is changed in transaction #186
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
Changes from all commits
2a23869
558da53
e9f8ba7
881d812
8219618
2a6a089
4a19246
6964597
23191d2
c358c42
5126a45
061ee13
87ff7cb
45a580b
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 |
---|---|---|
|
@@ -601,7 +601,7 @@ where | |
// in case the client is sending some custom protocol messages, e.g. | ||
// SET SHARDING KEY TO 'bigint'; | ||
|
||
let mut message = tokio::select! { | ||
let message = tokio::select! { | ||
_ = self.shutdown.recv() => { | ||
if !self.admin { | ||
error_response_terminal( | ||
|
@@ -792,47 +792,51 @@ where | |
// Set application_name. | ||
server.set_name(&self.application_name).await?; | ||
|
||
let mut initial_message = Some(message); | ||
|
||
// Transaction loop. Multiple queries can be issued by the client here. | ||
// The connection belongs to the client until the transaction is over, | ||
// or until the client disconnects if we are in session mode. | ||
// | ||
// If the client is in session mode, no more custom protocol | ||
// commands will be accepted. | ||
loop { | ||
let mut message = if message.len() == 0 { | ||
trace!("Waiting for message inside transaction or in session mode"); | ||
let message = match initial_message { | ||
None => { | ||
trace!("Waiting for message inside transaction or in session mode"); | ||
|
||
match read_message(&mut self.read).await { | ||
Ok(message) => message, | ||
Err(err) => { | ||
// Client disconnected inside a transaction. | ||
// Clean up the server and re-use it. | ||
server.checkin_cleanup().await?; | ||
match read_message(&mut self.read).await { | ||
Ok(message) => message, | ||
Err(err) => { | ||
// Client disconnected inside a transaction. | ||
// Clean up the server and re-use it. | ||
server.checkin_cleanup().await?; | ||
|
||
return Err(err); | ||
return Err(err); | ||
} | ||
} | ||
} | ||
} else { | ||
let msg = message.clone(); | ||
message.clear(); | ||
msg | ||
Some(message) => { | ||
initial_message = None; | ||
message | ||
} | ||
}; | ||
|
||
// The message will be forwarded to the server intact. We still would like to | ||
// parse it below to figure out what to do with it. | ||
let original = message.clone(); | ||
|
||
let code = message.get_u8() as char; | ||
let _len = message.get_i32() as usize; | ||
// Safe to unwrap because we know this message has a certain length and has the code | ||
// This reads the first byte without advancing the internal pointer and mutating the bytes | ||
let code = *message.get(0).unwrap() as char; | ||
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. Maybe add a comment here 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. Maybe change this to |
||
|
||
trace!("Message: {}", code); | ||
|
||
match code { | ||
// ReadyForQuery | ||
// Query | ||
'Q' => { | ||
debug!("Sending query to server"); | ||
|
||
self.send_and_receive_loop(code, original, server, &address, &pool) | ||
self.send_and_receive_loop(code, message, server, &address, &pool) | ||
.await?; | ||
|
||
if !server.in_transaction() { | ||
|
@@ -858,35 +862,34 @@ where | |
// Parse | ||
// The query with placeholders is here, e.g. `SELECT * FROM users WHERE email = $1 AND active = $2`. | ||
'P' => { | ||
self.buffer.put(&original[..]); | ||
self.buffer.put(&message[..]); | ||
} | ||
|
||
// Bind | ||
// The placeholder's replacements are here, e.g. '[email protected]' and 'true' | ||
'B' => { | ||
self.buffer.put(&original[..]); | ||
self.buffer.put(&message[..]); | ||
} | ||
|
||
// Describe | ||
// Command a client can issue to describe a previously prepared named statement. | ||
'D' => { | ||
self.buffer.put(&original[..]); | ||
self.buffer.put(&message[..]); | ||
} | ||
|
||
// Execute | ||
// Execute a prepared statement prepared in `P` and bound in `B`. | ||
'E' => { | ||
self.buffer.put(&original[..]); | ||
self.buffer.put(&message[..]); | ||
} | ||
|
||
// Sync | ||
// Frontend (client) is asking for the query result now. | ||
'S' => { | ||
debug!("Sending query to server"); | ||
|
||
self.buffer.put(&original[..]); | ||
self.buffer.put(&message[..]); | ||
|
||
// Clone after freeze does not allocate | ||
let first_message_code = (*self.buffer.get(0).unwrap_or(&0)) as char; | ||
|
||
// Almost certainly true | ||
|
@@ -929,14 +932,14 @@ where | |
'd' => { | ||
// Forward the data to the server, | ||
// don't buffer it since it can be rather large. | ||
self.send_server_message(server, original, &address, &pool) | ||
self.send_server_message(server, message, &address, &pool) | ||
.await?; | ||
} | ||
|
||
// CopyDone or CopyFail | ||
// Copy is done, successfully or not. | ||
'c' | 'f' => { | ||
self.send_server_message(server, original, &address, &pool) | ||
self.send_server_message(server, message, &address, &pool) | ||
.await?; | ||
|
||
let response = self.receive_server_message(server, &address, &pool).await?; | ||
|
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.
One less clone to worry about!