@@ -13,24 +13,32 @@ mod column;
1313mod de;
1414mod error;
1515mod row;
16+ mod statement;
1617mod value;
1718
1819pub use column:: { Columns , DataType } ;
1920pub use error:: { Error , Result } ;
20- pub use row:: Row ;
21+ pub use params:: { IntoParams , Params , Value as ParamValue } ;
22+ pub use row:: { IntoValueIndex , Row , ValueIndex } ;
23+ pub use statement:: Statement ;
2124pub use value:: Value ;
2225
2326use crossdb_sys:: * ;
24- use params :: { IntoParams , Value as ParamValue } ;
27+ use lru :: LruCache ;
2528use std:: ffi:: { CStr , CString } ;
2629use std:: fmt:: Display ;
30+ use std:: num:: NonZeroUsize ;
2731mod params;
2832
2933#[ derive( Debug ) ]
3034pub struct Connection {
3135 ptr : * mut xdb_conn_t ,
36+ cache : LruCache < CString , Statement > ,
3237}
3338
39+ unsafe impl Send for Connection { }
40+ unsafe impl Sync for Connection { }
41+
3442impl Drop for Connection {
3543 fn drop ( & mut self ) {
3644 unsafe {
@@ -43,30 +51,29 @@ impl Connection {
4351 pub fn open < P : AsRef < str > > ( path : P ) -> Result < Self > {
4452 let path = CString :: new ( path. as_ref ( ) ) ?;
4553 let ptr = unsafe { xdb_open ( path. as_ptr ( ) ) } ;
46- Ok ( Self { ptr } )
54+ let cap = NonZeroUsize :: new ( 256 ) . unwrap ( ) ;
55+ Ok ( Self {
56+ ptr,
57+ cache : LruCache :: new ( cap) ,
58+ } )
4759 }
4860
4961 pub fn open_with_memory ( ) -> Result < Self > {
5062 Self :: open ( ":memory:" )
5163 }
5264
53- pub fn exec < S : AsRef < str > > ( & self , sql : S ) -> Result < ExecResult > {
65+ pub fn query < S : AsRef < str > > ( & self , sql : S ) -> Result < Query > {
5466 let sql = CString :: new ( sql. as_ref ( ) ) ?;
5567 unsafe {
5668 let ptr = xdb_exec ( self . ptr , sql. as_ptr ( ) ) ;
57- let res = * ptr;
58- if res. errcode as u32 != xdb_errno_e_XDB_OK {
59- let msg = CStr :: from_ptr ( xdb_errmsg ( ptr) ) . to_str ( ) ?. to_string ( ) ;
60- return Err ( Error :: Query ( res. errcode , msg) ) ;
61- }
62- Ok ( ExecResult {
63- res,
64- ptr,
65- columns : Columns :: from_res ( ptr) ,
66- } )
69+ Query :: from_res ( ptr)
6770 }
6871 }
6972
73+ pub fn execute < S : AsRef < str > > ( & self , sql : S ) -> Result < u64 > {
74+ self . query ( sql) . map ( |q| q. affected_rows ( ) )
75+ }
76+
7077 pub fn begin ( & self ) -> bool {
7178 unsafe { xdb_begin ( self . ptr ) == 0 }
7279 }
@@ -79,67 +86,53 @@ impl Connection {
7986 unsafe { xdb_rollback ( self . ptr ) == 0 }
8087 }
8188
82- // TODO: LRU cache
83- pub fn prepare < S : AsRef < str > > ( & mut self , sql : S ) -> Result < Stmt > {
84- unsafe {
85- let sql = CString :: new ( sql. as_ref ( ) ) ?;
86- let ptr = xdb_stmt_prepare ( self . ptr , sql. as_ptr ( ) ) ;
87- Ok ( Stmt { ptr } )
88- }
89- }
90- }
91-
92- pub struct Stmt {
93- ptr : * mut xdb_stmt_t ,
94- }
95-
96- impl Drop for Stmt {
97- fn drop ( & mut self ) {
98- unsafe {
99- xdb_stmt_close ( self . ptr ) ;
100- }
89+ pub fn prepare < S : AsRef < str > > ( & mut self , sql : S ) -> Result < & Statement > {
90+ let sql = CString :: new ( sql. as_ref ( ) ) ?;
91+ let sql_ptr = sql. as_ptr ( ) ;
92+ let stmt = self . cache . get_or_insert ( sql, || {
93+ let ptr = unsafe { xdb_stmt_prepare ( self . ptr , sql_ptr) } ;
94+ Statement { ptr }
95+ } ) ;
96+ Ok ( stmt)
10197 }
102- }
10398
104- impl Stmt {
105- pub fn exec ( & self , params : impl IntoParams ) -> Result < ExecResult > {
106- unsafe {
107- let ret = xdb_clear_bindings ( self . ptr ) ;
108- if ret != 0 {
109- return Err ( Error :: ClearBindings ) ;
110- }
111- params. into_params ( ) ?. bind ( self . ptr ) ?;
112- let ptr = xdb_stmt_exec ( self . ptr ) ;
113- let res = * ptr;
114- if res. errcode as u32 != xdb_errno_e_XDB_OK {
115- let msg = CStr :: from_ptr ( xdb_errmsg ( ptr) ) . to_str ( ) ?. to_string ( ) ;
116- return Err ( Error :: Query ( res. errcode , msg) ) ;
117- }
118- Ok ( ExecResult {
119- res,
120- ptr,
121- columns : Columns :: from_res ( ptr) ,
122- } )
123- }
99+ pub fn clear_statement_cache ( & mut self ) {
100+ self . cache . clear ( ) ;
124101 }
125102}
126103
127104#[ derive( Debug ) ]
128- pub struct ExecResult {
105+ pub struct Query {
129106 res : xdb_res_t ,
130107 ptr : * mut xdb_res_t ,
131108 columns : Columns ,
132109}
133110
134- impl Drop for ExecResult {
111+ impl Drop for Query {
135112 fn drop ( & mut self ) {
136113 unsafe {
137114 xdb_free_result ( self . ptr ) ;
138115 }
139116 }
140117}
141118
142- impl ExecResult {
119+ unsafe impl Send for Query { }
120+ unsafe impl Sync for Query { }
121+
122+ impl Query {
123+ pub ( crate ) unsafe fn from_res ( ptr : * mut xdb_res_t ) -> Result < Self > {
124+ let res = * ptr;
125+ if res. errcode as u32 != xdb_errno_e_XDB_OK {
126+ let msg = CStr :: from_ptr ( xdb_errmsg ( ptr) ) . to_str ( ) ?. to_string ( ) ;
127+ return Err ( Error :: Query ( res. errcode , msg) ) ;
128+ }
129+ Ok ( Self {
130+ res,
131+ ptr,
132+ columns : Columns :: from_res ( ptr) ,
133+ } )
134+ }
135+
143136 pub fn column_count ( & self ) -> usize {
144137 self . res . col_count as usize
145138 }
0 commit comments