From d4172efa7466001dd466200dec6a20a21f3c32c0 Mon Sep 17 00:00:00 2001 From: danawan Date: Tue, 19 Aug 2025 10:27:59 +0700 Subject: [PATCH 1/6] add column type --- sqlite3/include/sqlite3.h | 7 ++++ sqlite3/src/lib.rs | 25 +++++++++++-- sqlite3/tests/compat/mod.rs | 69 +++++++++++++++++++++++++++++++++++ sqlite3/tests/sqlite3_tests.c | 47 +++++++++++++++++++++++- 4 files changed, 144 insertions(+), 4 deletions(-) diff --git a/sqlite3/include/sqlite3.h b/sqlite3/include/sqlite3.h index 56f3e1896..21695d4f1 100644 --- a/sqlite3/include/sqlite3.h +++ b/sqlite3/include/sqlite3.h @@ -41,6 +41,13 @@ #define SQLITE_CHECKPOINT_TRUNCATE 3 +#define SQLITE_INTEGER 1 +#define SQLITE_FLOAT 2 +#define SQLITE_BLOB 4 +#define SQLITE_NULL 5 +#define SQLITE_TEXT 3 +#define SQLITE3_TEXT 3 + typedef void (*sqlite3_destructor_type)(void*); #define SQLITE_STATIC ((sqlite3_destructor_type)0) #define SQLITE_TRANSIENT ((sqlite3_destructor_type)-1) diff --git a/sqlite3/src/lib.rs b/sqlite3/src/lib.rs index 30e3af817..66d4ff1a1 100644 --- a/sqlite3/src/lib.rs +++ b/sqlite3/src/lib.rs @@ -36,6 +36,13 @@ pub const SQLITE_CHECKPOINT_FULL: ffi::c_int = 1; pub const SQLITE_CHECKPOINT_RESTART: ffi::c_int = 2; pub const SQLITE_CHECKPOINT_TRUNCATE: ffi::c_int = 3; +pub const SQLITE_INTEGER: ffi::c_int = 1; +pub const SQLITE_FLOAT: ffi::c_int = 2; +pub const SQLITE_TEXT: ffi::c_int = 3; +pub const SQLITE3_TEXT: ffi::c_int = 3; +pub const SQLITE_BLOB: ffi::c_int = 4; +pub const SQLITE_NULL: ffi::c_int = 5; + pub struct sqlite3 { pub(crate) inner: Arc>, } @@ -697,10 +704,22 @@ pub unsafe extern "C" fn sqlite3_bind_blob( #[no_mangle] pub unsafe extern "C" fn sqlite3_column_type( - _stmt: *mut sqlite3_stmt, - _idx: ffi::c_int, + stmt: *mut sqlite3_stmt, + idx: ffi::c_int, ) -> ffi::c_int { - stub!(); + let stmt = &mut *stmt; + let row = stmt + .stmt + .row() + .expect("Function should only be called after `SQLITE_ROW`"); + + match row.get::<&Value>(idx as usize) { + Ok(turso_core::Value::Integer(_)) => SQLITE_INTEGER, + Ok(turso_core::Value::Text(_)) => SQLITE_TEXT, + Ok(turso_core::Value::Float(_)) => SQLITE_FLOAT, + Ok(turso_core::Value::Blob(_)) => SQLITE_BLOB, + _ => SQLITE_NULL, + } } #[no_mangle] diff --git a/sqlite3/tests/compat/mod.rs b/sqlite3/tests/compat/mod.rs index 836a93d8d..28f2ceffb 100644 --- a/sqlite3/tests/compat/mod.rs +++ b/sqlite3/tests/compat/mod.rs @@ -69,6 +69,7 @@ extern "C" { fn sqlite3_column_text(stmt: *mut sqlite3_stmt, idx: i32) -> *const libc::c_char; fn sqlite3_column_bytes(stmt: *mut sqlite3_stmt, idx: i32) -> i64; fn sqlite3_column_blob(stmt: *mut sqlite3_stmt, idx: i32) -> *const libc::c_void; + fn sqlite3_column_type(stmt: *mut sqlite3_stmt, idx: i32) -> i32; } const SQLITE_OK: i32 = 0; @@ -80,6 +81,12 @@ const SQLITE_CHECKPOINT_PASSIVE: i32 = 0; const SQLITE_CHECKPOINT_FULL: i32 = 1; const SQLITE_CHECKPOINT_RESTART: i32 = 2; const SQLITE_CHECKPOINT_TRUNCATE: i32 = 3; +const SQLITE_INTEGER: i32 = 1; +const SQLITE_FLOAT: i32 = 2; +const SQLITE_TEXT: i32 = 3; +const SQLITE3_TEXT: i32 = 3; +const SQLITE_BLOB: i32 = 4; +const SQLITE_NULL: i32 = 5; #[cfg(not(target_os = "windows"))] mod tests { @@ -647,6 +654,68 @@ mod tests { } } + #[test] + fn test_sqlite3_column_type() { + unsafe { + let temp_file = tempfile::NamedTempFile::with_suffix(".db").unwrap(); + let path = std::ffi::CString::new(temp_file.path().to_str().unwrap()).unwrap(); + let mut db = std::ptr::null_mut(); + assert_eq!(sqlite3_open(path.as_ptr(), &mut db), SQLITE_OK); + + let mut stmt = std::ptr::null_mut(); + assert_eq!( + sqlite3_prepare_v2( + db, + c"CREATE TABLE test_types (col_int INTEGER, col_float REAL, col_text TEXT, col_blob BLOB, col_null TEXT)".as_ptr(), + -1, + &mut stmt, + std::ptr::null_mut(), + ), + SQLITE_OK + ); + assert_eq!(sqlite3_step(stmt), SQLITE_DONE); + assert_eq!(sqlite3_finalize(stmt), SQLITE_OK); + + let mut stmt = std::ptr::null_mut(); + assert_eq!( + sqlite3_prepare_v2( + db, + c"INSERT INTO test_types VALUES (123, 45.67, 'hello', x'010203', NULL)" + .as_ptr(), + -1, + &mut stmt, + std::ptr::null_mut(), + ), + SQLITE_OK + ); + assert_eq!(sqlite3_step(stmt), SQLITE_DONE); + assert_eq!(sqlite3_finalize(stmt), SQLITE_OK); + + let mut stmt = std::ptr::null_mut(); + assert_eq!( + sqlite3_prepare_v2( + db, + c"SELECT col_int, col_float, col_text, col_blob, col_null FROM test_types" + .as_ptr(), + -1, + &mut stmt, + std::ptr::null_mut(), + ), + SQLITE_OK + ); + assert_eq!(sqlite3_step(stmt), SQLITE_ROW); + + assert_eq!(sqlite3_column_type(stmt, 0), SQLITE_INTEGER); + assert_eq!(sqlite3_column_type(stmt, 1), SQLITE_FLOAT); + assert_eq!(sqlite3_column_type(stmt, 2), SQLITE_TEXT); + assert_eq!(sqlite3_column_type(stmt, 3), SQLITE_BLOB); + assert_eq!(sqlite3_column_type(stmt, 4), SQLITE_NULL); + + assert_eq!(sqlite3_finalize(stmt), SQLITE_OK); + assert_eq!(sqlite3_close(db), SQLITE_OK); + } + } + #[cfg(not(feature = "sqlite3"))] mod libsql_ext { diff --git a/sqlite3/tests/sqlite3_tests.c b/sqlite3/tests/sqlite3_tests.c index 294588dd6..1e2603f3f 100644 --- a/sqlite3/tests/sqlite3_tests.c +++ b/sqlite3/tests/sqlite3_tests.c @@ -16,6 +16,7 @@ void test_sqlite3_last_insert_rowid(); void test_sqlite3_bind_text(); void test_sqlite3_bind_text2(); void test_sqlite3_bind_blob(); +void test_sqlite3_column_type(); int allocated = 0; @@ -31,7 +32,7 @@ int main(void) test_sqlite3_bind_text(); test_sqlite3_bind_text2(); test_sqlite3_bind_blob(); - + test_sqlite3_column_type(); return 0; } @@ -482,3 +483,47 @@ void test_sqlite3_bind_blob() sqlite3_finalize(stmt); sqlite3_close(db); } + +void test_sqlite3_column_type() +{ + sqlite3 *db; + sqlite3_stmt *stmt; + int rc; + + rc = sqlite3_open(":memory:", &db); + assert(rc == SQLITE_OK); + + rc = sqlite3_exec(db, + "CREATE TABLE test_column_type (col_int INTEGER, col_float REAL, col_text TEXT, col_blob BLOB, col_null TEXT);", + NULL, NULL, NULL); + assert(rc == SQLITE_OK); + + rc = sqlite3_exec(db, + "INSERT INTO test_column_type VALUES (42, 3.14, 'hello', x'010203', NULL);", + NULL, NULL, NULL); + assert(rc == SQLITE_OK); + + rc = sqlite3_prepare_v2(db, + "SELECT col_int, col_float, col_text, col_blob, col_null FROM test_column_type;", + -1, &stmt, NULL); + assert(rc == SQLITE_OK); + + rc = sqlite3_step(stmt); + assert(rc == SQLITE_ROW); + + for (int i = 0; i < sqlite3_column_count(stmt); i++) { + int type = sqlite3_column_type(stmt, i); + switch (i) { + case 0: assert(type == SQLITE_INTEGER); break; + case 1: assert(type == SQLITE_FLOAT); break; + case 2: assert(type == SQLITE_TEXT); break; + case 3: assert(type == SQLITE_BLOB); break; + case 4: assert(type == SQLITE_NULL); break; + } + } + + printf("sqlite3_column_type test completed!\n"); + + sqlite3_finalize(stmt); + sqlite3_close(db); +} From 85da74979e00c380a9fd1409b25d380736ebab31 Mon Sep 17 00:00:00 2001 From: danawan Date: Wed, 20 Aug 2025 07:55:41 +0700 Subject: [PATCH 2/6] change get column type from core --- sqlite3/src/lib.rs | 22 ++++++++++++---------- sqlite3/tests/compat/mod.rs | 4 ++-- sqlite3/tests/sqlite3_tests.c | 6 +++--- 3 files changed, 17 insertions(+), 15 deletions(-) diff --git a/sqlite3/src/lib.rs b/sqlite3/src/lib.rs index 66d4ff1a1..d4657f370 100644 --- a/sqlite3/src/lib.rs +++ b/sqlite3/src/lib.rs @@ -708,18 +708,20 @@ pub unsafe extern "C" fn sqlite3_column_type( idx: ffi::c_int, ) -> ffi::c_int { let stmt = &mut *stmt; - let row = stmt - .stmt - .row() - .expect("Function should only be called after `SQLITE_ROW`"); - match row.get::<&Value>(idx as usize) { - Ok(turso_core::Value::Integer(_)) => SQLITE_INTEGER, - Ok(turso_core::Value::Text(_)) => SQLITE_TEXT, - Ok(turso_core::Value::Float(_)) => SQLITE_FLOAT, - Ok(turso_core::Value::Blob(_)) => SQLITE_BLOB, - _ => SQLITE_NULL, + if let Some(val) = stmt.stmt.get_column_type(idx as usize) { + match val.as_str() { + "INTEGER" => return SQLITE_INTEGER, + "REAL" => return SQLITE_FLOAT, + "TEXT" => return SQLITE_TEXT, + "BLOB" => return SQLITE_BLOB, + + //SQLite3 column type doesn't cover numeric value + _ => return SQLITE_NULL, + } } + + SQLITE_NULL } #[no_mangle] diff --git a/sqlite3/tests/compat/mod.rs b/sqlite3/tests/compat/mod.rs index 28f2ceffb..efc018487 100644 --- a/sqlite3/tests/compat/mod.rs +++ b/sqlite3/tests/compat/mod.rs @@ -666,7 +666,7 @@ mod tests { assert_eq!( sqlite3_prepare_v2( db, - c"CREATE TABLE test_types (col_int INTEGER, col_float REAL, col_text TEXT, col_blob BLOB, col_null TEXT)".as_ptr(), + c"CREATE TABLE test_types (col_int INTEGER, col_float REAL, col_text TEXT, col_blob BLOB, col_null NULL)".as_ptr(), -1, &mut stmt, std::ptr::null_mut(), @@ -680,7 +680,7 @@ mod tests { assert_eq!( sqlite3_prepare_v2( db, - c"INSERT INTO test_types VALUES (123, 45.67, 'hello', x'010203', NULL)" + c"INSERT INTO test_types VALUES (123, 45.67, 'hello', x'010203', 'null')" .as_ptr(), -1, &mut stmt, diff --git a/sqlite3/tests/sqlite3_tests.c b/sqlite3/tests/sqlite3_tests.c index 1e2603f3f..6f39f4773 100644 --- a/sqlite3/tests/sqlite3_tests.c +++ b/sqlite3/tests/sqlite3_tests.c @@ -494,12 +494,12 @@ void test_sqlite3_column_type() assert(rc == SQLITE_OK); rc = sqlite3_exec(db, - "CREATE TABLE test_column_type (col_int INTEGER, col_float REAL, col_text TEXT, col_blob BLOB, col_null TEXT);", + "CREATE TABLE test_column_type (col_int INTEGER, col_float REAL, col_text TEXT, col_blob BLOB, col_null NULL);", NULL, NULL, NULL); assert(rc == SQLITE_OK); - + rc = sqlite3_exec(db, - "INSERT INTO test_column_type VALUES (42, 3.14, 'hello', x'010203', NULL);", + "INSERT INTO test_column_type VALUES (42, 3.14, 'hello', x'010203', 'null');", NULL, NULL, NULL); assert(rc == SQLITE_OK); From f1c2277543bbd3d47cfc2db35b4a445618439e29 Mon Sep 17 00:00:00 2001 From: danawan Date: Wed, 20 Aug 2025 09:34:30 +0700 Subject: [PATCH 3/6] change column type using value type --- sqlite3/src/lib.rs | 22 ++++++++++------------ sqlite3/tests/compat/mod.rs | 4 ++-- sqlite3/tests/sqlite3_tests.c | 4 ++-- 3 files changed, 14 insertions(+), 16 deletions(-) diff --git a/sqlite3/src/lib.rs b/sqlite3/src/lib.rs index d4657f370..66d4ff1a1 100644 --- a/sqlite3/src/lib.rs +++ b/sqlite3/src/lib.rs @@ -708,20 +708,18 @@ pub unsafe extern "C" fn sqlite3_column_type( idx: ffi::c_int, ) -> ffi::c_int { let stmt = &mut *stmt; + let row = stmt + .stmt + .row() + .expect("Function should only be called after `SQLITE_ROW`"); - if let Some(val) = stmt.stmt.get_column_type(idx as usize) { - match val.as_str() { - "INTEGER" => return SQLITE_INTEGER, - "REAL" => return SQLITE_FLOAT, - "TEXT" => return SQLITE_TEXT, - "BLOB" => return SQLITE_BLOB, - - //SQLite3 column type doesn't cover numeric value - _ => return SQLITE_NULL, - } + match row.get::<&Value>(idx as usize) { + Ok(turso_core::Value::Integer(_)) => SQLITE_INTEGER, + Ok(turso_core::Value::Text(_)) => SQLITE_TEXT, + Ok(turso_core::Value::Float(_)) => SQLITE_FLOAT, + Ok(turso_core::Value::Blob(_)) => SQLITE_BLOB, + _ => SQLITE_NULL, } - - SQLITE_NULL } #[no_mangle] diff --git a/sqlite3/tests/compat/mod.rs b/sqlite3/tests/compat/mod.rs index efc018487..bc9fffa98 100644 --- a/sqlite3/tests/compat/mod.rs +++ b/sqlite3/tests/compat/mod.rs @@ -666,7 +666,7 @@ mod tests { assert_eq!( sqlite3_prepare_v2( db, - c"CREATE TABLE test_types (col_int INTEGER, col_float REAL, col_text TEXT, col_blob BLOB, col_null NULL)".as_ptr(), + c"CREATE TABLE test_types (col_int INTEGER, col_float REAL, col_text TEXT, col_blob BLOB, col_null text)".as_ptr(), -1, &mut stmt, std::ptr::null_mut(), @@ -680,7 +680,7 @@ mod tests { assert_eq!( sqlite3_prepare_v2( db, - c"INSERT INTO test_types VALUES (123, 45.67, 'hello', x'010203', 'null')" + c"INSERT INTO test_types VALUES (123, 45.67, 'hello', x'010203', null)" .as_ptr(), -1, &mut stmt, diff --git a/sqlite3/tests/sqlite3_tests.c b/sqlite3/tests/sqlite3_tests.c index 6f39f4773..3315c8273 100644 --- a/sqlite3/tests/sqlite3_tests.c +++ b/sqlite3/tests/sqlite3_tests.c @@ -494,12 +494,12 @@ void test_sqlite3_column_type() assert(rc == SQLITE_OK); rc = sqlite3_exec(db, - "CREATE TABLE test_column_type (col_int INTEGER, col_float REAL, col_text TEXT, col_blob BLOB, col_null NULL);", + "CREATE TABLE test_column_type (col_int INTEGER, col_float REAL, col_text TEXT, col_blob BLOB, col_null TEXT);", NULL, NULL, NULL); assert(rc == SQLITE_OK); rc = sqlite3_exec(db, - "INSERT INTO test_column_type VALUES (42, 3.14, 'hello', x'010203', 'null');", + "INSERT INTO test_column_type VALUES (42, 3.14, 'hello', x'010203', NULL);", NULL, NULL, NULL); assert(rc == SQLITE_OK); From 804bb868c7e434acafe45abad19c85a46ec284eb Mon Sep 17 00:00:00 2001 From: danawan Date: Wed, 20 Aug 2025 11:28:14 +0700 Subject: [PATCH 4/6] add column decltype --- core/lib.rs | 2 +- sqlite3/src/lib.rs | 13 +++++++-- sqlite3/tests/compat/mod.rs | 53 +++++++++++++++++++++++++++++++++++ sqlite3/tests/sqlite3_tests.c | 35 +++++++++++++++++++++++ 4 files changed, 99 insertions(+), 4 deletions(-) diff --git a/core/lib.rs b/core/lib.rs index e1e5c6ae4..68d616fbc 100644 --- a/core/lib.rs +++ b/core/lib.rs @@ -2095,7 +2095,7 @@ impl Statement { crate::schema::Type::Text => Some("TEXT".to_string()), crate::schema::Type::Blob => Some("BLOB".to_string()), crate::schema::Type::Numeric => Some("NUMERIC".to_string()), - crate::schema::Type::Null => None, + crate::schema::Type::Null => Some("NULL".to_string()), } } _ => None, diff --git a/sqlite3/src/lib.rs b/sqlite3/src/lib.rs index 66d4ff1a1..6c3946600 100644 --- a/sqlite3/src/lib.rs +++ b/sqlite3/src/lib.rs @@ -730,10 +730,17 @@ pub unsafe extern "C" fn sqlite3_column_count(stmt: *mut sqlite3_stmt) -> ffi::c #[no_mangle] pub unsafe extern "C" fn sqlite3_column_decltype( - _stmt: *mut sqlite3_stmt, - _idx: ffi::c_int, + stmt: *mut sqlite3_stmt, + idx: ffi::c_int, ) -> *const ffi::c_char { - stub!(); + let stmt = &mut *stmt; + + if let Some(val) = stmt.stmt.get_column_type(idx as usize) { + let c_string = CString::new(val).expect("CString::new failed"); + c_string.into_raw() + } else { + std::ptr::null() + } } #[no_mangle] diff --git a/sqlite3/tests/compat/mod.rs b/sqlite3/tests/compat/mod.rs index bc9fffa98..bbb54f00f 100644 --- a/sqlite3/tests/compat/mod.rs +++ b/sqlite3/tests/compat/mod.rs @@ -70,6 +70,7 @@ extern "C" { fn sqlite3_column_bytes(stmt: *mut sqlite3_stmt, idx: i32) -> i64; fn sqlite3_column_blob(stmt: *mut sqlite3_stmt, idx: i32) -> *const libc::c_void; fn sqlite3_column_type(stmt: *mut sqlite3_stmt, idx: i32) -> i32; + fn sqlite3_column_decltype(stmt: *mut sqlite3_stmt, idx: i32) -> *const libc::c_char; } const SQLITE_OK: i32 = 0; @@ -716,6 +717,58 @@ mod tests { } } + #[test] + fn test_sqlite3_column_decltype() { + unsafe { + let temp_file = tempfile::NamedTempFile::with_suffix(".db").unwrap(); + let path = std::ffi::CString::new(temp_file.path().to_str().unwrap()).unwrap(); + let mut db = std::ptr::null_mut(); + assert_eq!(sqlite3_open(path.as_ptr(), &mut db), SQLITE_OK); + + let mut stmt = std::ptr::null_mut(); + assert_eq!( + sqlite3_prepare_v2( + db, + c"CREATE TABLE test_decltype (col_int INTEGER, col_float REAL, col_text TEXT, col_blob BLOB, col_null NULL)".as_ptr(), + -1, + &mut stmt, + std::ptr::null_mut(), + ), + SQLITE_OK + ); + assert_eq!(sqlite3_step(stmt), SQLITE_DONE); + assert_eq!(sqlite3_finalize(stmt), SQLITE_OK); + + let mut stmt = std::ptr::null_mut(); + assert_eq!( + sqlite3_prepare_v2( + db, + c"SELECT col_int, col_float, col_text, col_blob, col_null FROM test_decltype" + .as_ptr(), + -1, + &mut stmt, + std::ptr::null_mut(), + ), + SQLITE_OK + ); + + let expected = ["INTEGER", "REAL", "TEXT", "BLOB", "NULL"]; + + for i in 0..sqlite3_column_count(stmt) { + let decl = sqlite3_column_decltype(stmt, i); + assert!(!decl.is_null()); + let s = std::ffi::CStr::from_ptr(decl) + .to_string_lossy() + .into_owned(); + println!("{s}"); + assert_eq!(s, expected[i as usize]); + } + + assert_eq!(sqlite3_finalize(stmt), SQLITE_OK); + assert_eq!(sqlite3_close(db), SQLITE_OK); + } + } + #[cfg(not(feature = "sqlite3"))] mod libsql_ext { diff --git a/sqlite3/tests/sqlite3_tests.c b/sqlite3/tests/sqlite3_tests.c index 3315c8273..6af119335 100644 --- a/sqlite3/tests/sqlite3_tests.c +++ b/sqlite3/tests/sqlite3_tests.c @@ -17,6 +17,7 @@ void test_sqlite3_bind_text(); void test_sqlite3_bind_text2(); void test_sqlite3_bind_blob(); void test_sqlite3_column_type(); +void test_sqlite3_column_decltype(); int allocated = 0; @@ -33,6 +34,7 @@ int main(void) test_sqlite3_bind_text2(); test_sqlite3_bind_blob(); test_sqlite3_column_type(); + test_sqlite3_column_decltype(); return 0; } @@ -527,3 +529,36 @@ void test_sqlite3_column_type() sqlite3_finalize(stmt); sqlite3_close(db); } + +void test_sqlite3_column_decltype() +{ + sqlite3 *db; + sqlite3_stmt *stmt; + int rc; + + rc = sqlite3_open(":memory:", &db); + assert(rc == SQLITE_OK); + + rc = sqlite3_exec(db, + "CREATE TABLE test_decltype (col_int INTEGER, col_float REAL, col_text TEXT, col_blob BLOB, col_null NULL);", + NULL, NULL, NULL); + assert(rc == SQLITE_OK); + + rc = sqlite3_prepare_v2(db, + "SELECT col_int, col_float, col_text, col_blob, col_null FROM test_decltype;", + -1, &stmt, NULL); + assert(rc == SQLITE_OK); + + const char* expected[] = { "INTEGER", "REAL", "TEXT", "BLOB", "NULL"}; + + for (int i = 0; i < sqlite3_column_count(stmt); i++) { + const char* decl = sqlite3_column_decltype(stmt, i); + assert(decl != NULL); + assert(strcmp(decl, expected[i]) == 0); + } + + printf("sqlite3_column_decltype test completed!\n"); + + sqlite3_finalize(stmt); + sqlite3_close(db); +} From 72cdd32ba110c36c514d0b3bc2b9968ca2ff3a0c Mon Sep 17 00:00:00 2001 From: danawan Date: Wed, 20 Aug 2025 11:59:27 +0700 Subject: [PATCH 5/6] fix null testing --- core/lib.rs | 2 +- sqlite3/tests/compat/mod.rs | 23 ++++++++++++++++------- sqlite3/tests/sqlite3_tests.c | 14 +++++++++++--- 3 files changed, 28 insertions(+), 11 deletions(-) diff --git a/core/lib.rs b/core/lib.rs index 68d616fbc..e1e5c6ae4 100644 --- a/core/lib.rs +++ b/core/lib.rs @@ -2095,7 +2095,7 @@ impl Statement { crate::schema::Type::Text => Some("TEXT".to_string()), crate::schema::Type::Blob => Some("BLOB".to_string()), crate::schema::Type::Numeric => Some("NUMERIC".to_string()), - crate::schema::Type::Null => Some("NULL".to_string()), + crate::schema::Type::Null => None, } } _ => None, diff --git a/sqlite3/tests/compat/mod.rs b/sqlite3/tests/compat/mod.rs index bbb54f00f..2192a89f9 100644 --- a/sqlite3/tests/compat/mod.rs +++ b/sqlite3/tests/compat/mod.rs @@ -752,16 +752,25 @@ mod tests { SQLITE_OK ); - let expected = ["INTEGER", "REAL", "TEXT", "BLOB", "NULL"]; + let expected = [ + Some("INTEGER"), + Some("REAL"), + Some("TEXT"), + Some("BLOB"), + None, + ]; for i in 0..sqlite3_column_count(stmt) { let decl = sqlite3_column_decltype(stmt, i); - assert!(!decl.is_null()); - let s = std::ffi::CStr::from_ptr(decl) - .to_string_lossy() - .into_owned(); - println!("{s}"); - assert_eq!(s, expected[i as usize]); + + if decl.is_null() { + assert!(expected[i as usize].is_none()); + } else { + let s = std::ffi::CStr::from_ptr(decl) + .to_string_lossy() + .into_owned(); + assert_eq!(Some(s.as_str()), expected[i as usize]); + } } assert_eq!(sqlite3_finalize(stmt), SQLITE_OK); diff --git a/sqlite3/tests/sqlite3_tests.c b/sqlite3/tests/sqlite3_tests.c index 6af119335..56a35abe6 100644 --- a/sqlite3/tests/sqlite3_tests.c +++ b/sqlite3/tests/sqlite3_tests.c @@ -549,12 +549,20 @@ void test_sqlite3_column_decltype() -1, &stmt, NULL); assert(rc == SQLITE_OK); - const char* expected[] = { "INTEGER", "REAL", "TEXT", "BLOB", "NULL"}; + const char* expected[] = { "INTEGER", "REAL", "TEXT", "BLOB", NULL}; for (int i = 0; i < sqlite3_column_count(stmt); i++) { const char* decl = sqlite3_column_decltype(stmt, i); - assert(decl != NULL); - assert(strcmp(decl, expected[i]) == 0); + //printf("DECL %s \n", decl); + //assert(decl != NULL); + //assert(strcmp(decl, expected[i]) == 0); + if (decl == NULL) { + printf("DECL (null)\n"); + assert(expected[i] == NULL); + } else { + printf("DECL %s\n", decl); + assert(strcmp(decl, expected[i]) == 0); + } } printf("sqlite3_column_decltype test completed!\n"); From 45376e0b351d12a18209c2fcd7f9c4e89fb648d0 Mon Sep 17 00:00:00 2001 From: danawan Date: Wed, 20 Aug 2025 12:01:55 +0700 Subject: [PATCH 6/6] delete printf in C test --- sqlite3/tests/sqlite3_tests.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/sqlite3/tests/sqlite3_tests.c b/sqlite3/tests/sqlite3_tests.c index 56a35abe6..2cd490a93 100644 --- a/sqlite3/tests/sqlite3_tests.c +++ b/sqlite3/tests/sqlite3_tests.c @@ -553,14 +553,9 @@ void test_sqlite3_column_decltype() for (int i = 0; i < sqlite3_column_count(stmt); i++) { const char* decl = sqlite3_column_decltype(stmt, i); - //printf("DECL %s \n", decl); - //assert(decl != NULL); - //assert(strcmp(decl, expected[i]) == 0); if (decl == NULL) { - printf("DECL (null)\n"); assert(expected[i] == NULL); } else { - printf("DECL %s\n", decl); assert(strcmp(decl, expected[i]) == 0); } }