@@ -14,19 +14,42 @@ macro_rules! stub {
1414 } ;
1515}
1616
17- pub const SQLITE_OK : ffi:: c_int = 0 ;
18- pub const SQLITE_ERROR : ffi:: c_int = 1 ;
19- pub const SQLITE_ABORT : ffi:: c_int = 4 ;
20- pub const SQLITE_BUSY : ffi:: c_int = 5 ;
21- pub const SQLITE_NOMEM : ffi:: c_int = 7 ;
22- pub const SQLITE_INTERRUPT : ffi:: c_int = 9 ;
23- pub const SQLITE_NOTFOUND : ffi:: c_int = 12 ;
24- pub const SQLITE_CANTOPEN : ffi:: c_int = 14 ;
25- pub const SQLITE_MISUSE : ffi:: c_int = 21 ;
26- pub const SQLITE_RANGE : ffi:: c_int = 25 ;
27- pub const SQLITE_ROW : ffi:: c_int = 100 ;
28- pub const SQLITE_DONE : ffi:: c_int = 101 ;
17+ /* generic error-codes */
18+ pub const SQLITE_OK : ffi:: c_int = 0 ; /* Successful result */
19+ pub const SQLITE_ERROR : ffi:: c_int = 1 ; /* Generic error */
20+ pub const SQLITE_INTERNAL : ffi:: c_int = 2 ; /* Internal logic error in SQLite */
21+ pub const SQLITE_PERM : ffi:: c_int = 3 ; /* Access permission denied */
22+ pub const SQLITE_ABORT : ffi:: c_int = 4 ; /* Callback routine requested an abort */
23+ pub const SQLITE_BUSY : ffi:: c_int = 5 ; /* The database file is locked */
24+ pub const SQLITE_LOCKED : ffi:: c_int = 6 ; /* A table in the database is locked */
25+ pub const SQLITE_NOMEM : ffi:: c_int = 7 ; /* A malloc() failed */
26+ pub const SQLITE_READONLY : ffi:: c_int = 8 ; /* Attempt to write a readonly database */
27+ pub const SQLITE_INTERRUPT : ffi:: c_int = 9 ; /* Operation terminated by sqlite3_interrupt()*/
28+ pub const SQLITE_IOERR : ffi:: c_int = 10 ; /* Some kind of disk I/O error occurred */
29+ pub const SQLITE_CORRUPT : ffi:: c_int = 11 ; /* The database disk image is malformed */
30+ pub const SQLITE_NOTFOUND : ffi:: c_int = 12 ; /* Unknown opcode in sqlite3_file_control() */
31+ pub const SQLITE_FULL : ffi:: c_int = 13 ; /* Insertion failed because database is full */
32+ pub const SQLITE_CANTOPEN : ffi:: c_int = 14 ; /* Unable to open the database file */
33+ pub const SQLITE_PROTOCOL : ffi:: c_int = 15 ; /* Database lock protocol error */
34+ pub const SQLITE_EMPTY : ffi:: c_int = 16 ; /* Internal use only */
35+ pub const SQLITE_SCHEMA : ffi:: c_int = 17 ; /* The database schema changed */
36+ pub const SQLITE_TOOBIG : ffi:: c_int = 18 ; /* String or BLOB exceeds size limit */
37+ pub const SQLITE_CONSTRAINT : ffi:: c_int = 19 ; /* Abort due to constraint violation */
38+ pub const SQLITE_MISMATCH : ffi:: c_int = 20 ; /* Data type mismatch */
39+ pub const SQLITE_MISUSE : ffi:: c_int = 21 ; /* Library used incorrectly */
40+ pub const SQLITE_NOLFS : ffi:: c_int = 22 ; /* Uses OS features not supported on host */
41+ pub const SQLITE_AUTH : ffi:: c_int = 23 ; /* Authorization denied */
42+ pub const SQLITE_FORMAT : ffi:: c_int = 24 ; /* Not used */
43+ pub const SQLITE_RANGE : ffi:: c_int = 25 ; /* 2nd parameter to sqlite3_bind out of range */
44+ pub const SQLITE_NOTADB : ffi:: c_int = 26 ; /* File opened that is not a database file */
45+ pub const SQLITE_NOTICE : ffi:: c_int = 27 ; /* Notifications from sqlite3_log() */
46+ pub const SQLITE_WARNING : ffi:: c_int = 28 ; /* Warnings from sqlite3_log() */
47+ pub const SQLITE_ROW : ffi:: c_int = 100 ; /* sqlite3_step() has another row ready */
48+ pub const SQLITE_DONE : ffi:: c_int = 101 ; /* sqlite3_step() has finished executing */
49+
50+ /* extended error-codes */
2951pub const SQLITE_ABORT_ROLLBACK : ffi:: c_int = SQLITE_ABORT | ( 2 << 8 ) ;
52+
3053pub const SQLITE_STATE_OPEN : u8 = 0x76 ;
3154pub const SQLITE_STATE_SICK : u8 = 0xba ;
3255pub const SQLITE_STATE_BUSY : u8 = 0x6d ;
@@ -39,7 +62,6 @@ pub const SQLITE_CHECKPOINT_TRUNCATE: ffi::c_int = 3;
3962pub const SQLITE_INTEGER : ffi:: c_int = 1 ;
4063pub const SQLITE_FLOAT : ffi:: c_int = 2 ;
4164pub const SQLITE_TEXT : ffi:: c_int = 3 ;
42- pub const SQLITE3_TEXT : ffi:: c_int = 3 ;
4365pub const SQLITE_BLOB : ffi:: c_int = 4 ;
4466pub const SQLITE_NULL : ffi:: c_int = 5 ;
4567
@@ -161,7 +183,7 @@ pub unsafe extern "C" fn sqlite3_open(
161183 Err ( _) => return SQLITE_CANTOPEN ,
162184 } ,
163185 } ;
164- match turso_core:: Database :: open_file ( io. clone ( ) , filename_str, false , false ) {
186+ match turso_core:: Database :: open_file ( io. clone ( ) , filename_str, false , true ) {
165187 Ok ( db) => {
166188 let conn = db. connect ( ) . unwrap ( ) ;
167189 let filename = match filename_str {
@@ -288,9 +310,10 @@ pub unsafe extern "C" fn sqlite3_prepare_v2(
288310 } ;
289311 let stmt = match db. conn . prepare ( sql) {
290312 Ok ( stmt) => stmt,
291- Err ( _) => {
292- db. err_code = SQLITE_ERROR ;
293- return SQLITE_ERROR ;
313+ Err ( err) => {
314+ let code = handle_limbo_err ( err, std:: ptr:: null_mut ( ) ) ;
315+ db. err_code = code;
316+ return code;
294317 }
295318 } ;
296319 let new_stmt = Box :: leak ( Box :: new ( sqlite3_stmt:: new ( raw_db, stmt) ) ) ;
@@ -344,8 +367,8 @@ pub unsafe extern "C" fn sqlite3_step(stmt: *mut sqlite3_stmt) -> ffi::c_int {
344367 let db = & mut * stmt. db ;
345368 loop {
346369 let _db = db. inner . lock ( ) . unwrap ( ) ;
347- if let Ok ( result ) = stmt. stmt . step ( ) {
348- match result {
370+ match stmt. stmt . step ( ) {
371+ Ok ( result ) => match result {
349372 turso_core:: StepResult :: IO => {
350373 stmt. stmt . run_once ( ) . unwrap ( ) ;
351374 continue ;
@@ -360,9 +383,8 @@ pub unsafe extern "C" fn sqlite3_step(stmt: *mut sqlite3_stmt) -> ffi::c_int {
360383 return SQLITE_ROW ;
361384 }
362385 turso_core:: StepResult :: Busy => return SQLITE_BUSY ,
363- }
364- } else {
365- return SQLITE_ERROR ;
386+ } ,
387+ Err ( err) => return handle_limbo_err ( err, std:: ptr:: null_mut ( ) ) ,
366388 }
367389 }
368390}
@@ -412,11 +434,7 @@ pub unsafe extern "C" fn sqlite3_exec(
412434 match db_inner. conn . execute ( trimmed) {
413435 Ok ( _) => continue ,
414436 Err ( e) => {
415- if !err. is_null ( ) {
416- let err_msg = format ! ( "SQL error: {e:?}" ) ;
417- * err = CString :: new ( err_msg) . unwrap ( ) . into_raw ( ) ;
418- }
419- return SQLITE_ERROR ;
437+ return handle_limbo_err ( e, err) ;
420438 }
421439 }
422440 } else if callback. is_none ( ) {
@@ -964,7 +982,6 @@ pub unsafe extern "C" fn sqlite3_bind_double(
964982 idx : ffi:: c_int ,
965983 val : f64 ,
966984) -> ffi:: c_int {
967- println ! ( "Bind Double Rust" ) ;
968985 if stmt. is_null ( ) {
969986 return SQLITE_MISUSE ;
970987 }
@@ -1801,7 +1818,6 @@ pub unsafe extern "C" fn sqlite3_wal_checkpoint_v2(
18011818 SQLITE_OK
18021819 }
18031820 Err ( e) => {
1804- println ! ( "Checkpoint error: {e}" ) ;
18051821 if matches ! ( e, turso_core:: LimboError :: Busy ) {
18061822 SQLITE_BUSY
18071823 } else {
@@ -1946,13 +1962,10 @@ pub unsafe extern "C" fn libsql_wal_disable_checkpoint(db: *mut sqlite3) -> ffi:
19461962}
19471963
19481964fn sqlite3_safety_check_sick_or_ok ( db : & sqlite3Inner ) -> bool {
1949- match db. e_open_state {
1950- SQLITE_STATE_SICK | SQLITE_STATE_OPEN | SQLITE_STATE_BUSY => true ,
1951- _ => {
1952- eprintln ! ( "Invalid database state: {}" , db. e_open_state) ;
1953- false
1954- }
1955- }
1965+ matches ! (
1966+ db. e_open_state,
1967+ SQLITE_STATE_SICK | SQLITE_STATE_OPEN | SQLITE_STATE_BUSY
1968+ )
19561969}
19571970
19581971// https://sqlite.org/c3ref/table_column_metadata.html
@@ -2096,3 +2109,20 @@ pub unsafe extern "C" fn sqlite3_table_column_metadata(
20962109
20972110 rc
20982111}
2112+
2113+ fn handle_limbo_err ( err : LimboError , container : * mut * mut ffi:: c_char ) -> i32 {
2114+ if !container. is_null ( ) {
2115+ let err_msg = format ! ( "{err}" ) ;
2116+ unsafe { * container = CString :: new ( err_msg) . unwrap ( ) . into_raw ( ) } ;
2117+ }
2118+ match err {
2119+ LimboError :: Corrupt ( ..) => SQLITE_CORRUPT ,
2120+ LimboError :: NotADB => SQLITE_NOTADB ,
2121+ LimboError :: Constraint ( _) => SQLITE_CONSTRAINT ,
2122+ LimboError :: DatabaseFull ( _) => SQLITE_FULL ,
2123+ LimboError :: TableLocked => SQLITE_LOCKED ,
2124+ LimboError :: ReadOnly => SQLITE_READONLY ,
2125+ LimboError :: Busy => SQLITE_BUSY ,
2126+ _ => SQLITE_ERROR ,
2127+ }
2128+ }
0 commit comments