mgtzm/src/Item.zig

83 lines
2.1 KiB
Zig

const std = @import("std");
const json = @import("json.zig");
const Db = @import("Db.zig");
const sqlite = @import("sqlite");
const Self = @This();
pub const Tag = struct{
// :0 for C compatility
name: [:0]const u8,
value: ?[:0]const u8,
};
id: ?i64, // If null, the object hasn't been persisted
tags: ?[]Tag,
pub fn persist(self: *Self, db: *sqlite.Db) !void {
///////////////////////////////////
// ** Insert item **
/////////////////////////////////
// Insert only if there's no ID.
if (self.id == null) {
const query = "INSERT INTO item VALUES(NULL);";
try db.exec(query, .{}, .{});
// Update the ID field
self.id = try Db.getLastId(db);
}
///////////////////////////////////
// ** Insert tags **
/////////////////////////////////
// If the tags haven't been initialized, don't touch anything
if (self.tags) |tags| {
// TODO: Remove unused tag relations
// If the count drops to zero, delete.
// Create new tags if they don't exist
for (tags) |*tags_i| {
try db.exec(
"INSERT INTO tag (name) VALUES (?);",
.{},
.{ .name = tags_i.name }
);
try db.exec(
"INSERT INTO item_tag (item, tag, value) VALUES (?, ?, ?);",
.{},
.{ .item = self.id, .tag = tags_i.name, .value = tags_i.value }
);
}
}
}
/// Convert into a JSON object. A call to deinit() is necessary from the caller's side
pub fn toJson(self: Self) json.Obj {
var jobj = json.Obj.newObject();
jobj.objectAdd("id", &json.Obj.newInt64(self.id.?));
var jtags = json.Obj.newObject();
jobj.objectAdd("tags", &jtags);
// If there are tags there's no point on continuing
if (self.tags) |tags| {
for (tags) |tag_i| {
const jtag = if (tag_i.value) |value|
&json.Obj.newString(value)
else
null;
jtags.objectAdd(tag_i.name, jtag);
}
}
return jobj;
}