diff --git a/src/fileEngine.zig b/src/fileEngine.zig index f1c45b7..4b4f88f 100644 --- a/src/fileEngine.zig +++ b/src/fileEngine.zig @@ -16,6 +16,7 @@ const DataType = dtype.DataType; const AdditionalData = @import("stuffs/additionalData.zig").AdditionalData; const Filter = @import("stuffs/filter.zig").Filter; +const ConditionValue = @import("stuffs/filter.zig").ConditionValue; const ZipponError = @import("stuffs/errors.zig").ZipponError; const FileEngineError = @import("stuffs/errors.zig").FileEngineError; @@ -563,7 +564,7 @@ pub const FileEngine = struct { pub fn addEntity( self: *FileEngine, struct_name: []const u8, - map: std.StringHashMap([]const u8), + map: std.StringHashMap(ConditionValue), writer: anytype, n: usize, ) ZipponError!void { @@ -589,7 +590,7 @@ pub const FileEngine = struct { self: *FileEngine, struct_name: []const u8, filter: ?Filter, - map: std.StringHashMap([]const u8), + map: std.StringHashMap(ConditionValue), writer: anytype, additional_data: *AdditionalData, ) ZipponError!void { @@ -619,9 +620,7 @@ pub const FileEngine = struct { // Convert the map to an array of ZipponData Data type, to be use with ZipponData writter for (sstruct.members, 0..) |member, i| { if (!map.contains(member)) continue; - - const dt = try self.schema_engine.memberName2DataType(struct_name, member); - new_data_buff[i] = try string2Data(allocator, dt, map.get(member).?); + new_data_buff[i] = try string2Data(allocator, map.get(member).?); } // Spawn threads for each file @@ -655,7 +654,7 @@ pub const FileEngine = struct { new_data_buff: []zid.Data, sstruct: SchemaStruct, filter: ?Filter, - map: *const std.StringHashMap([]const u8), + map: *const std.StringHashMap(ConditionValue), writer: anytype, file_index: u64, dir: std.fs.Dir, @@ -888,67 +887,34 @@ pub const FileEngine = struct { // --------------------ZipponData utils-------------------- - fn string2Data(allocator: Allocator, dt: DataType, value: []const u8) ZipponError!zid.Data { - switch (dt) { - .int => return zid.Data.initInt(s2t.parseInt(value)), - .float => return zid.Data.initFloat(s2t.parseFloat(value)), - .bool => return zid.Data.initBool(s2t.parseBool(value)), - .date => return zid.Data.initUnix(s2t.parseDate(value).toUnix()), - .time => return zid.Data.initUnix(s2t.parseTime(value).toUnix()), - .datetime => return zid.Data.initUnix(s2t.parseDatetime(value).toUnix()), - .str => return zid.Data.initStr(value), - .link, .self => { - const uuid = UUID.parse(value) catch return FileEngineError.InvalidUUID; - return zid.Data.initUUID(uuid.bytes); - }, - .int_array => { - const array = s2t.parseArrayInt(allocator, value) catch return FileEngineError.MemoryError; - defer allocator.free(array); + //TODO: Update to make it use ConditionValue + fn string2Data(allocator: Allocator, value: ConditionValue) ZipponError!zid.Data { + switch (value) { + .int => |v| return zid.Data.initInt(v), + .float => |v| return zid.Data.initFloat(v), + .bool_ => |v| return zid.Data.initBool(v), + .unix => |v| return zid.Data.initUnix(v), + .str => |v| return zid.Data.initStr(v), + .link => |v| { + var iter = v.keyIterator(); + if (v.count() == 1) { + return zid.Data.initUUID(iter.next().?.bytes); + } else { + var items = std.ArrayList([16]u8).init(allocator); + defer items.deinit(); - return zid.Data.initIntArray(zid.allocEncodArray.Int(allocator, array) catch return FileEngineError.AllocEncodError); - }, - .float_array => { - const array = s2t.parseArrayFloat(allocator, value) catch return FileEngineError.MemoryError; - defer allocator.free(array); - - return zid.Data.initFloatArray(zid.allocEncodArray.Float(allocator, array) catch return FileEngineError.AllocEncodError); - }, - .str_array => { - const array = s2t.parseArrayStr(allocator, value) catch return FileEngineError.MemoryError; - defer allocator.free(array); - - return zid.Data.initStrArray(zid.allocEncodArray.Str(allocator, array) catch return FileEngineError.AllocEncodError); - }, - .bool_array => { - const array = s2t.parseArrayBool(allocator, value) catch return FileEngineError.MemoryError; - defer allocator.free(array); - - return zid.Data.initBoolArray(zid.allocEncodArray.Bool(allocator, array) catch return FileEngineError.AllocEncodError); - }, - .date_array => { - const array = s2t.parseArrayDateUnix(allocator, value) catch return FileEngineError.MemoryError; - defer allocator.free(array); - - return zid.Data.initUnixArray(zid.allocEncodArray.Unix(allocator, array) catch return FileEngineError.AllocEncodError); - }, - .time_array => { - const array = s2t.parseArrayTimeUnix(allocator, value) catch return FileEngineError.MemoryError; - defer allocator.free(array); - - return zid.Data.initUnixArray(zid.allocEncodArray.Unix(allocator, array) catch return FileEngineError.AllocEncodError); - }, - .datetime_array => { - const array = s2t.parseArrayDatetimeUnix(allocator, value) catch return FileEngineError.MemoryError; - defer allocator.free(array); - - return zid.Data.initUnixArray(zid.allocEncodArray.Unix(allocator, array) catch return FileEngineError.AllocEncodError); - }, - .link_array => { - const array = s2t.parseArrayUUIDBytes(allocator, value) catch return FileEngineError.MemoryError; - defer allocator.free(array); - - return zid.Data.initUUIDArray(zid.allocEncodArray.UUID(allocator, array) catch return FileEngineError.AllocEncodError); + while (iter.next()) |uuid| { + items.append(uuid.bytes) catch return ZipponError.MemoryError; + } + return zid.Data.initUUIDArray(zid.allocEncodArray.UUID(allocator, items.items) catch return FileEngineError.AllocEncodError); + } }, + .self => |v| return zid.Data.initUUID(v.bytes), + .int_array => |v| return zid.Data.initIntArray(zid.allocEncodArray.Int(allocator, v) catch return FileEngineError.AllocEncodError), + .float_array => |v| return zid.Data.initFloatArray(zid.allocEncodArray.Float(allocator, v) catch return FileEngineError.AllocEncodError), + .str_array => |v| return zid.Data.initStrArray(zid.allocEncodArray.Str(allocator, v) catch return FileEngineError.AllocEncodError), + .bool_array => |v| return zid.Data.initBoolArray(zid.allocEncodArray.Bool(allocator, v) catch return FileEngineError.AllocEncodError), + .unix_array => |v| return zid.Data.initUnixArray(zid.allocEncodArray.Unix(allocator, v) catch return FileEngineError.AllocEncodError), } } @@ -958,19 +924,17 @@ pub const FileEngine = struct { self: *FileEngine, allocator: Allocator, struct_name: []const u8, - map: std.StringHashMap([]const u8), + map: std.StringHashMap(ConditionValue), ) ZipponError![]zid.Data { const members = try self.schema_engine.structName2structMembers(struct_name); - const types = try self.schema_engine.structName2DataType(struct_name); - var datas = allocator.alloc(zid.Data, (members.len)) catch return FileEngineError.MemoryError; const new_uuid = UUID.init(); datas[0] = zid.Data.initUUID(new_uuid.bytes); - for (members, types, 0..) |member, dt, i| { + for (members, 0..) |member, i| { if (i == 0) continue; // Skip the id - datas[i] = try string2Data(allocator, dt, map.get(member).?); + datas[i] = try string2Data(allocator, map.get(member).?); } log.debug("New ordered data: {any}\n", .{datas}); diff --git a/src/schemaEngine.zig b/src/schemaEngine.zig index fe96b40..6a54eb7 100644 --- a/src/schemaEngine.zig +++ b/src/schemaEngine.zig @@ -6,6 +6,8 @@ const Tokenizer = @import("tokenizers/schema.zig").Tokenizer; const ZipponError = @import("stuffs/errors.zig").ZipponError; const dtype = @import("dtype"); const DataType = dtype.DataType; +const ConditionValue = @import("stuffs/filter.zig").ConditionValue; +const UUID = dtype.UUID; const UUIDFileIndex = @import("stuffs/UUIDFileIndex.zig").UUIDIndexMap; const FileEngine = @import("fileEngine.zig").FileEngine; @@ -200,7 +202,7 @@ pub const SchemaEngine = struct { pub fn checkIfAllMemberInMap( self: *SchemaEngine, struct_name: []const u8, - map: *std.StringHashMap([]const u8), + map: *std.StringHashMap(ConditionValue), error_message_buffer: *std.ArrayList(u8), ) ZipponError!bool { const all_struct_member = try self.structName2structMembers(struct_name); @@ -215,4 +217,9 @@ pub const SchemaEngine = struct { return ((count == all_struct_member.len - 1) and (count == map.count())); } + + pub fn isUUIDExist(self: *SchemaEngine, struct_name: []const u8, uuid: UUID) bool { + const sstruct = self.structName2SchemaStruct(struct_name) catch return false; + return sstruct.uuid_file_index.contains(uuid); + } }; diff --git a/src/stuffs/filter.zig b/src/stuffs/filter.zig index d83f580..04f8d5c 100644 --- a/src/stuffs/filter.zig +++ b/src/stuffs/filter.zig @@ -18,7 +18,7 @@ const Data = @import("ZipponData").Data; const log = std.log.scoped(.filter); -const ComparisonOperator = enum { +pub const ComparisonOperator = enum { equal, different, superior, @@ -61,28 +61,13 @@ pub const ConditionValue = union(enum) { bool_: bool, self: UUID, unix: u64, - int_array: std.ArrayList(i32), - str_array: std.ArrayList([]const u8), - float_array: std.ArrayList(f64), - bool_array: std.ArrayList(bool), - unix_array: std.ArrayList(u64), + int_array: []const i32, + str_array: []const []const u8, + float_array: []const f64, + bool_array: []const bool, + unix_array: []const u64, link: *std.AutoHashMap(UUID, void), - pub fn deinit(self: ConditionValue, allocator: std.mem.Allocator) void { - switch (self) { - .int_array => self.int_array.deinit(), - .str_array => self.str_array.deinit(), - .float_array => self.float_array.deinit(), - .bool_array => self.bool_array.deinit(), - .unix_array => self.unix_array.deinit(), - .link => { - self.link.deinit(); - allocator.destroy(self.link); - }, - else => {}, - } - } - pub fn initInt(value: []const u8) ConditionValue { return ConditionValue{ .int = s2t.parseInt(value) }; } @@ -116,32 +101,32 @@ pub const ConditionValue = union(enum) { } // Array - pub fn initArrayInt(allocator: std.mem.Allocator, value: []const u8) ConditionValue { - return ConditionValue{ .int_array = s2t.parseArrayInt(allocator, value) }; + pub fn initArrayInt(allocator: std.mem.Allocator, value: []const u8) ZipponError!ConditionValue { + return ConditionValue{ .int_array = s2t.parseArrayInt(allocator, value) catch return ZipponError.ParsingValueError }; } - pub fn initArrayFloat(allocator: std.mem.Allocator, value: []const u8) ConditionValue { - return ConditionValue{ .float_array = s2t.parseArrayFloat(allocator, value) }; + pub fn initArrayFloat(allocator: std.mem.Allocator, value: []const u8) ZipponError!ConditionValue { + return ConditionValue{ .float_array = s2t.parseArrayFloat(allocator, value) catch return ZipponError.ParsingValueError }; } - pub fn initArrayStr(allocator: std.mem.Allocator, value: []const u8) ConditionValue { - return ConditionValue{ .str_array = s2t.parseArrayStr(allocator, value) }; + pub fn initArrayStr(allocator: std.mem.Allocator, value: []const u8) ZipponError!ConditionValue { + return ConditionValue{ .str_array = s2t.parseArrayStr(allocator, value) catch return ZipponError.ParsingValueError }; } - pub fn initArrayBool(allocator: std.mem.Allocator, value: []const u8) ConditionValue { - return ConditionValue{ .bool_array = s2t.parseArrayBool(allocator, value) }; + pub fn initArrayBool(allocator: std.mem.Allocator, value: []const u8) ZipponError!ConditionValue { + return ConditionValue{ .bool_array = s2t.parseArrayBool(allocator, value) catch return ZipponError.ParsingValueError }; } - pub fn initArrayDate(allocator: std.mem.Allocator, value: []const u8) ConditionValue { - return ConditionValue{ .unix_array = s2t.parseArrayDateUnix(allocator, value) }; + pub fn initArrayDate(allocator: std.mem.Allocator, value: []const u8) ZipponError!ConditionValue { + return ConditionValue{ .unix_array = s2t.parseArrayDateUnix(allocator, value) catch return ZipponError.ParsingValueError }; } - pub fn initArrayTime(allocator: std.mem.Allocator, value: []const u8) ConditionValue { - return ConditionValue{ .unix_array = s2t.parseArrayTimeUnix(allocator, value) }; + pub fn initArrayTime(allocator: std.mem.Allocator, value: []const u8) ZipponError!ConditionValue { + return ConditionValue{ .unix_array = s2t.parseArrayTimeUnix(allocator, value) catch return ZipponError.ParsingValueError }; } - pub fn initArrayDateTime(allocator: std.mem.Allocator, value: []const u8) ConditionValue { - return ConditionValue{ .unix_array = s2t.parseArrayDatetimeUnix(allocator, value) }; + pub fn initArrayDateTime(allocator: std.mem.Allocator, value: []const u8) ZipponError!ConditionValue { + return ConditionValue{ .unix_array = s2t.parseArrayDatetimeUnix(allocator, value) catch return ZipponError.ParsingValueError }; } pub fn initLink(value: *std.AutoHashMap(UUID, void)) ConditionValue { @@ -154,10 +139,6 @@ pub const Condition = struct { operation: ComparisonOperator = undefined, data_type: DataType = undefined, data_index: usize = undefined, // Index in the file - - pub fn deinit(self: Condition, allocator: std.mem.Allocator) void { - self.value.deinit(allocator); - } }; const FilterNode = union(enum) { @@ -183,7 +164,6 @@ pub const Filter = struct { pub fn deinit(self: *Filter) void { switch (self.root.*) { .logical => self.freeNode(self.root), - .condition => |condition| condition.deinit(self.allocator), else => {}, } self.allocator.destroy(self.root); @@ -197,8 +177,7 @@ pub const Filter = struct { self.allocator.destroy(logical.left); self.allocator.destroy(logical.right); }, - .condition => |condition| condition.deinit(self.allocator), - .empty => {}, + else => {}, } } diff --git a/src/ziqlParser.zig b/src/ziqlParser.zig index b87a598..6439738 100644 --- a/src/ziqlParser.zig +++ b/src/ziqlParser.zig @@ -11,6 +11,7 @@ const UUID = dtype.UUID; const Filter = @import("stuffs/filter.zig").Filter; const Condition = @import("stuffs/filter.zig").Condition; const ConditionValue = @import("stuffs/filter.zig").ConditionValue; +const ComparisonOperator = @import("stuffs/filter.zig").ComparisonOperator; const AdditionalData = @import("stuffs/additionalData.zig").AdditionalData; const AdditionalDataMember = @import("stuffs/additionalData.zig").AdditionalDataMember; @@ -230,9 +231,9 @@ pub const Parser = struct { token.loc.end, ); - var data_map = std.StringHashMap([]const u8).init(allocator); + var data_map = std.StringHashMap(ConditionValue).init(allocator); defer data_map.deinit(); - try self.parseNewData(&data_map, struct_name); + try self.parseNewData(allocator, &data_map, struct_name); var buff = std.ArrayList(u8).init(allocator); defer buff.deinit(); @@ -251,9 +252,9 @@ pub const Parser = struct { token.loc.end, ); - var data_map = std.StringHashMap([]const u8).init(allocator); + var data_map = std.StringHashMap(ConditionValue).init(allocator); defer data_map.deinit(); - try self.parseNewData(&data_map, struct_name); + try self.parseNewData(allocator, &data_map, struct_name); var buff = std.ArrayList(u8).init(allocator); defer buff.deinit(); @@ -315,9 +316,9 @@ pub const Parser = struct { }, .parse_new_data_and_add_data => { - var data_map = std.StringHashMap([]const u8).init(allocator); + var data_map = std.StringHashMap(ConditionValue).init(allocator); defer data_map.deinit(); - try self.parseNewData(&data_map, struct_name); + try self.parseNewData(allocator, &data_map, struct_name); var error_message_buffer = std.ArrayList(u8).init(allocator); defer error_message_buffer.deinit(); @@ -511,7 +512,7 @@ pub const Parser = struct { struct_name, self.toker.getTokenSlice(token), ) catch return ZiQlParserError.MemberNotFound; - state = State.expect_operation; + state = .expect_operation; }, else => return printError( "Error: Expected member name.", @@ -523,149 +524,12 @@ pub const Parser = struct { }, .expect_operation => { - switch (token.tag) { - .equal => condition.operation = .equal, // = - .angle_bracket_left => condition.operation = .inferior, // < - .angle_bracket_right => condition.operation = .superior, // > - .angle_bracket_left_equal => condition.operation = .inferior_or_equal, // <= - .angle_bracket_right_equal => condition.operation = .superior_or_equal, // >= - .bang_equal => condition.operation = .different, // != - .keyword_in => condition.operation = .in, - .keyword_not_in => condition.operation = .not_in, - else => return printError( - "Error: Expected condition. Including < > <= >= = !=", - ZiQlParserError.SynthaxError, - self.toker.buffer, - token.loc.start, - token.loc.end, - ), - } - state = State.expect_value; + condition.operation = try self.parseComparisonOperator(token); + state = .expect_value; }, .expect_value => { - const start_index = token.loc.start; - const expected_tag: ?Token.Tag = switch (condition.data_type) { - .int => .int_literal, - .float => .float_literal, - .str => .string_literal, - .self => .uuid_literal, - .date => .date_literal, - .time => .time_literal, - .datetime => .datetime_literal, - .int_array => .int_literal, - .float_array => .float_literal, - .str_array => .string_literal, - .date_array => .date_literal, - .time_array => .time_literal, - .datetime_array => .datetime_literal, - .bool, .bool_array, .link, .link_array => null, // handle separately - }; - - var filter: ?Filter = null; - defer if (filter != null) filter.?.deinit(); - var additional_data = AdditionalData.init(allocator); - defer additional_data.deinit(); - - if (expected_tag) |tag| { - if (condition.data_type.is_array()) { - token = try self.checkTokensInArray(tag); - } else { - if (token.tag != tag) { - return printError( - "Error: Wrong type", // TODO: Print the expected type - ZiQlParserError.SynthaxError, - self.toker.buffer, - token.loc.start, - token.loc.end, - ); - } - } - } else switch (condition.data_type) { - .bool => { - if (token.tag != .bool_literal_true and token.tag != .bool_literal_false) { - return printError( - "Error: Expected bool", - ZiQlParserError.SynthaxError, - self.toker.buffer, - token.loc.start, - token.loc.end, - ); - } - }, - .bool_array => { - token = self.toker.next(); - while (token.tag != .r_bracket) : (token = self.toker.next()) { - if (token.tag != .bool_literal_true and token.tag != .bool_literal_false) { - return printError( - "Error: Expected bool or ]", - ZiQlParserError.SynthaxError, - self.toker.buffer, - token.loc.start, - token.loc.end, - ); - } - } - }, - .link, .link_array => { - switch (token.tag) { - .l_bracket => { - try self.parseAdditionalData(allocator, &additional_data, struct_name); - }, - .uuid_literal => {}, - else => {}, - } - - if (condition.data_type == .link) additional_data.entity_count_to_find = 1; - - switch (token.tag) { - .l_brace => { - filter = try self.parseFilter(allocator, struct_name, false); - }, - .uuid_literal => {}, - else => return printError( - "Error: Expected new filter or UUID", - ZiQlParserError.SynthaxError, - self.toker.buffer, - token.loc.start, - token.loc.end, - ), - } - }, - else => unreachable, - } - - switch (condition.data_type) { - .int => condition.value = ConditionValue.initInt(self.toker.buffer[start_index..token.loc.end]), - .float => condition.value = ConditionValue.initFloat(self.toker.buffer[start_index..token.loc.end]), - .str => condition.value = ConditionValue.initStr(self.toker.buffer[start_index + 1 .. token.loc.end - 1]), - .date => condition.value = ConditionValue.initDate(self.toker.buffer[start_index..token.loc.end]), - .time => condition.value = ConditionValue.initTime(self.toker.buffer[start_index..token.loc.end]), - .datetime => condition.value = ConditionValue.initDateTime(self.toker.buffer[start_index..token.loc.end]), - .bool => condition.value = ConditionValue.initBool(self.toker.buffer[start_index..token.loc.end]), - .link_array, .link => switch (token.tag) { - .l_brace, .l_bracket => { - const map = allocator.create(std.AutoHashMap(UUID, void)) catch return ZipponError.MemoryError; - map.* = std.AutoHashMap(UUID, void).init(allocator); - try self.file_engine.populateVoidUUIDMap( - struct_name, - filter, - map, - &additional_data, - ); - log.debug("Found {d} entity when parsing for populateVoidUUID\n", .{map.count()}); - condition.value = ConditionValue.initLink(map); - }, - else => return printError( - "Error: Expected filter", - ZiQlParserError.SynthaxError, - self.toker.buffer, - token.loc.start, - token.loc.end, - ), - }, - else => unreachable, // TODO: Make for link and array =/ - } + condition.value = try self.parseConditionValue(allocator, struct_name, condition.data_type, &token); state = .end; }, @@ -881,7 +745,7 @@ pub const Parser = struct { /// Take the tokenizer and return a map of the ADD action. /// Keys are the member name and value are the string of the value in the query. E.g. 'Adrien' or '10' /// Entry token need to be ( - fn parseNewData(self: Parser, member_map: *std.StringHashMap([]const u8), struct_name: []const u8) !void { + fn parseNewData(self: Parser, allocator: Allocator, map: *std.StringHashMap(ConditionValue), struct_name: []const u8) !void { var token = self.toker.next(); var keep_next = false; var member_name: []const u8 = undefined; // Maybe use allocator.alloc @@ -928,119 +792,7 @@ pub const Parser = struct { .expect_new_value => { const data_type = self.schema_engine.memberName2DataType(struct_name, member_name) catch return ZiQlParserError.StructNotFound; - const start_index = token.loc.start; - - const expected_tag: ?Token.Tag = switch (data_type) { - .int => .int_literal, - .float => .float_literal, - .str => .string_literal, - .self => .uuid_literal, - .date => .date_literal, - .time => .time_literal, - .datetime => .datetime_literal, - .int_array => .int_literal, - .float_array => .float_literal, - .str_array => .string_literal, - .date_array => .date_literal, - .time_array => .time_literal, - .datetime_array => .datetime_literal, - // Handle bool and arrays separately - .bool, .bool_array, .link, .link_array => null, - }; - - if (expected_tag) |tag| { - if (data_type.is_array()) { - if (token.tag != .l_bracket) { - return printError( - "Error: Expected [ to start an array", - ZiQlParserError.SynthaxError, - self.toker.buffer, - token.loc.start, - token.loc.end, - ); - } - token = try self.checkTokensInArray(tag); - } else { - if (token.tag != tag) { - return printError( - "Error: Expected {s}", - ZiQlParserError.SynthaxError, - self.toker.buffer, - token.loc.start, - token.loc.end, - ); - } - } - - switch (data_type) { - .str => member_map.put(member_name, self.toker.buffer[start_index + 1 .. token.loc.end - 1]) catch return ZipponError.MemoryError, // TO remove ' on each side - else => member_map.put(member_name, self.toker.buffer[start_index..token.loc.end]) catch return ZipponError.MemoryError, - } - } else switch (data_type) { - .bool => { - switch (token.tag) { - .bool_literal_true => { - member_map.put(member_name, "1") catch return ZiQlParserError.MemoryError; - }, - .bool_literal_false => { - member_map.put(member_name, "0") catch return ZiQlParserError.MemoryError; - }, - else => return printError( - "Error: Expected bool: true, false, or null", - ZiQlParserError.SynthaxError, - self.toker.buffer, - token.loc.start, - token.loc.end, - ), - } - }, - .bool_array => { - if (token.tag != .l_bracket) { - return printError( - "Error: Expected [ to start an array", - ZiQlParserError.SynthaxError, - self.toker.buffer, - token.loc.start, - token.loc.end, - ); - } - token = self.toker.next(); - while (token.tag != .r_bracket) : (token = self.toker.next()) { - if (token.tag != .bool_literal_true and token.tag != .bool_literal_false) { - return printError( - "Error: Expected bool or ]", - ZiQlParserError.SynthaxError, - self.toker.buffer, - token.loc.start, - token.loc.end, - ); - } - } - member_map.put(member_name, self.toker.buffer[start_index..token.loc.end]) catch return ZipponError.MemoryError; - }, - .link => { - switch (token.tag) { - .keyword_none => { - member_map.put(member_name, "00000000-0000-0000-0000-000000000000") catch return ZipponError.MemoryError; - }, - .uuid_literal => { - // TODO: Check if the uuid is in the struct, otherwise return and error - member_map.put(member_name, self.toker.buffer[start_index..token.loc.end]) catch return ZipponError.MemoryError; - }, - .l_brace => {}, // TODO: Get the filter and return the first value found - else => return printError( - "Error: Expected uuid or none", - ZiQlParserError.SynthaxError, - self.toker.buffer, - token.loc.start, - token.loc.end, - ), - } - }, - .link_array => {}, - else => unreachable, - } - + map.put(member_name, try self.parseConditionValue(allocator, struct_name, data_type, &token)) catch return ZipponError.MemoryError; state = .expect_comma_OR_end; }, @@ -1062,6 +814,177 @@ pub const Parser = struct { }; } + fn parseComparisonOperator(self: Parser, token: Token) ZipponError!ComparisonOperator { + return switch (token.tag) { + .equal => .equal, // = + .angle_bracket_left => .inferior, // < + .angle_bracket_right => .superior, // > + .angle_bracket_left_equal => .inferior_or_equal, // <= + .angle_bracket_right_equal => .superior_or_equal, // >= + .bang_equal => .different, // != + .keyword_in => .in, + .keyword_not_in => .not_in, + else => return printError( + "Error: Expected condition. Including < > <= >= = !=", + ZiQlParserError.SynthaxError, + self.toker.buffer, + token.loc.start, + token.loc.end, + ), + }; + } + + /// To run just after a condition like = or > or >= to get the corresponding ConditionValue that you need to compare + fn parseConditionValue(self: Parser, allocator: Allocator, struct_name: []const u8, data_type: dtype.DataType, token: *Token) ZipponError!ConditionValue { + const start_index = token.loc.start; + const expected_tag: ?Token.Tag = switch (data_type) { + .int => .int_literal, + .float => .float_literal, + .str => .string_literal, + .self => .uuid_literal, + .date => .date_literal, + .time => .time_literal, + .datetime => .datetime_literal, + .int_array => .int_literal, + .float_array => .float_literal, + .str_array => .string_literal, + .date_array => .date_literal, + .time_array => .time_literal, + .datetime_array => .datetime_literal, + .bool, .bool_array, .link, .link_array => null, // handle separately + }; + + // Check if the all next tokens are the right one + if (expected_tag) |tag| { + if (data_type.is_array()) { + token.* = try self.checkTokensInArray(tag); + } else { + if (token.tag != tag) { + return printError( + "Error: Wrong type", // TODO: Print the expected type + ZiQlParserError.SynthaxError, + self.toker.buffer, + token.loc.start, + token.loc.end, + ); + } + } + } else switch (data_type) { + .bool => { + if (token.tag != .bool_literal_true and token.tag != .bool_literal_false) { + return printError( + "Error: Expected bool", + ZiQlParserError.SynthaxError, + self.toker.buffer, + token.loc.start, + token.loc.end, + ); + } + }, + .bool_array => { + token.* = self.toker.next(); + while (token.tag != .r_bracket) : (token.* = self.toker.next()) { + if (token.tag != .bool_literal_true and token.tag != .bool_literal_false) { + return printError( + "Error: Expected bool or ]", + ZiQlParserError.SynthaxError, + self.toker.buffer, + token.loc.start, + token.loc.end, + ); + } + } + }, + .link, .link_array => {}, // TODO: Check if next token is either [ or { + else => unreachable, + } + + // And finally create the ConditionValue + var value: ConditionValue = undefined; + switch (data_type) { + .int => value = ConditionValue.initInt(self.toker.buffer[start_index..token.loc.end]), + .float => value = ConditionValue.initFloat(self.toker.buffer[start_index..token.loc.end]), + .str => value = ConditionValue.initStr(self.toker.buffer[start_index + 1 .. token.loc.end - 1]), + .date => value = ConditionValue.initDate(self.toker.buffer[start_index..token.loc.end]), + .time => value = ConditionValue.initTime(self.toker.buffer[start_index..token.loc.end]), + .datetime => value = ConditionValue.initDateTime(self.toker.buffer[start_index..token.loc.end]), + .bool => value = ConditionValue.initBool(self.toker.buffer[start_index..token.loc.end]), + .link_array, .link => switch (token.tag) { + .keyword_none => { + const map = allocator.create(std.AutoHashMap(UUID, void)) catch return ZipponError.MemoryError; + map.* = std.AutoHashMap(UUID, void).init(allocator); + _ = map.getOrPut(UUID.parse("00000000-0000-0000-0000-000000000000") catch @panic("Sorry wot ?")) catch return ZipponError.MemoryError; + value = ConditionValue.initLink(map); + }, + .uuid_literal => { + const uuid = UUID.parse(self.toker.buffer[start_index..token.loc.end]) catch return ZipponError.InvalidUUID; + if (!self.schema_engine.isUUIDExist(struct_name, uuid)) return printError( + "Error: UUID do not exist in database.", + ZiQlParserError.SynthaxError, + self.toker.buffer, + token.loc.start, + token.loc.end, + ); + + const map = allocator.create(std.AutoHashMap(UUID, void)) catch return ZipponError.MemoryError; + map.* = std.AutoHashMap(UUID, void).init(allocator); + _ = map.getOrPut(uuid) catch return ZipponError.MemoryError; + value = ConditionValue.initLink(map); + }, + .l_brace, .l_bracket => { + var filter: ?Filter = null; + defer if (filter != null) filter.?.deinit(); + var additional_data = AdditionalData.init(allocator); + defer additional_data.deinit(); + + if (token.tag == .l_bracket) { + try self.parseAdditionalData(allocator, &additional_data, struct_name); + token.* = self.toker.next(); + } + + if (data_type == .link) additional_data.entity_count_to_find = 1; + + if (token.tag == .l_brace) filter = try self.parseFilter(allocator, struct_name, false) else return printError( + "Error: Expected filter", + ZiQlParserError.SynthaxError, + self.toker.buffer, + token.loc.start, + token.loc.end, + ); + + // Here I have the filter and additionalData + const map = allocator.create(std.AutoHashMap(UUID, void)) catch return ZipponError.MemoryError; + map.* = std.AutoHashMap(UUID, void).init(allocator); + try self.file_engine.populateVoidUUIDMap( + struct_name, + filter, + map, + &additional_data, + ); + log.debug("Found {d} entity when parsing for populateVoidUUID\n", .{map.count()}); + value = ConditionValue.initLink(map); + }, + else => return printError( + "Error: Expected uuid or none", + ZiQlParserError.SynthaxError, + self.toker.buffer, + token.loc.start, + token.loc.end, + ), + }, + .int_array => value = try ConditionValue.initArrayInt(allocator, self.toker.buffer[start_index..token.loc.end]), + .str_array => value = try ConditionValue.initArrayStr(allocator, self.toker.buffer[start_index..token.loc.end]), + .bool_array => value = try ConditionValue.initArrayBool(allocator, self.toker.buffer[start_index..token.loc.end]), + .float_array => value = try ConditionValue.initArrayFloat(allocator, self.toker.buffer[start_index..token.loc.end]), + .date_array => value = try ConditionValue.initArrayDate(allocator, self.toker.buffer[start_index..token.loc.end]), + .time_array => value = try ConditionValue.initArrayTime(allocator, self.toker.buffer[start_index..token.loc.end]), + .datetime_array => value = try ConditionValue.initArrayDateTime(allocator, self.toker.buffer[start_index..token.loc.end]), + else => unreachable, + } + + return value; + } + /// Check if all token in an array is of one specific type fn checkTokensInArray(self: Parser, tag: Token.Tag) ZipponError!Token { var token = self.toker.next(); @@ -1142,6 +1065,7 @@ test "Specific query" { //} test "Synthax error" { + try expectParsingError("ADD User (name = 'Bob', email='bob@email.com', age=-55, scores=[ 1 ], best_friend=7db1f06d-a5a7-4917-8cc6-4d490191c9c1, bday=2000/01/01, a_time=12:04:54.8741, last_order=2000/01/01-12:45)", ZiQlParserError.SynthaxError); try expectParsingError("GRAB {}", ZiQlParserError.StructNotFound); try expectParsingError("GRAB User {qwe = 'qwe'}", ZiQlParserError.MemberNotFound); try expectParsingError("ADD User (name='Bob')", ZiQlParserError.MemberMissing);