ZipponDB/src/schemaEngine.zig
MrBounty 7b2a754d81 Check if additional data count is reached at each iteration
Before I was checking after the filter.evaluate is true. So I can end up
with the limit reach, but the thread will continue parsing until it find
one that is true, add it and then check if the limit is reach.

Which mean I endup with more than what I want and the thread could stop
before, making things faster.
2024-11-17 20:45:58 +01:00

160 lines
6.2 KiB
Zig

const std = @import("std");
const Allocator = std.mem.Allocator;
const SchemaStruct = @import("schemaParser.zig").Parser.SchemaStruct;
const Parser = @import("schemaParser.zig").Parser;
const Tokenizer = @import("tokenizers/schema.zig").Tokenizer;
const ZipponError = @import("stuffs/errors.zig").ZipponError;
const dtype = @import("dtype");
const DataType = dtype.DataType;
const FileEngine = @import("fileEngine.zig").FileEngine;
const config = @import("config.zig");
const BUFFER_SIZE = config.BUFFER_SIZE;
const log = std.log.scoped(.schemaEngine);
/// Manage everything that is relate to the schema
/// This include keeping in memory the schema and schema file, and some functions to get like all members of a specific struct.
/// For now it is a bit empty. But this is where I will manage migration
pub const SchemaEngine = struct {
allocator: Allocator,
null_terminated_schema_buff: [:0]u8,
struct_array: []SchemaStruct,
// The path is the path to the schema file
pub fn init(allocator: Allocator, path: []const u8, file_engine: *FileEngine) ZipponError!SchemaEngine {
log.debug("Trying to init a SchemaEngine with path {s}", .{path});
var schema_buf = allocator.alloc(u8, BUFFER_SIZE) catch return ZipponError.MemoryError;
defer allocator.free(schema_buf);
const len: usize = try FileEngine.readSchemaFile(path, schema_buf);
const null_terminated_schema_buff = allocator.dupeZ(u8, schema_buf[0..len]) catch return ZipponError.MemoryError;
errdefer allocator.free(null_terminated_schema_buff);
var toker = Tokenizer.init(null_terminated_schema_buff);
var parser = Parser.init(&toker, allocator);
var struct_array = std.ArrayList(SchemaStruct).init(allocator);
errdefer struct_array.deinit();
parser.parse(&struct_array) catch return ZipponError.SchemaNotConform;
log.debug("SchemaEngine init with {d} SchemaStruct.", .{struct_array.items.len});
for (struct_array.items) |sstruct| {
file_engine.populateFileIndexUUIDMap(sstruct, sstruct.uuid_file_index) catch |err| {
log.err("Error populate file index UUID map {any}", .{err});
};
}
return SchemaEngine{
.allocator = allocator,
.null_terminated_schema_buff = null_terminated_schema_buff,
.struct_array = struct_array.toOwnedSlice() catch return ZipponError.MemoryError,
};
}
pub fn deinit(self: *SchemaEngine) void {
for (self.struct_array) |*elem| elem.deinit();
self.allocator.free(self.struct_array);
self.allocator.free(self.null_terminated_schema_buff);
}
/// Get the type of the member
pub fn memberName2DataType(self: *SchemaEngine, struct_name: []const u8, member_name: []const u8) ZipponError!DataType {
var i: usize = 0;
for (try self.structName2structMembers(struct_name)) |mn| {
const dtypes = try self.structName2DataType(struct_name);
if (std.mem.eql(u8, mn, member_name)) return dtypes[i];
i += 1;
}
return ZipponError.MemberNotFound;
}
pub fn memberName2DataIndex(self: *SchemaEngine, struct_name: []const u8, member_name: []const u8) ZipponError!usize {
var i: usize = 0;
for (try self.structName2structMembers(struct_name)) |mn| {
if (std.mem.eql(u8, mn, member_name)) return i;
i += 1;
}
return ZipponError.MemberNotFound;
}
/// Get the list of all member name for a struct name
pub fn structName2structMembers(self: *SchemaEngine, struct_name: []const u8) ZipponError![][]const u8 {
var i: usize = 0;
while (i < self.struct_array.len) : (i += 1) if (std.mem.eql(u8, self.struct_array[i].name, struct_name)) break;
if (i == self.struct_array.len) {
return ZipponError.StructNotFound;
}
return self.struct_array[i].members;
}
pub fn structName2SchemaStruct(self: *SchemaEngine, struct_name: []const u8) ZipponError!SchemaStruct {
var i: usize = 0;
while (i < self.struct_array.len) : (i += 1) if (std.mem.eql(u8, self.struct_array[i].name, struct_name)) break;
if (i == self.struct_array.len) {
return ZipponError.StructNotFound;
}
return self.struct_array[i];
}
pub fn structName2DataType(self: *SchemaEngine, struct_name: []const u8) ZipponError![]const DataType {
var i: u16 = 0;
while (i < self.struct_array.len) : (i += 1) {
if (std.mem.eql(u8, self.struct_array[i].name, struct_name)) break;
}
if (i == self.struct_array.len and !std.mem.eql(u8, self.struct_array[i].name, struct_name)) {
return ZipponError.StructNotFound;
}
return self.struct_array[i].types;
}
/// Chech if the name of a struct is in the current schema
pub fn isStructNameExists(self: *SchemaEngine, struct_name: []const u8) bool {
var i: u16 = 0;
while (i < self.struct_array.len) : (i += 1) if (std.mem.eql(u8, self.struct_array[i].name, struct_name)) return true;
return false;
}
/// Check if a struct have the member name
pub fn isMemberNameInStruct(self: *SchemaEngine, struct_name: []const u8, member_name: []const u8) ZipponError!bool {
for (try self.structName2structMembers(struct_name)) |mn| {
if (std.mem.eql(u8, mn, member_name)) return true;
}
return false;
}
// Return true if the map have all the member name as key and not more
pub fn checkIfAllMemberInMap(
self: *SchemaEngine,
struct_name: []const u8,
map: *std.StringHashMap([]const u8),
error_message_buffer: *std.ArrayList(u8),
) ZipponError!bool {
const all_struct_member = try self.structName2structMembers(struct_name);
var count: u16 = 0;
const writer = error_message_buffer.writer();
for (all_struct_member) |mn| {
if (std.mem.eql(u8, mn, "id")) continue;
if (map.contains(mn)) count += 1 else writer.print(" {s},", .{mn}) catch return ZipponError.WriteError;
}
return ((count == all_struct_member.len - 1) and (count == map.count()));
}
};