@@ -7,7 +7,7 @@ use lru::LruCache;
77use once_cell:: sync:: Lazy ;
88use parking_lot:: { Mutex , RwLock } ;
99use postgres_protocol:: message;
10- use std:: collections:: { HashMap , HashSet } ;
10+ use std:: collections:: { HashMap , HashSet , VecDeque } ;
1111use std:: mem;
1212use std:: net:: IpAddr ;
1313use std:: num:: NonZeroUsize ;
@@ -325,6 +325,9 @@ pub struct Server {
325325
326326 /// Prepared statements
327327 prepared_statement_cache : Option < LruCache < String , ( ) > > ,
328+
329+ /// Prepared statement being currently registered on the server.
330+ registering_prepared_statement : VecDeque < String > ,
328331}
329332
330333impl Server {
@@ -827,6 +830,7 @@ impl Server {
827830 NonZeroUsize :: new ( prepared_statement_cache_size) . unwrap ( ) ,
828831 ) ) ,
829832 } ,
833+ registering_prepared_statement : VecDeque :: new ( ) ,
830834 } ;
831835
832836 return Ok ( server) ;
@@ -956,7 +960,6 @@ impl Server {
956960
957961 // There is no more data available from the server.
958962 self . data_available = false ;
959-
960963 break ;
961964 }
962965
@@ -966,6 +969,23 @@ impl Server {
966969 self . in_copy_mode = false ;
967970 }
968971
972+ // Remove the prepared statement from the cache, it has a syntax error or something else bad happened.
973+ if let Some ( prepared_stmt_name) =
974+ self . registering_prepared_statement . pop_front ( )
975+ {
976+ if let Some ( ref mut cache) = self . prepared_statement_cache {
977+ if let Some ( _removed) = cache. pop ( & prepared_stmt_name) {
978+ debug ! (
979+ "Removed {} from prepared statement cache" ,
980+ prepared_stmt_name
981+ ) ;
982+ } else {
983+ // Shouldn't happen.
984+ debug ! ( "Prepared statement {} was not cached" , prepared_stmt_name) ;
985+ }
986+ }
987+ }
988+
969989 if self . prepared_statement_cache . is_some ( ) {
970990 let error_message = PgErrorMsg :: parse ( & message) ?;
971991 if error_message. message == "cached plan must not change result type" {
@@ -1068,6 +1088,11 @@ impl Server {
10681088 // Buffer until ReadyForQuery shows up, so don't exit the loop yet.
10691089 'c' => ( ) ,
10701090
1091+ // Parse complete successfully
1092+ '1' => {
1093+ self . registering_prepared_statement . pop_front ( ) ;
1094+ }
1095+
10711096 // Anything else, e.g. errors, notices, etc.
10721097 // Keep buffering until ReadyForQuery shows up.
10731098 _ => ( ) ,
@@ -1107,7 +1132,7 @@ impl Server {
11071132 has_it
11081133 }
11091134
1110- pub fn add_prepared_statement_to_cache ( & mut self , name : & str ) -> Option < String > {
1135+ fn add_prepared_statement_to_cache ( & mut self , name : & str ) -> Option < String > {
11111136 let cache = match & mut self . prepared_statement_cache {
11121137 Some ( cache) => cache,
11131138 None => return None ,
@@ -1129,7 +1154,7 @@ impl Server {
11291154 None
11301155 }
11311156
1132- pub fn remove_prepared_statement_from_cache ( & mut self , name : & str ) {
1157+ fn remove_prepared_statement_from_cache ( & mut self , name : & str ) {
11331158 let cache = match & mut self . prepared_statement_cache {
11341159 Some ( cache) => cache,
11351160 None => return ,
@@ -1145,6 +1170,9 @@ impl Server {
11451170 should_send_parse_to_server : bool ,
11461171 ) -> Result < ( ) , Error > {
11471172 if !self . has_prepared_statement ( & parse. name ) {
1173+ self . registering_prepared_statement
1174+ . push_back ( parse. name . clone ( ) ) ;
1175+
11481176 let mut bytes = BytesMut :: new ( ) ;
11491177
11501178 if should_send_parse_to_server {
@@ -1176,7 +1204,13 @@ impl Server {
11761204 }
11771205 } ;
11781206
1179- Ok ( ( ) )
1207+ // If it's not there, something went bad, I'm guessing bad syntax or permissions error
1208+ // on the server.
1209+ if !self . has_prepared_statement ( & parse. name ) {
1210+ Err ( Error :: PreparedStatementError )
1211+ } else {
1212+ Ok ( ( ) )
1213+ }
11801214 }
11811215
11821216 /// If the server is still inside a transaction.
@@ -1186,6 +1220,7 @@ impl Server {
11861220 self . in_transaction
11871221 }
11881222
1223+ /// Currently copying data from client to server or vice-versa.
11891224 pub fn in_copy_mode ( & self ) -> bool {
11901225 self . in_copy_mode
11911226 }
0 commit comments