Skip to content
This repository was archived by the owner on Oct 18, 2023. It is now read-only.

Commit d1e88fe

Browse files
committed
treewide: migrate from rusqlite to libsql and libsql_sys
This huge patch migrates sqld from rusqlite to libsql crate. Since both rusqlite and libsql link with compiled sqlite3.c, the migration has to be done in one piece. Good luck, reviewers!
1 parent 2ffd4ef commit d1e88fe

25 files changed

+305
-368
lines changed

Cargo.toml

+1-6
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,4 @@ members = [
1010
]
1111

1212
[workspace.dependencies]
13-
rusqlite = { version = "0.29.0", git = "https://github.com/psarna/rusqlite", rev = "477264453b", default-features = false, features = [
14-
"buildtime_bindgen",
15-
"bundled-libsql-wasm-experimental",
16-
"column_decltype",
17-
"load_extension"
18-
] }
13+
libsql = { version = "0.1.6", default-features = false }

bottomless/src/lib.rs

+34-34
Original file line numberDiff line numberDiff line change
@@ -57,18 +57,18 @@ pub extern "C" fn xOpen(
5757
let rc = unsafe {
5858
(orig_methods.xOpen.unwrap())(vfs, db_file, wal_name, no_shm_mode, max_size, methods, wal)
5959
};
60-
if rc != ffi::SQLITE_OK {
60+
if rc != ffi::SQLITE_OK as i32 {
6161
return rc;
6262
}
6363

6464
if !is_regular(vfs) {
6565
tracing::error!("Bottomless WAL is currently only supported for regular VFS");
66-
return ffi::SQLITE_CANTOPEN;
66+
return ffi::SQLITE_CANTOPEN as i32;
6767
}
6868

6969
if is_local() {
7070
tracing::info!("Running in local-mode only, without any replication");
71-
return ffi::SQLITE_OK;
71+
return ffi::SQLITE_OK as i32;
7272
}
7373

7474
let runtime = match tokio::runtime::Builder::new_current_thread()
@@ -78,7 +78,7 @@ pub extern "C" fn xOpen(
7878
Ok(runtime) => runtime,
7979
Err(e) => {
8080
tracing::error!("Failed to initialize async runtime: {}", e);
81-
return ffi::SQLITE_CANTOPEN;
81+
return ffi::SQLITE_CANTOPEN as i32;
8282
}
8383
};
8484

@@ -88,7 +88,7 @@ pub extern "C" fn xOpen(
8888
Ok(path) => path,
8989
Err(e) => {
9090
tracing::error!("Failed to parse the main database path: {}", e);
91-
return ffi::SQLITE_CANTOPEN;
91+
return ffi::SQLITE_CANTOPEN as i32;
9292
}
9393
}
9494
};
@@ -98,12 +98,12 @@ pub extern "C" fn xOpen(
9898
Ok(repl) => repl,
9999
Err(e) => {
100100
tracing::error!("Failed to initialize replicator: {}", e);
101-
return ffi::SQLITE_CANTOPEN;
101+
return ffi::SQLITE_CANTOPEN as i32;
102102
}
103103
};
104104

105105
let rc = block_on!(runtime, try_restore(&mut replicator));
106-
if rc != ffi::SQLITE_OK {
106+
if rc != ffi::SQLITE_OK as i32 {
107107
return rc;
108108
}
109109

@@ -114,7 +114,7 @@ pub extern "C" fn xOpen(
114114
let context_ptr = Box::into_raw(Box::new(context)) as *mut c_void;
115115
unsafe { (*(*wal)).pMethodsData = context_ptr };
116116

117-
ffi::SQLITE_OK
117+
ffi::SQLITE_OK as i32
118118
}
119119

120120
fn get_orig_methods(wal: *mut Wal) -> &'static libsql_wal_methods {
@@ -138,7 +138,7 @@ pub extern "C" fn xClose(
138138
let orig_methods = get_orig_methods(wal);
139139
let methods_data = unsafe { (*wal).pMethodsData as *mut replicator::Context };
140140
let rc = unsafe { (orig_methods.xClose.unwrap())(wal, db, sync_flags, n_buf, z_buf) };
141-
if rc != ffi::SQLITE_OK {
141+
if rc != ffi::SQLITE_OK as i32 {
142142
return rc;
143143
}
144144
if !is_local() && !methods_data.is_null() {
@@ -194,7 +194,7 @@ pub extern "C" fn xUndo(
194194
) -> i32 {
195195
let orig_methods = get_orig_methods(wal);
196196
let rc = unsafe { (orig_methods.xUndo.unwrap())(wal, func, ctx) };
197-
if is_local() || rc != ffi::SQLITE_OK {
197+
if is_local() || rc != ffi::SQLITE_OK as i32 {
198198
return rc;
199199
}
200200

@@ -207,7 +207,7 @@ pub extern "C" fn xUndo(
207207
);
208208
ctx.replicator.rollback_to_frame(last_valid_frame);
209209

210-
ffi::SQLITE_OK
210+
ffi::SQLITE_OK as i32
211211
}
212212

213213
pub extern "C" fn xSavepoint(wal: *mut Wal, wal_data: *mut u32) {
@@ -218,7 +218,7 @@ pub extern "C" fn xSavepoint(wal: *mut Wal, wal_data: *mut u32) {
218218
pub extern "C" fn xSavepointUndo(wal: *mut Wal, wal_data: *mut u32) -> i32 {
219219
let orig_methods = get_orig_methods(wal);
220220
let rc = unsafe { (orig_methods.xSavepointUndo.unwrap())(wal, wal_data) };
221-
if is_local() || rc != ffi::SQLITE_OK {
221+
if is_local() || rc != ffi::SQLITE_OK as i32 {
222222
return rc;
223223
}
224224

@@ -231,7 +231,7 @@ pub extern "C" fn xSavepointUndo(wal: *mut Wal, wal_data: *mut u32) -> i32 {
231231
);
232232
ctx.replicator.rollback_to_frame(last_valid_frame);
233233

234-
ffi::SQLITE_OK
234+
ffi::SQLITE_OK as i32
235235
}
236236

237237
pub extern "C" fn xFrames(
@@ -253,7 +253,7 @@ pub extern "C" fn xFrames(
253253
// supported by bottomless storage.
254254
if let Err(e) = ctx.replicator.set_page_size(page_size as usize) {
255255
tracing::error!("{}", e);
256-
return ffi::SQLITE_IOERR_WRITE;
256+
return ffi::SQLITE_IOERR_WRITE as i32;
257257
}
258258
let frame_count = ffi::PageHdrIter::new(page_headers, page_size as usize).count();
259259
if size_after != 0 {
@@ -273,11 +273,11 @@ pub extern "C" fn xFrames(
273273
sync_flags,
274274
)
275275
};
276-
if is_local() || rc != ffi::SQLITE_OK {
276+
if is_local() || rc != ffi::SQLITE_OK as i32 {
277277
return rc;
278278
}
279279

280-
ffi::SQLITE_OK
280+
ffi::SQLITE_OK as i32
281281
}
282282

283283
extern "C" fn always_wait(_busy_param: *mut c_void) -> i32 {
@@ -307,9 +307,9 @@ pub extern "C" fn xCheckpoint(
307307
** In order to avoid autocheckpoint on close (that's too often),
308308
** checkpoint attempts weaker than TRUNCATE are ignored.
309309
*/
310-
if emode < ffi::SQLITE_CHECKPOINT_TRUNCATE {
310+
if emode < ffi::SQLITE_CHECKPOINT_TRUNCATE as i32 {
311311
tracing::trace!("Ignoring a checkpoint request weaker than TRUNCATE");
312-
return ffi::SQLITE_OK;
312+
return ffi::SQLITE_OK as i32;
313313
}
314314
/* If there's no busy handler, let's provide a default one,
315315
** since we auto-upgrade the passive checkpoint
@@ -335,14 +335,14 @@ pub extern "C" fn xCheckpoint(
335335
)
336336
};
337337

338-
if is_local() || rc != ffi::SQLITE_OK {
338+
if is_local() || rc != ffi::SQLITE_OK as i32 {
339339
return rc;
340340
}
341341

342342
let ctx = get_replicator_context(wal);
343343
if ctx.replicator.commits_in_current_generation() == 0 {
344344
tracing::debug!("No commits happened in this generation, not snapshotting");
345-
return ffi::SQLITE_OK;
345+
return ffi::SQLITE_OK as i32;
346346
}
347347

348348
let last_known_frame = ctx.replicator.last_known_frame();
@@ -352,7 +352,7 @@ pub extern "C" fn xCheckpoint(
352352
ctx.replicator.wait_until_committed(last_known_frame)
353353
) {
354354
tracing::error!("Failed to finalize replication: {}", e);
355-
return ffi::SQLITE_IOERR_WRITE;
355+
return ffi::SQLITE_IOERR_WRITE as i32;
356356
}
357357

358358
ctx.replicator.new_generation();
@@ -363,10 +363,10 @@ pub extern "C" fn xCheckpoint(
363363
"Failed to snapshot the main db file during checkpoint: {}",
364364
e
365365
);
366-
return ffi::SQLITE_IOERR_WRITE;
366+
return ffi::SQLITE_IOERR_WRITE as i32;
367367
}
368368

369-
ffi::SQLITE_OK
369+
ffi::SQLITE_OK as i32
370370
}
371371

372372
pub extern "C" fn xCallback(wal: *mut Wal) -> i32 {
@@ -416,42 +416,42 @@ async fn try_restore(replicator: &mut replicator::Replicator) -> i32 {
416416
replicator.new_generation();
417417
if let Err(e) = replicator.snapshot_main_db_file().await {
418418
tracing::error!("Failed to snapshot the main db file: {}", e);
419-
return ffi::SQLITE_CANTOPEN;
419+
return ffi::SQLITE_CANTOPEN as i32;
420420
}
421421
// Restoration process only leaves the local WAL file if it was
422422
// detected to be newer than its remote counterpart.
423423
if let Err(e) = replicator.maybe_replicate_wal().await {
424424
tracing::error!("Failed to replicate local WAL: {}", e);
425-
return ffi::SQLITE_CANTOPEN;
425+
return ffi::SQLITE_CANTOPEN as i32;
426426
}
427427
}
428428
Ok(replicator::RestoreAction::ReuseGeneration(gen)) => {
429429
replicator.set_generation(gen);
430430
}
431431
Err(e) => {
432432
tracing::error!("Failed to restore the database: {}", e);
433-
return ffi::SQLITE_CANTOPEN;
433+
return ffi::SQLITE_CANTOPEN as i32;
434434
}
435435
}
436436

437-
ffi::SQLITE_OK
437+
ffi::SQLITE_OK as i32
438438
}
439439

440440
pub extern "C" fn xPreMainDbOpen(_methods: *mut libsql_wal_methods, path: *const c_char) -> i32 {
441441
if is_local() {
442442
tracing::info!("Running in local-mode only, without any replication");
443-
return ffi::SQLITE_OK;
443+
return ffi::SQLITE_OK as i32;
444444
}
445445

446446
if path.is_null() {
447-
return ffi::SQLITE_OK;
447+
return ffi::SQLITE_OK as i32;
448448
}
449449
let path = unsafe {
450450
match std::ffi::CStr::from_ptr(path).to_str() {
451451
Ok(path) => path,
452452
Err(e) => {
453453
tracing::error!("Failed to parse the main database path: {}", e);
454-
return ffi::SQLITE_CANTOPEN;
454+
return ffi::SQLITE_CANTOPEN as i32;
455455
}
456456
}
457457
};
@@ -464,23 +464,23 @@ pub extern "C" fn xPreMainDbOpen(_methods: *mut libsql_wal_methods, path: *const
464464
Ok(runtime) => runtime,
465465
Err(e) => {
466466
tracing::error!("Failed to initialize async runtime: {}", e);
467-
return ffi::SQLITE_CANTOPEN;
467+
return ffi::SQLITE_CANTOPEN as i32;
468468
}
469469
};
470470

471471
let options = match replicator::Options::from_env() {
472472
Ok(options) => options,
473473
Err(e) => {
474474
tracing::error!("Failed to parse replicator options: {}", e);
475-
return ffi::SQLITE_CANTOPEN;
475+
return ffi::SQLITE_CANTOPEN as i32;
476476
}
477477
};
478478
let replicator = block_on!(runtime, replicator::Replicator::with_options(path, options));
479479
let mut replicator = match replicator {
480480
Ok(repl) => repl,
481481
Err(e) => {
482482
tracing::error!("Failed to initialize replicator: {}", e);
483-
return ffi::SQLITE_CANTOPEN;
483+
return ffi::SQLITE_CANTOPEN as i32;
484484
}
485485
};
486486
block_on!(runtime, try_restore(&mut replicator))
@@ -561,7 +561,7 @@ pub mod static_init {
561561
if orig_methods.is_null() {}
562562
let methods = crate::bottomless_methods(orig_methods);
563563
let rc = unsafe { libsql_wal_methods_register(methods) };
564-
if rc != crate::ffi::SQLITE_OK {
564+
if rc != crate::ffi::SQLITE_OK as i32 {
565565
let _box = unsafe { Box::from_raw(methods as *mut libsql_wal_methods) };
566566
tracing::warn!("Failed to instantiate bottomless WAL methods");
567567
}

sqld-libsql-bindings/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@ edition = "2021"
77

88
[dependencies]
99
anyhow = "1.0.66"
10-
rusqlite = { workspace = true }
1110
tracing = "0.1.37"
1211
once_cell = "1.17.1"
12+
libsql = { workspace = true }
1313

1414
[features]
1515
unix-excl-vfs = []

sqld-libsql-bindings/src/ffi/mod.rs

+3-10
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,9 @@
22

33
pub mod types;
44

5-
pub use rusqlite::ffi::{
6-
libsql_wal_methods, libsql_wal_methods_find, libsql_wal_methods_register,
7-
libsql_wal_methods_unregister, sqlite3, sqlite3_file, sqlite3_hard_heap_limit64,
8-
sqlite3_io_methods, sqlite3_soft_heap_limit64, sqlite3_vfs, WalIndexHdr, SQLITE_CANTOPEN,
9-
SQLITE_CHECKPOINT_FULL, SQLITE_CHECKPOINT_TRUNCATE, SQLITE_IOERR_WRITE, SQLITE_OK,
10-
};
11-
12-
pub use rusqlite::ffi::libsql_pghdr as PgHdr;
13-
pub use rusqlite::ffi::libsql_wal as Wal;
14-
pub use rusqlite::ffi::*;
5+
pub use libsql::ffi::libsql_pghdr as PgHdr;
6+
pub use libsql::ffi::libsql_wal as Wal;
7+
pub use libsql::ffi::*;
158

169
pub struct PageHdrIter {
1710
current_ptr: *const PgHdr,

sqld-libsql-bindings/src/ffi/types.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
use std::ffi::{c_char, c_int, c_uint, c_void};
33

44
use super::{libsql_wal_methods, sqlite3_file, sqlite3_vfs, PgHdr, Wal};
5-
use rusqlite::ffi::sqlite3;
5+
use libsql::ffi::sqlite3;
66

77
// WAL methods
88
pub type XWalLimitFn = extern "C" fn(wal: *mut Wal, limit: i64);
@@ -18,7 +18,7 @@ pub type XWalSavepointFn = extern "C" fn(wal: *mut Wal, wal_data: *mut u32);
1818
pub type XWalSavePointUndoFn = unsafe extern "C" fn(wal: *mut Wal, wal_data: *mut u32) -> c_int;
1919
pub type XWalCheckpointFn = unsafe extern "C" fn(
2020
wal: *mut Wal,
21-
db: *mut rusqlite::ffi::sqlite3,
21+
db: *mut libsql::ffi::sqlite3,
2222
emode: c_int,
2323
busy_handler: Option<unsafe extern "C" fn(busy_param: *mut c_void) -> c_int>,
2424
busy_arg: *mut c_void,
@@ -32,7 +32,7 @@ pub type XWalCallbackFn = extern "C" fn(wal: *mut Wal) -> c_int;
3232
pub type XWalExclusiveModeFn = extern "C" fn(wal: *mut Wal, op: c_int) -> c_int;
3333
pub type XWalHeapMemoryFn = extern "C" fn(wal: *mut Wal) -> c_int;
3434
pub type XWalFileFn = extern "C" fn(wal: *mut Wal) -> *mut sqlite3_file;
35-
pub type XWalDbFn = extern "C" fn(wal: *mut Wal, db: *mut rusqlite::ffi::sqlite3);
35+
pub type XWalDbFn = extern "C" fn(wal: *mut Wal, db: *mut libsql::ffi::sqlite3);
3636
pub type XWalPathNameLenFn = extern "C" fn(orig_len: c_int) -> c_int;
3737
pub type XWalGetPathNameFn = extern "C" fn(buf: *mut c_char, orig: *const c_char, orig_len: c_int);
3838
pub type XWalPreMainDbOpen =

0 commit comments

Comments
 (0)