11use std:: libc:: c_int;
22use std:: ptr;
33use std:: str;
4+ use std:: vec;
5+ use std:: uint;
46
57mod ffi {
68 use std:: libc:: { c_char, c_int, c_void} ;
@@ -13,6 +15,8 @@ mod ffi {
1315 pub static SQLITE_ROW : c_int = 100 ;
1416 pub static SQLITE_DONE : c_int = 101 ;
1517
18+ pub static SQLITE_NULL : c_int = 5 ;
19+
1620 // A function because Rust doesn't like casting from an int to a function
1721 // pointer in a static declaration
1822 pub fn SQLITE_TRANSIENT ( ) -> extern "C" fn ( * c_void ) {
@@ -31,8 +35,10 @@ mod ffi {
3135 fn sqlite3_reset ( pStmt : * sqlite3_stmt ) -> c_int ;
3236 fn sqlite3_bind_text ( pStmt : * sqlite3_stmt , idx : c_int , text : * c_char ,
3337 n : c_int , free : extern "C" fn ( * c_void ) ) -> c_int ;
38+ fn sqlite3_bind_null ( pStmt : * sqlite3_stmt , idx : c_int ) -> c_int ;
3439 fn sqlite3_step ( pStmt : * sqlite3_stmt ) -> c_int ;
3540 fn sqlite3_column_count ( pStmt : * sqlite3_stmt ) -> c_int ;
41+ fn sqlite3_column_type ( pStmt : * sqlite3_stmt , iCol : c_int ) -> c_int ;
3642 fn sqlite3_column_text ( pStmt : * sqlite3_stmt , iCol : c_int ) -> * c_char ;
3743 fn sqlite3_finalize ( pStmt : * sqlite3_stmt ) -> c_int ;
3844 }
@@ -161,11 +167,16 @@ impl<'self> PreparedStatement<'self> {
161167
162168 fn bind_params ( & self , params : & [ @SqlType ] ) -> Result < ( ) , ~str > {
163169 for params. iter( ) . enumerate( ) . advance |( idx, param) | {
164- let ret = do param. to_sql_str( ) . as_c_str |c_param| {
165- unsafe {
166- ffi : : sqlite3_bind_text( self . stmt, ( idx+1 ) as c_int,
167- c_param, -1 ,
168- ffi:: SQLITE_TRANSIENT ( ) )
170+ let ret = match param. to_sql_str ( ) {
171+ Some ( val) => do val. as_c_str |c_param| {
172+ unsafe {
173+ ffi:: sqlite3_bind_text ( self . stmt , ( idx+1 ) as c_int ,
174+ c_param, -1 ,
175+ ffi:: SQLITE_TRANSIENT ( ) )
176+ }
177+ } ,
178+ None => unsafe {
179+ ffi:: sqlite3_bind_null ( self . stmt , ( idx+1 ) as c_int )
169180 }
170181 } ;
171182
@@ -218,15 +229,16 @@ impl<'self> Iterator<Row<'self>> for ResultIterator<'self> {
218229 fn next ( & mut self ) -> Option < Row < ' self > > {
219230 let ret = unsafe { ffi:: sqlite3_step ( self . stmt . stmt ) } ;
220231 match ret {
221- ffi:: SQLITE_ROW => Some ( Row { stmt : self . stmt } ) ,
232+ ffi:: SQLITE_ROW => Some ( Row :: new ( self . stmt ) ) ,
222233 // TODO: Ignoring errors for now
223234 _ => None
224235 }
225236 }
226237}
227238
228239pub struct Row < ' self > {
229- priv stmt : & ' self PreparedStatement < ' self >
240+ priv stmt : & ' self PreparedStatement < ' self > ,
241+ priv cols : ~[ Option < ~str > ]
230242}
231243
232244impl < ' self > Container for Row < ' self > {
@@ -240,30 +252,61 @@ impl<'self> Container for Row<'self> {
240252}
241253
242254impl < ' self > Row < ' self > {
243- pub fn get < T : SqlType > ( & self , idx : uint ) -> Option < T > {
244- let raw = unsafe {
245- ffi:: sqlite3_column_text ( self . stmt . stmt , idx as c_int )
246- } ;
255+ fn new ( stmt : & ' self PreparedStatement < ' self > ) -> Row < ' self > {
256+ let count = unsafe { ffi:: sqlite3_column_count ( stmt. stmt ) as uint } ;
257+ let mut row = Row { stmt : stmt, cols : vec:: with_capacity ( count) } ;
247258
248- if ptr:: is_null ( raw) {
249- return None ;
259+ for uint:: range( 0 , count) |i| {
260+ let typ = unsafe {
261+ ffi:: sqlite3_column_type ( stmt. stmt , i as c_int )
262+ } ;
263+ let val = match typ {
264+ ffi:: SQLITE_NULL => None ,
265+ _ => Some ( unsafe {
266+ str:: raw:: from_c_str ( ffi:: sqlite3_column_text ( stmt. stmt ,
267+ i as c_int ) )
268+ } )
269+ } ;
270+ row. cols . push ( val) ;
250271 }
251272
252- SqlType :: from_sql_str ( unsafe { str:: raw:: from_c_str ( raw) } )
273+ return row
274+ }
275+ }
276+
277+ impl < ' self > Row < ' self > {
278+ pub fn get < T : SqlType > ( & self , idx : uint ) -> T {
279+ SqlType :: from_sql_str ( & self . cols [ idx] )
253280 }
254281}
255282
256283pub trait SqlType {
257- fn to_sql_str ( & self ) -> ~str ;
258- fn from_sql_str ( sql_str : & str ) -> Option < Self > ;
284+ fn to_sql_str ( & self ) -> Option < ~str > ;
285+ fn from_sql_str ( sql_str : & Option < ~ str > ) -> Self ;
259286}
260287
261288impl SqlType for int {
262- fn to_sql_str ( & self ) -> ~str {
263- self . to_str ( )
289+ fn to_sql_str ( & self ) -> Option < ~str > {
290+ Some ( self . to_str ( ) )
291+ }
292+
293+ fn from_sql_str ( sql_str : & Option < ~str > ) -> int {
294+ FromStr :: from_str ( * sql_str. get_ref ( ) ) . get ( )
295+ }
296+ }
297+
298+ impl SqlType for Option < int > {
299+ fn to_sql_str ( & self ) -> Option < ~str > {
300+ match * self {
301+ None => None ,
302+ Some ( v) => Some ( v. to_str ( ) )
303+ }
264304 }
265305
266- fn from_sql_str ( sql_str : & str ) -> Option < int > {
267- FromStr :: from_str ( sql_str)
306+ fn from_sql_str ( sql_str : & Option < ~str > ) -> Option < int > {
307+ match * sql_str {
308+ None => None ,
309+ Some ( ref s) => Some ( FromStr :: from_str ( * s) . get ( ) )
310+ }
268311 }
269312}
0 commit comments