From b1ce5e99237f3123aa9491b451162207b19db2d1 Mon Sep 17 00:00:00 2001 From: MrBounty Date: Thu, 30 Jan 2025 20:01:18 +0100 Subject: [PATCH] Working POP command, now doing CLEAR --- src/file/array.zig | 76 +++++++++++++++++++++++--------------- src/test.zig | 13 +++++++ src/ziql/parts/newData.zig | 16 +++++--- 3 files changed, 71 insertions(+), 34 deletions(-) diff --git a/src/file/array.zig b/src/file/array.zig index 277e184..c91aa08 100644 --- a/src/file/array.zig +++ b/src/file/array.zig @@ -7,14 +7,15 @@ const ArrayCondition = @import("../ziql/parts//newData.zig").ArrayCondition; // This shouldn't be here, to move somewhere, idk yet /// Update an array based on keyword like append or remove -pub fn updateData(allocator: std.mem.Allocator, condition: ArrayCondition, input: *zid.Data, data: ConditionValue) !void { - switch (condition) { - .append => try append(allocator, input, data), - .pop => pop(input), - .clear => clear(input), - .remove => try remove(allocator, input, data), - .removeat => try removeat(allocator, input, data), - } +pub fn updateData(allocator: std.mem.Allocator, condition: ArrayCondition, input: *zid.Data, data: ?ConditionValue) !void { + std.debug.print("HERE {any}\n", .{condition}); + try switch (condition) { + .append => append(allocator, input, data.?), + .pop => pop(allocator, input), + .clear => clear(allocator, input), + .remove => remove(allocator, input, data.?), + .removeat => removeat(allocator, input, data.?), + }; } // This does not work, I think because I cant access the value at the pointer and so not update it. @@ -23,37 +24,54 @@ fn popInline(input: *zid.Data) void { inline for (comptime std.meta.fields(zid.Data)) |field| { if (comptime std.mem.endsWith(u8, field.name, "Array")) { if (@field(input, field.name).len > 8) { // If array is not empty, only 8 bytes mean that there is just the size of the array that's encode, meaning a u64 of 8 bytes - @field(input, field.name) = @field(input, field.name)[0 .. @field(input, field.name).len - input.size()]; + @field(input.*, field.name) = @field(input, field.name)[0 .. @field(input, field.name).len - input.size()]; } } } } -fn pop(input: *zid.Data) void { +fn pop(allocator: std.mem.Allocator, input: *zid.Data) !void { + var updated_array = std.ArrayList(u8).init(allocator); + errdefer updated_array.deinit(); + + var new_len: ?u64 = null; + if (input.size() > 8) switch (input.*) { + .IntArray => |v| try updated_array.appendSlice(v[0 .. v.len - @sizeOf(i32)]), + .FloatArray => |v| try updated_array.appendSlice(v[0 .. v.len - @sizeOf(f64)]), + .UnixArray => |v| try updated_array.appendSlice(v[0 .. v.len - @sizeOf(u64)]), + .UUIDArray => |v| try updated_array.appendSlice(v[0 .. v.len - @sizeOf([16]u8)]), + .BoolArray => |v| try updated_array.appendSlice(v[0 .. v.len - @sizeOf(bool)]), + .StrArray => |v| { + var iter = try zid.ArrayIterator.init(input.*); + var last_str: []const u8 = undefined; + while (iter.next()) |item| last_str = item.Str; + try updated_array.appendSlice(v[0 .. v.len - last_str.len - 8]); + new_len = input.size() - 16 - last_str.len; + }, + else => unreachable, + } else { + new_len = 0; + } + + new_len = new_len orelse updated_array.items.len - 8; + + @memcpy(updated_array.items[0..@sizeOf(u64)], std.mem.asBytes(&new_len.?)); + switch (input.*) { - .IntArray => |v| if (v.len > 8) { - input.*.IntArray = v[0 .. v.len - @sizeOf(i32)]; - }, - .FloatArray => |v| if (v.len > 8) { - input.*.FloatArray = v[0 .. v.len - @sizeOf(f64)]; - }, - .UnixArray => |v| if (v.len > 8) { - input.*.UnixArray = v[0 .. v.len - @sizeOf(u64)]; - }, - .UUIDArray => |v| if (v.len > 8) { - input.*.UUIDArray = v[0 .. v.len - @sizeOf([16]u8)]; - }, - .BoolArray => |v| if (v.len > 8) { - input.*.BoolArray = v[0 .. v.len - @sizeOf(bool)]; - }, - .StrArray => |v| if (v.len > 8) { - input.*.StrArray = v[0 .. v.len - @sizeOf(f64)]; // FIXME: Obviously the size of is wrong - }, + .IntArray => input.*.IntArray = try updated_array.toOwnedSlice(), + .FloatArray => input.*.FloatArray = try updated_array.toOwnedSlice(), + .UnixArray => input.*.UnixArray = try updated_array.toOwnedSlice(), + .UUIDArray => input.*.UUIDArray = try updated_array.toOwnedSlice(), + .BoolArray => input.*.BoolArray = try updated_array.toOwnedSlice(), + .StrArray => input.*.StrArray = try updated_array.toOwnedSlice(), else => unreachable, } } -fn clear(input: *zid.Data) void { +fn clear(allocator: std.mem.Allocator, input: *zid.Data) void { + var updated_array = std.ArrayList(u8).init(allocator); + errdefer updated_array.deinit(); + switch (input.*) { .IntArray => input.*.IntArray = zid.allocEncodArray.Empty(), .FloatArray => input.*.FloatArray = zid.allocEncodArray.Empty(), diff --git a/src/test.zig b/src/test.zig index 16925c9..f319718 100644 --- a/src/test.zig +++ b/src/test.zig @@ -114,6 +114,19 @@ test "UPDATE APPEND" { // OK try testParsing(db, "GRAB User {name IN ['Bob', 'Bobibou']}"); } +// FIXME: Look like it never call updateData, to investigate +test "UPDATE POP" { // OK + const db = DB{ .path = "test1", .schema = "schema/test" }; + try testParsing(db, "UPDATE User {name IN ['Bob', 'Bobibou']} TO (scores POP)"); + try testParsing(db, "GRAB User {name IN ['Bob', 'Bobibou']}"); +} + +test "UPDATE CLEAR" { // OK + const db = DB{ .path = "test1", .schema = "schema/test" }; + try testParsing(db, "UPDATE User {name IN ['Bob', 'Bobibou']} TO (scores CLEAR)"); + try testParsing(db, "GRAB User {name IN ['Bob', 'Bobibou']}"); +} + // Single Struct Relationship // =============================================================== diff --git a/src/ziql/parts/newData.zig b/src/ziql/parts/newData.zig index be0d7c9..4f7e203 100644 --- a/src/ziql/parts/newData.zig +++ b/src/ziql/parts/newData.zig @@ -28,7 +28,7 @@ pub const ArrayCondition = enum { append, clear, pop, remove, removeat }; pub const ArrayUpdate = struct { condition: ArrayCondition, - data: ConditionValue, + data: ?ConditionValue, }; /// Take the tokenizer and return a map of the ADD action. @@ -104,7 +104,11 @@ pub fn parseNewData( .expect_equal => switch (token.tag) { .equal => state = .expect_new_value, .keyword_pop => if (for_update) { - state = .expect_new_array; + map.put( + member_name, + ValueOrArray{ .array = .{ .condition = .pop, .data = null } }, + ) catch return ZipponError.MemoryError; + state = .expect_comma_OR_end; } else return printError( "Error: Can only manipulate array with UPDATE.", ZipponError.SynthaxError, @@ -113,7 +117,11 @@ pub fn parseNewData( token.loc.end, ), .keyword_clear => if (for_update) { - state = .expect_new_array; + map.put( + member_name, + ValueOrArray{ .array = .{ .condition = .pop, .data = null } }, + ) catch return ZipponError.MemoryError; + state = .expect_comma_OR_end; } else return printError( "Error: Can only manipulate array with UPDATE.", ZipponError.SynthaxError, @@ -265,8 +273,6 @@ pub fn parseNewData( }; map.put( member_name, - // TODO: Get right keyword - // TODO: Update ValueOrArray.array to use a single ConditionValue value instead of current array of it ValueOrArray{ .array = .{ .condition = .append, .data = try self.parseConditionValue(allocator, struct_name, member_name, new_data_type, &token) } }, ) catch return ZipponError.MemoryError; if (member_data_type == .link or member_data_type == .link_array) {