git » sdk » commit a12daf8

Optional array for sqlite query

author Stephen Paul Weber
2025-04-14 18:18:51 UTC
committer Stephen Paul Weber
2025-04-14 18:18:51 UTC
parent 7705d954e6799815f415747e9178f6a8c7388272

Optional array for sqlite query

To send in multiple queries to execute at once. Can only bind values
into the first one. Mostly for migrations.

snikket/persistence/Sqlite.hx +22 -22
snikket/persistence/SqliteDriver.hx +18 -2
snikket/persistence/SqliteDriver.js.hx +14 -3

diff --git a/snikket/persistence/Sqlite.hx b/snikket/persistence/Sqlite.hx
index 68979ad..dcd55bd 100644
--- a/snikket/persistence/Sqlite.hx
+++ b/snikket/persistence/Sqlite.hx
@@ -36,10 +36,10 @@ class Sqlite implements Persistence implements KeyValueStore {
 		this.media = media;
 		media.setKV(this);
 		db = new SqliteDriver(dbfile);
-		final version = db.exec("PRAGMA user_version;").then(iter -> {
+		db.exec("PRAGMA user_version;").then(iter -> {
 			final version = Std.parseInt(iter.next()?.user_version) ?? 0;
 			return if (version < 1) {
-				db.exec("CREATE TABLE messages (
+				db.exec(["CREATE TABLE messages (
 					account_id TEXT NOT NULL,
 					mam_id TEXT NOT NULL,
 					mam_by TEXT NOT NULL,
@@ -54,10 +54,10 @@ class Sqlite implements Persistence implements KeyValueStore {
 					type INTEGER NOT NULL,
 					stanza TEXT NOT NULL,
 					PRIMARY KEY (account_id, mam_id, mam_by, stanza_id)
-				) STRICT;
-				CREATE INDEX messages_created_at ON messages (account_id, chat_id, created_at);
-				CREATE INDEX messages_correction_id ON messages (correction_id);
-				CREATE TABLE chats (
+				) STRICT;",
+				"CREATE INDEX messages_created_at ON messages (account_id, chat_id, created_at);",
+				"CREATE INDEX messages_correction_id ON messages (correction_id);",
+				"CREATE TABLE chats (
 					account_id TEXT NOT NULL,
 					chat_id TEXT NOT NULL,
 					trusted INTEGER NOT NULL,
@@ -72,24 +72,24 @@ class Sqlite implements Persistence implements KeyValueStore {
 					presence BLOB NOT NULL,
 					class TEXT NOT NULL,
 					PRIMARY KEY (account_id, chat_id)
-				) STRICT;
-				CREATE TABLE keyvaluepairs (
+				) STRICT;",
+				"CREATE TABLE keyvaluepairs (
 					k TEXT NOT NULL PRIMARY KEY,
 					v TEXT NOT NULL
-				) STRICT;
-				CREATE TABLE caps (
+				) STRICT;",
+				"CREATE TABLE caps (
 					sha1 BLOB NOT NULL PRIMARY KEY,
 					caps BLOB NOT NULL
-				) STRICT;
-				CREATE TABLE services (
+				) STRICT;",
+				"CREATE TABLE services (
 					account_id TEXT NOT NULL,
 					service_id TEXT NOT NULL,
 					name TEXT,
 					node TEXT,
 					caps BLOB NOT NULL,
 					PRIMARY KEY (account_id, service_id)
-				) STRICT;
-				CREATE TABLE accounts (
+				) STRICT;",
+				"CREATE TABLE accounts (
 					account_id TEXT NOT NULL,
 					client_id TEXT NOT NULL,
 					display_name TEXT,
@@ -97,8 +97,8 @@ class Sqlite implements Persistence implements KeyValueStore {
 					fast_count INTEGER NOT NULL DEFAULT 0,
 					sm_state BLOB,
 					PRIMARY KEY (account_id)
-				) STRICT;
-				CREATE TABLE reactions (
+				) STRICT;",
+				"CREATE TABLE reactions (
 					account_id TEXT NOT NULL,
 					update_id TEXT NOT NULL,
 					mam_id TEXT,
@@ -110,13 +110,13 @@ class Sqlite implements Persistence implements KeyValueStore {
 					reactions BLOB NOT NULL,
 					kind INTEGER NOT NULL,
 					PRIMARY KEY (account_id, chat_id, sender_id, update_id)
-				) STRICT;
-				PRAGMA user_version = 1;");
+				) STRICT;",
+				"PRAGMA user_version = 1;"]);
 			} else if (version < 2) {
-				db.exec("ALTER TABLE chats ADD COLUMN notifications_filtered INTEGER;
-				ALTER TABLE chats ADD COLUMN notify_mention INTEGER NOT NULL DEFAULT 0;
-				ALTER TABLE chats ADD COLUMN notify_reply INTEGER NOT NULL DEFAULT 0;
-				PRAGMA user_version = 2;");
+				db.exec(["ALTER TABLE chats ADD COLUMN notifications_filtered INTEGER;",
+				"ALTER TABLE chats ADD COLUMN notify_mention INTEGER NOT NULL DEFAULT 0;",
+				"ALTER TABLE chats ADD COLUMN notify_reply INTEGER NOT NULL DEFAULT 0;",
+				"PRAGMA user_version = 2;"]);
 			} else {
 				Promise.resolve(null);
 			}
diff --git a/snikket/persistence/SqliteDriver.hx b/snikket/persistence/SqliteDriver.hx
index 099d880..f90b584 100644
--- a/snikket/persistence/SqliteDriver.hx
+++ b/snikket/persistence/SqliteDriver.hx
@@ -12,9 +12,22 @@ class SqliteDriver {
 		db = sys.db.Sqlite.open(dbfile);
 	}
 
-	public function exec(sql: String, ?params: Array<Dynamic>) {
+	public function exec(sql: haxe.extern.EitherType<String, Array<String>>, ?params: Array<Dynamic>) {
+		var result = null;
+		final qs = if (Std.isOfType(sql, String)) {
+			[sql];
+		} else {
+			cast (sql, Array<Dynamic>);
+		}
 		try {
-			final result = db.request(prepare(sql, params ?? []));
+			for (q in qs) {
+				if (result == null) {
+					final prepared = prepare(q, params ?? []);
+					result = db.request(prepared);
+				} else {
+					db.request(q);
+				}
+			}
 			return Promise.resolve(result);
 		} catch (e) {
 			return Promise.reject(e);
@@ -35,6 +48,9 @@ class SqliteDriver {
 					Std.string(p);
 				case TNull:
 					"NULL";
+				case TClass(Array):
+					var bytes:Bytes = Bytes.ofData(p);
+					"X'" + bytes.toHex() + "'";
 				case TClass(haxe.io.Bytes):
 					var bytes:Bytes = cast p;
 					"X'" + bytes.toHex() + "'";
diff --git a/snikket/persistence/SqliteDriver.js.hx b/snikket/persistence/SqliteDriver.js.hx
index 5dcdade..99be4b3 100644
--- a/snikket/persistence/SqliteDriver.js.hx
+++ b/snikket/persistence/SqliteDriver.js.hx
@@ -28,20 +28,21 @@ class SqliteDriver {
 		});
 	}
 
-	public function exec(sql: String, ?params: Array<Dynamic>): Promise<haxe.iterators.ArrayIterator<Dynamic>> {
+	public function exec(sql: haxe.extern.EitherType<String, Array<String>>, ?params: Array<Dynamic>) {
 		if (sqlite == null || dbId == null) {
 			// Not ready yet
 			return new Promise((resolve, reject) -> haxe.Timer.delay(() -> resolve(null), 100))
 				.then(_ -> exec(sql, params));
 		}
 
+		final qs = Std.isOfType(sql, String) ? sql : (cast sql).join("");
 		final items: Array<Dynamic> = [];
 		var signalAllDone;
 		final allDone = new Promise((resolve, reject) -> signalAllDone = resolve);
 		return sqlite('exec', {
 			dbId: dbId,
-			sql: sql,
-			bind: params,
+			sql: qs,
+			bind: params.map(formatParam),
 			rowMode: "object",
 			callback: (r) -> {
 				if (r.rowNumber == null) {
@@ -53,4 +54,14 @@ class SqliteDriver {
 			}
 		}).then(_ -> allDone).then(_ -> items.iterator());
 	}
+
+	private function formatParam(p: Dynamic): Dynamic {
+		return switch (Type.typeof(p)) {
+			case TClass(haxe.io.Bytes):
+				var bytes:Bytes = cast p;
+				return bytes.getData();
+			case _:
+				return p;
+		}
+	}
 }