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,
|
.target = target,
|
||||||
.optimize = optimize,
|
.optimize = optimize,
|
||||||
.name = "CLI tokenizer",
|
.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") }));
|
tests1.root_module.addImport("dtype", b.createModule(.{ .root_source_file = b.path("lib/types/out.zig") }));
|
||||||
const run_tests1 = b.addRunArtifact(tests1);
|
const run_tests1 = b.addRunArtifact(tests1);
|
||||||
@ -44,7 +44,7 @@ pub fn build(b: *std.Build) void {
|
|||||||
.target = target,
|
.target = target,
|
||||||
.optimize = optimize,
|
.optimize = optimize,
|
||||||
.name = "CLI tokenizer",
|
.name = "CLI tokenizer",
|
||||||
.test_runner = b.path("test_runner.zig"),
|
.test_runner = b.path("src/test_runner.zig"),
|
||||||
});
|
});
|
||||||
const run_tests2 = b.addRunArtifact(tests2);
|
const run_tests2 = b.addRunArtifact(tests2);
|
||||||
|
|
||||||
@ -53,7 +53,7 @@ pub fn build(b: *std.Build) void {
|
|||||||
.target = target,
|
.target = target,
|
||||||
.optimize = optimize,
|
.optimize = optimize,
|
||||||
.name = "ZiQL tokenizer",
|
.name = "ZiQL tokenizer",
|
||||||
.test_runner = b.path("test_runner.zig"),
|
.test_runner = b.path("src/test_runner.zig"),
|
||||||
});
|
});
|
||||||
const run_tests3 = b.addRunArtifact(tests3);
|
const run_tests3 = b.addRunArtifact(tests3);
|
||||||
|
|
||||||
@ -62,18 +62,18 @@ pub fn build(b: *std.Build) void {
|
|||||||
.target = target,
|
.target = target,
|
||||||
.optimize = optimize,
|
.optimize = optimize,
|
||||||
.name = "Schema tokenizer",
|
.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("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") }));
|
tests4.root_module.addImport("dtype", b.createModule(.{ .root_source_file = b.path("lib/types/out.zig") }));
|
||||||
const run_tests4 = b.addRunArtifact(tests4);
|
const run_tests4 = b.addRunArtifact(tests4);
|
||||||
|
|
||||||
const tests5 = b.addTest(.{
|
const tests5 = b.addTest(.{
|
||||||
.root_source_file = b.path("test.zig"),
|
.root_source_file = b.path("src/test.zig"),
|
||||||
.target = target,
|
.target = target,
|
||||||
.optimize = optimize,
|
.optimize = optimize,
|
||||||
.name = "ZiQL parser",
|
.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("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") }));
|
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,
|
.target = target,
|
||||||
.optimize = optimize,
|
.optimize = optimize,
|
||||||
.name = "Filter tree",
|
.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("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") }));
|
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,
|
.target = target,
|
||||||
.optimize = optimize,
|
.optimize = optimize,
|
||||||
.name = "File parsing",
|
.name = "File parsing",
|
||||||
.test_runner = b.path("test_runner.zig"),
|
.test_runner = b.path("src/test_runner.zig"),
|
||||||
});
|
});
|
||||||
const run_tests1 = b.addRunArtifact(tests1);
|
const run_tests1 = b.addRunArtifact(tests1);
|
||||||
|
|
||||||
@ -124,7 +124,7 @@ pub fn build(b: *std.Build) void {
|
|||||||
{
|
{
|
||||||
const benchmark = b.addExecutable(.{
|
const benchmark = b.addExecutable(.{
|
||||||
.name = "benchmark",
|
.name = "benchmark",
|
||||||
.root_source_file = b.path("benchmark.zig"),
|
.root_source_file = b.path("src/benchmark.zig"),
|
||||||
.target = target,
|
.target = target,
|
||||||
.optimize = optimize,
|
.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;
|
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 {
|
pub fn parseFloat(value_str: []const u8) f64 {
|
||||||
return std.fmt.parseFloat(f64, value_str) catch return 0;
|
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 {
|
pub fn parseBool(value_str: []const u8) bool {
|
||||||
return (value_str[0] != '0');
|
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);
|
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 {
|
pub fn parseTime(value_str: []const u8) DateTime {
|
||||||
if (std.mem.eql(u8, value_str, "NOW")) return DateTime.now();
|
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);
|
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 {
|
pub fn parseDatetime(value_str: []const u8) DateTime {
|
||||||
if (std.mem.eql(u8, value_str, "NOW")) return DateTime.now();
|
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);
|
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" {
|
test "Value parsing: Int" {
|
||||||
const allocator = std.testing.allocator;
|
|
||||||
|
|
||||||
// Int
|
|
||||||
const values: [3][]const u8 = .{ "1", "42", "Hello" };
|
const values: [3][]const u8 = .{ "1", "42", "Hello" };
|
||||||
const expected_values: [3]i32 = .{ 1, 42, 0 };
|
const expected_values: [3]i32 = .{ 1, 42, 0 };
|
||||||
for (values, 0..) |value, i| {
|
for (values, 0..) |value, i| {
|
||||||
try std.testing.expect(parseInt(value) == expected_values[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" {
|
test "Value parsing: Float" {
|
||||||
const allocator = std.testing.allocator;
|
|
||||||
// Float
|
|
||||||
const values: [3][]const u8 = .{ "1.3", "65.991", "Hello" };
|
const values: [3][]const u8 = .{ "1.3", "65.991", "Hello" };
|
||||||
const expected_values: [3]f64 = .{ 1.3, 65.991, 0 };
|
const expected_values: [3]f64 = .{ 1.3, 65.991, 0 };
|
||||||
for (values, 0..) |value, i| {
|
for (values, 0..) |value, i| {
|
||||||
try std.testing.expect(parseFloat(value) == expected_values[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" {
|
test "Value parsing: Bool array" {
|
||||||
const allocator = std.testing.allocator;
|
|
||||||
|
|
||||||
const values: [3][]const u8 = .{ "1", "Hello", "0" };
|
const values: [3][]const u8 = .{ "1", "Hello", "0" };
|
||||||
const expected_values: [3]bool = .{ true, true, false };
|
const expected_values: [3]bool = .{ true, true, false };
|
||||||
for (values, 0..) |value, i| {
|
for (values, 0..) |value, i| {
|
||||||
try std.testing.expect(parseBool(value) == expected_values[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" {
|
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 values: [3][]const u8 = .{ "1920/01/01", "1998/01/21", "2024/12/31" };
|
||||||
const expected_values: [3]DateTime = .{
|
const expected_values: [3]DateTime = .{
|
||||||
DateTime.init(1920, 0, 0, 0, 0, 0, 0),
|
DateTime.init(1920, 0, 0, 0, 0, 0, 0),
|
||||||
@ -279,24 +83,9 @@ test "Value parsing: Date" {
|
|||||||
for (values, 0..) |value, i| {
|
for (values, 0..) |value, i| {
|
||||||
try std.testing.expect(expected_values[i].compareDate(parseDate(value)));
|
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" {
|
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 values: [4][]const u8 = .{ "12:45:00.0000", "18:12:53.7491", "02:30:10", "12:30" };
|
||||||
const expected_values: [4]DateTime = .{
|
const expected_values: [4]DateTime = .{
|
||||||
DateTime.init(0, 0, 0, 12, 45, 0, 0),
|
DateTime.init(0, 0, 0, 12, 45, 0, 0),
|
||||||
@ -307,25 +96,9 @@ test "Value parsing: Time" {
|
|||||||
for (values, 0..) |value, i| {
|
for (values, 0..) |value, i| {
|
||||||
try std.testing.expect(expected_values[i].compareTime(parseTime(value)));
|
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" {
|
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 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 = .{
|
const expected_values: [4]DateTime = .{
|
||||||
DateTime.init(1920, 0, 0, 12, 45, 0, 0),
|
DateTime.init(1920, 0, 0, 12, 45, 0, 0),
|
||||||
@ -336,18 +109,4 @@ test "Value parsing: Datetime" {
|
|||||||
for (values, 0..) |value, i| {
|
for (values, 0..) |value, i| {
|
||||||
try std.testing.expect(expected_values[i].compareDatetime(parseDatetime(value)));
|
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 (
|
User (
|
||||||
name: str,
|
name: str,
|
||||||
email: str,
|
email: str,
|
||||||
|
age: int,
|
||||||
|
address: str,
|
||||||
)
|
)
|
||||||
|
|
||||||
Order (
|
Order (
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const dtype = @import("dtype");
|
const dtype = @import("dtype");
|
||||||
const DBEngine = @import("src/cli/core.zig");
|
const DBEngine = @import("cli/core.zig");
|
||||||
const ZipponError = @import("error").ZipponError;
|
const ZipponError = @import("error").ZipponError;
|
||||||
|
|
||||||
const names = [_][]const u8{ "Alice", "Bob", "Charlie", "Dave", "Eve" };
|
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 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 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 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{
|
pub const std_options = std.Options{
|
||||||
.log_level = .info,
|
.log_level = .info,
|
||||||
.logFn = myLog,
|
.logFn = myLog,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const NUMBER_OF_RUN: usize = 10;
|
||||||
var date_buffer: [64]u8 = undefined;
|
var date_buffer: [64]u8 = undefined;
|
||||||
var date_fa = std.heap.FixedBufferAllocator.init(&date_buffer);
|
var date_fa = std.heap.FixedBufferAllocator.init(&date_buffer);
|
||||||
const date_allocator = date_fa.allocator();
|
const date_allocator = date_fa.allocator();
|
||||||
@ -144,19 +146,23 @@ pub fn benchmark(allocator: std.mem.Allocator) !void {
|
|||||||
var writer = array.writer();
|
var writer = array.writer();
|
||||||
|
|
||||||
try writer.print(
|
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)],
|
names[rng.uintAtMost(usize, names.len - 1)],
|
||||||
emails[rng.uintAtMost(usize, emails.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) |_| {
|
for (0..users_count - 1) |_| {
|
||||||
try writer.print(
|
try writer.print(
|
||||||
"('{s}', '{s}', none)",
|
"('{s}', '{s}', {s}, '{s}')",
|
||||||
.{
|
.{
|
||||||
names[rng.uintAtMost(usize, names.len - 1)],
|
names[rng.uintAtMost(usize, names.len - 1)],
|
||||||
emails[rng.uintAtMost(usize, emails.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
|
// Order
|
||||||
{
|
if (false) {
|
||||||
// Linked array not yet implemented and array manipulation not tested
|
// Linked array not yet implemented and array manipulation not tested
|
||||||
const null_term_query_str = try std.fmt.bufPrintZ(
|
const null_term_query_str = try std.fmt.bufPrintZ(
|
||||||
&line_buffer, // I dont like 'category = {name='Book'}'. Maybe att a IS keyword ?
|
&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
|
// Run query
|
||||||
{
|
{
|
||||||
|
var read_time: f64 = 0;
|
||||||
|
var read_write_time: f64 = 0;
|
||||||
const queries = [_][]const u8{
|
const queries = [_][]const u8{
|
||||||
"GRAB User {}",
|
"GRAB User {}",
|
||||||
"GRAB User {name='asd'}",
|
"GRAB User {name='asd'}",
|
||||||
@ -212,24 +220,78 @@ pub fn benchmark(allocator: std.mem.Allocator) !void {
|
|||||||
"GRAB Category {}",
|
"GRAB Category {}",
|
||||||
"GRAB Item {}",
|
"GRAB Item {}",
|
||||||
"GRAB Order {}",
|
"GRAB Order {}",
|
||||||
"GRAB Order [from, items, quantity, at] {at > 2024}",
|
"GRAB Order [from, items, quantity, at] {}",
|
||||||
"DELETE User {}",
|
"DELETE User {}",
|
||||||
};
|
};
|
||||||
|
|
||||||
// Run benchmarks
|
// Run benchmarks
|
||||||
for (queries) |query| {
|
for (queries, 0..) |query, j| {
|
||||||
const start_time = std.time.nanoTimestamp();
|
var time_buff: [NUMBER_OF_RUN]f64 = undefined;
|
||||||
|
for (0..NUMBER_OF_RUN) |i| {
|
||||||
|
const start_time = std.time.nanoTimestamp();
|
||||||
|
|
||||||
// Execute the query here
|
// Execute the query here
|
||||||
const null_term_query_str = try std.fmt.bufPrintZ(&line_buffer, "{s}", .{query});
|
const null_term_query_str = try std.fmt.bufPrintZ(&line_buffer, "{s}", .{query});
|
||||||
db_engine.runQuery(null_term_query_str);
|
db_engine.runQuery(null_term_query_str);
|
||||||
|
|
||||||
const end_time = std.time.nanoTimestamp();
|
const end_time = std.time.nanoTimestamp();
|
||||||
const duration = @as(f64, @floatFromInt(end_time - start_time)) / 1e6;
|
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", .{});
|
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: *std.AutoHashMap(UUID, void),
|
||||||
link_array: *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 {
|
pub fn initInt(value: []const u8) ConditionValue {
|
||||||
return ConditionValue{ .int = s2t.parseInt(value) };
|
return ConditionValue{ .int = s2t.parseInt(value) };
|
||||||
}
|
}
|
||||||
@ -102,32 +114,24 @@ pub const ConditionValue = union(enum) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Array
|
// Array
|
||||||
pub fn initArrayInt(allocator: std.mem.Allocator, value: []const u8) ZipponError!ConditionValue {
|
pub fn initArrayInt(value: []const i32) ZipponError!ConditionValue {
|
||||||
return ConditionValue{ .int_array = s2t.parseArrayInt(allocator, value) catch return ZipponError.ParsingValueError };
|
return ConditionValue{ .int_array = value };
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn initArrayFloat(allocator: std.mem.Allocator, value: []const u8) ZipponError!ConditionValue {
|
pub fn initArrayFloat(value: []const f64) ZipponError!ConditionValue {
|
||||||
return ConditionValue{ .float_array = s2t.parseArrayFloat(allocator, value) catch return ZipponError.ParsingValueError };
|
return ConditionValue{ .float_array = value };
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn initArrayStr(allocator: std.mem.Allocator, value: []const u8) ZipponError!ConditionValue {
|
pub fn initArrayStr(value: []const []const u8) ZipponError!ConditionValue {
|
||||||
return ConditionValue{ .str_array = s2t.parseArrayStr(allocator, value) catch return ZipponError.ParsingValueError };
|
return ConditionValue{ .str_array = value };
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn initArrayBool(allocator: std.mem.Allocator, value: []const u8) ZipponError!ConditionValue {
|
pub fn initArrayBool(value: []const bool) ZipponError!ConditionValue {
|
||||||
return ConditionValue{ .bool_array = s2t.parseArrayBool(allocator, value) catch return ZipponError.ParsingValueError };
|
return ConditionValue{ .bool_array = value };
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn initArrayDate(allocator: std.mem.Allocator, value: []const u8) ZipponError!ConditionValue {
|
pub fn initArrayUnix(value: []const u64) ZipponError!ConditionValue {
|
||||||
return ConditionValue{ .unix_array = s2t.parseArrayDateUnix(allocator, value) catch return ZipponError.ParsingValueError };
|
return ConditionValue{ .unix_array = 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) ZipponError!ConditionValue {
|
|
||||||
return ConditionValue{ .unix_array = s2t.parseArrayDatetimeUnix(allocator, value) catch return ZipponError.ParsingValueError };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn initLink(value: *std.AutoHashMap(UUID, void)) ConditionValue {
|
pub fn initLink(value: *std.AutoHashMap(UUID, void)) ConditionValue {
|
||||||
@ -308,13 +312,28 @@ pub const Filter = struct {
|
|||||||
else => unreachable,
|
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) {
|
.in => switch (condition.data_type) {
|
||||||
.link => condition.value.link.contains(UUID{ .bytes = row_value.UUID }),
|
.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,
|
else => unreachable,
|
||||||
},
|
},
|
||||||
|
|
||||||
.not_in => switch (condition.data_type) {
|
.not_in => switch (condition.data_type) {
|
||||||
.link => !condition.value.link.contains(UUID{ .bytes = row_value.UUID }),
|
.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,
|
else => unreachable,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@ -343,6 +362,16 @@ pub const Filter = struct {
|
|||||||
.empty => std.debug.print("Empty", .{}),
|
.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" {
|
test "Evaluate" {
|
||||||
|
@ -8,7 +8,7 @@ const DataType = dtype.DataType;
|
|||||||
const DateTime = dtype.DateTime;
|
const DateTime = dtype.DateTime;
|
||||||
const UUID = dtype.UUID;
|
const UUID = dtype.UUID;
|
||||||
|
|
||||||
// TODO: Move this from FileEngine
|
// TODO: Move this outside of FileEngine and make it faster
|
||||||
|
|
||||||
const ZipponError = @import("error").ZipponError;
|
const ZipponError = @import("error").ZipponError;
|
||||||
|
|
||||||
|
@ -61,7 +61,6 @@ pub fn parse(self: *Parser, allocator: Allocator, struct_array: *std.ArrayList(S
|
|||||||
},
|
},
|
||||||
.eof => state = .end,
|
.eof => state = .end,
|
||||||
else => {
|
else => {
|
||||||
std.debug.print("{s}\n", .{self.toker.getTokenSlice(token)});
|
|
||||||
return printError(
|
return printError(
|
||||||
"Error parsing schema: Expected a struct name",
|
"Error parsing schema: Expected a struct name",
|
||||||
ZipponError.SynthaxError,
|
ZipponError.SynthaxError,
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const Allocator = std.mem.Allocator;
|
const Allocator = std.mem.Allocator;
|
||||||
const Parser = @import("src/ziql/parser.zig");
|
const Parser = @import("ziql/parser.zig");
|
||||||
const Tokenizer = @import("src/ziql/tokenizer.zig").Tokenizer;
|
const Tokenizer = @import("ziql/tokenizer.zig").Tokenizer;
|
||||||
const DBEngine = @import("src/cli/core.zig");
|
const DBEngine = @import("cli/core.zig");
|
||||||
const ZipponError = @import("error").ZipponError;
|
const ZipponError = @import("error").ZipponError;
|
||||||
|
|
||||||
const DB = struct {
|
const DB = struct {
|
||||||
@ -124,6 +124,11 @@ test "GRAB Relationship AdditionalData Filtered" {
|
|||||||
try testParsing(db, "GRAB User [2; name, best_friend] {best_friend !IN {}}");
|
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" {
|
test "GRAB Relationship dot" {
|
||||||
// DO I add this ? I'm not sure about this feature
|
// DO I add this ? I'm not sure about this feature
|
||||||
const db = DB{ .path = "test1", .schema = "schema/test" };
|
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,
|
&db_engine.schema_engine,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
std.debug.print("Running: {s}\n", .{source});
|
||||||
try parser.parse(allocator, source);
|
try parser.parse(allocator, source);
|
||||||
|
std.debug.print("\n\n-------------------------------\n\n", .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expectParsingError(db: DB, source: [:0]const u8, err: ZipponError) !void {
|
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,
|
&db_engine.schema_engine,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
std.debug.print("Running: {s}\n", .{source});
|
||||||
try std.testing.expectError(err, parser.parse(allocator, 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/value.zig");
|
||||||
pub usingnamespace @import("parts/filter.zig");
|
pub usingnamespace @import("parts/filter.zig");
|
||||||
pub usingnamespace @import("parts/additionalData.zig");
|
pub usingnamespace @import("parts/additionalData.zig");
|
||||||
pub usingnamespace @import("utils.zig");
|
|
||||||
|
|
||||||
toker: *Tokenizer = undefined,
|
toker: *Tokenizer = undefined,
|
||||||
file_engine: *FileEngine,
|
file_engine: *FileEngine,
|
||||||
|
@ -71,11 +71,21 @@ pub fn parseCondition(
|
|||||||
|
|
||||||
.expect_operation => {
|
.expect_operation => {
|
||||||
condition.operation = try self.parseComparisonOperator(token);
|
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;
|
state = .expect_value;
|
||||||
},
|
},
|
||||||
|
|
||||||
.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);
|
condition.value = try self.parseConditionValue(allocator, struct_name, member_name, condition.data_type, &token);
|
||||||
state = .end;
|
state = .end;
|
||||||
},
|
},
|
||||||
@ -87,3 +97,87 @@ pub fn parseCondition(
|
|||||||
|
|
||||||
return condition;
|
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 std = @import("std");
|
||||||
const dtype = @import("dtype");
|
const dtype = @import("dtype");
|
||||||
|
const s2t = dtype.s2t;
|
||||||
const UUID = dtype.UUID;
|
const UUID = dtype.UUID;
|
||||||
const Allocator = std.mem.Allocator;
|
const Allocator = std.mem.Allocator;
|
||||||
const Token = @import("../tokenizer.zig").Token;
|
const Token = @import("../tokenizer.zig").Token;
|
||||||
@ -12,9 +13,10 @@ const ZipponError = @import("error").ZipponError;
|
|||||||
|
|
||||||
var buff: [1024]u8 = undefined;
|
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 fba = std.heap.FixedBufferAllocator.init(&zero_map_buf);
|
||||||
var zero_map = std.AutoHashMap(UUID, void).init(fba.allocator());
|
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");
|
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
|
/// 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 start_index = token.loc.start;
|
||||||
const expected_tag: ?Token.Tag = switch (data_type) {
|
|
||||||
.int => .int_literal,
|
if (data_type.is_array()) switch (token.tag) {
|
||||||
.float => .float_literal,
|
.l_bracket => token.* = self.toker.next(),
|
||||||
.str => .string_literal,
|
else => return printError(
|
||||||
.self => .uuid_literal,
|
"Error: expecting [ to start array.",
|
||||||
.int_array => .int_literal,
|
ZipponError.SynthaxError,
|
||||||
.float_array => .float_literal,
|
self.toker.buffer,
|
||||||
.str_array => .string_literal,
|
token.loc.start,
|
||||||
.bool, .bool_array, .link, .link_array, .date, .time, .datetime, .date_array, .time_array, .datetime_array => null, // handle separately
|
token.loc.end,
|
||||||
|
),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Check if the all next tokens are the right one
|
switch (data_type) {
|
||||||
if (expected_tag) |tag| {
|
.self => unreachable,
|
||||||
if (data_type.is_array()) {
|
|
||||||
token.* = try self.checkTokensInArray(tag);
|
.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 {
|
} else {
|
||||||
if (token.tag != tag) {
|
return ConditionValue.initInt(self.toker.buffer[start_index..token.loc.end]);
|
||||||
const msg = std.fmt.bufPrint(&buff, "Error: Wrong type. Expected: {any}", .{tag}) catch return ZipponError.MemoryError;
|
},
|
||||||
return printError(
|
|
||||||
msg,
|
.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,
|
ZipponError.SynthaxError,
|
||||||
self.toker.buffer,
|
self.toker.buffer,
|
||||||
token.loc.start,
|
token.loc.start,
|
||||||
token.loc.end,
|
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
|
return try ConditionValue.initArrayInt(array.toOwnedSlice() catch return ZipponError.MemoryError);
|
||||||
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]),
|
.float_array => {
|
||||||
.str => return ConditionValue.initStr(self.toker.buffer[start_index + 1 .. token.loc.end - 1]),
|
var array = std.ArrayList(f64).init(allocator);
|
||||||
.date => return ConditionValue.initDate(self.toker.buffer[start_index..token.loc.end]),
|
errdefer array.deinit();
|
||||||
.time => return ConditionValue.initTime(self.toker.buffer[start_index..token.loc.end]),
|
|
||||||
.datetime => return ConditionValue.initDateTime(self.toker.buffer[start_index..token.loc.end]),
|
var first = true;
|
||||||
.bool => return ConditionValue.initBool(self.toker.buffer[start_index..token.loc.end]),
|
while (token.tag != .r_bracket) : (token.* = self.toker.next()) {
|
||||||
.int_array => return try ConditionValue.initArrayInt(allocator, self.toker.buffer[start_index..token.loc.end]),
|
if (!first) {
|
||||||
.str_array => return try ConditionValue.initArrayStr(allocator, self.toker.buffer[start_index..token.loc.end]),
|
if (token.tag != .comma) return printError(
|
||||||
.bool_array => return try ConditionValue.initArrayBool(allocator, self.toker.buffer[start_index..token.loc.end]),
|
"Error: Expected comma.",
|
||||||
.float_array => return try ConditionValue.initArrayFloat(allocator, self.toker.buffer[start_index..token.loc.end]),
|
ZipponError.SynthaxError,
|
||||||
.date_array => return try ConditionValue.initArrayDate(allocator, self.toker.buffer[start_index..token.loc.end]),
|
self.toker.buffer,
|
||||||
.time_array => return try ConditionValue.initArrayTime(allocator, self.toker.buffer[start_index..token.loc.end]),
|
token.loc.start,
|
||||||
.datetime_array => return try ConditionValue.initArrayDateTime(allocator, self.toker.buffer[start_index..token.loc.end]),
|
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) {
|
.link => switch (token.tag) {
|
||||||
.keyword_none => {
|
.keyword_none => {
|
||||||
_ = self.toker.next();
|
_ = self.toker.next();
|
||||||
@ -239,12 +417,11 @@ pub fn parseConditionValue(self: Self, allocator: Allocator, struct_name: []cons
|
|||||||
token.loc.end,
|
token.loc.end,
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
|
||||||
.link_array => switch (token.tag) {
|
.link_array => switch (token.tag) {
|
||||||
.keyword_none => {
|
.keyword_none => {
|
||||||
const map = allocator.create(std.AutoHashMap(UUID, void)) catch return ZipponError.MemoryError;
|
|
||||||
map.* = std.AutoHashMap(UUID, void).init(allocator);
|
|
||||||
_ = self.toker.next();
|
_ = self.toker.next();
|
||||||
return ConditionValue.initArrayLink(map);
|
return ConditionValue.initArrayLink(&empty_map);
|
||||||
},
|
},
|
||||||
.l_brace, .l_bracket => {
|
.l_brace, .l_bracket => {
|
||||||
var filter: ?Filter = null;
|
var filter: ?Filter = null;
|
||||||
@ -292,6 +469,5 @@ pub fn parseConditionValue(self: Self, allocator: Allocator, struct_name: []cons
|
|||||||
token.loc.end,
|
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