From b4adb9da6874e109a5115701c4e5235aeb07a9c8 Mon Sep 17 00:00:00 2001 From: Joey Bright Date: Mon, 17 Aug 2026 20:14:53 -0700 Subject: [PATCH 1/3] Implement `Sqlite.backup` Implementation and integration tests for the `backup` SQLite function --- integration-tests/sqlite/src/Main.gren | 45 ++++++++++++++++++++++++++ src/Gren/Kernel/Sqlite.js | 21 ++++++++++++ src/Sqlite.gren | 33 +++++++++++++++++++ 3 files changed, 99 insertions(+) diff --git a/integration-tests/sqlite/src/Main.gren b/integration-tests/sqlite/src/Main.gren index bb9588a..bb933a4 100644 --- a/integration-tests/sqlite/src/Main.gren +++ b/integration-tests/sqlite/src/Main.gren @@ -73,6 +73,44 @@ tests fsPerm = test "Works" <| \_ -> Expect.pass ] + , await "Create database for backup testing" createTestDb <| \db -> + let + backupDbPath = + Path.fromPosixString ".backup.db" + + slowBackupDbPath = + Path.fromPosixString ".backup-slow.db" + in + concat + [ await "Insert a person into the created database" (insertPerson joey db) <| \_ -> + concat + [ await "Backup the database" + (Sqlite.backup fsPerm backupDbPath db |> Sqlite.runBackup) <| \_ -> + await "Open the newly backed up database" + (Sqlite.open fsPerm Sqlite.defaultOptions (Sqlite.File backupDbPath)) <| \backupDb -> + await "Get the person from the backup database" + (Sqlite.getOne backupDb (personByNameQ joey.name)) <| \backupPerson -> + await "Also get the person from the original database" + (Sqlite.getOne backupDb (personByNameQ joey.name)) <| \originalPerson -> + concat + [ test "Name is the same in original and backup database" <| \_ -> + Expect.equal backupPerson.name originalPerson.name + , test "Role is the same in original and backup database" <| \_ -> + Expect.equal backupPerson.role originalPerson.role + , await "Remove from disk" (FileSystem.remove fsPerm { recursive = False } backupDbPath) <| \_ -> + test "Worked" <| \_ -> + Expect.pass + ] + , await "Backup the database to a different file with a smaller page count" + (Sqlite.backup fsPerm slowBackupDbPath db + |> Sqlite.withBackupPageRate 1 + |> Sqlite.runBackup + ) <| \_ -> + await "Remove from disk" (FileSystem.remove fsPerm { recursive = False } slowBackupDbPath) <| \_ -> + test "Worked" <| \_ -> + Expect.pass + ] + ] , await "Open physical database" (initializePhysicalDb fsPerm) <| \db -> await "Can be closed" (Sqlite.close db) <| \_ -> await "Remove from disk" (FileSystem.remove fsPerm { recursive = False } diskDbPath) <| \_ -> @@ -258,6 +296,13 @@ justin = } +joey : Person +joey = + { name = "Joey" + , role = "Contributor" + } + + people : Array Person people = [ robin, justin ] diff --git a/src/Gren/Kernel/Sqlite.js b/src/Gren/Kernel/Sqlite.js index 5ee456c..0929e06 100644 --- a/src/Gren/Kernel/Sqlite.js +++ b/src/Gren/Kernel/Sqlite.js @@ -52,6 +52,27 @@ var _Sqlite_close = function (db) { }); }; +var _Sqlite_backup = F3(function (destination, pages, db) { + return __Scheduler_binding(function (callback) { + try { + sqlite + .backup(db, destination, { + source: "main", + target: "main", + rate: pages, + }) + .then(function (res) { + callback(__Scheduler_succeed({})); + }) + .catch(function (e) { + callback(_Sqlite_constructError(e)); + }); + } catch (e) { + callback(_Sqlite_constructError(e)); + } + }); +}); + var _Sqlite_foldl = F4(function (query, db, func, acc) { return __Scheduler_binding(function (callback) { try { diff --git a/src/Sqlite.gren b/src/Sqlite.gren index 66c6207..91b88d7 100644 --- a/src/Sqlite.gren +++ b/src/Sqlite.gren @@ -65,6 +65,39 @@ close = Gren.Kernel.Sqlite.close + +-- Backup + + +type Backup + = Backup + { destination : Path + , pages : Int + , db : Database + } + + + +backup : FileSystem.Permission -> Path -> Database -> Backup +backup _ path db = + Backup + { destination = path + , pages = 100 + , db = db + } + + +withBackupPageRate : Int -> Backup -> Backup +withBackupPageRate pages (Backup record) = + Backup { record | pages = pages } + + +runBackup : Backup -> Task Error {} +runBackup (Backup { destination, pages, db }) = + Gren.Kernel.Sqlite.backup (FileSystem.Path.toPosixString destination) pages db + + + -- Query From c5aad5a13721998052e066e74cf3a1944251a895 Mon Sep 17 00:00:00 2001 From: Joey Bright Date: Sat, 22 Aug 2026 17:24:39 -0700 Subject: [PATCH 2/3] Fix mistake getting value from backup database that should have been gotten from original database --- integration-tests/sqlite/src/Main.gren | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integration-tests/sqlite/src/Main.gren b/integration-tests/sqlite/src/Main.gren index bb933a4..5a6f4e0 100644 --- a/integration-tests/sqlite/src/Main.gren +++ b/integration-tests/sqlite/src/Main.gren @@ -91,7 +91,7 @@ tests fsPerm = await "Get the person from the backup database" (Sqlite.getOne backupDb (personByNameQ joey.name)) <| \backupPerson -> await "Also get the person from the original database" - (Sqlite.getOne backupDb (personByNameQ joey.name)) <| \originalPerson -> + (Sqlite.getOne db (personByNameQ joey.name)) <| \originalPerson -> concat [ test "Name is the same in original and backup database" <| \_ -> Expect.equal backupPerson.name originalPerson.name From 2ea5faa367cc030078b72dfc8b2e05929a006485 Mon Sep 17 00:00:00 2001 From: Joey Bright Date: Tue, 25 Aug 2026 18:47:00 -0700 Subject: [PATCH 3/3] Using `_FilePath_toString` in kernel code instead of `toPosixString` in Gren --- src/Gren/Kernel/Sqlite.js | 2 +- src/Sqlite.gren | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Gren/Kernel/Sqlite.js b/src/Gren/Kernel/Sqlite.js index 0929e06..c516be1 100644 --- a/src/Gren/Kernel/Sqlite.js +++ b/src/Gren/Kernel/Sqlite.js @@ -56,7 +56,7 @@ var _Sqlite_backup = F3(function (destination, pages, db) { return __Scheduler_binding(function (callback) { try { sqlite - .backup(db, destination, { + .backup(db, _FilePath_toString(destination), { source: "main", target: "main", rate: pages, diff --git a/src/Sqlite.gren b/src/Sqlite.gren index 91b88d7..7438e74 100644 --- a/src/Sqlite.gren +++ b/src/Sqlite.gren @@ -94,7 +94,7 @@ withBackupPageRate pages (Backup record) = runBackup : Backup -> Task Error {} runBackup (Backup { destination, pages, db }) = - Gren.Kernel.Sqlite.backup (FileSystem.Path.toPosixString destination) pages db + Gren.Kernel.Sqlite.backup destination pages db