borogove

created pr with borogove/sqlite-injectable-driver.1 on 2026-11-09T19:46:34Z · by 3c31bc8c
commented on 2026-11-09T19:46:34Z · by 3c31bc8c
Changes are available at https://tangled.org/mrry.band/borogove on branch sqlite-injectable-driver.
added borogove/sqlite-injectable-driver.2 on 2026-11-09T20:05:07Z · by 3c31bc8c
1: 981fe7d = 1: 981fe7d Use arrays
2: ef9e639 = 2: ef9e639 Make prepare public, remove formatParam and first
3: f949361 ! 3: a97c836 Allow injectable drivers for Sqlite
commented on 2026-11-09T20:49:02Z · by 9e834e0d
browser tests dont pass
added borogove/sqlite-injectable-driver.3 on 2026-11-09T21:28:45Z · by 3c31bc8c
1: 981fe7d = 1: 981fe7d Use arrays
2: ef9e639 ! 2: 11eb826 Make prepare public, remove formatParam and first
3: a97c836 ! 3: 34cee7d Allow injectable drivers for Sqlite
cmds
checkout latest patchset:
ssh pr.pico.sh pull borogove:sqlite-injectable-driver | git am -3
checkout specific patchset revision:
ssh pr.pico.sh pull borogove:sqlite-injectable-driver [rev] | git am -3
add changes to patch request:
git format-patch main --stdout | ssh pr.pico.sh borogove:sqlite-injectable-driver
add comment to patch request:
ssh pr.pico.sh comment borogove:sqlite-injectable-driver "lgtm!"

Patchset borogove/sqlite-injectable-driver.3 on 2026-11-09T21:28:45Z · commit 34cee7d

Allow injectable drivers for Sqlite
Eric Roberts 2026-11-09T19:41:16Z
In Tauri I want to use https://v2.tauri.app/plugin/sql/ so we can put
the db on the filesystem. To do that I need to be able to pass in a
custom driver in borogove. This does that.
Semantic diff summary
0 added, 0 modified, 0 signature changed, 0 removed across 0 analyzed files (2 files skipped: unsupported file type)
+24 -3 borogove/persistence/Sqlite.hx #
......@@ -34,13 +34,25 @@ typedef InsertColumn = {
3434 value:(ChatMessage)->Dynamic
3535 }
3636
37+@:expose
38+typedef SqliteDriverInterface = {
39+ function exec(sql: String, ?params: Array<Dynamic>): Promise<Array<Dynamic>>;
40+ function execMany(qs: Array<{ sql: String, ?params: Array<Dynamic> }>): Promise<Array<Dynamic>>;
41+}
42+
43+typedef SqliteDriverFactory = (String, (Array<String>->Promise<Array<Dynamic>>)->Promise<Any>)->SqliteDriverInterface;
44+
3745 @:expose
3846 #if cpp
3947 @:build(HaxeCBridge.expose())
4048 @:build(HaxeSwiftBridge.expose())
4149 #end
4250 class Sqlite implements Persistence implements KeyValueStore {
51+ #if js
52+ final db: SqliteDriverInterface;
53+ #else
4354 final db: SqliteDriver;
55+ #end
4456 final media: MediaStore;
4557 final storeMessagesSerialized = new AsyncLock();
4658
......@@ -85,10 +97,14 @@ class Sqlite implements Persistence implements KeyValueStore {
8597 @param media a MediaStore to use for media
8698 @returns new persistence layer
8799 **/
88- public function new(dbfile: String, media: MediaStore) {
100+ public function new(
101+ dbfile: String,
102+ media: MediaStore,
103+ #if js ?driver: SqliteDriverFactory, #end
104+ ) {
89105 this.media = media;
90106 media.setKV(this);
91- db = new SqliteDriver(dbfile, (exec) -> {
107+ final migrate = (exec: Array<String>->Promise<Array<Dynamic>>) -> {
92108 exec(["PRAGMA user_version"]).then(rows -> {
93109 final version = Std.parseInt(rows[0]?.user_version) ?? 0;
94110 return Promise.resolve(null).then(_ -> {
......@@ -387,7 +403,12 @@ class Sqlite implements Persistence implements KeyValueStore {
387403 return Promise.resolve(null);
388404 });
389405 });
390- });
406+ };
407+ #if js
408+ db = driver == null ? new SqliteDriver(dbfile, migrate) : driver(dbfile, migrate);
409+ #else
410+ db = new SqliteDriver(dbfile, migrate);
411+ #end
391412 }
392413
393414 @HaxeCBridge.noemit
+29 -0 test/TestSqlite.hx #
......@@ -104,6 +104,35 @@ class TestSqlite extends utest.Test {
104104 mediaStore = new MockMediaStore();
105105 persistence = new Sqlite("file:" + ID.unique() + "?mode=memory&cache=shared", mediaStore);
106106 }
107+ #if js
108+ public function testInjectedDriver(async: Async) {
109+ var migrated = Promise.resolve(null);
110+ var migrationQueries: Array<String> = [];
111+ final injected = new Sqlite("injected.sqlite3", mediaStore, (file, migrate) -> {
112+ Assert.equals("injected.sqlite3", file);
113+ migrated = migrate(sql -> {
114+ migrationQueries = migrationQueries.concat(sql);
115+ return Promise.resolve([{ user_version: 24 }]);
116+ });
117+ return {
118+ exec: (sql: String, ?params: Array<Dynamic>) -> {
119+ Assert.equals("SELECT v FROM keyvaluepairs WHERE k=? LIMIT 1", sql);
120+ Assert.equals("key", params[0]);
121+ return Promise.resolve([{ v: "injected value" }]);
122+ },
123+ execMany: qs -> Promise.resolve([])
124+ };
125+ });
126+ migrated.then(_ -> injected.get("key")).then(value -> {
127+ Assert.same(["PRAGMA user_version"], migrationQueries);
128+ Assert.equals("injected value", value);
129+ async.done();
130+ }).catchError(e -> {
131+ Assert.fail(Std.string(e));
132+ async.done();
133+ });
134+ }
135+ #end
107136
108137 public function testOrder(async: Async) {
109138 final account = "alice@example.com";
Back to top