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.1 on 2026-11-09T19:46:34Z · commit f949361

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)
+18 -4 borogove/persistence/Sqlite.hx #
......@@ -34,13 +34,21 @@ typedef InsertColumn = {
3434 value:(ChatMessage)->Dynamic
3535 }
3636
37+@:expose
38+typedef SqliteConnection = {
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>)->SqliteConnection;
44+
3745 @:expose
3846 #if cpp
3947 @:build(HaxeCBridge.expose())
4048 @:build(HaxeSwiftBridge.expose())
4149 #end
4250 class Sqlite implements Persistence implements KeyValueStore {
43- final db: SqliteDriver;
51+ final db: SqliteConnection;
4452 final media: MediaStore;
4553 final storeMessagesSerialized = new AsyncLock();
4654
......@@ -83,12 +91,13 @@ class Sqlite implements Persistence implements KeyValueStore {
8391
8492 @param dbfile path to sqlite database
8593 @param media a MediaStore to use for media
94+ @param driver optional JavaScript driver factory; defaults to the built-in SQLite driver
8695 @returns new persistence layer
8796 **/
88- public function new(dbfile: String, media: MediaStore) {
97+ public function new(dbfile: String, media: MediaStore #if js , ?driver: SqliteDriverFactory #end) {
8998 this.media = media;
9099 media.setKV(this);
91- db = new SqliteDriver(dbfile, (exec) -> {
100+ final migrate = (exec: Array<String>->Promise<Array<Dynamic>>) -> {
92101 exec(["PRAGMA user_version"]).then(rows -> {
93102 final version = Std.parseInt(rows[0]?.user_version) ?? 0;
94103 return Promise.resolve(null).then(_ -> {
......@@ -387,7 +396,12 @@ class Sqlite implements Persistence implements KeyValueStore {
387396 return Promise.resolve(null);
388397 });
389398 });
390- });
399+ };
400+ #if js
401+ db = driver == null ? new SqliteDriver(dbfile, migrate) : driver(dbfile, migrate);
402+ #else
403+ db = new SqliteDriver(dbfile, migrate);
404+ #end
391405 }
392406
393407 @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