0
0
mirror of https://github.com/tursodatabase/libsql.git synced 2025-09-04 09:40:34 +00:00
Files
libsql/libsql-sqlite3/test/rust_suite/src/lib.rs
Avinash Sajjanshetty d178de8f07 bugfix: reset modifications of sqlite3_vtab (#1027)
* Remove `libsql_module` field from `sqlite3_vtab`

* remove `libsql_module` struct

Also removed the associated functions `libsql_create_module_v2`, `libsql_create_module` functions'.

The `libsql_module` had a function `xPreparedSql` which is now moved to `sqlite_module`. The `sqlite_module` might get changed in the upstream, so added some padding space for our custom functions

* generate ffi bindings

* Add a github workflow to test crsqlite

* fix crsqlite: remove `pLibsqlModule` references

* Add tests for sqlite-vss extension
2024-02-15 18:18:30 +00:00

175 lines
5.2 KiB
Rust

#[cfg(test)]
mod alter_column;
mod random_rowid;
mod virtual_wal;
#[cfg(all(test, feature = "extensions"))]
mod extensions;
#[cfg(all(test, feature = "udf"))]
mod user_defined_functions;
#[cfg(all(test, feature = "udf"))]
mod user_defined_functions_src;
#[cfg(test)]
mod tests {
extern "C" {
fn libsql_close_hook(
db: *mut libsql_sys::ffi::sqlite3,
callback: Option<
extern "C" fn(arg: *mut std::ffi::c_void, db: *mut libsql_sys::ffi::sqlite3),
>,
arg: *mut std::ffi::c_void,
);
}
use std::ffi::c_void;
use libsql_sys::rusqlite::Connection;
#[derive(Debug, PartialEq)]
struct Person {
name: String,
data: Option<Vec<u8>>,
}
#[test]
fn test_insert_steven() {
let conn = Connection::open_in_memory().unwrap();
conn.execute(
"CREATE TABLE person (
name TEXT NOT NULL,
data BLOB
)",
(),
)
.unwrap();
let steven = Person {
name: "Steven".to_string(),
data: Some(vec![4, 2]),
};
conn.execute(
"INSERT INTO person (name, data) VALUES (?1, ?2)",
(&steven.name, &steven.data),
)
.unwrap();
let mut stmt = conn.prepare("SELECT name, data FROM person").unwrap();
let mut person_iter = stmt
.query_map([], |row| {
Ok(Person {
name: row.get(0).unwrap(),
data: row.get(1).unwrap(),
})
})
.unwrap();
let also_steven = person_iter.next().unwrap().unwrap();
println!("Read {also_steven:#?}");
assert!(also_steven == steven);
assert!(person_iter.next().is_none())
}
fn get_read_written(conn: &Connection, stmt: &str) -> (i32, i32) {
const STMT_ROWS_READ: i32 = 1024 + 1;
const STMT_ROWS_WRITTEN: i32 = 1024 + 2;
let mut stmt = conn.prepare(stmt).unwrap();
let mut rows = stmt.query(()).unwrap();
while let Ok(Some(_)) = rows.next() {}
drop(rows);
let mut rows_read = libsql_sys::rusqlite::StatementStatus::FullscanStep;
let mut rows_written = libsql_sys::rusqlite::StatementStatus::FullscanStep;
// FIXME: there's no API for ROWS_READ/WRITTEN yet, so let's rewrite to checking ROWS_* instead
unsafe {
std::ptr::copy(
&[STMT_ROWS_READ] as *const i32,
&mut rows_read as *mut _ as *mut i32,
4,
)
}
unsafe {
std::ptr::copy(
&[STMT_ROWS_WRITTEN] as *const i32,
&mut rows_written as *mut _ as *mut i32,
4,
)
}
(stmt.get_status(rows_read), stmt.get_status(rows_written))
}
#[test]
fn test_rows_read_written() {
let conn = Connection::open_in_memory().unwrap();
conn.execute("CREATE TABLE test(id)", ()).unwrap();
for _ in 0..16 {
conn.execute("INSERT INTO test values (1)", ()).unwrap();
}
assert_eq!(get_read_written(&conn, "SELECT * FROM test"), (16, 0));
assert_eq!(get_read_written(&conn, "SELECT count(*) FROM test"), (1, 0));
assert_eq!(
get_read_written(&conn, "SELECT min(id), max(id) FROM test where 1 = 1"),
(16, 0)
);
assert_eq!(
get_read_written(&conn, "SELECT * FROM test LIMIT 3"),
(3, 0)
);
assert_eq!(
get_read_written(&conn, "SELECT * FROM test LIMIT 3"),
(3, 0)
);
assert_eq!(
get_read_written(&conn, "SELECT * FROM test WHERE id = 2"),
(16, 0)
);
assert_eq!(
get_read_written(&conn, "SELECT * FROM test WHERE id = 2 ORDER BY rowid DESC"),
(16, 0)
);
assert_eq!(
get_read_written(&conn, "SELECT * FROM test WHERE rowid = 1"),
(1, 0)
);
assert_eq!(
get_read_written(&conn, "INSERT INTO test VALUES (1)"),
(0, 1)
);
assert_eq!(
get_read_written(&conn, "INSERT INTO test(id) SELECT id FROM test"),
(34, 17)
);
assert_eq!(
get_read_written(
&conn,
"SELECT * FROM test WHERE id IN (SELECT id FROM test)"
),
(68, 0)
);
assert_eq!(
get_read_written(&conn, "INSERT INTO test VALUES (1), (2), (3), (4)"),
(0, 4)
);
assert_eq!(get_read_written(&conn, "SELECT COUNT(*) FROM test"), (1, 0));
}
#[test]
fn test_close_hook() {
let conn = Connection::open_in_memory().unwrap();
let mut closed = false;
extern "C" fn cb(closed: *mut c_void, _db: *mut libsql_sys::ffi::sqlite3) {
unsafe {
println!("Close hook called!");
let closed = &mut *(closed as *mut bool);
*closed = true;
}
}
unsafe {
libsql_close_hook(conn.handle(), Some(cb), &mut closed as *mut _ as *mut _);
}
assert!(!closed);
drop(conn);
assert!(closed);
}
}