NewData map now use ConditionValue

This commit is contained in:
Adrien Bouvais 2024-11-24 16:26:26 +01:00
parent 23e8ed8709
commit ceab51da27
4 changed files with 248 additions and 374 deletions

View File

@ -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});

View File

@ -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);
}
};

View File

@ -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 => {},
}
}

View File

@ -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);