Skip to content

Commit 9514b3b

Browse files
authored
Clean connection state up after protocol named prepared statement (#163)
* Clean connection state up after protocol named prepared statement * Avoid cloning + add test * fmt
1 parent 6d41640 commit 9514b3b

File tree

3 files changed

+29
-0
lines changed

3 files changed

+29
-0
lines changed

src/client.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -879,6 +879,23 @@ where
879879

880880
self.buffer.put(&original[..]);
881881

882+
// Clone after freeze does not allocate
883+
let first_message_code = (*self.buffer.get(0).unwrap_or(&0)) as char;
884+
885+
// Almost certainly true
886+
if first_message_code == 'P' {
887+
// Message layout
888+
// P followed by 32 int followed by null-terminated statement name
889+
// So message code should be in offset 0 of the buffer, first character
890+
// in prepared statement name would be index 5
891+
let first_char_in_name = *self.buffer.get(5).unwrap_or(&0);
892+
if first_char_in_name != 0 {
893+
// This is a named prepared statement
894+
// Server connection state will need to be cleared at checkin
895+
server.mark_dirty();
896+
}
897+
}
898+
882899
self.send_and_receive_loop(
883900
code,
884901
self.buffer.clone(),

src/server.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -638,6 +638,11 @@ impl Server {
638638
pub fn last_activity(&self) -> SystemTime {
639639
self.last_activity
640640
}
641+
642+
// Marks a connection as needing DISCARD ALL at checkin
643+
pub fn mark_dirty(&mut self) {
644+
self.needs_cleanup = true;
645+
}
641646
}
642647

643648
impl Drop for Server {

tests/ruby/misc_spec.rb

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,13 +159,20 @@
159159
conn.async_exec("PREPARE prepared_q (int) AS SELECT $1")
160160
conn.close
161161
end
162+
163+
15.times do
164+
conn = PG::connect(processes.pgcat.connection_string("sharded_db", "sharding_user"))
165+
conn.prepare("prepared_q", "SELECT $1")
166+
conn.close
167+
end
162168
end
163169

164170
it "Does not send DISCARD ALL unless necessary" do
165171
10.times do
166172
conn = PG::connect(processes.pgcat.connection_string("sharded_db", "sharding_user"))
167173
conn.async_exec("SET SERVER ROLE to 'primary'")
168174
conn.async_exec("SELECT 1")
175+
conn.exec_params("SELECT $1", [1])
169176
conn.close
170177
end
171178

0 commit comments

Comments
 (0)