@@ -6,8 +6,13 @@ use either::Either;
66use flume:: { SendError , Sender } ;
77use odbc_api:: handles:: StatementImpl ;
88use odbc_api:: { Cursor , CursorRow , IntoParameter , Nullable , Preallocated , ResultSetMetadata } ;
9+ use std:: collections:: HashMap ;
910
10- pub type OdbcConn = odbc_api:: Connection < ' static > ;
11+ #[ derive( Debug ) ]
12+ pub struct OdbcConn {
13+ pub conn : odbc_api:: Connection < ' static > ,
14+ pub prepared_meta_cache : HashMap < u64 , ( Vec < OdbcColumn > , usize ) > ,
15+ }
1116pub type ExecuteResult = Result < Either < OdbcQueryResult , OdbcRow > , Error > ;
1217pub type ExecuteSender = Sender < ExecuteResult > ;
1318
@@ -16,17 +21,20 @@ pub fn establish_connection(options: &crate::odbc::OdbcConnectOptions) -> Result
1621 let conn = env
1722 . connect_with_connection_string ( options. connection_string ( ) , Default :: default ( ) )
1823 . map_err ( |e| Error :: Configuration ( e. to_string ( ) . into ( ) ) ) ?;
19- Ok ( conn)
24+ Ok ( OdbcConn {
25+ conn,
26+ prepared_meta_cache : HashMap :: new ( ) ,
27+ } )
2028}
2129
2230pub fn execute_sql (
23- conn : & mut OdbcConn ,
31+ inner : & mut OdbcConn ,
2432 sql : & str ,
2533 args : Option < OdbcArguments > ,
2634 tx : & ExecuteSender ,
2735) -> Result < ( ) , Error > {
2836 let params = prepare_parameters ( args) ;
29- let stmt = & mut conn. preallocate ( ) . map_err ( Error :: from) ?;
37+ let stmt = & mut inner . conn . preallocate ( ) . map_err ( Error :: from) ?;
3038
3139 if let Some ( mut cursor) = stmt. execute ( sql, & params[ ..] ) ? {
3240 handle_cursor ( & mut cursor, tx) ;
@@ -314,11 +322,25 @@ fn extract_binary(
314322}
315323
316324pub fn do_prepare (
317- conn : & mut OdbcConn ,
325+ inner : & mut OdbcConn ,
318326 sql : Box < str > ,
319327) -> Result < ( u64 , Vec < OdbcColumn > , usize ) , Error > {
320- let mut prepared = conn. prepare ( & sql) ?;
328+ use std:: collections:: hash_map:: DefaultHasher ;
329+ use std:: hash:: { Hash , Hasher } ;
330+
331+ let mut hasher = DefaultHasher :: new ( ) ;
332+ sql. hash ( & mut hasher) ;
333+ let key = hasher. finish ( ) ;
334+
335+ if let Some ( ( cols, params) ) = inner. prepared_meta_cache . get ( & key) {
336+ return Ok ( ( key, cols. clone ( ) , * params) ) ;
337+ }
338+
339+ let mut prepared = inner. conn . prepare ( & sql) ?;
321340 let columns = collect_columns ( & mut prepared) ;
322341 let params = usize:: from ( prepared. num_params ( ) . unwrap_or ( 0 ) ) ;
323- Ok ( ( 0 , columns, params) )
342+ inner
343+ . prepared_meta_cache
344+ . insert ( key, ( columns. clone ( ) , params) ) ;
345+ Ok ( ( key, columns, params) )
324346}
0 commit comments