From 6b96dfd0214499fcc179cbd3f0ab1b1f82bc0c61 Mon Sep 17 00:00:00 2001 From: Pekka Enberg Date: Fri, 16 May 2025 13:09:45 +0300 Subject: [PATCH 1/4] libsql: Add Statement::column_count() API --- libsql/src/hrana/hyper.rs | 4 ++++ libsql/src/local/impls.rs | 4 ++++ libsql/src/replication/connection.rs | 10 ++++++++++ libsql/src/statement.rs | 7 +++++++ libsql/src/sync/statement.rs | 4 ++++ 5 files changed, 29 insertions(+) diff --git a/libsql/src/hrana/hyper.rs b/libsql/src/hrana/hyper.rs index 57840f56f4..675865ea24 100644 --- a/libsql/src/hrana/hyper.rs +++ b/libsql/src/hrana/hyper.rs @@ -234,6 +234,10 @@ impl crate::statement::Stmt for crate::hrana::Statement { Some(&named_param.name) } + fn column_count(&self) -> usize { + self.cols.len() + } + fn columns(&self) -> Vec { //FIXME: there are several blockers here: // 1. We cannot know the column types before sending a query, so this method will never return results right diff --git a/libsql/src/local/impls.rs b/libsql/src/local/impls.rs index 30d219fb6a..65ade9dcfe 100644 --- a/libsql/src/local/impls.rs +++ b/libsql/src/local/impls.rs @@ -145,6 +145,10 @@ impl Stmt for LibsqlStmt { self.0.parameter_name(idx) } + fn column_count(&self) -> usize { + self.0.column_count() + } + fn columns(&self) -> Vec { self.0.columns() } diff --git a/libsql/src/replication/connection.rs b/libsql/src/replication/connection.rs index 576e6179de..c9f0eac242 100644 --- a/libsql/src/replication/connection.rs +++ b/libsql/src/replication/connection.rs @@ -779,6 +779,16 @@ impl Stmt for RemoteStatement { } } + fn column_count(&self) -> usize { + if let Some(stmt) = self.local_statement.as_ref() { + return stmt.column_count(); + } + match self.metas.first() { + Some(meta) => meta.columns.len(), + None => 0, + } + } + fn columns(&self) -> Vec { if let Some(stmt) = self.local_statement.as_ref() { return stmt.columns(); diff --git a/libsql/src/statement.rs b/libsql/src/statement.rs index 25c058a7a7..fa451350e9 100644 --- a/libsql/src/statement.rs +++ b/libsql/src/statement.rs @@ -22,6 +22,8 @@ pub(crate) trait Stmt { fn parameter_name(&self, idx: i32) -> Option<&str>; + fn column_count(&self) -> usize; + fn columns(&self) -> Vec; } @@ -95,6 +97,11 @@ impl Statement { self.inner.parameter_name(idx) } + /// Fetch the number of columns for the prepared statement. + pub fn column_count(&self) -> usize { + self.inner.column_count() + } + /// Fetch the list of columns for the prepared statement. pub fn columns(&self) -> Vec { self.inner.columns() diff --git a/libsql/src/sync/statement.rs b/libsql/src/sync/statement.rs index be7c377fd1..679933298b 100644 --- a/libsql/src/sync/statement.rs +++ b/libsql/src/sync/statement.rs @@ -56,6 +56,10 @@ impl Stmt for SyncedStatement { self.inner.parameter_name(idx) } + fn column_count(&self) -> usize { + self.inner.column_count() + } + fn columns(&self) -> Vec { self.inner.columns() } From 50b84a17f932f6934f0f373da6e9ee3642b750ed Mon Sep 17 00:00:00 2001 From: Avinash Sajjanshetty Date: Tue, 20 May 2025 11:48:00 +0530 Subject: [PATCH 2/4] create a connection only if required to spawn a bg thread for background sync, we need a connection. however, we are creating a connection even if no `sync_interval` was configured. --- libsql/src/database/builder.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libsql/src/database/builder.rs b/libsql/src/database/builder.rs index a8be27598e..c31f7cadf7 100644 --- a/libsql/src/database/builder.rs +++ b/libsql/src/database/builder.rs @@ -644,11 +644,11 @@ cfg_sync! { } let mut bg_abort: Option> = None; - let conn = db.connect()?; - - let sync_ctx = db.sync_ctx.as_ref().unwrap().clone(); if let Some(sync_interval) = sync_interval { + let conn = db.connect()?; + let sync_ctx = db.sync_ctx.as_ref().unwrap().clone(); + let jh = tokio::spawn( async move { loop { From 3fc95ba597428919222ed757eb766ab7db347b3c Mon Sep 17 00:00:00 2001 From: Avinash Sajjanshetty Date: Tue, 20 May 2025 11:55:58 +0530 Subject: [PATCH 3/4] bugfix: call `bootstrap_db` before calling `connect` `bootstrap_db` calls the `export` endpoint and bootstraps the db quickly. If we call `connect` before calling `bootstrap_db`, it will create a local `.db` file and sync falls back to incremental bootstrap which is super slow --- libsql/src/database/builder.rs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/libsql/src/database/builder.rs b/libsql/src/database/builder.rs index c31f7cadf7..b8b128cb5b 100644 --- a/libsql/src/database/builder.rs +++ b/libsql/src/database/builder.rs @@ -2,9 +2,8 @@ cfg_core! { use crate::EncryptionConfig; } -use crate::{Database, Result}; - use super::DbType; +use crate::{Database, Result}; /// A builder for [`Database`]. This struct can be used to build /// all variants of [`Database`]. These variants include: @@ -646,9 +645,16 @@ cfg_sync! { let mut bg_abort: Option> = None; if let Some(sync_interval) = sync_interval { - let conn = db.connect()?; let sync_ctx = db.sync_ctx.as_ref().unwrap().clone(); + { + let mut ctx = sync_ctx.lock().await; + crate::sync::bootstrap_db(&mut ctx).await?; + } + // db.connect creates a local db file, so it is important that we always call + // `bootstrap_db` (for synced dbs) before calling connect. Otherwise, the sync + // protocol skips calling `export` endpoint causing slowdown in initial bootstrap. + let conn = db.connect()?; let jh = tokio::spawn( async move { loop { From 41eae61b6fcd45829f2231d133725484bcc4f1ae Mon Sep 17 00:00:00 2001 From: Pekka Enberg Date: Tue, 20 May 2025 10:52:25 +0300 Subject: [PATCH 4/4] 0.9.8 --- Cargo.lock | 12 ++++++------ Cargo.toml | 12 ++++++------ vendored/rusqlite/Cargo.toml | 2 +- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b292723a40..cefbbd361a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2896,7 +2896,7 @@ dependencies = [ [[package]] name = "libsql" -version = "0.9.7" +version = "0.9.8" dependencies = [ "anyhow", "async-stream", @@ -2956,7 +2956,7 @@ dependencies = [ [[package]] name = "libsql-ffi" -version = "0.9.7" +version = "0.9.8" dependencies = [ "bindgen", "cc", @@ -2966,7 +2966,7 @@ dependencies = [ [[package]] name = "libsql-hrana" -version = "0.9.7" +version = "0.9.8" dependencies = [ "base64 0.21.7", "bytes", @@ -2977,7 +2977,7 @@ dependencies = [ [[package]] name = "libsql-rusqlite" -version = "0.9.7" +version = "0.9.8" dependencies = [ "bencher", "bitflags 2.6.0", @@ -3120,7 +3120,7 @@ dependencies = [ [[package]] name = "libsql-sys" -version = "0.9.7" +version = "0.9.8" dependencies = [ "bytes", "libsql-ffi", @@ -3151,7 +3151,7 @@ dependencies = [ [[package]] name = "libsql_replication" -version = "0.9.7" +version = "0.9.8" dependencies = [ "aes", "arbitrary", diff --git a/Cargo.toml b/Cargo.toml index fd0219e0d4..ab1d3ed8c2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,18 +25,18 @@ exclude = [ ] [workspace.package] -version = "0.9.7" +version = "0.9.8" authors = ["the libSQL authors"] edition = "2021" license = "MIT" repository = "https://github.com/tursodatabase/libsql" [workspace.dependencies] -libsql-ffi = { path = "libsql-ffi", version = "0.9.7" } -libsql-sys = { path = "libsql-sys", version = "0.9.7", default-features = false } -libsql-hrana = { path = "libsql-hrana", version = "0.9.7" } -libsql_replication = { path = "libsql-replication", version = "0.9.7" } -rusqlite = { package = "libsql-rusqlite", path = "vendored/rusqlite", version = "0.9.7", default-features = false, features = [ +libsql-ffi = { path = "libsql-ffi", version = "0.9.8" } +libsql-sys = { path = "libsql-sys", version = "0.9.8", default-features = false } +libsql-hrana = { path = "libsql-hrana", version = "0.9.8" } +libsql_replication = { path = "libsql-replication", version = "0.9.8" } +rusqlite = { package = "libsql-rusqlite", path = "vendored/rusqlite", version = "0.9.8", default-features = false, features = [ "libsql-experimental", "column_decltype", "load_extension", diff --git a/vendored/rusqlite/Cargo.toml b/vendored/rusqlite/Cargo.toml index 9bf84936f3..5c4555450f 100644 --- a/vendored/rusqlite/Cargo.toml +++ b/vendored/rusqlite/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "libsql-rusqlite" # Note: Update version in README.md when you change this. -version = "0.9.7" +version = "0.9.8" authors = ["The rusqlite developers"] edition = "2018" description = "Ergonomic wrapper for SQLite (libsql fork)"