IN filter working

Now if I do like GRAB User { best_friends IN {name = 'Bob'}} it should
work

At least now the condition value is a hashmap with key as UUID.
This commit is contained in:
Adrien Bouvais 2024-11-17 21:52:11 +01:00
parent 7b2a754d81
commit 979690fec4
3 changed files with 37 additions and 48 deletions

View File

@ -29,7 +29,7 @@ pub const DataType = enum {
pub fn is_array(self: DataType) bool { pub fn is_array(self: DataType) bool {
return switch (self) { return switch (self) {
.int_array, .float_array, .str_array, .bool_array, .date_array, .time_array, .datetime_array => true, .int_array, .float_array, .str_array, .bool_array, .date_array, .time_array, .datetime_array, .link_array => true,
else => false, else => false,
}; };
} }

View File

@ -16,6 +16,8 @@ const DateTime = @import("dtype").DateTime;
const UUID = @import("dtype").UUID; const UUID = @import("dtype").UUID;
const Data = @import("ZipponData").Data; const Data = @import("ZipponData").Data;
const log = std.log.scoped(.filter);
const ComparisonOperator = enum { const ComparisonOperator = enum {
equal, equal,
different, different,
@ -64,7 +66,7 @@ pub const ConditionValue = union(enum) {
float_array: std.ArrayList(f64), float_array: std.ArrayList(f64),
bool_array: std.ArrayList(bool), bool_array: std.ArrayList(bool),
unix_array: std.ArrayList(u64), unix_array: std.ArrayList(u64),
link_array: *std.AutoHashMap(UUID, void), link: *std.AutoHashMap(UUID, void),
pub fn deinit(self: ConditionValue, allocator: std.mem.Allocator) void { pub fn deinit(self: ConditionValue, allocator: std.mem.Allocator) void {
switch (self) { switch (self) {
@ -73,9 +75,9 @@ pub const ConditionValue = union(enum) {
.float_array => self.float_array.deinit(), .float_array => self.float_array.deinit(),
.bool_array => self.bool_array.deinit(), .bool_array => self.bool_array.deinit(),
.unix_array => self.unix_array.deinit(), .unix_array => self.unix_array.deinit(),
.link_array => { .link => {
self.link_array.deinit(); self.link.deinit();
allocator.destroy(self.link_array); allocator.destroy(self.link);
}, },
else => {}, else => {},
} }
@ -142,8 +144,8 @@ pub const ConditionValue = union(enum) {
return ConditionValue{ .unix_array = s2t.parseArrayDatetimeUnix(allocator, value) }; return ConditionValue{ .unix_array = s2t.parseArrayDatetimeUnix(allocator, value) };
} }
pub fn initLinkArray(value: *std.AutoHashMap(UUID, void)) ConditionValue { pub fn initLink(value: *std.AutoHashMap(UUID, void)) ConditionValue {
return ConditionValue{ .link_array = value }; return ConditionValue{ .link = value };
} }
}; };
@ -267,9 +269,9 @@ pub const Filter = struct {
fn evaluateNode(self: Filter, node: *FilterNode, row: []Data) bool { fn evaluateNode(self: Filter, node: *FilterNode, row: []Data) bool {
return switch (node.*) { return switch (node.*) {
.condition => |cond| Filter.evaluateCondition(cond, row), .condition => |cond| Filter.evaluateCondition(cond, row),
.logical => |log| switch (log.operator) { .logical => |logical| switch (logical.operator) {
.AND => self.evaluateNode(log.left, row) and self.evaluateNode(log.right, row), .AND => self.evaluateNode(logical.left, row) and self.evaluateNode(logical.right, row),
.OR => self.evaluateNode(log.left, row) or self.evaluateNode(log.right, row), .OR => self.evaluateNode(logical.left, row) or self.evaluateNode(logical.right, row),
}, },
.empty => true, .empty => true,
}; };
@ -277,6 +279,7 @@ pub const Filter = struct {
fn evaluateCondition(condition: Condition, row: []Data) bool { fn evaluateCondition(condition: Condition, row: []Data) bool {
const row_value: Data = row[condition.data_index]; const row_value: Data = row[condition.data_index];
log.debug("Checking condition {any}", .{condition});
return switch (condition.operation) { return switch (condition.operation) {
.equal => switch (condition.data_type) { .equal => switch (condition.data_type) {
.int => row_value.Int == condition.value.int, .int => row_value.Int == condition.value.int,
@ -324,7 +327,15 @@ pub const Filter = struct {
else => unreachable, else => unreachable,
}, },
else => false, .in => switch (condition.data_type) {
.link => condition.value.link.contains(UUID{ .bytes = row_value.UUID }),
else => unreachable,
},
.not_in => switch (condition.data_type) {
.link => !condition.value.link.contains(UUID{ .bytes = row_value.UUID }),
else => unreachable,
},
}; };
} }
@ -390,12 +401,12 @@ test "ConditionValue: link" {
try hash_map.put(uuid2, {}); try hash_map.put(uuid2, {});
// Create a ConditionValue with the link // Create a ConditionValue with the link
var value = ConditionValue.initLinkArray(&hash_map); var value = ConditionValue.initLink(&hash_map);
// Check that the hash map contains the correct number of UUIDs // Check that the hash map contains the correct number of UUIDs
try std.testing.expectEqual(@as(usize, 2), value.link_array.count()); try std.testing.expectEqual(@as(usize, 2), value.link.count());
// Check that specific UUIDs are in the hash map // Check that specific UUIDs are in the hash map
try std.testing.expect(value.link_array.contains(uuid1)); try std.testing.expect(value.link.contains(uuid1));
try std.testing.expect(value.link_array.contains(uuid2)); try std.testing.expect(value.link.contains(uuid2));
} }

View File

@ -582,9 +582,8 @@ pub const Parser = struct {
); );
} }
} }
} else { } else switch (condition.data_type) {
// handle bool and bool array separately .bool => {
if (condition.data_type == .bool) {
if (token.tag != .bool_literal_true and token.tag != .bool_literal_false) { if (token.tag != .bool_literal_true and token.tag != .bool_literal_false) {
return printError( return printError(
"Error: Expected bool", "Error: Expected bool",
@ -594,7 +593,8 @@ pub const Parser = struct {
token.loc.end, token.loc.end,
); );
} }
} else if (condition.data_type == .bool_array) { },
.bool_array => {
token = self.toker.next(); token = self.toker.next();
while (token.tag != .r_bracket) : (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) { if (token.tag != .bool_literal_true and token.tag != .bool_literal_false) {
@ -607,7 +607,8 @@ pub const Parser = struct {
); );
} }
} }
} else if (condition.data_type == .link) { },
.link, .link_array => {
switch (token.tag) { switch (token.tag) {
.l_bracket => { .l_bracket => {
try self.parseAdditionalData( try self.parseAdditionalData(
@ -619,7 +620,7 @@ pub const Parser = struct {
else => {}, else => {},
} }
additional_data.entity_count_to_find = 1; if (condition.data_type == .link) additional_data.entity_count_to_find = 1;
switch (token.tag) { switch (token.tag) {
.l_brace => { .l_brace => {
@ -634,30 +635,8 @@ pub const Parser = struct {
token.loc.end, token.loc.end,
), ),
} }
} else if (condition.data_type == .link_array) { },
switch (token.tag) { // TODO: Also be able to do an array of UUID like [00000-00000-00000 000000-000000-0000001] else => unreachable,
.l_bracket => {
try self.parseAdditionalData(
&additional_data,
struct_name,
);
},
else => {},
}
switch (token.tag) {
.l_brace => {
filter = try self.parseFilter(struct_name, false);
},
else => return printError(
"Error: Expected new filter",
ZiQlParserError.SynthaxError,
self.toker.buffer,
token.loc.start,
token.loc.end,
),
}
}
} }
switch (condition.data_type) { switch (condition.data_type) {
@ -672,7 +651,6 @@ pub const Parser = struct {
.l_brace, .l_bracket => { .l_brace, .l_bracket => {
const map = self.allocator.create(std.AutoHashMap(UUID, void)) catch return ZipponError.MemoryError; const map = self.allocator.create(std.AutoHashMap(UUID, void)) catch return ZipponError.MemoryError;
map.* = std.AutoHashMap(UUID, void).init(self.allocator); map.* = std.AutoHashMap(UUID, void).init(self.allocator);
if (condition.data_type == .link) additional_data.entity_count_to_find = 1; // FIXME: Look like it return 2 of them, not 1
try self.file_engine.populateVoidUUIDMap( try self.file_engine.populateVoidUUIDMap(
struct_name, struct_name,
filter, filter,
@ -680,7 +658,7 @@ pub const Parser = struct {
&additional_data, &additional_data,
); );
log.debug("Found {d} entity when parsing for populateVoidUUID\n", .{map.count()}); log.debug("Found {d} entity when parsing for populateVoidUUID\n", .{map.count()});
condition.value = ConditionValue.initLinkArray(map); condition.value = ConditionValue.initLink(map);
}, },
else => return printError( else => return printError(
"Error: Expected filter", "Error: Expected filter",
@ -769,7 +747,7 @@ pub const Parser = struct {
.in => switch (condition.data_type) { .in => switch (condition.data_type) {
.link => {}, .link => {},
else => return printError( else => return printError(
"Error: Only link can be compare with in.", "Error: Only link can be compare with in for now.",
ZiQlParserError.ConditionError, ZiQlParserError.ConditionError,
self.toker.buffer, self.toker.buffer,
token.loc.start, token.loc.start,