@@ -7,7 +7,7 @@ use lru::LruCache;
7
7
use once_cell:: sync:: Lazy ;
8
8
use parking_lot:: { Mutex , RwLock } ;
9
9
use postgres_protocol:: message;
10
- use std:: collections:: { HashMap , HashSet } ;
10
+ use std:: collections:: { HashMap , HashSet , VecDeque } ;
11
11
use std:: mem;
12
12
use std:: net:: IpAddr ;
13
13
use std:: num:: NonZeroUsize ;
@@ -325,6 +325,9 @@ pub struct Server {
325
325
326
326
/// Prepared statements
327
327
prepared_statement_cache : Option < LruCache < String , ( ) > > ,
328
+
329
+ /// Prepared statement being currently registered on the server.
330
+ registering_prepared_statement : VecDeque < String > ,
328
331
}
329
332
330
333
impl Server {
@@ -827,6 +830,7 @@ impl Server {
827
830
NonZeroUsize :: new ( prepared_statement_cache_size) . unwrap ( ) ,
828
831
) ) ,
829
832
} ,
833
+ registering_prepared_statement : VecDeque :: new ( ) ,
830
834
} ;
831
835
832
836
return Ok ( server) ;
@@ -956,7 +960,6 @@ impl Server {
956
960
957
961
// There is no more data available from the server.
958
962
self . data_available = false ;
959
-
960
963
break ;
961
964
}
962
965
@@ -966,6 +969,23 @@ impl Server {
966
969
self . in_copy_mode = false ;
967
970
}
968
971
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
+
969
989
if self . prepared_statement_cache . is_some ( ) {
970
990
let error_message = PgErrorMsg :: parse ( & message) ?;
971
991
if error_message. message == "cached plan must not change result type" {
@@ -1068,6 +1088,11 @@ impl Server {
1068
1088
// Buffer until ReadyForQuery shows up, so don't exit the loop yet.
1069
1089
'c' => ( ) ,
1070
1090
1091
+ // Parse complete successfully
1092
+ '1' => {
1093
+ self . registering_prepared_statement . pop_front ( ) ;
1094
+ }
1095
+
1071
1096
// Anything else, e.g. errors, notices, etc.
1072
1097
// Keep buffering until ReadyForQuery shows up.
1073
1098
_ => ( ) ,
@@ -1107,7 +1132,7 @@ impl Server {
1107
1132
has_it
1108
1133
}
1109
1134
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 > {
1111
1136
let cache = match & mut self . prepared_statement_cache {
1112
1137
Some ( cache) => cache,
1113
1138
None => return None ,
@@ -1129,7 +1154,7 @@ impl Server {
1129
1154
None
1130
1155
}
1131
1156
1132
- pub fn remove_prepared_statement_from_cache ( & mut self , name : & str ) {
1157
+ fn remove_prepared_statement_from_cache ( & mut self , name : & str ) {
1133
1158
let cache = match & mut self . prepared_statement_cache {
1134
1159
Some ( cache) => cache,
1135
1160
None => return ,
@@ -1145,6 +1170,9 @@ impl Server {
1145
1170
should_send_parse_to_server : bool ,
1146
1171
) -> Result < ( ) , Error > {
1147
1172
if !self . has_prepared_statement ( & parse. name ) {
1173
+ self . registering_prepared_statement
1174
+ . push_back ( parse. name . clone ( ) ) ;
1175
+
1148
1176
let mut bytes = BytesMut :: new ( ) ;
1149
1177
1150
1178
if should_send_parse_to_server {
@@ -1176,7 +1204,13 @@ impl Server {
1176
1204
}
1177
1205
} ;
1178
1206
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
+ }
1180
1214
}
1181
1215
1182
1216
/// If the server is still inside a transaction.
@@ -1186,6 +1220,7 @@ impl Server {
1186
1220
self . in_transaction
1187
1221
}
1188
1222
1223
+ /// Currently copying data from client to server or vice-versa.
1189
1224
pub fn in_copy_mode ( & self ) -> bool {
1190
1225
self . in_copy_mode
1191
1226
}
0 commit comments