Moved benchmark and test to src. Implemented array without testing yet
This commit is contained in:
parent
a476cef2df
commit
78e8b67b80
18
build.zig
18
build.zig
@ -34,7 +34,7 @@ pub fn build(b: *std.Build) void {
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
.name = "CLI tokenizer",
|
||||
.test_runner = b.path("test_runner.zig"),
|
||||
.test_runner = b.path("src/test_runner.zig"),
|
||||
});
|
||||
tests1.root_module.addImport("dtype", b.createModule(.{ .root_source_file = b.path("lib/types/out.zig") }));
|
||||
const run_tests1 = b.addRunArtifact(tests1);
|
||||
@ -44,7 +44,7 @@ pub fn build(b: *std.Build) void {
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
.name = "CLI tokenizer",
|
||||
.test_runner = b.path("test_runner.zig"),
|
||||
.test_runner = b.path("src/test_runner.zig"),
|
||||
});
|
||||
const run_tests2 = b.addRunArtifact(tests2);
|
||||
|
||||
@ -53,7 +53,7 @@ pub fn build(b: *std.Build) void {
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
.name = "ZiQL tokenizer",
|
||||
.test_runner = b.path("test_runner.zig"),
|
||||
.test_runner = b.path("src/test_runner.zig"),
|
||||
});
|
||||
const run_tests3 = b.addRunArtifact(tests3);
|
||||
|
||||
@ -62,18 +62,18 @@ pub fn build(b: *std.Build) void {
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
.name = "Schema tokenizer",
|
||||
.test_runner = b.path("test_runner.zig"),
|
||||
.test_runner = b.path("src/test_runner.zig"),
|
||||
});
|
||||
tests4.root_module.addImport("config", b.createModule(.{ .root_source_file = b.path("lib/config.zig") }));
|
||||
tests4.root_module.addImport("dtype", b.createModule(.{ .root_source_file = b.path("lib/types/out.zig") }));
|
||||
const run_tests4 = b.addRunArtifact(tests4);
|
||||
|
||||
const tests5 = b.addTest(.{
|
||||
.root_source_file = b.path("test.zig"),
|
||||
.root_source_file = b.path("src/test.zig"),
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
.name = "ZiQL parser",
|
||||
.test_runner = b.path("test_runner.zig"),
|
||||
.test_runner = b.path("src/test_runner.zig"),
|
||||
});
|
||||
tests5.root_module.addImport("dtype", b.createModule(.{ .root_source_file = b.path("lib/types/out.zig") }));
|
||||
tests5.root_module.addImport("config", b.createModule(.{ .root_source_file = b.path("lib/config.zig") }));
|
||||
@ -86,7 +86,7 @@ pub fn build(b: *std.Build) void {
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
.name = "Filter tree",
|
||||
.test_runner = b.path("test_runner.zig"),
|
||||
.test_runner = b.path("src/test_runner.zig"),
|
||||
});
|
||||
tests6.root_module.addImport("dtype", b.createModule(.{ .root_source_file = b.path("lib/types/out.zig") }));
|
||||
tests6.root_module.addImport("config", b.createModule(.{ .root_source_file = b.path("lib/config.zig") }));
|
||||
@ -111,7 +111,7 @@ pub fn build(b: *std.Build) void {
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
.name = "File parsing",
|
||||
.test_runner = b.path("test_runner.zig"),
|
||||
.test_runner = b.path("src/test_runner.zig"),
|
||||
});
|
||||
const run_tests1 = b.addRunArtifact(tests1);
|
||||
|
||||
@ -124,7 +124,7 @@ pub fn build(b: *std.Build) void {
|
||||
{
|
||||
const benchmark = b.addExecutable(.{
|
||||
.name = "benchmark",
|
||||
.root_source_file = b.path("benchmark.zig"),
|
||||
.root_source_file = b.path("src/benchmark.zig"),
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
});
|
||||
|
@ -6,34 +6,10 @@ pub fn parseInt(value_str: []const u8) i32 {
|
||||
return std.fmt.parseInt(i32, value_str, 10) catch return 0;
|
||||
}
|
||||
|
||||
pub fn parseArrayInt(allocator: std.mem.Allocator, array_str: []const u8) ![]const i32 {
|
||||
var array = std.ArrayList(i32).init(allocator);
|
||||
|
||||
var it = std.mem.splitAny(u8, array_str[1 .. array_str.len - 1], " ");
|
||||
while (it.next()) |x| {
|
||||
if (std.mem.eql(u8, " ", x) or std.mem.eql(u8, "", x)) continue;
|
||||
try array.append(parseInt(x));
|
||||
}
|
||||
|
||||
return try array.toOwnedSlice();
|
||||
}
|
||||
|
||||
pub fn parseFloat(value_str: []const u8) f64 {
|
||||
return std.fmt.parseFloat(f64, value_str) catch return 0;
|
||||
}
|
||||
|
||||
pub fn parseArrayFloat(allocator: std.mem.Allocator, array_str: []const u8) ![]const f64 {
|
||||
var array = std.ArrayList(f64).init(allocator);
|
||||
|
||||
var it = std.mem.splitAny(u8, array_str[1 .. array_str.len - 1], " ");
|
||||
while (it.next()) |x| {
|
||||
if (std.mem.eql(u8, " ", x) or std.mem.eql(u8, "", x)) continue;
|
||||
try array.append(parseFloat(x));
|
||||
}
|
||||
|
||||
return try array.toOwnedSlice();
|
||||
}
|
||||
|
||||
pub fn parseBool(value_str: []const u8) bool {
|
||||
return (value_str[0] != '0');
|
||||
}
|
||||
@ -48,30 +24,6 @@ pub fn parseDate(value_str: []const u8) DateTime {
|
||||
return DateTime.init(year, month - 1, day - 1, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
pub fn parseArrayDate(allocator: std.mem.Allocator, array_str: []const u8) ![]const DateTime {
|
||||
var array = std.ArrayList(DateTime).init(allocator);
|
||||
|
||||
var it = std.mem.splitAny(u8, array_str[1 .. array_str.len - 1], " ");
|
||||
while (it.next()) |x| {
|
||||
if (std.mem.eql(u8, " ", x) or std.mem.eql(u8, "", x)) continue;
|
||||
try array.append(parseDate(x));
|
||||
}
|
||||
|
||||
return try array.toOwnedSlice();
|
||||
}
|
||||
|
||||
pub fn parseArrayDateUnix(allocator: std.mem.Allocator, array_str: []const u8) ![]const u64 {
|
||||
var array = std.ArrayList(u64).init(allocator);
|
||||
|
||||
var it = std.mem.splitAny(u8, array_str[1 .. array_str.len - 1], " ");
|
||||
while (it.next()) |x| {
|
||||
if (std.mem.eql(u8, " ", x) or std.mem.eql(u8, "", x)) continue;
|
||||
try array.append(parseDate(x).toUnix());
|
||||
}
|
||||
|
||||
return array.toOwnedSlice();
|
||||
}
|
||||
|
||||
pub fn parseTime(value_str: []const u8) DateTime {
|
||||
if (std.mem.eql(u8, value_str, "NOW")) return DateTime.now();
|
||||
|
||||
@ -83,30 +35,6 @@ pub fn parseTime(value_str: []const u8) DateTime {
|
||||
return DateTime.init(0, 0, 0, hours, minutes, seconds, milliseconds);
|
||||
}
|
||||
|
||||
pub fn parseArrayTime(allocator: std.mem.Allocator, array_str: []const u8) ![]const DateTime {
|
||||
var array = std.ArrayList(DateTime).init(allocator);
|
||||
|
||||
var it = std.mem.splitAny(u8, array_str[1 .. array_str.len - 1], " ");
|
||||
while (it.next()) |x| {
|
||||
if (std.mem.eql(u8, " ", x) or std.mem.eql(u8, "", x)) continue;
|
||||
try array.append(parseTime(x));
|
||||
}
|
||||
|
||||
return try array.toOwnedSlice();
|
||||
}
|
||||
|
||||
pub fn parseArrayTimeUnix(allocator: std.mem.Allocator, array_str: []const u8) ![]const u64 {
|
||||
var array = std.ArrayList(u64).init(allocator);
|
||||
|
||||
var it = std.mem.splitAny(u8, array_str[1 .. array_str.len - 1], " ");
|
||||
while (it.next()) |x| {
|
||||
if (std.mem.eql(u8, " ", x) or std.mem.eql(u8, "", x)) continue;
|
||||
try array.append(parseTime(x).toUnix());
|
||||
}
|
||||
|
||||
return try array.toOwnedSlice();
|
||||
}
|
||||
|
||||
pub fn parseDatetime(value_str: []const u8) DateTime {
|
||||
if (std.mem.eql(u8, value_str, "NOW")) return DateTime.now();
|
||||
|
||||
@ -121,155 +49,31 @@ pub fn parseDatetime(value_str: []const u8) DateTime {
|
||||
return DateTime.init(year, month - 1, day - 1, hours, minutes, seconds, milliseconds);
|
||||
}
|
||||
|
||||
pub fn parseArrayDatetime(allocator: std.mem.Allocator, array_str: []const u8) ![]const DateTime {
|
||||
var array = std.ArrayList(DateTime).init(allocator);
|
||||
|
||||
var it = std.mem.splitAny(u8, array_str[1 .. array_str.len - 1], " ");
|
||||
while (it.next()) |x| {
|
||||
if (std.mem.eql(u8, " ", x) or std.mem.eql(u8, "", x)) continue;
|
||||
try array.append(parseDatetime(x));
|
||||
}
|
||||
|
||||
return try array.toOwnedSlice();
|
||||
}
|
||||
|
||||
pub fn parseArrayDatetimeUnix(allocator: std.mem.Allocator, array_str: []const u8) ![]const u64 {
|
||||
var array = std.ArrayList(u64).init(allocator);
|
||||
|
||||
var it = std.mem.splitAny(u8, array_str[1 .. array_str.len - 1], " ");
|
||||
while (it.next()) |x| {
|
||||
if (std.mem.eql(u8, " ", x) or std.mem.eql(u8, "", x)) continue;
|
||||
try array.append(parseDatetime(x).toUnix());
|
||||
}
|
||||
|
||||
return try array.toOwnedSlice();
|
||||
}
|
||||
|
||||
pub fn parseArrayBool(allocator: std.mem.Allocator, array_str: []const u8) ![]const bool {
|
||||
var array = std.ArrayList(bool).init(allocator);
|
||||
|
||||
var it = std.mem.splitAny(u8, array_str[1 .. array_str.len - 1], " ");
|
||||
while (it.next()) |x| {
|
||||
if (std.mem.eql(u8, " ", x) or std.mem.eql(u8, "", x)) continue;
|
||||
try array.append(parseBool(x));
|
||||
}
|
||||
|
||||
return try array.toOwnedSlice();
|
||||
}
|
||||
|
||||
pub fn parseArrayUUID(allocator: std.mem.Allocator, array_str: []const u8) ![]const UUID {
|
||||
var array = std.ArrayList(UUID).init(allocator);
|
||||
|
||||
var it = std.mem.splitAny(u8, array_str[1 .. array_str.len - 1], " ");
|
||||
while (it.next()) |x| {
|
||||
if (std.mem.eql(u8, " ", x) or std.mem.eql(u8, "", x)) continue;
|
||||
const uuid = try UUID.parse(x);
|
||||
try array.append(uuid);
|
||||
}
|
||||
|
||||
return try array.toOwnedSlice();
|
||||
}
|
||||
|
||||
pub fn parseArrayUUIDBytes(allocator: std.mem.Allocator, array_str: []const u8) ![]const [16]u8 {
|
||||
var array = std.ArrayList([16]u8).init(allocator);
|
||||
|
||||
var it = std.mem.splitAny(u8, array_str[1 .. array_str.len - 1], " ");
|
||||
while (it.next()) |x| {
|
||||
if (std.mem.eql(u8, " ", x) or std.mem.eql(u8, "", x)) continue;
|
||||
const uuid = try UUID.parse(x);
|
||||
try array.append(uuid.bytes);
|
||||
}
|
||||
|
||||
return try array.toOwnedSlice();
|
||||
}
|
||||
|
||||
// FIXME: I think it will not work if there is a ' inside the string, even \', need to fix that
|
||||
pub fn parseArrayStr(allocator: std.mem.Allocator, array_str: []const u8) ![]const []const u8 {
|
||||
var array = std.ArrayList([]const u8).init(allocator);
|
||||
|
||||
var it = std.mem.splitAny(u8, array_str[1 .. array_str.len - 1], "'");
|
||||
_ = it.next(); // SSkip first token that is empty
|
||||
while (it.next()) |x| {
|
||||
if (std.mem.eql(u8, " ", x) or std.mem.eql(u8, "", x)) continue;
|
||||
try array.append(x);
|
||||
}
|
||||
|
||||
if (array.items.len > 0) allocator.free(array.pop()); // Remove the last because empty like the first one
|
||||
|
||||
return try array.toOwnedSlice();
|
||||
}
|
||||
|
||||
test "Value parsing: Int" {
|
||||
const allocator = std.testing.allocator;
|
||||
|
||||
// Int
|
||||
const values: [3][]const u8 = .{ "1", "42", "Hello" };
|
||||
const expected_values: [3]i32 = .{ 1, 42, 0 };
|
||||
for (values, 0..) |value, i| {
|
||||
try std.testing.expect(parseInt(value) == expected_values[i]);
|
||||
}
|
||||
|
||||
// Int array
|
||||
const array_str = "[1 14 44 42 hello]";
|
||||
const array = try parseArrayInt(allocator, array_str);
|
||||
defer allocator.free(array);
|
||||
const expected_array: [5]i32 = .{ 1, 14, 44, 42, 0 };
|
||||
try std.testing.expect(std.mem.eql(i32, array, &expected_array));
|
||||
}
|
||||
|
||||
test "Value parsing: Float" {
|
||||
const allocator = std.testing.allocator;
|
||||
// Float
|
||||
const values: [3][]const u8 = .{ "1.3", "65.991", "Hello" };
|
||||
const expected_values: [3]f64 = .{ 1.3, 65.991, 0 };
|
||||
for (values, 0..) |value, i| {
|
||||
try std.testing.expect(parseFloat(value) == expected_values[i]);
|
||||
}
|
||||
|
||||
// Float array
|
||||
const array_str = "[1.5 14.3 44.9999 42 hello]";
|
||||
const array = try parseArrayFloat(allocator, array_str);
|
||||
defer allocator.free(array);
|
||||
const expected_array: [5]f64 = .{ 1.5, 14.3, 44.9999, 42, 0 };
|
||||
try std.testing.expect(std.mem.eql(f64, array, &expected_array));
|
||||
}
|
||||
|
||||
test "Value parsing: String" {
|
||||
// Note that I dont parse string because I dont need to, a string is a string
|
||||
|
||||
const allocator = std.testing.allocator;
|
||||
|
||||
// string array
|
||||
const array_str = "['Hello' 'How are you doing ?' '']";
|
||||
const array = try parseArrayStr(allocator, array_str);
|
||||
defer allocator.free(array);
|
||||
const expected_array: [3][]const u8 = .{ "Hello", "How are you doing ?", "" };
|
||||
for (array, expected_array) |parsed, expected| {
|
||||
std.debug.print("{s} : {s}\n", .{ parsed, expected });
|
||||
try std.testing.expect(std.mem.eql(u8, parsed, expected));
|
||||
}
|
||||
}
|
||||
|
||||
test "Value parsing: Bool array" {
|
||||
const allocator = std.testing.allocator;
|
||||
|
||||
const values: [3][]const u8 = .{ "1", "Hello", "0" };
|
||||
const expected_values: [3]bool = .{ true, true, false };
|
||||
for (values, 0..) |value, i| {
|
||||
try std.testing.expect(parseBool(value) == expected_values[i]);
|
||||
}
|
||||
|
||||
// Bool array
|
||||
const array_str = "[1 0 0 1 1]";
|
||||
const array = try parseArrayBool(allocator, array_str);
|
||||
defer allocator.free(array);
|
||||
const expected_array: [5]bool = .{ true, false, false, true, true };
|
||||
try std.testing.expect(std.mem.eql(bool, array, &expected_array));
|
||||
}
|
||||
|
||||
test "Value parsing: Date" {
|
||||
const allocator = std.testing.allocator;
|
||||
// Date
|
||||
const values: [3][]const u8 = .{ "1920/01/01", "1998/01/21", "2024/12/31" };
|
||||
const expected_values: [3]DateTime = .{
|
||||
DateTime.init(1920, 0, 0, 0, 0, 0, 0),
|
||||
@ -279,24 +83,9 @@ test "Value parsing: Date" {
|
||||
for (values, 0..) |value, i| {
|
||||
try std.testing.expect(expected_values[i].compareDate(parseDate(value)));
|
||||
}
|
||||
|
||||
// Date array
|
||||
const array_str = "[1920/01/01 1998/01/21 2024/12/31]";
|
||||
const array = try parseArrayDate(allocator, array_str);
|
||||
defer allocator.free(array);
|
||||
const expected_array: [3]DateTime = .{
|
||||
DateTime.init(1920, 0, 0, 0, 0, 0, 0),
|
||||
DateTime.init(1998, 0, 20, 0, 0, 0, 0),
|
||||
DateTime.init(2024, 11, 30, 0, 0, 0, 0),
|
||||
};
|
||||
for (array, expected_array) |parsed, expected| {
|
||||
try std.testing.expect(expected.compareDate(parsed));
|
||||
}
|
||||
}
|
||||
|
||||
test "Value parsing: Time" {
|
||||
const allocator = std.testing.allocator;
|
||||
|
||||
const values: [4][]const u8 = .{ "12:45:00.0000", "18:12:53.7491", "02:30:10", "12:30" };
|
||||
const expected_values: [4]DateTime = .{
|
||||
DateTime.init(0, 0, 0, 12, 45, 0, 0),
|
||||
@ -307,25 +96,9 @@ test "Value parsing: Time" {
|
||||
for (values, 0..) |value, i| {
|
||||
try std.testing.expect(expected_values[i].compareTime(parseTime(value)));
|
||||
}
|
||||
|
||||
// Time array
|
||||
const array_str = "[12:45:00.0000 18:12:53.7491 02:30:10 12:30]";
|
||||
const array = try parseArrayTime(allocator, array_str);
|
||||
defer allocator.free(array);
|
||||
const expected_array: [4]DateTime = .{
|
||||
DateTime.init(0, 0, 0, 12, 45, 0, 0),
|
||||
DateTime.init(0, 0, 0, 18, 12, 53, 7491),
|
||||
DateTime.init(0, 0, 0, 2, 30, 10, 0),
|
||||
DateTime.init(0, 0, 0, 12, 30, 0, 0),
|
||||
};
|
||||
for (array, expected_array) |parsed, expected| {
|
||||
try std.testing.expect(expected.compareTime(parsed));
|
||||
}
|
||||
}
|
||||
|
||||
test "Value parsing: Datetime" {
|
||||
const allocator = std.testing.allocator;
|
||||
|
||||
const values: [4][]const u8 = .{ "1920/01/01-12:45:00.0000", "1920/01/01-18:12:53.7491", "1920/01/01-02:30:10", "1920/01/01-12:30" };
|
||||
const expected_values: [4]DateTime = .{
|
||||
DateTime.init(1920, 0, 0, 12, 45, 0, 0),
|
||||
@ -336,18 +109,4 @@ test "Value parsing: Datetime" {
|
||||
for (values, 0..) |value, i| {
|
||||
try std.testing.expect(expected_values[i].compareDatetime(parseDatetime(value)));
|
||||
}
|
||||
|
||||
// Time array
|
||||
const array_str = "[1920/01/01-12:45:00.0000 1920/01/01-18:12:53.7491 1920/01/01-02:30:10 1920/01/01-12:30]";
|
||||
const array = try parseArrayDatetime(allocator, array_str);
|
||||
defer allocator.free(array);
|
||||
const expected_array: [4]DateTime = .{
|
||||
DateTime.init(1920, 0, 0, 12, 45, 0, 0),
|
||||
DateTime.init(1920, 0, 0, 18, 12, 53, 7491),
|
||||
DateTime.init(1920, 0, 0, 2, 30, 10, 0),
|
||||
DateTime.init(1920, 0, 0, 12, 30, 0, 0),
|
||||
};
|
||||
for (array, expected_array) |parsed, expected| {
|
||||
try std.testing.expect(expected.compareDatetime(parsed));
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,8 @@
|
||||
User (
|
||||
name: str,
|
||||
email: str,
|
||||
age: int,
|
||||
address: str,
|
||||
)
|
||||
|
||||
Order (
|
||||
|
@ -1,6 +1,6 @@
|
||||
const std = @import("std");
|
||||
const dtype = @import("dtype");
|
||||
const DBEngine = @import("src/cli/core.zig");
|
||||
const DBEngine = @import("cli/core.zig");
|
||||
const ZipponError = @import("error").ZipponError;
|
||||
|
||||
const names = [_][]const u8{ "Alice", "Bob", "Charlie", "Dave", "Eve" };
|
||||
@ -8,13 +8,15 @@ const emails = [_][]const u8{ "alice@email.com", "bob@email.com", "charlie@email
|
||||
const dates = [_][]const u8{ "2000/01/01", "1954/04/02", "1998/01/21", "1977/12/31" };
|
||||
const times = [_][]const u8{ "12:04", "20:45:11", "03:11:13", "03:00:01.0152" };
|
||||
const datetimes = [_][]const u8{ "2000/01/01-12:04", "1954/04/02-20:45:11", "1998/01/21-03:11:13", "1977/12/31-03:00:01.0153" };
|
||||
const scores = [_]i32{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
|
||||
const ages = [_][]const u8{ "15", "11", "53", "34", "96", "64" };
|
||||
const address = [_][]const u8{ "01 rue Notre Dame", "11 street St Bob", "Route to Heaven bis", "Here", "Not here", "Maybe here" };
|
||||
|
||||
pub const std_options = std.Options{
|
||||
.log_level = .info,
|
||||
.logFn = myLog,
|
||||
};
|
||||
|
||||
const NUMBER_OF_RUN: usize = 10;
|
||||
var date_buffer: [64]u8 = undefined;
|
||||
var date_fa = std.heap.FixedBufferAllocator.init(&date_buffer);
|
||||
const date_allocator = date_fa.allocator();
|
||||
@ -144,19 +146,23 @@ pub fn benchmark(allocator: std.mem.Allocator) !void {
|
||||
var writer = array.writer();
|
||||
|
||||
try writer.print(
|
||||
"ADD User (name = '{s}', email='{s}', orders=none)",
|
||||
"ADD User (name = '{s}', email='{s}', age={s}, address='{s}')",
|
||||
.{
|
||||
names[rng.uintAtMost(usize, names.len - 1)],
|
||||
emails[rng.uintAtMost(usize, emails.len - 1)],
|
||||
ages[rng.uintAtMost(usize, ages.len - 1)],
|
||||
address[rng.uintAtMost(usize, address.len - 1)],
|
||||
},
|
||||
);
|
||||
|
||||
for (0..users_count - 1) |_| {
|
||||
try writer.print(
|
||||
"('{s}', '{s}', none)",
|
||||
"('{s}', '{s}', {s}, '{s}')",
|
||||
.{
|
||||
names[rng.uintAtMost(usize, names.len - 1)],
|
||||
emails[rng.uintAtMost(usize, emails.len - 1)],
|
||||
ages[rng.uintAtMost(usize, ages.len - 1)],
|
||||
address[rng.uintAtMost(usize, address.len - 1)],
|
||||
},
|
||||
);
|
||||
}
|
||||
@ -173,7 +179,7 @@ pub fn benchmark(allocator: std.mem.Allocator) !void {
|
||||
}
|
||||
|
||||
// Order
|
||||
{
|
||||
if (false) {
|
||||
// Linked array not yet implemented and array manipulation not tested
|
||||
const null_term_query_str = try std.fmt.bufPrintZ(
|
||||
&line_buffer, // I dont like 'category = {name='Book'}'. Maybe att a IS keyword ?
|
||||
@ -203,6 +209,8 @@ pub fn benchmark(allocator: std.mem.Allocator) !void {
|
||||
|
||||
// Run query
|
||||
{
|
||||
var read_time: f64 = 0;
|
||||
var read_write_time: f64 = 0;
|
||||
const queries = [_][]const u8{
|
||||
"GRAB User {}",
|
||||
"GRAB User {name='asd'}",
|
||||
@ -212,24 +220,78 @@ pub fn benchmark(allocator: std.mem.Allocator) !void {
|
||||
"GRAB Category {}",
|
||||
"GRAB Item {}",
|
||||
"GRAB Order {}",
|
||||
"GRAB Order [from, items, quantity, at] {at > 2024}",
|
||||
"GRAB Order [from, items, quantity, at] {}",
|
||||
"DELETE User {}",
|
||||
};
|
||||
|
||||
// Run benchmarks
|
||||
for (queries) |query| {
|
||||
const start_time = std.time.nanoTimestamp();
|
||||
for (queries, 0..) |query, j| {
|
||||
var time_buff: [NUMBER_OF_RUN]f64 = undefined;
|
||||
for (0..NUMBER_OF_RUN) |i| {
|
||||
const start_time = std.time.nanoTimestamp();
|
||||
|
||||
// Execute the query here
|
||||
const null_term_query_str = try std.fmt.bufPrintZ(&line_buffer, "{s}", .{query});
|
||||
db_engine.runQuery(null_term_query_str);
|
||||
// Execute the query here
|
||||
const null_term_query_str = try std.fmt.bufPrintZ(&line_buffer, "{s}", .{query});
|
||||
db_engine.runQuery(null_term_query_str);
|
||||
|
||||
const end_time = std.time.nanoTimestamp();
|
||||
const duration = @as(f64, @floatFromInt(end_time - start_time)) / 1e6;
|
||||
const end_time = std.time.nanoTimestamp();
|
||||
time_buff[i] = @as(f64, @floatFromInt(end_time - start_time)) / 1e6;
|
||||
}
|
||||
std.debug.print(
|
||||
"Query: \t{s}\nTime: \t{d:>6.2} ± {d:<6.2}ms | Min {d:>8.2}ms | Max {d:>8.2}ms\n\n",
|
||||
.{ query, mean(time_buff), std_dev(time_buff), min(time_buff), max(time_buff) },
|
||||
);
|
||||
|
||||
std.debug.print("Query: \t\t{s}\nDuration: \t{d:.6} ms\n\n", .{ query, duration });
|
||||
if (j == 0) read_write_time = mean(time_buff);
|
||||
if (j == 1) read_time = mean(time_buff);
|
||||
}
|
||||
std.debug.print(
|
||||
"Read: \t{d:.0} Entity/second\t*Include small condition\n",
|
||||
.{@as(f64, @floatFromInt(users_count)) / (read_time / 1000)},
|
||||
);
|
||||
std.debug.print(
|
||||
"Write: \t{d:.0} Entity/second\n",
|
||||
.{@as(f64, @floatFromInt(users_count)) / ((read_write_time - read_time) / 1000)},
|
||||
);
|
||||
}
|
||||
}
|
||||
std.debug.print("=====================================\n\n", .{});
|
||||
}
|
||||
|
||||
fn min(array: [NUMBER_OF_RUN]f64) f64 {
|
||||
var current_min: f64 = 999999999999;
|
||||
for (array) |value| {
|
||||
if (value < current_min) current_min = value;
|
||||
}
|
||||
return current_min;
|
||||
}
|
||||
|
||||
fn max(array: [NUMBER_OF_RUN]f64) f64 {
|
||||
var current_max: f64 = 0;
|
||||
for (array) |value| {
|
||||
if (value > current_max) current_max = value;
|
||||
}
|
||||
return current_max;
|
||||
}
|
||||
|
||||
fn mean(array: [NUMBER_OF_RUN]f64) f64 {
|
||||
var total: f64 = 0;
|
||||
for (array) |value| {
|
||||
total += value;
|
||||
}
|
||||
return total / @as(f64, @floatFromInt(NUMBER_OF_RUN));
|
||||
}
|
||||
|
||||
fn variance(array: [NUMBER_OF_RUN]f64) f64 {
|
||||
const m = mean(array);
|
||||
var square_diff: f64 = 0;
|
||||
for (array) |value| {
|
||||
square_diff += (value - m) * (value - m);
|
||||
}
|
||||
return square_diff / @as(f64, @floatFromInt(NUMBER_OF_RUN));
|
||||
}
|
||||
|
||||
fn std_dev(array: [NUMBER_OF_RUN]f64) f64 {
|
||||
const vari = variance(array);
|
||||
return @sqrt(vari);
|
||||
}
|
@ -69,6 +69,18 @@ pub const ConditionValue = union(enum) {
|
||||
link: *std.AutoHashMap(UUID, void),
|
||||
link_array: *std.AutoHashMap(UUID, void),
|
||||
|
||||
pub fn init(dtype: DataType, value: []const u8) ConditionValue {
|
||||
return switch (dtype) {
|
||||
.int => ConditionValue.initInt(value),
|
||||
.float => ConditionValue.initFloat(value),
|
||||
.bool => ConditionValue.initBool(value),
|
||||
.date => ConditionValue.initDate(value),
|
||||
.time => ConditionValue.initTime(value),
|
||||
.datetime => ConditionValue.initDateTime(value),
|
||||
.str => ConditionValue.initStr(value[1 .. value.len - 1]),
|
||||
};
|
||||
}
|
||||
|
||||
pub fn initInt(value: []const u8) ConditionValue {
|
||||
return ConditionValue{ .int = s2t.parseInt(value) };
|
||||
}
|
||||
@ -102,32 +114,24 @@ pub const ConditionValue = union(enum) {
|
||||
}
|
||||
|
||||
// Array
|
||||
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 initArrayInt(value: []const i32) ZipponError!ConditionValue {
|
||||
return ConditionValue{ .int_array = 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 initArrayFloat(value: []const f64) ZipponError!ConditionValue {
|
||||
return ConditionValue{ .float_array = 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 initArrayStr(value: []const []const u8) ZipponError!ConditionValue {
|
||||
return ConditionValue{ .str_array = 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 initArrayBool(value: []const bool) ZipponError!ConditionValue {
|
||||
return ConditionValue{ .bool_array = 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) ZipponError!ConditionValue {
|
||||
return ConditionValue{ .unix_array = s2t.parseArrayTimeUnix(allocator, value) catch return ZipponError.ParsingValueError };
|
||||
}
|
||||
|
||||
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 initArrayUnix(value: []const u64) ZipponError!ConditionValue {
|
||||
return ConditionValue{ .unix_array = value };
|
||||
}
|
||||
|
||||
pub fn initLink(value: *std.AutoHashMap(UUID, void)) ConditionValue {
|
||||
@ -308,13 +312,28 @@ pub const Filter = struct {
|
||||
else => unreachable,
|
||||
},
|
||||
|
||||
// TODO: Add stuff to compare array, now condition with value as int, operator as in and to compare as []int should exist
|
||||
.in => switch (condition.data_type) {
|
||||
.link => condition.value.link.contains(UUID{ .bytes = row_value.UUID }),
|
||||
.int => in(i32, row_value.Int, condition.value.int_array),
|
||||
.float => in(f64, row_value.Float, condition.value.float_array),
|
||||
.str => inStr(row_value.Str, condition.value.str_array),
|
||||
.bool => in(bool, row_value.Bool, condition.value.bool_array),
|
||||
.date => in(u64, row_value.Unix, condition.value.unix_array),
|
||||
.time => in(u64, row_value.Unix, condition.value.unix_array),
|
||||
.datetime => in(u64, row_value.Unix, condition.value.unix_array),
|
||||
else => unreachable,
|
||||
},
|
||||
|
||||
.not_in => switch (condition.data_type) {
|
||||
.link => !condition.value.link.contains(UUID{ .bytes = row_value.UUID }),
|
||||
.int => !in(i32, row_value.Int, condition.value.int_array),
|
||||
.float => !in(f64, row_value.Float, condition.value.float_array),
|
||||
.str => !inStr(row_value.Str, condition.value.str_array),
|
||||
.bool => !in(bool, row_value.Bool, condition.value.bool_array),
|
||||
.date => !in(u64, row_value.Unix, condition.value.unix_array),
|
||||
.time => !in(u64, row_value.Unix, condition.value.unix_array),
|
||||
.datetime => !in(u64, row_value.Unix, condition.value.unix_array),
|
||||
else => unreachable,
|
||||
},
|
||||
};
|
||||
@ -343,6 +362,16 @@ pub const Filter = struct {
|
||||
.empty => std.debug.print("Empty", .{}),
|
||||
}
|
||||
}
|
||||
|
||||
fn in(comptime T: type, value: T, array: []const T) bool {
|
||||
for (array) |v| if (v == value) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
fn inStr(value: []const u8, array: []const []const u8) bool {
|
||||
for (array) |v| if (std.mem.eql(u8, v, value)) return true;
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
test "Evaluate" {
|
||||
|
@ -8,7 +8,7 @@ const DataType = dtype.DataType;
|
||||
const DateTime = dtype.DateTime;
|
||||
const UUID = dtype.UUID;
|
||||
|
||||
// TODO: Move this from FileEngine
|
||||
// TODO: Move this outside of FileEngine and make it faster
|
||||
|
||||
const ZipponError = @import("error").ZipponError;
|
||||
|
||||
|
@ -61,7 +61,6 @@ pub fn parse(self: *Parser, allocator: Allocator, struct_array: *std.ArrayList(S
|
||||
},
|
||||
.eof => state = .end,
|
||||
else => {
|
||||
std.debug.print("{s}\n", .{self.toker.getTokenSlice(token)});
|
||||
return printError(
|
||||
"Error parsing schema: Expected a struct name",
|
||||
ZipponError.SynthaxError,
|
||||
|
@ -1,8 +1,8 @@
|
||||
const std = @import("std");
|
||||
const Allocator = std.mem.Allocator;
|
||||
const Parser = @import("src/ziql/parser.zig");
|
||||
const Tokenizer = @import("src/ziql/tokenizer.zig").Tokenizer;
|
||||
const DBEngine = @import("src/cli/core.zig");
|
||||
const Parser = @import("ziql/parser.zig");
|
||||
const Tokenizer = @import("ziql/tokenizer.zig").Tokenizer;
|
||||
const DBEngine = @import("cli/core.zig");
|
||||
const ZipponError = @import("error").ZipponError;
|
||||
|
||||
const DB = struct {
|
||||
@ -124,6 +124,11 @@ test "GRAB Relationship AdditionalData Filtered" {
|
||||
try testParsing(db, "GRAB User [2; name, best_friend] {best_friend !IN {}}");
|
||||
}
|
||||
|
||||
test "GRAB name IN" {
|
||||
const db = DB{ .path = "test1", .schema = "schema/test" };
|
||||
try testParsing(db, "GRAB User {name IN ['Bob' 'Bobinou']}");
|
||||
}
|
||||
|
||||
test "GRAB Relationship dot" {
|
||||
// DO I add this ? I'm not sure about this feature
|
||||
const db = DB{ .path = "test1", .schema = "schema/test" };
|
||||
@ -174,7 +179,9 @@ fn testParsing(db: DB, source: [:0]const u8) !void {
|
||||
&db_engine.schema_engine,
|
||||
);
|
||||
|
||||
std.debug.print("Running: {s}\n", .{source});
|
||||
try parser.parse(allocator, source);
|
||||
std.debug.print("\n\n-------------------------------\n\n", .{});
|
||||
}
|
||||
|
||||
fn expectParsingError(db: DB, source: [:0]const u8, err: ZipponError) !void {
|
||||
@ -187,5 +194,7 @@ fn expectParsingError(db: DB, source: [:0]const u8, err: ZipponError) !void {
|
||||
&db_engine.schema_engine,
|
||||
);
|
||||
|
||||
std.debug.print("Running: {s}\n", .{source});
|
||||
try std.testing.expectError(err, parser.parse(allocator, source));
|
||||
std.debug.print("\n\n-------------------------------\n\n", .{});
|
||||
}
|
@ -67,7 +67,6 @@ pub usingnamespace @import("parts/newData.zig");
|
||||
pub usingnamespace @import("parts/value.zig");
|
||||
pub usingnamespace @import("parts/filter.zig");
|
||||
pub usingnamespace @import("parts/additionalData.zig");
|
||||
pub usingnamespace @import("utils.zig");
|
||||
|
||||
toker: *Tokenizer = undefined,
|
||||
file_engine: *FileEngine,
|
||||
|
@ -71,11 +71,21 @@ pub fn parseCondition(
|
||||
|
||||
.expect_operation => {
|
||||
condition.operation = try self.parseComparisonOperator(token);
|
||||
if (condition.operation == .in) condition.data_type = switch (condition.data_type) {
|
||||
.int => .int_array,
|
||||
.float => .float_array,
|
||||
.str => .str_array,
|
||||
.bool => .bool_array,
|
||||
.date => .date_array,
|
||||
.time => .time_array,
|
||||
.datetime => .datetime_array,
|
||||
else => condition.data_type,
|
||||
};
|
||||
log.debug("Condition operation {any}\n", .{condition.operation});
|
||||
state = .expect_value;
|
||||
},
|
||||
|
||||
.expect_value => {
|
||||
log.debug("Parse condition value of member {s}", .{member_name});
|
||||
condition.value = try self.parseConditionValue(allocator, struct_name, member_name, condition.data_type, &token);
|
||||
state = .end;
|
||||
},
|
||||
@ -87,3 +97,87 @@ pub fn parseCondition(
|
||||
|
||||
return condition;
|
||||
}
|
||||
|
||||
pub fn checkConditionValidity(
|
||||
self: Self,
|
||||
condition: Condition,
|
||||
token: Token,
|
||||
) ZipponError!void {
|
||||
switch (condition.operation) {
|
||||
.equal => switch (condition.data_type) {
|
||||
.int, .float, .str, .bool, .date, .time, .datetime => {},
|
||||
else => return printError(
|
||||
"Error: Only int, float, str, bool, date, time, datetime can be compare with =",
|
||||
ZipponError.ConditionError,
|
||||
self.toker.buffer,
|
||||
token.loc.start,
|
||||
token.loc.end,
|
||||
),
|
||||
},
|
||||
|
||||
.different => switch (condition.data_type) {
|
||||
.int, .float, .str, .bool, .date, .time, .datetime => {},
|
||||
else => return printError(
|
||||
"Error: Only int, float, str, bool, date, time, datetime can be compare with !=",
|
||||
ZipponError.ConditionError,
|
||||
self.toker.buffer,
|
||||
token.loc.start,
|
||||
token.loc.end,
|
||||
),
|
||||
},
|
||||
|
||||
.superior_or_equal => switch (condition.data_type) {
|
||||
.int, .float, .date, .time, .datetime => {},
|
||||
else => return printError(
|
||||
"Error: Only int, float, date, time, datetime can be compare with >=",
|
||||
ZipponError.ConditionError,
|
||||
self.toker.buffer,
|
||||
token.loc.start,
|
||||
token.loc.end,
|
||||
),
|
||||
},
|
||||
|
||||
.superior => switch (condition.data_type) {
|
||||
.int, .float, .date, .time, .datetime => {},
|
||||
else => return printError(
|
||||
"Error: Only int, float, date, time, datetime can be compare with >",
|
||||
ZipponError.ConditionError,
|
||||
self.toker.buffer,
|
||||
token.loc.start,
|
||||
token.loc.end,
|
||||
),
|
||||
},
|
||||
|
||||
.inferior_or_equal => switch (condition.data_type) {
|
||||
.int, .float, .date, .time, .datetime => {},
|
||||
else => return printError(
|
||||
"Error: Only int, float, date, time, datetime can be compare with <=",
|
||||
ZipponError.ConditionError,
|
||||
self.toker.buffer,
|
||||
token.loc.start,
|
||||
token.loc.end,
|
||||
),
|
||||
},
|
||||
|
||||
.inferior => switch (condition.data_type) {
|
||||
.int, .float, .date, .time, .datetime => {},
|
||||
else => return printError(
|
||||
"Error: Only int, float, date, time, datetime can be compare with <",
|
||||
ZipponError.ConditionError,
|
||||
self.toker.buffer,
|
||||
token.loc.start,
|
||||
token.loc.end,
|
||||
),
|
||||
},
|
||||
|
||||
.in => switch (condition.data_type) {
|
||||
.link, .int_array, .float_array, .str_array, .bool_array, .time_array, .date_array, .datetime_array => {},
|
||||
else => unreachable,
|
||||
},
|
||||
|
||||
.not_in => switch (condition.data_type) {
|
||||
.link, .int_array, .float_array, .str_array, .bool_array, .time_array, .date_array, .datetime_array => {},
|
||||
else => unreachable,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
const std = @import("std");
|
||||
const dtype = @import("dtype");
|
||||
const s2t = dtype.s2t;
|
||||
const UUID = dtype.UUID;
|
||||
const Allocator = std.mem.Allocator;
|
||||
const Token = @import("../tokenizer.zig").Token;
|
||||
@ -12,9 +13,10 @@ const ZipponError = @import("error").ZipponError;
|
||||
|
||||
var buff: [1024]u8 = undefined;
|
||||
|
||||
var zero_map_buf: [1024 * 4]u8 = undefined;
|
||||
var zero_map_buf: [200]u8 = undefined;
|
||||
var fba = std.heap.FixedBufferAllocator.init(&zero_map_buf);
|
||||
var zero_map = std.AutoHashMap(UUID, void).init(fba.allocator());
|
||||
var empty_map = std.AutoHashMap(UUID, void).init(fba.allocator());
|
||||
|
||||
const Self = @import("../parser.zig");
|
||||
|
||||
@ -23,148 +25,324 @@ pub fn initZeroMap() ZipponError!void {
|
||||
}
|
||||
|
||||
/// To run just after a condition like = or > or >= to get the corresponding ConditionValue that you need to compare
|
||||
pub fn parseConditionValue(self: Self, allocator: Allocator, struct_name: []const u8, member_name: []const u8, data_type: dtype.DataType, token: *Token) ZipponError!ConditionValue {
|
||||
pub fn parseConditionValue(
|
||||
self: Self,
|
||||
allocator: Allocator,
|
||||
struct_name: []const u8,
|
||||
member_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,
|
||||
.int_array => .int_literal,
|
||||
.float_array => .float_literal,
|
||||
.str_array => .string_literal,
|
||||
.bool, .bool_array, .link, .link_array, .date, .time, .datetime, .date_array, .time_array, .datetime_array => null, // handle separately
|
||||
|
||||
if (data_type.is_array()) switch (token.tag) {
|
||||
.l_bracket => token.* = self.toker.next(),
|
||||
else => return printError(
|
||||
"Error: expecting [ to start array.",
|
||||
ZipponError.SynthaxError,
|
||||
self.toker.buffer,
|
||||
token.loc.start,
|
||||
token.loc.end,
|
||||
),
|
||||
};
|
||||
|
||||
// Check if the all next tokens are the right one
|
||||
if (expected_tag) |tag| {
|
||||
if (data_type.is_array()) {
|
||||
token.* = try self.checkTokensInArray(tag);
|
||||
switch (data_type) {
|
||||
.self => unreachable,
|
||||
|
||||
.int => if (token.tag != .int_literal) {
|
||||
return printError(
|
||||
"Error: Wrong type. Expected: int.",
|
||||
ZipponError.SynthaxError,
|
||||
self.toker.buffer,
|
||||
token.loc.start,
|
||||
token.loc.end,
|
||||
);
|
||||
} else {
|
||||
if (token.tag != tag) {
|
||||
const msg = std.fmt.bufPrint(&buff, "Error: Wrong type. Expected: {any}", .{tag}) catch return ZipponError.MemoryError;
|
||||
return printError(
|
||||
msg,
|
||||
return ConditionValue.initInt(self.toker.buffer[start_index..token.loc.end]);
|
||||
},
|
||||
|
||||
.float => if (token.tag != .float_literal) {
|
||||
return printError(
|
||||
"Error: Wrong type. Expected: float.",
|
||||
ZipponError.SynthaxError,
|
||||
self.toker.buffer,
|
||||
token.loc.start,
|
||||
token.loc.end,
|
||||
);
|
||||
} else {
|
||||
return ConditionValue.initFloat(self.toker.buffer[start_index..token.loc.end]);
|
||||
},
|
||||
|
||||
.str => if (token.tag != .string_literal) {
|
||||
return printError(
|
||||
"Error: Wrong type. Expected: string.",
|
||||
ZipponError.SynthaxError,
|
||||
self.toker.buffer,
|
||||
token.loc.start,
|
||||
token.loc.end,
|
||||
);
|
||||
} else {
|
||||
return ConditionValue.initStr(self.toker.buffer[start_index..token.loc.end]);
|
||||
},
|
||||
|
||||
.bool => if (token.tag != .bool_literal_true and token.tag != .bool_literal_false) {
|
||||
return printError(
|
||||
"Error: Wrong type. Expected: bool.",
|
||||
ZipponError.SynthaxError,
|
||||
self.toker.buffer,
|
||||
token.loc.start,
|
||||
token.loc.end,
|
||||
);
|
||||
} else {
|
||||
return ConditionValue.initBool(self.toker.buffer[start_index..token.loc.end]);
|
||||
},
|
||||
|
||||
.date => if (token.tag != .date_literal and token.tag != .keyword_now) {
|
||||
return printError(
|
||||
"Error: Wrong type. Expected: date.",
|
||||
ZipponError.SynthaxError,
|
||||
self.toker.buffer,
|
||||
token.loc.start,
|
||||
token.loc.end,
|
||||
);
|
||||
} else {
|
||||
return ConditionValue.initDate(self.toker.buffer[start_index..token.loc.end]);
|
||||
},
|
||||
|
||||
.time => if (token.tag != .time_literal and token.tag != .keyword_now) {
|
||||
return printError(
|
||||
"Error: Wrong type. Expected: time.",
|
||||
ZipponError.SynthaxError,
|
||||
self.toker.buffer,
|
||||
token.loc.start,
|
||||
token.loc.end,
|
||||
);
|
||||
} else {
|
||||
return ConditionValue.initTime(self.toker.buffer[start_index..token.loc.end]);
|
||||
},
|
||||
|
||||
.datetime => if (token.tag != .date_literal and token.tag != .datetime_literal and token.tag != .keyword_now) {
|
||||
return printError(
|
||||
"Error: Wrong type. Expected: datetime.",
|
||||
ZipponError.SynthaxError,
|
||||
self.toker.buffer,
|
||||
token.loc.start,
|
||||
token.loc.end,
|
||||
);
|
||||
} else {
|
||||
return ConditionValue.initDateTime(self.toker.buffer[start_index..token.loc.end]);
|
||||
},
|
||||
|
||||
.int_array => {
|
||||
var array = std.ArrayList(i32).init(allocator);
|
||||
errdefer array.deinit();
|
||||
|
||||
var first = true;
|
||||
while (token.tag != .r_bracket) : (token.* = self.toker.next()) {
|
||||
if (!first) {
|
||||
if (token.tag != .comma) return printError(
|
||||
"Error: Expected comma.",
|
||||
ZipponError.SynthaxError,
|
||||
self.toker.buffer,
|
||||
token.loc.start,
|
||||
token.loc.end,
|
||||
);
|
||||
token.* = self.toker.next();
|
||||
} else first = false;
|
||||
|
||||
if (token.tag != .int_literal) return printError(
|
||||
"Error: Wrong type. Expected int.",
|
||||
ZipponError.SynthaxError,
|
||||
self.toker.buffer,
|
||||
token.loc.start,
|
||||
token.loc.end,
|
||||
);
|
||||
array.append(s2t.parseInt(self.toker.getTokenSlice(token.*))) catch return ZipponError.MemoryError;
|
||||
}
|
||||
}
|
||||
} else switch (data_type) {
|
||||
.bool => if (token.tag != .bool_literal_true and token.tag != .bool_literal_false) {
|
||||
return printError(
|
||||
"Error: Expected bool",
|
||||
ZipponError.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 ]",
|
||||
ZipponError.SynthaxError,
|
||||
self.toker.buffer,
|
||||
token.loc.start,
|
||||
token.loc.end,
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
.date => if (token.tag != .date_literal and token.tag != .keyword_now) {
|
||||
return printError(
|
||||
"Error: Expected date",
|
||||
ZipponError.SynthaxError,
|
||||
self.toker.buffer,
|
||||
token.loc.start,
|
||||
token.loc.end,
|
||||
);
|
||||
},
|
||||
.date_array => {
|
||||
token.* = self.toker.next();
|
||||
while (token.tag != .r_bracket) : (token.* = self.toker.next()) {
|
||||
if (token.tag != .date_literal and token.tag != .keyword_now) {
|
||||
return printError(
|
||||
"Error: Expected date",
|
||||
ZipponError.SynthaxError,
|
||||
self.toker.buffer,
|
||||
token.loc.start,
|
||||
token.loc.end,
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
.time => if (token.tag != .time_literal and token.tag != .keyword_now) {
|
||||
return printError(
|
||||
"Error: Expected time",
|
||||
ZipponError.SynthaxError,
|
||||
self.toker.buffer,
|
||||
token.loc.start,
|
||||
token.loc.end,
|
||||
);
|
||||
},
|
||||
.time_array => {
|
||||
token.* = self.toker.next();
|
||||
while (token.tag != .r_bracket) : (token.* = self.toker.next()) {
|
||||
if (token.tag != .time_literal and token.tag != .keyword_now) {
|
||||
return printError(
|
||||
"Error: Expected time",
|
||||
ZipponError.SynthaxError,
|
||||
self.toker.buffer,
|
||||
token.loc.start,
|
||||
token.loc.end,
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
.datetime => if (token.tag != .datetime_literal and token.tag != .keyword_now) {
|
||||
return printError(
|
||||
"Error: Expected datetime",
|
||||
ZipponError.SynthaxError,
|
||||
self.toker.buffer,
|
||||
token.loc.start,
|
||||
token.loc.end,
|
||||
);
|
||||
},
|
||||
.datetime_array => {
|
||||
token.* = self.toker.next();
|
||||
while (token.tag != .r_bracket) : (token.* = self.toker.next()) {
|
||||
if (token.tag != .datetime_literal and token.tag != .keyword_now) {
|
||||
return printError(
|
||||
"Error: Expected datetime",
|
||||
ZipponError.SynthaxError,
|
||||
self.toker.buffer,
|
||||
token.loc.start,
|
||||
token.loc.end,
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
.link, .link_array => {},
|
||||
else => unreachable,
|
||||
}
|
||||
|
||||
// And finally create the ConditionValue
|
||||
switch (data_type) {
|
||||
.int => return ConditionValue.initInt(self.toker.buffer[start_index..token.loc.end]),
|
||||
.float => return ConditionValue.initFloat(self.toker.buffer[start_index..token.loc.end]),
|
||||
.str => return ConditionValue.initStr(self.toker.buffer[start_index + 1 .. token.loc.end - 1]),
|
||||
.date => return ConditionValue.initDate(self.toker.buffer[start_index..token.loc.end]),
|
||||
.time => return ConditionValue.initTime(self.toker.buffer[start_index..token.loc.end]),
|
||||
.datetime => return ConditionValue.initDateTime(self.toker.buffer[start_index..token.loc.end]),
|
||||
.bool => return ConditionValue.initBool(self.toker.buffer[start_index..token.loc.end]),
|
||||
.int_array => return try ConditionValue.initArrayInt(allocator, self.toker.buffer[start_index..token.loc.end]),
|
||||
.str_array => return try ConditionValue.initArrayStr(allocator, self.toker.buffer[start_index..token.loc.end]),
|
||||
.bool_array => return try ConditionValue.initArrayBool(allocator, self.toker.buffer[start_index..token.loc.end]),
|
||||
.float_array => return try ConditionValue.initArrayFloat(allocator, self.toker.buffer[start_index..token.loc.end]),
|
||||
.date_array => return try ConditionValue.initArrayDate(allocator, self.toker.buffer[start_index..token.loc.end]),
|
||||
.time_array => return try ConditionValue.initArrayTime(allocator, self.toker.buffer[start_index..token.loc.end]),
|
||||
.datetime_array => return try ConditionValue.initArrayDateTime(allocator, self.toker.buffer[start_index..token.loc.end]),
|
||||
return try ConditionValue.initArrayInt(array.toOwnedSlice() catch return ZipponError.MemoryError);
|
||||
},
|
||||
|
||||
.float_array => {
|
||||
var array = std.ArrayList(f64).init(allocator);
|
||||
errdefer array.deinit();
|
||||
|
||||
var first = true;
|
||||
while (token.tag != .r_bracket) : (token.* = self.toker.next()) {
|
||||
if (!first) {
|
||||
if (token.tag != .comma) return printError(
|
||||
"Error: Expected comma.",
|
||||
ZipponError.SynthaxError,
|
||||
self.toker.buffer,
|
||||
token.loc.start,
|
||||
token.loc.end,
|
||||
);
|
||||
token.* = self.toker.next();
|
||||
} else first = false;
|
||||
|
||||
if (token.tag != .float_literal) return printError(
|
||||
"Error: Wrong type. Expected float.",
|
||||
ZipponError.SynthaxError,
|
||||
self.toker.buffer,
|
||||
token.loc.start,
|
||||
token.loc.end,
|
||||
);
|
||||
array.append(s2t.parseFloat(self.toker.getTokenSlice(token.*))) catch return ZipponError.MemoryError;
|
||||
}
|
||||
|
||||
return try ConditionValue.initArrayFloat(array.toOwnedSlice() catch return ZipponError.MemoryError);
|
||||
},
|
||||
|
||||
.bool_array => {
|
||||
var array = std.ArrayList(bool).init(allocator);
|
||||
errdefer array.deinit();
|
||||
|
||||
var first = true;
|
||||
while (token.tag != .r_bracket) : (token.* = self.toker.next()) {
|
||||
if (!first) {
|
||||
if (token.tag != .comma) return printError(
|
||||
"Error: Expected comma.",
|
||||
ZipponError.SynthaxError,
|
||||
self.toker.buffer,
|
||||
token.loc.start,
|
||||
token.loc.end,
|
||||
);
|
||||
token.* = self.toker.next();
|
||||
} else first = false;
|
||||
|
||||
if (token.tag != .bool_literal_false and token.tag != .bool_literal_true) return printError(
|
||||
"Error: Wrong type. Expected bool.",
|
||||
ZipponError.SynthaxError,
|
||||
self.toker.buffer,
|
||||
token.loc.start,
|
||||
token.loc.end,
|
||||
);
|
||||
array.append(s2t.parseBool(self.toker.getTokenSlice(token.*))) catch return ZipponError.MemoryError;
|
||||
}
|
||||
|
||||
return try ConditionValue.initArrayBool(array.toOwnedSlice() catch return ZipponError.MemoryError);
|
||||
},
|
||||
|
||||
.str_array => {
|
||||
var array = std.ArrayList([]const u8).init(allocator);
|
||||
errdefer array.deinit();
|
||||
|
||||
var first = true;
|
||||
while (token.tag != .r_bracket) : (token.* = self.toker.next()) {
|
||||
if (!first) {
|
||||
if (token.tag != .comma) return printError(
|
||||
"Error: Expected comma.",
|
||||
ZipponError.SynthaxError,
|
||||
self.toker.buffer,
|
||||
token.loc.start,
|
||||
token.loc.end,
|
||||
);
|
||||
token.* = self.toker.next();
|
||||
} else first = false;
|
||||
|
||||
if (token.tag != .string_literal) return printError(
|
||||
"Error: Wrong type. Expected str.",
|
||||
ZipponError.SynthaxError,
|
||||
self.toker.buffer,
|
||||
token.loc.start,
|
||||
token.loc.end,
|
||||
);
|
||||
array.append(self.toker.getTokenSlice(token.*)) catch return ZipponError.MemoryError;
|
||||
}
|
||||
|
||||
return try ConditionValue.initArrayStr(array.toOwnedSlice() catch return ZipponError.MemoryError);
|
||||
},
|
||||
|
||||
.date_array => {
|
||||
var array = std.ArrayList(u64).init(allocator);
|
||||
errdefer array.deinit();
|
||||
|
||||
var first = true;
|
||||
while (token.tag != .r_bracket) : (token.* = self.toker.next()) {
|
||||
if (!first) {
|
||||
if (token.tag != .comma) return printError(
|
||||
"Error: Expected comma.",
|
||||
ZipponError.SynthaxError,
|
||||
self.toker.buffer,
|
||||
token.loc.start,
|
||||
token.loc.end,
|
||||
);
|
||||
token.* = self.toker.next();
|
||||
} else first = false;
|
||||
|
||||
if (token.tag != .date_literal and token.tag != .keyword_now) return printError(
|
||||
"Error: Wrong type. Expected date.",
|
||||
ZipponError.SynthaxError,
|
||||
self.toker.buffer,
|
||||
token.loc.start,
|
||||
token.loc.end,
|
||||
);
|
||||
array.append(s2t.parseDate(self.toker.getTokenSlice(token.*)).toUnix()) catch return ZipponError.MemoryError;
|
||||
}
|
||||
|
||||
return try ConditionValue.initArrayUnix(array.toOwnedSlice() catch return ZipponError.MemoryError);
|
||||
},
|
||||
|
||||
.time_array => {
|
||||
var array = std.ArrayList(u64).init(allocator);
|
||||
errdefer array.deinit();
|
||||
|
||||
var first = true;
|
||||
while (token.tag != .r_bracket) : (token.* = self.toker.next()) {
|
||||
if (!first) {
|
||||
if (token.tag != .comma) return printError(
|
||||
"Error: Expected comma.",
|
||||
ZipponError.SynthaxError,
|
||||
self.toker.buffer,
|
||||
token.loc.start,
|
||||
token.loc.end,
|
||||
);
|
||||
token.* = self.toker.next();
|
||||
} else first = false;
|
||||
|
||||
if (token.tag != .time_literal and token.tag != .keyword_now) return printError(
|
||||
"Error: Wrong type. Expected time.",
|
||||
ZipponError.SynthaxError,
|
||||
self.toker.buffer,
|
||||
token.loc.start,
|
||||
token.loc.end,
|
||||
);
|
||||
array.append(s2t.parseTime(self.toker.getTokenSlice(token.*)).toUnix()) catch return ZipponError.MemoryError;
|
||||
}
|
||||
|
||||
return try ConditionValue.initArrayUnix(array.toOwnedSlice() catch return ZipponError.MemoryError);
|
||||
},
|
||||
|
||||
.datetime_array => {
|
||||
var array = std.ArrayList(u64).init(allocator);
|
||||
errdefer array.deinit();
|
||||
|
||||
var first = true;
|
||||
while (token.tag != .r_bracket) : (token.* = self.toker.next()) {
|
||||
if (!first) {
|
||||
if (token.tag != .comma) return printError(
|
||||
"Error: Expected comma.",
|
||||
ZipponError.SynthaxError,
|
||||
self.toker.buffer,
|
||||
token.loc.start,
|
||||
token.loc.end,
|
||||
);
|
||||
token.* = self.toker.next();
|
||||
} else first = false;
|
||||
|
||||
if (token.tag != .datetime_literal and token.tag != .date_literal and token.tag != .keyword_now) return printError(
|
||||
"Error: Wrong type. Expected datetime.",
|
||||
ZipponError.SynthaxError,
|
||||
self.toker.buffer,
|
||||
token.loc.start,
|
||||
token.loc.end,
|
||||
);
|
||||
array.append(s2t.parseDatetime(self.toker.getTokenSlice(token.*)).toUnix()) catch return ZipponError.MemoryError;
|
||||
}
|
||||
|
||||
return try ConditionValue.initArrayUnix(array.toOwnedSlice() catch return ZipponError.MemoryError);
|
||||
},
|
||||
|
||||
.link => switch (token.tag) {
|
||||
.keyword_none => {
|
||||
_ = self.toker.next();
|
||||
@ -239,12 +417,11 @@ pub fn parseConditionValue(self: Self, allocator: Allocator, struct_name: []cons
|
||||
token.loc.end,
|
||||
),
|
||||
},
|
||||
|
||||
.link_array => switch (token.tag) {
|
||||
.keyword_none => {
|
||||
const map = allocator.create(std.AutoHashMap(UUID, void)) catch return ZipponError.MemoryError;
|
||||
map.* = std.AutoHashMap(UUID, void).init(allocator);
|
||||
_ = self.toker.next();
|
||||
return ConditionValue.initArrayLink(map);
|
||||
return ConditionValue.initArrayLink(&empty_map);
|
||||
},
|
||||
.l_brace, .l_bracket => {
|
||||
var filter: ?Filter = null;
|
||||
@ -292,6 +469,5 @@ pub fn parseConditionValue(self: Self, allocator: Allocator, struct_name: []cons
|
||||
token.loc.end,
|
||||
),
|
||||
},
|
||||
.self => unreachable,
|
||||
}
|
||||
}
|
||||
|
@ -1,122 +0,0 @@
|
||||
const std = @import("std");
|
||||
const config = @import("config");
|
||||
const Allocator = std.mem.Allocator;
|
||||
const Token = @import("tokenizer.zig").Token;
|
||||
const Condition = @import("../dataStructure/filter.zig").Condition;
|
||||
const printError = @import("../utils.zig").printError;
|
||||
|
||||
const ZipponError = @import("error").ZipponError;
|
||||
|
||||
const Self = @import("parser.zig");
|
||||
|
||||
/// Check if all token in an array is of one specific type
|
||||
pub fn checkTokensInArray(self: Self, tag: Token.Tag) ZipponError!Token {
|
||||
var token = self.toker.next();
|
||||
while (token.tag != .r_bracket) : (token = self.toker.next()) {
|
||||
if (token.tag != tag) return printError(
|
||||
"Error: Wrong type.",
|
||||
ZipponError.SynthaxError,
|
||||
self.toker.buffer,
|
||||
token.loc.start,
|
||||
token.loc.end,
|
||||
);
|
||||
}
|
||||
return token;
|
||||
}
|
||||
|
||||
/// Will check if what is compared is ok, like comparing if a string is superior to another string is not for example.
|
||||
pub fn checkConditionValidity(
|
||||
self: Self,
|
||||
condition: Condition,
|
||||
token: Token,
|
||||
) ZipponError!void {
|
||||
switch (condition.operation) {
|
||||
.equal => switch (condition.data_type) {
|
||||
.int, .float, .str, .bool, .date, .time, .datetime => {},
|
||||
else => return printError(
|
||||
"Error: Only int, float, str, bool, date, time, datetime can be compare with =",
|
||||
ZipponError.ConditionError,
|
||||
self.toker.buffer,
|
||||
token.loc.start,
|
||||
token.loc.end,
|
||||
),
|
||||
},
|
||||
|
||||
.different => switch (condition.data_type) {
|
||||
.int, .float, .str, .bool, .date, .time, .datetime => {},
|
||||
else => return printError(
|
||||
"Error: Only int, float, str, bool, date, time, datetime can be compare with !=",
|
||||
ZipponError.ConditionError,
|
||||
self.toker.buffer,
|
||||
token.loc.start,
|
||||
token.loc.end,
|
||||
),
|
||||
},
|
||||
|
||||
.superior_or_equal => switch (condition.data_type) {
|
||||
.int, .float, .date, .time, .datetime => {},
|
||||
else => return printError(
|
||||
"Error: Only int, float, date, time, datetime can be compare with >=",
|
||||
ZipponError.ConditionError,
|
||||
self.toker.buffer,
|
||||
token.loc.start,
|
||||
token.loc.end,
|
||||
),
|
||||
},
|
||||
|
||||
.superior => switch (condition.data_type) {
|
||||
.int, .float, .date, .time, .datetime => {},
|
||||
else => return printError(
|
||||
"Error: Only int, float, date, time, datetime can be compare with >",
|
||||
ZipponError.ConditionError,
|
||||
self.toker.buffer,
|
||||
token.loc.start,
|
||||
token.loc.end,
|
||||
),
|
||||
},
|
||||
|
||||
.inferior_or_equal => switch (condition.data_type) {
|
||||
.int, .float, .date, .time, .datetime => {},
|
||||
else => return printError(
|
||||
"Error: Only int, float, date, time, datetime can be compare with <=",
|
||||
ZipponError.ConditionError,
|
||||
self.toker.buffer,
|
||||
token.loc.start,
|
||||
token.loc.end,
|
||||
),
|
||||
},
|
||||
|
||||
.inferior => switch (condition.data_type) {
|
||||
.int, .float, .date, .time, .datetime => {},
|
||||
else => return printError(
|
||||
"Error: Only int, float, date, time, datetime can be compare with <",
|
||||
ZipponError.ConditionError,
|
||||
self.toker.buffer,
|
||||
token.loc.start,
|
||||
token.loc.end,
|
||||
),
|
||||
},
|
||||
|
||||
.in => switch (condition.data_type) {
|
||||
.link => {},
|
||||
else => return printError(
|
||||
"Error: Only link can be compare with IN.",
|
||||
ZipponError.ConditionError,
|
||||
self.toker.buffer,
|
||||
token.loc.start,
|
||||
token.loc.end,
|
||||
),
|
||||
},
|
||||
|
||||
.not_in => switch (condition.data_type) {
|
||||
.link => {},
|
||||
else => return printError(
|
||||
"Error: Only link can be compare with !IN.",
|
||||
ZipponError.ConditionError,
|
||||
self.toker.buffer,
|
||||
token.loc.start,
|
||||
token.loc.end,
|
||||
),
|
||||
},
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user