119 lines
4.5 KiB
Zig
119 lines
4.5 KiB
Zig
const sqlite = @import("sqlite");
|
|
const std = @import("std");
|
|
const models = @import("models.zig");
|
|
const utils = @import("../utils.zig");
|
|
|
|
const Allocator = std.mem.Allocator;
|
|
const print = std.debug.print;
|
|
|
|
pub const Db = struct {
|
|
allocator: Allocator,
|
|
_mode: ?sqlite.Db.Mode,
|
|
_sql_db: sqlite.Db,
|
|
|
|
pub fn init(allocator: Allocator, mode: ?sqlite.Db.Mode) !Db {
|
|
var sqlDb = try sqlite.Db.init(.{
|
|
.mode = if (mode != null) mode.? else sqlite.Db.Mode{ .File = "/home/nate/Source/rluv/zerver/data.db" },
|
|
.open_flags = .{
|
|
.write = true,
|
|
.create = true,
|
|
},
|
|
.threading_mode = .MultiThread,
|
|
});
|
|
return Db{ .allocator = allocator, ._mode = mode, ._sql_db = sqlDb };
|
|
}
|
|
|
|
pub fn deinit(self: *Db) void {
|
|
self._sql_db.deinit();
|
|
}
|
|
|
|
pub fn selectAllWhere(
|
|
self: *Db,
|
|
comptime Type: type,
|
|
allocator: Allocator,
|
|
comptime whereClause: []const u8,
|
|
values: anytype,
|
|
comptime limit: ?u32,
|
|
) !?[]Type {
|
|
_ = limit;
|
|
|
|
var res_array: std.ArrayList(Type) = std.ArrayList(Type).init(allocator);
|
|
|
|
const query = "SELECT * FROM " ++ models.getTypeTableName(Type) ++ " " ++ whereClause ++ ";";
|
|
var stmt = try self._sql_db.prepare(query);
|
|
defer stmt.deinit();
|
|
|
|
var iter = try stmt.iteratorAlloc(Type, allocator, values);
|
|
while (try iter.nextAlloc(allocator, .{})) |row| {
|
|
try res_array.append(row);
|
|
}
|
|
|
|
return try res_array.toOwnedSlice();
|
|
}
|
|
pub fn selectOneById(self: *Db, comptime Type: type, allocator: Allocator, id: u32) !?Type {
|
|
const row = try self._sql_db.oneAlloc(Type, allocator, models.createSelectOnIdQuery(Type), .{}, .{ .id = id });
|
|
// std.debug.print("{any}", .{row});
|
|
return row;
|
|
}
|
|
|
|
pub fn selectOne(self: *Db, comptime Type: type, allocator: Allocator, comptime query: []const u8, values: anytype) !?Type {
|
|
const row = try self._sql_db.oneAlloc(Type, allocator, query, .{}, values);
|
|
// std.debug.print("{any}", .{row});
|
|
return row;
|
|
}
|
|
|
|
pub fn updateById(self: *Db, comptime Type: type, values: anytype) !void {
|
|
// TODO check there is an ID field
|
|
const data = utils.structConcatFields(values, .{ .id2 = values.id });
|
|
self._sql_db.exec(models.createUpdateQuery(Type), .{}, data) catch |err| {
|
|
std.debug.print("Encountered error while updating data:\n{any}\n\tQuery:{s}\n{any}\n", .{ values, models.createUpdateQuery(Type), err });
|
|
return err;
|
|
};
|
|
}
|
|
|
|
pub fn insert(self: *Db, comptime Type: type, values: anytype) !void {
|
|
// TODO check there is an ID field
|
|
self._sql_db.exec(models.createInsertQuery(Type), .{}, values) catch |err| {
|
|
std.debug.print("Encountered error while inserting data:\n{any}\n\tQuery:{s}\n{any}\n", .{ values, models.createInsertQuery(Type), err });
|
|
return err;
|
|
};
|
|
}
|
|
|
|
pub fn deleteById(self: *Db, comptime Type: type, id: u32) !void {
|
|
// TODO check there is an ID field
|
|
self._sql_db.exec(models.createDeleteOnIdQuery(Type), .{}, .{ .id = id }) catch |err| {
|
|
std.debug.print("Encountered error while deleting id {}\n\tQuery:{s}\n{any}\n", .{ id, models.createInsertQuery(Type), err });
|
|
return err;
|
|
};
|
|
}
|
|
|
|
pub fn migrateDb(self: *Db) !void {
|
|
print("Making migration in DB...\n", .{});
|
|
_ = try self._sql_db.pragma(void, .{}, "foreign_keys", "1");
|
|
inline for (models.ModelTypes) |model_type| {
|
|
self._sql_db.exec(models.createTableMigrationQuery(model_type), .{}, .{}) catch |err| {
|
|
std.debug.print("Encountered error while executing migration\n\tQuery:{s}\n{any}\n", .{ models.createTableMigrationQuery(model_type), err });
|
|
return err;
|
|
};
|
|
}
|
|
}
|
|
|
|
pub fn wipeAndMigrateDb(self: *Db) !void {
|
|
print("Wiping DB data and schema...\n", .{});
|
|
inline for (models.ModelTypes) |model_type| {
|
|
self._sql_db.exec(models.createTableDeleteQuery(model_type), .{}, .{}) catch |err| {
|
|
std.debug.print("Encountered error while executing table deletion\n\tQuery:{s}\n{any}\n", .{ models.createTableDeleteQuery(model_type), err });
|
|
return err;
|
|
};
|
|
}
|
|
try self.migrateDb();
|
|
}
|
|
|
|
fn formatQuery(
|
|
query: []const u8,
|
|
) []const u8 {
|
|
const max_chars = 260;
|
|
return if (query.len > max_chars) query[0..max_chars] ++ "..." else query;
|
|
}
|
|
};
|