Implement item deletion

This commit is contained in:
Dendy 2022-11-05 04:23:28 +01:00
parent b603972a40
commit 4d9f3e32e2
4 changed files with 106 additions and 4 deletions

View File

@ -64,7 +64,7 @@ pub fn open(path: [:0]const u8, writable: bool, params: [:0]const u8) Self {
};
}
// TODO: Returrn error
// TODO: Return error
pub fn set(self: *Self, key: []const u8, value: []const u8) void {
const key_len = @intCast(i32, key.len);
const value_len = @intCast(i32, value.len);
@ -72,7 +72,12 @@ pub fn set(self: *Self, key: []const u8, value: []const u8) void {
_ = c.tkrzw_dbm_set(self.dbm, key.ptr, key_len, value.ptr, value_len, true);
}
// TODO: Returrn error
// TODO: Return error
pub fn remove(self: *Self, key: []const u8) bool {
return c.tkrzw_dbm_remove(self.dbm, key.ptr, @intCast(i32, key.len));
}
// TODO: Return error
pub fn append(self: *Self, key: []const u8, value: []const u8, delim: []const u8) void {
const key_len = @intCast(i32, key.len);
const value_len = @intCast(i32, value.len);
@ -126,6 +131,27 @@ pub fn isInList(self: *Self, key: []const u8, needle: []const u8) bool {
return false;
}
// TODO: Return wether or not the list is void after this
pub fn removeFromList(self: *Self, key: []const u8, needle: []const u8) void {
// TODO: Better error handling, do not fail silently
const haystack = self.get(key) orelse return;
// If there's no start, somesthing's wrong
const start = std.mem.indexOf(u8, haystack, needle) orelse return;
const end = start + needle.len;
// Re-set the rest of the IDs
self.set(key, haystack[0..start]);
// We were deleting the last in the list, no need to append anything
if (end >= haystack.len) return;
// +1 to remove the space
self.append(key, haystack[(end + 1)..], " ");
return;
}
/// Generic function to find occurences of a string inside another one with delimiters
fn isInStringDelim(haystack: []const u8, needle: []const u8, delim: u8) bool {
var spliter = std.mem.split(u8, haystack, &[_]u8{delim});

View File

@ -110,7 +110,39 @@ pub fn persist(self: *Self, db: *Db, allocator: std.mem.Allocator) !void {
}
}
// TODO: Return error or something, check for it
pub fn delete(self: Self, db: *Db) !void {
// TODO: Throw proper error
const id = self.id orelse return;
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
defer arena.deinit();
const allocator = arena.allocator();
// Delete the id inside the tags
if (self.tags) |tags| {
for (tags) |tag| {
// Get the tag selector: "tag:<tag>"
// TODO: Put this inside a function so is is comfier
const tag_sel = try std.mem.concat(allocator, u8, &[_][]const u8{ "tag:", tag });
defer allocator.free(tag_sel);
// TODO: See what to do when the tag doesn't exist
// TODO: Grab when it's the last of that tag
db.removeFromList(tag_sel, tag);
}
}
var item_sel = "item:----".*;
std.mem.copy(u8, item_sel[5..], id[0..]);
// Finally delete the item per se
// TODO: Return error on error
_ = db.remove(&item_sel);
}
pub fn getById(id: []const u8, db: *Db, allocator: std.mem.Allocator) !?Self {
// TODO: Create a function that returns the selector
var item_sel = "item:----".*;
std.mem.copy(u8, item_sel[5..], id[0..]);
@ -122,6 +154,7 @@ pub fn getById(id: []const u8, db: *Db, allocator: std.mem.Allocator) !?Self {
return Self{
.id = aid,
.tags = tags,
.allocator = allocator,
};
}

View File

@ -10,6 +10,8 @@ pub fn main() !void {
var db = Db.open("test.tkh", true, "");
// ---------------------- ADD ---------------------------
const jsonText: [:0]const u8 =
\\{ "add" : [
\\ [
@ -44,6 +46,19 @@ pub fn main() !void {
std.debug.print("\n\n", .{});
// -------------------- DELETE --------------------------
const jsonDelete: [:0]const u8 =
\\{ "delete" : [ "0000", "0003" ] }
;
var jdelete = json.Obj.newFromString(jsonDelete);
defer jdelete.deinit();
try request.process(&jdelete, &db);
// -------------------- QUERY ---------------------------
const jsonQuery: [:0]const u8 =
\\{ "query" : "fur made_with:krita date:2022", "limit" : 20 }
;

View File

@ -25,7 +25,12 @@ pub fn process(jobj: *json.Obj, db: *Db) !void {
jret.objectAdd("queried", &ret);
}
std.debug.print("{s}", .{jret.toString()});
if (jobj.objectGet("delete") catch null) |*jaction| {
var ret = try delete(jaction, db, allocator);
jret.objectAdd("deleted", &ret);
}
std.debug.print("{s}\n", .{jret.toString()});
}
pub fn add(jobj: *json.Obj, db: *Db, allocator: std.mem.Allocator) !json.Obj {
@ -53,6 +58,8 @@ pub fn add(jobj: *json.Obj, db: *Db, allocator: std.mem.Allocator) !json.Obj {
}
pub fn query(jobj: *json.Obj, db: *Db, allocator: std.mem.Allocator) !json.Obj {
// TODO: Have into account limits so it is scalable
// TODO: Do not fetch EVERY id at once, iterate where possible
const query_str = jobj.getString();
var jret = json.Obj.newArray();
@ -81,10 +88,31 @@ pub fn query(jobj: *json.Obj, db: *Db, allocator: std.mem.Allocator) !json.Obj {
var id_iter = util.intersection(ids.items);
while (id_iter.next()) |item_id| {
const item = (try Item.getById(item_id, db, allocator)) orelse continue;
var item = (try Item.getById(item_id, db, allocator)) orelse continue;
defer item.deinit();
jret.arrayAdd(&item.toJson());
}
return jret;
}
pub fn delete(jobj: *json.Obj, db: *Db, allocator: std.mem.Allocator) !json.Obj {
var jret = json.Obj.newArray();
// Go over each tag
var id_iter = jobj.arrayGetIterator();
while (id_iter.next()) |*jid| {
const id = jid.getString();
// TODO: Return some kind of error or somethign telling that some were not found
var item = (try Item.getById(id, db, allocator)) orelse continue;
defer item.deinit();
jret.arrayAdd(&item.toJson());
try item.delete(db);
}
return jret;
}