Skip to content

Commit 1ba8443

Browse files
committed
Update rusqlite to v0.38 and vendor serde-rusqlite.
1 parent 54115a9 commit 1ba8443

File tree

9 files changed

+96
-71
lines changed

9 files changed

+96
-71
lines changed

.gitmodules

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,6 @@
44
[submodule "vendor/sqlite-vec"]
55
path = vendor/sqlite-vec
66
url = https://github.com/ignatz/sqlite-vec.git
7+
[submodule "vendor/serde_rusqlite"]
8+
path = vendor/serde_rusqlite
9+
url = https://github.com/ignatz/serde_rusqlite.git

Cargo.lock

Lines changed: 25 additions & 11 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,15 +76,16 @@ askama = { version = "0.15.1", default-features = false, features = ["derive", "
7676
axum = { version = "^0.8.1", features = ["multipart"] }
7777
base64 = { version = "0.22.1", default-features = false, features = ["alloc", "std"] }
7878
env_logger = { version = "^0.11.8", default-features = false, features = ["auto-color", "humantime"] }
79-
libsqlite3-sys = { version = "0.35.0", default-features = false, features = ["bundled", "preupdate_hook"] }
79+
libsqlite3-sys = { version = "0.36.0", default-features = false, features = ["bundled", "preupdate_hook"] }
8080
minijinja = { version = "2.1.2", default-features = false }
8181
parking_lot = { version = "0.12.3", default-features = false, features = ["send_guard", "arc_lock"] }
8282
rand = { version = "^0.9.0" }
8383
reqwest = { version = "0.12.8", default-features = false, features = ["rustls-tls", "json"] }
84-
rusqlite = { version = "0.37.0", default-features = false, features = ["bundled", "column_decltype", "functions", "backup", "preupdate_hook"] }
84+
rusqlite = { version = "0.38.0", default-features = false, features = ["bundled", "cache", "column_decltype", "functions", "backup", "preupdate_hook"] }
8585
rust-embed = { version = "8.4.0", default-features = false, features = ["mime-guess"] }
8686
serde = { version = "^1.0.203", features = ["derive"] }
8787
serde_json = { version = "^1.0.117" }
88+
serde_rusqlite = { path = "vendor/serde_rusqlite" }
8889
sqlite-vec = { path = "vendor/sqlite-vec/bindings/rust", default-features = false }
8990
tokio = { version = "^1.38.0", default-features = false, features = ["macros", "net", "rt-multi-thread", "fs", "signal", "time", "sync"] }
9091
tracing = { version = "0.1.40", default-features = false }

crates/core/src/logging.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -421,7 +421,7 @@ struct LogFieldStorage {
421421
version: HttpVersion,
422422

423423
// Response fields/properties
424-
status: u64,
424+
status: i64,
425425
latency_ms: f64,
426426
length: i64,
427427

@@ -452,7 +452,7 @@ struct JsonLog {
452452
client_ip: Option<String>,
453453

454454
// HTTP response status code.
455-
status: u64,
455+
status: i64,
456456
// latency in milliseconds with fractional microseconds.
457457
latency_ms: f64,
458458
}
@@ -490,6 +490,7 @@ impl tracing::field::Visit for LogVisitor<'_> {
490490
fn record_i64(&mut self, field: &Field, int: i64) {
491491
match field.name() {
492492
"length" => self.0.length = int,
493+
"status" => self.0.status = int,
493494
name => {
494495
self.0.fields.insert(name.into(), int.into());
495496
}
@@ -498,7 +499,7 @@ impl tracing::field::Visit for LogVisitor<'_> {
498499

499500
fn record_u64(&mut self, field: &Field, uint: u64) {
500501
match field.name() {
501-
"status" => self.0.status = uint,
502+
"status" => self.0.status = uint as i64,
502503
name => {
503504
self.0.fields.insert(name.into(), uint.into());
504505
}

crates/core/src/records/create_record.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -423,7 +423,7 @@ mod test {
423423

424424
{
425425
// Bulk inserts are rolled back in a transaction is second insert fails.
426-
let count_before: usize = state
426+
let count_before: i64 = state
427427
.conn()
428428
.read_query_row_f("SELECT COUNT(*) FROM message", (), |row| row.get(0))
429429
.await
@@ -449,12 +449,13 @@ mod test {
449449
.await;
450450
assert!(response.is_err(), "{response:?}");
451451

452-
let count_after: usize = state
452+
let count_after: i64 = state
453453
.conn()
454454
.read_query_row_f("SELECT COUNT(*) FROM message", (), |row| row.get(0))
455455
.await
456456
.unwrap()
457457
.unwrap();
458+
458459
assert_eq!(count_before, count_after);
459460
}
460461

crates/core/src/records/subscribe.rs

Lines changed: 55 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ impl PerConnectionState {
213213
lock.remove(&id.table_name);
214214

215215
if lock.is_empty() {
216-
conn.preupdate_hook(NO_HOOK);
216+
conn.preupdate_hook(NO_HOOK).expect("owned conn");
217217
}
218218
}
219219
});
@@ -224,59 +224,63 @@ impl PerConnectionState {
224224
let conn = api.conn().clone();
225225
let state = self.clone();
226226

227-
api.conn().write_lock().preupdate_hook(Some(
228-
move |action: Action, db: &str, table_name: &str, case: &PreUpdateCase| {
229-
let action: RecordAction = match action {
230-
Action::SQLITE_UPDATE | Action::SQLITE_INSERT | Action::SQLITE_DELETE => action.into(),
231-
a => {
232-
error!("Unknown action: {a:?}");
227+
api
228+
.conn()
229+
.write_lock()
230+
.preupdate_hook(Some(
231+
move |action: Action, db: &str, table_name: &str, case: &PreUpdateCase| {
232+
let action: RecordAction = match action {
233+
Action::SQLITE_UPDATE | Action::SQLITE_INSERT | Action::SQLITE_DELETE => action.into(),
234+
a => {
235+
error!("Unknown action: {a:?}");
236+
return;
237+
}
238+
};
239+
240+
let Some(rowid) = extract_row_id(case) else {
241+
error!("Failed to extract row id");
233242
return;
234-
}
235-
};
243+
};
236244

237-
let Some(rowid) = extract_row_id(case) else {
238-
error!("Failed to extract row id");
239-
return;
240-
};
245+
let qualified_table_name = QualifiedName {
246+
name: table_name.to_string(),
247+
database_schema: Some(db.to_string()),
248+
};
241249

242-
let qualified_table_name = QualifiedName {
243-
name: table_name.to_string(),
244-
database_schema: Some(db.to_string()),
245-
};
250+
// If there are no matching subscriptions, skip.
251+
{
252+
let lock = state.subscriptions.read();
253+
let Some(subscriptions) = lock.get(&qualified_table_name).map(|r| r.read()) else {
254+
return;
255+
};
246256

247-
// If there are no matching subscriptions, skip.
248-
{
249-
let lock = state.subscriptions.read();
250-
let Some(subscriptions) = lock.get(&qualified_table_name).map(|r| r.read()) else {
251-
return;
252-
};
257+
if subscriptions.table.is_empty() && !subscriptions.record.contains_key(&rowid) {
258+
return;
259+
}
260+
}
253261

254-
if subscriptions.table.is_empty() && !subscriptions.record.contains_key(&rowid) {
262+
let Some(record_values) = extract_record_values(case) else {
263+
error!("Failed to extract values");
255264
return;
256-
}
257-
}
265+
};
258266

259-
let Some(record_values) = extract_record_values(case) else {
260-
error!("Failed to extract values");
261-
return;
262-
};
267+
let s = ContinuationState {
268+
state: state.clone(),
269+
table_name: qualified_table_name,
270+
action,
271+
rowid,
272+
record_values,
273+
};
263274

264-
let s = ContinuationState {
265-
state: state.clone(),
266-
table_name: qualified_table_name,
267-
action,
268-
rowid,
269-
record_values,
270-
};
271-
272-
// TODO: Optimization: in cases where there's only table-level access restrictions, we
273-
// could avoid the continuation and even dispatch the subscription handling to a
274-
// different thread entirely to take more work off the SQLite thread.
275-
conn.call_and_forget(move |conn| {
276-
hook_continuation(conn, s);
277-
});
278-
},
279-
));
275+
// TODO: Optimization: in cases where there's only table-level access restrictions, we
276+
// could avoid the continuation and even dispatch the subscription handling to a
277+
// different thread entirely to take more work off the SQLite thread.
278+
conn.call_and_forget(move |conn| {
279+
hook_continuation(conn, s);
280+
});
281+
},
282+
))
283+
.expect("owned conn");
280284
}
281285

282286
async fn add_record_subscription(
@@ -408,9 +412,9 @@ impl PerConnectionState {
408412
impl Drop for PerConnectionState {
409413
fn drop(&mut self) {
410414
if let Some(first) = self.record_apis.read().values().nth(0) {
411-
first
412-
.conn()
413-
.call_and_forget(|conn| conn.preupdate_hook(NO_HOOK));
415+
first.conn().call_and_forget(|conn| {
416+
conn.preupdate_hook(NO_HOOK).expect("owned conn");
417+
});
414418
}
415419
}
416420
}
@@ -643,7 +647,7 @@ fn hook_continuation(conn: &rusqlite::Connection, s: ContinuationState) {
643647
let mut subscriptions = state.subscriptions.write();
644648
subscriptions.remove(&table_name);
645649
if subscriptions.is_empty() {
646-
conn.preupdate_hook(NO_HOOK);
650+
conn.preupdate_hook(NO_HOOK).expect("owned conn");
647651
}
648652

649653
return;
@@ -753,7 +757,7 @@ fn hook_continuation(conn: &rusqlite::Connection, s: ContinuationState) {
753757
if lock.get(&table_name).is_some_and(|e| e.read().is_empty()) {
754758
lock.remove(&table_name);
755759
if lock.is_empty() {
756-
conn.preupdate_hook(NO_HOOK);
760+
conn.preupdate_hook(NO_HOOK).expect("owned conn");
757761
}
758762
}
759763
});

crates/sqlite/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ log = { version = "^0.4.21", default-features = false }
2020
parking_lot = { workspace = true }
2121
rusqlite = { workspace = true }
2222
serde = { workspace = true }
23-
serde_rusqlite = "0.40"
23+
serde_rusqlite = { workspace = true }
2424
thiserror = "2.0.12"
2525
tokio = { workspace = true }
2626

vendor/serde_rusqlite

Submodule serde_rusqlite added at ec15ec4

vendor/sqlite-vec

0 commit comments

Comments
 (0)