diff options
Diffstat (limited to 'backend/src/repos/repos.zig')
-rw-r--r-- | backend/src/repos/repos.zig | 62 |
1 files changed, 62 insertions, 0 deletions
diff --git a/backend/src/repos/repos.zig b/backend/src/repos/repos.zig new file mode 100644 index 0000000..860811d --- /dev/null +++ b/backend/src/repos/repos.zig @@ -0,0 +1,62 @@ +const std = @import("std"); +const zqlite = @import("zqlite"); + +pub fn init(allocator: std.mem.Allocator, path: [*:0]const u8) !zqlite.Conn { + const flags = zqlite.OpenFlags.Create | zqlite.OpenFlags.EXResCode; + const conn = try zqlite.open(path, flags); + try conn.execNoArgs("PRAGMA foreign_keys = ON"); + try conn.execNoArgs("PRAGMA journal_mode = WAL"); + try migrate(allocator, conn, .{@embedFile("migrations/01.sql")}); + return conn; +} + +fn migrate(allocator: std.mem.Allocator, conn: zqlite.Conn, migrations: [1][]const u8) !void { + var version: i64 = 0; + if (try conn.row("PRAGMA user_version", .{})) |row| { + defer row.deinit(); + version = row.int(0); + } + + // Start transaction + try conn.transaction(); + errdefer conn.rollback(); + + for (migrations, 1..) |migration, i| { + const v: i64 = @intCast(i); + if (version < v) { + std.debug.print("Applying migration: {d}\n", .{i}); + + var it = std.mem.splitScalar(u8, migration, ';'); + while (it.next()) |statement| { + if (!is_statement_empty(statement)) { + try conn.exec(statement, .{}); + } + } + + try set_version(allocator, conn, @intCast(i)); + } + } + + // Commit transaction + try conn.commit(); +} + +fn is_statement_empty(str: []const u8) bool { + for (str) |c| { + if (c == ' ') continue; + if (c == '\n') continue; + if (c == '\t') continue; + return false; + } + return true; +} + +fn set_version(allocator: std.mem.Allocator, conn: zqlite.Conn, version: i64) !void { + const string = try std.fmt.allocPrint( + allocator, + "PRAGMA user_version = {d}", + .{version}, + ); + defer allocator.free(string); + try conn.exec(string, .{}); +} |