borogove
created pr with
borogove/sqlite-injectable-driver.1
commented
Changes are available at https://tangled.org/mrry.band/borogove on branch sqlite-injectable-driver.
added borogove/sqlite-injectable-driver.2
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
browser tests dont pass
added borogove/sqlite-injectable-driver.3
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 -3checkout specific patchset revision:
ssh pr.pico.sh pull borogove:sqlite-injectable-driver [rev] | git am -3add changes to patch request:
git format-patch main --stdout | ssh pr.pico.sh borogove:sqlite-injectable-driveradd comment to patch request:
ssh pr.pico.sh comment borogove:sqlite-injectable-driver "lgtm!"
Patchset
borogove/sqlite-injectable-driver.2
Use arrays
Eric Roberts
2026-11-09T19:27:25ZWe are not getting any benefit out of using iterators, and only pain and suffering. Trying to write an injectable driver for the tauri app to use, and I don't want to have to have it send in something that acts like an iterator when we just have arrays.
Semantic diff summary
0 added,
0 modified,
0 signature changed,
0 removed
across 0 analyzed files
(4 files skipped: unsupported file type)
+19
-21
borogove/persistence/Sqlite.hx
#
| ... | ... | @@ -90,8 +90,8 @@ class Sqlite implements Persistence implements KeyValueStore { | |
| 90 | 90 | this.media = media; | |
| 91 | 91 | media.setKV(this); | |
| 92 | 92 | db = new SqliteDriver(dbfile, (exec) -> { | |
| 93 | - | exec(["PRAGMA user_version"]).then(iter -> { | |
| 94 | - | final version = Std.parseInt(iter.next()?.user_version) ?? 0; | |
| 93 | + | exec(["PRAGMA user_version"]).then(rows -> { | |
| 94 | + | final version = Std.parseInt(rows[0]?.user_version) ?? 0; | |
| 95 | 95 | return Promise.resolve(null).then(_ -> { | |
| 96 | 96 | if (version < 1) { | |
| 97 | 97 | return exec(["CREATE TABLE messages ( |
| ... | ... | @@ -644,7 +644,7 @@ class Sqlite implements Persistence implements KeyValueStore { | |
| 644 | 644 | "SELECT member_id, display_name, photo_uri, is_self, chat, json(roles) AS roles, json(presence) AS presence, jid FROM members WHERE account_id=? AND member_id=? LIMIT 1", | |
| 645 | 645 | [accountId, update.id] | |
| 646 | 646 | ).then(rows -> | |
| 647 | - | return rows.hasNext() ? rows.next() : null | |
| 647 | + | return rows[0] | |
| 648 | 648 | )).then(existing -> { | |
| 649 | 649 | if (existing != null || update.jid == null) return Promise.resolve(existing); | |
| 650 | 650 |
| ... | ... | @@ -652,7 +652,7 @@ class Sqlite implements Persistence implements KeyValueStore { | |
| 652 | 652 | "SELECT member_id, display_name, photo_uri, is_self, chat, json(roles) AS roles, json(presence) AS presence, jid FROM members WHERE account_id=? AND chat_id=? AND jid=? LIMIT 1", | |
| 653 | 653 | [accountId, chat.chatId, update.jid.asString()] | |
| 654 | 654 | ).then(rows -> | |
| 655 | - | return rows.hasNext() ? rows.next() : null | |
| 655 | + | return rows[0] | |
| 656 | 656 | ); | |
| 657 | 657 | }).then(existing -> { | |
| 658 | 658 | final member = hydrateStoredMember(chat, existing); |
| ... | ... | @@ -801,8 +801,7 @@ class Sqlite implements Persistence implements KeyValueStore { | |
| 801 | 801 | return db.exec( | |
| 802 | 802 | "SELECT chat_id, trusted, bookmarked, avatar_sha1, fn, ui_state, blocked, extensions, read_up_to_id, read_up_to_by, notifications_filtered, notify_mention, notify_reply, json(caps) AS caps, caps_ver, json(meta) AS meta, class FROM chats LEFT JOIN caps ON chats.caps_ver=caps.sha1 WHERE account_id=?", | |
| 803 | 803 | [accountId] | |
| 804 | - | ).then(result -> { | |
| 805 | - | final rows = { iterator: () -> result }.array(); | |
| 804 | + | ).then(rows -> { | |
| 806 | 805 | return chatPresenceAndMembersForName(accountId, rows).then(chatData -> { | |
| 807 | 806 | final chats: Array<SerializedChat> = []; | |
| 808 | 807 | for (row in rows) { |
| ... | ... | @@ -896,9 +895,9 @@ class Sqlite implements Persistence implements KeyValueStore { | |
| 896 | 895 | } | |
| 897 | 896 | q += " GROUP BY correction_id, CASE WHEN messages.type=? THEN 'call' ELSE messages.sender_id END"; | |
| 898 | 897 | return db.exec(q, params).then(results -> { | |
| 899 | - | final row = results.next(); | |
| 898 | + | final row = results[0]; | |
| 900 | 899 | if (row == null) return stub; | |
| 901 | - | return hydrateMessages(accountId, [row].iterator())[0]; | |
| 900 | + | return hydrateMessages(accountId, [row])[0]; | |
| 902 | 901 | }); | |
| 903 | 902 | } | |
| 904 | 903 |
| ... | ... | @@ -1082,8 +1081,8 @@ class Sqlite implements Persistence implements KeyValueStore { | |
| 1082 | 1081 | ', | |
| 1083 | 1082 | [accountId, chat.chatId, MessageChannelPrivate, chat.readUpToId, MessageSent, accountId, chat.chatId, MessageChannelPrivate] | |
| 1084 | 1083 | ).then(result -> { | |
| 1085 | - | final row: Dynamic = result.next(); | |
| 1086 | - | final lastMessage = row.stanza == null ? [] : hydrateMessages(accountId, [row].iterator()); | |
| 1084 | + | final row: Dynamic = result[0]; | |
| 1085 | + | final lastMessage = row.stanza == null ? [] : hydrateMessages(accountId, [row]); | |
| 1087 | 1086 | return { unreadCount: row.unreadCount, chatId: chat.chatId, message: lastMessage[0] }; | |
| 1088 | 1087 | }); | |
| 1089 | 1088 | } |
| ... | ... | @@ -1266,7 +1265,7 @@ class Sqlite implements Persistence implements KeyValueStore { | |
| 1266 | 1265 | @HaxeCBridge.noemit | |
| 1267 | 1266 | public function listAccounts(): Promise<Array<String>> { | |
| 1268 | 1267 | return db.exec("SELECT account_id FROM accounts").then(result -> | |
| 1269 | - | result == null ? [] : { iterator: () -> result }.map(row -> row.account_id) | |
| 1268 | + | result == null ? [] : result.map(row -> row.account_id) | |
| 1270 | 1269 | ); | |
| 1271 | 1270 | } | |
| 1272 | 1271 |
| ... | ... | @@ -1440,13 +1439,12 @@ class Sqlite implements Persistence implements KeyValueStore { | |
| 1440 | 1439 | params = params.concat(stanzaIds); | |
| 1441 | 1440 | } | |
| 1442 | 1441 | db.exec(q.join(" UNION ALL "), params); | |
| 1443 | - | }).then(iter -> { | |
| 1444 | - | if (iter != null) { | |
| 1445 | - | final parents = { iterator: () -> iter }.array(); | |
| 1442 | + | }).then(parents -> { | |
| 1443 | + | if (parents != null) { | |
| 1446 | 1444 | for (message in messages) { | |
| 1447 | 1445 | if (message.replyToMessage != null) { | |
| 1448 | - | final found: Dynamic = Util.findFast(parents, p -> p.chat_id == message.chatId() && (message.replyToMessage.serverId == null || p.mam_id == message.replyToMessage.serverId) && (message.replyToMessage.localId == null || p.stanza_id == message.replyToMessage.localId)); | |
| 1449 | - | if (found != null) message.set_replyToMessage(hydrateMessages(accountId, [found].iterator())[0]); | |
| 1446 | + | final found: Dynamic = Util.findFast(parents, (p: Dynamic) -> p.chat_id == message.chatId() && (message.replyToMessage.serverId == null || p.mam_id == message.replyToMessage.serverId) && (message.replyToMessage.localId == null || p.stanza_id == message.replyToMessage.localId)); | |
| 1447 | + | if (found != null) message.set_replyToMessage(hydrateMessages(accountId, [found])[0]); | |
| 1450 | 1448 | } | |
| 1451 | 1449 | } | |
| 1452 | 1450 | } |
| ... | ... | @@ -1474,7 +1472,7 @@ class Sqlite implements Persistence implements KeyValueStore { | |
| 1474 | 1472 | ||
| 1475 | 1473 | private function hydrateMessagesAndLoadMeta( | |
| 1476 | 1474 | accountId: String, | |
| 1477 | - | rows: Iterator<{ | |
| 1475 | + | rows: Iterable<{ | |
| 1478 | 1476 | stanza: String, | |
| 1479 | 1477 | time_sent: String, | |
| 1480 | 1478 | time_received: String, |
| ... | ... | @@ -1514,7 +1512,7 @@ class Sqlite implements Persistence implements KeyValueStore { | |
| 1514 | 1512 | ||
| 1515 | 1513 | private function hydrateMessages( | |
| 1516 | 1514 | accountId: String, | |
| 1517 | - | rows: Iterator<{ | |
| 1515 | + | rows: Iterable<{ | |
| 1518 | 1516 | stanza: String, | |
| 1519 | 1517 | time_sent: String, | |
| 1520 | 1518 | time_received: String, |
| ... | ... | @@ -1535,7 +1533,7 @@ class Sqlite implements Persistence implements KeyValueStore { | |
| 1535 | 1533 | ): Array<ChatMessage> { | |
| 1536 | 1534 | // TODO: Calls can "edit" from multiple senders, but the original direction and sender holds | |
| 1537 | 1535 | final accountJid = JID.parse(accountId); | |
| 1538 | - | return { iterator: () -> rows }.map(row -> ChatMessage.fromStanza(Stanza.parse(row.stanza), accountJid, (builder, _) -> { | |
| 1536 | + | return Lambda.map(rows, row -> ChatMessage.fromStanza(Stanza.parse(row.stanza), accountJid, (builder, _) -> { | |
| 1539 | 1537 | builder.syncPoint = row.sync_point != 0; | |
| 1540 | 1538 | builder.timeSent = row.time_sent; | |
| 1541 | 1539 | builder.timeReceived = row.time_received; |
| ... | ... | @@ -1640,7 +1638,7 @@ class Sqlite implements Persistence implements KeyValueStore { | |
| 1640 | 1638 | "SELECT device_id FROM omemo_devices WHERE identifier=?", | |
| 1641 | 1639 | [identifier], | |
| 1642 | 1640 | ).then(result -> { | |
| 1643 | - | return { iterator: () -> result }.map(row -> row.device_id).array(); | |
| 1641 | + | return result.map(row -> row.device_id); | |
| 1644 | 1642 | }); | |
| 1645 | 1643 | } | |
| 1646 | 1644 |
| ... | ... | @@ -1730,7 +1728,7 @@ class Sqlite implements Persistence implements KeyValueStore { | |
| 1730 | 1728 | return db.exec( | |
| 1731 | 1729 | "SELECT key_id, private_key, public_key FROM omemo_prekeys WHERE account_id=? ORDER BY key_id", | |
| 1732 | 1730 | [login], | |
| 1733 | - | ).then(result -> { iterator: () -> result }.map(row -> ({ | |
| 1731 | + | ).then(result -> result.map(row -> ({ | |
| 1734 | 1732 | keyId: row.key_id, | |
| 1735 | 1733 | keyPair: { | |
| 1736 | 1734 | privKey: row.private_key, |
+2
-2
borogove/persistence/SqliteDriver.hx
#
| ... | ... | @@ -14,7 +14,7 @@ class SqliteDriver { | |
| 14 | 14 | private var setReady: (Bool)->Void; | |
| 15 | 15 | private var setFailed: (Dynamic)->Void; | |
| 16 | 16 | ||
| 17 | - | public function new(dbfile: String, migrate: (Array<String>->Promise<haxe.iterators.ArrayIterator<Dynamic>>)->Promise<Any>) { | |
| 17 | + | public function new(dbfile: String, migrate: (Array<String>->Promise<Array<Dynamic>>)->Promise<Any>) { | |
| 18 | 18 | this.dbfile = dbfile; | |
| 19 | 19 | readPool = Config.constrainedMemoryMode ? writePool : new sys.thread.ElasticThreadPool(10); | |
| 20 | 20 | ready = new Promise((resolve, reject) -> { |
+8
-8
borogove/persistence/SqliteDriver.js.hx
#
| ... | ... | @@ -69,7 +69,7 @@ class SqliteDriver { | |
| 69 | 69 | return worker; | |
| 70 | 70 | } | |
| 71 | 71 | ||
| 72 | - | public function new(dbfile: String, migrate: (Array<String>->Promise<haxe.iterators.ArrayIterator<Dynamic>>)->Promise<Any>) { | |
| 72 | + | public function new(dbfile: String, migrate: (Array<String>->Promise<Array<Dynamic>>)->Promise<Any>) { | |
| 73 | 73 | ready = new Promise((resolve, reject) -> setReady = resolve); | |
| 74 | 74 | ||
| 75 | 75 | writePool.push(mkWorker(dbfile, true)); |
| ... | ... | @@ -86,7 +86,7 @@ class SqliteDriver { | |
| 86 | 86 | }); | |
| 87 | 87 | } | |
| 88 | 88 | ||
| 89 | - | private function execute(pool: Array<Worker>, qs: Array<{ sql: String, ?params: Array<Dynamic> }>): Promise<haxe.iterators.ArrayIterator<Dynamic>> { | |
| 89 | + | private function execute(pool: Array<Worker>, qs: Array<{ sql: String, ?params: Array<Dynamic> }>): Promise<Array<Dynamic>> { | |
| 90 | 90 | final worker = pool.pop(); | |
| 91 | 91 | if (worker == null) { | |
| 92 | 92 | return new Promise((resolve, reject) -> haxe.Timer.delay(() -> resolve(null), 10)).then(_ -> |
| ... | ... | @@ -98,11 +98,11 @@ class SqliteDriver { | |
| 98 | 98 | worker.postMessage({ id: id, qs: qs.map(q -> Sqlite.prepare(q)) }); | |
| 99 | 99 | return promise.then(result -> { | |
| 100 | 100 | pool.push(worker); | |
| 101 | - | return result.iterator(); | |
| 101 | + | return result; | |
| 102 | 102 | }); | |
| 103 | 103 | } | |
| 104 | 104 | ||
| 105 | - | public function execMany(qs: Array<{ sql: String, ?params: Array<Dynamic> }>): Promise<haxe.iterators.ArrayIterator<Dynamic>> { | |
| 105 | + | public function execMany(qs: Array<{ sql: String, ?params: Array<Dynamic> }>): Promise<Array<Dynamic>> { | |
| 106 | 106 | return ready.then(_ -> { | |
| 107 | 107 | final pool = StringTools.startsWith(qs[0].sql, "SELECT") ? readPool : writePool; | |
| 108 | 108 | return execute(pool, qs); |
| ... | ... | @@ -126,7 +126,7 @@ class SqliteDriver { | |
| 126 | 126 | private final ready: Promise<Bool>; | |
| 127 | 127 | private var setReady: (Bool)->Void; | |
| 128 | 128 | ||
| 129 | - | public function new(dbfile: String, migrate: (Array<String>->Promise<haxe.iterators.ArrayIterator<Dynamic>>)->Promise<Any>) { | |
| 129 | + | public function new(dbfile: String, migrate: (Array<String>->Promise<Array<Dynamic>>)->Promise<Any>) { | |
| 130 | 130 | ready = new Promise((resolve, reject) -> setReady = resolve); | |
| 131 | 131 | Worker1.v2({ | |
| 132 | 132 | worker: () -> new js.html.Worker( |
| ... | ... | @@ -144,7 +144,7 @@ class SqliteDriver { | |
| 144 | 144 | }); | |
| 145 | 145 | } | |
| 146 | 146 | ||
| 147 | - | private function execute(qs: Array<{ sql: String, ?params: Array<Dynamic> }>): Promise<haxe.iterators.ArrayIterator<Dynamic>> { | |
| 147 | + | private function execute(qs: Array<{ sql: String, ?params: Array<Dynamic> }>): Promise<Array<Dynamic>> { | |
| 148 | 148 | final first = qs.shift(); | |
| 149 | 149 | final sql = qs.map(q -> Sqlite.prepare(q) + ";"); | |
| 150 | 150 | final items: Array<Dynamic> = []; |
| ... | ... | @@ -167,10 +167,10 @@ class SqliteDriver { | |
| 167 | 167 | } | |
| 168 | 168 | null; | |
| 169 | 169 | } | |
| 170 | - | }).then(_ -> allDone).then(_ -> items.iterator()); | |
| 170 | + | }).then(_ -> allDone).then(_ -> items); | |
| 171 | 171 | } | |
| 172 | 172 | ||
| 173 | - | public function execMany(qs: Array<{ sql: String, ?params: Array<Dynamic> }>): Promise<haxe.iterators.ArrayIterator<Dynamic>> { | |
| 173 | + | public function execMany(qs: Array<{ sql: String, ?params: Array<Dynamic> }>): Promise<Array<Dynamic>> { | |
| 174 | 174 | return ready.then(_ -> execute(qs)); | |
| 175 | 175 | } | |
| 176 | 176 |
+5
-5
test/TestSqlite.hx
#
| ... | ... | @@ -607,7 +607,7 @@ class TestSqlite extends utest.Test { | |
| 607 | 607 | persistence.storeMessages(account, [correctable]).then(_ -> { | |
| 608 | 608 | return persistence.db.exec("SELECT correction_id FROM messages WHERE mam_id=?", [version.serverId]); | |
| 609 | 609 | }).then(rows -> { | |
| 610 | - | final row = rows.next(); | |
| 610 | + | final row = rows[0]; | |
| 611 | 611 | Assert.equals("call-sid", row.correction_id); | |
| 612 | 612 | async.done(); | |
| 613 | 613 | }).catchError(e -> { |
| ... | ... | @@ -638,7 +638,7 @@ class TestSqlite extends utest.Test { | |
| 638 | 638 | persistence.storeMessages(account, [correctable]).then(_ -> { | |
| 639 | 639 | return persistence.db.exec("SELECT sync_point, chat_id, sender_id FROM messages WHERE mam_id=?", [version.serverId]); | |
| 640 | 640 | }).then(rows -> { | |
| 641 | - | final row = rows.next(); | |
| 641 | + | final row = rows[0]; | |
| 642 | 642 | Assert.equals(1, row.sync_point); | |
| 643 | 643 | Assert.equals("correctable-chat@example.com", row.chat_id); | |
| 644 | 644 | Assert.equals("correctable@example.com", row.sender_id); |
| ... | ... | @@ -666,7 +666,7 @@ class TestSqlite extends utest.Test { | |
| 666 | 666 | persistence.storeMessages(account, [correctable]).then(_ -> { | |
| 667 | 667 | return persistence.db.exec("SELECT correction_id FROM messages WHERE mam_id=?", [version.serverId]); | |
| 668 | 668 | }).then(rows -> { | |
| 669 | - | Assert.equals("correctable-local-local", rows.next().correction_id); | |
| 669 | + | Assert.equals("correctable-local-local", rows[0].correction_id); | |
| 670 | 670 | async.done(); | |
| 671 | 671 | }).catchError(e -> { | |
| 672 | 672 | Assert.fail(Std.string(e)); |
| ... | ... | @@ -690,7 +690,7 @@ class TestSqlite extends utest.Test { | |
| 690 | 690 | persistence.storeMessages(account, [correctable]).then(_ -> { | |
| 691 | 691 | return persistence.db.exec("SELECT correction_id FROM messages WHERE mam_id=?", [version.serverId]); | |
| 692 | 692 | }).then(rows -> { | |
| 693 | - | Assert.equals("correctable-server-server", rows.next().correction_id); | |
| 693 | + | Assert.equals("correctable-server-server", rows[0].correction_id); | |
| 694 | 694 | async.done(); | |
| 695 | 695 | }).catchError(e -> { | |
| 696 | 696 | Assert.fail(Std.string(e)); |
| ... | ... | @@ -709,7 +709,7 @@ class TestSqlite extends utest.Test { | |
| 709 | 709 | persistence.storeMessages(account, [message]).then(_ -> { | |
| 710 | 710 | return persistence.db.exec("SELECT strftime('%FT%H:%M:%fZ', time_received / 1000.0, 'unixepoch') AS time_received FROM messages WHERE mam_id=?", [message.serverId]); | |
| 711 | 711 | }).then(rows -> { | |
| 712 | - | Assert.equals("2020-01-01T00:00:00.123Z", rows.next().time_received); | |
| 712 | + | Assert.equals("2020-01-01T00:00:00.123Z", rows[0].time_received); | |
| 713 | 713 | async.done(); | |
| 714 | 714 | }).catchError(e -> { | |
| 715 | 715 | Assert.fail(Std.string(e)); |