225 lines
11 KiB
Zig
225 lines
11 KiB
Zig
const std = @import("std");
|
|
const Allocator = std.mem.Allocator;
|
|
const Parser = @import("src/parser/core.zig").Parser;
|
|
const Tokenizer = @import("src/parser/tokenizer.zig").Tokenizer;
|
|
const DBEngine = @import("src/cli/core.zig");
|
|
const ZipponError = @import("error").ZipponError;
|
|
|
|
const DB = struct {
|
|
path: []const u8,
|
|
schema: []const u8,
|
|
};
|
|
|
|
test "Synthax error" {
|
|
const db = DB{ .path = "test1", .schema = "schema/example" };
|
|
try expectParsingError(db, "ADD User (name = 'Bob', email='bob@email.com', age=-55, scores=[ 1 ], best_friend=7db1f06d-a5a7-4917-8cc6-4d490191c9c1, bday=2000/01/01, a_time=12:04:54.8741, last_order=2000/01/01-12:45)", ZipponError.SynthaxError);
|
|
try expectParsingError(db, "GRAB {}", ZipponError.StructNotFound);
|
|
try expectParsingError(db, "GRAB User {qwe = 'qwe'}", ZipponError.MemberNotFound);
|
|
try expectParsingError(db, "ADD User (name='Bob')", ZipponError.MemberMissing);
|
|
try expectParsingError(db, "GRAB User {name='Bob'", ZipponError.SynthaxError);
|
|
try expectParsingError(db, "GRAB User {age = 50 name='Bob'}", ZipponError.SynthaxError);
|
|
try expectParsingError(db, "GRAB User {age <14 AND (age>55}", ZipponError.SynthaxError);
|
|
try expectParsingError(db, "GRAB User {name < 'Hello'}", ZipponError.ConditionError);
|
|
}
|
|
|
|
test "Clear" {
|
|
const db = DB{ .path = "test1", .schema = "schema/example" };
|
|
try testParsing(db, "DELETE User {}");
|
|
}
|
|
|
|
test "ADD" {
|
|
const db = DB{ .path = "test1", .schema = "schema/example" };
|
|
try testParsing(db, "ADD User (name = 'Bob', email='bob@email.com', age=55, scores=[ 1 ], best_friend=none, friends=none, bday=2000/01/01, a_time=12:04, last_order=2000/01/01-12:45)");
|
|
try testParsing(db, "ADD User (name = 'Bob', email='bob@email.com', age=55, scores=[ 666 123 331 ], best_friend=none, friends=none, bday=2000/11/01, a_time=12:04:54, last_order=2000/01/01-12:45)");
|
|
try testParsing(db, "ADD User (name = 'Bob', email='bob@email.com', age=-55, scores=[ 33 ], best_friend=none, friends=none, bday=2000/01/04, a_time=12:04:54.8741, last_order=2000/01/01-12:45)");
|
|
try testParsing(db, "ADD User (name = 'Boba', email='boba@email.com', age=20, scores=[ ], best_friend=none, friends=none, bday=2000/06/06, a_time=04:04:54.8741, last_order=2000/01/01-12:45)");
|
|
|
|
try testParsing(db, "ADD User (name = 'Bob', email='bob@email.com', age=-55, scores=[ 1 ], best_friend={name='Bob'}, friends=none, bday=2000/01/01, a_time=12:04:54.8741, last_order=2000/01/01-12:45)");
|
|
try testParsing(db, "ADD User (name = 'Bou', email='bob@email.com', age=66, scores=[ 1 ], best_friend={name = 'Boba'}, friends={name = 'Bob'}, bday=2000/01/01, a_time=02:04:54.8741, last_order=2000/01/01-12:45)");
|
|
try testParsing(db, "ADD User (name = 'Bobibou', email='bob@email.com', age=66, scores=[ 1 ], best_friend={name = 'Boba'}, friends=[1]{name = 'Bob'}, bday=2000/01/01, a_time=02:04:54.8741, last_order=2000/01/01-12:45)");
|
|
|
|
try testParsing(db, "GRAB User {}");
|
|
}
|
|
|
|
test "ADD batch" {
|
|
const db = DB{ .path = "test1", .schema = "schema/example" };
|
|
try testParsing(db, "ADD User (name = 'ewq', email='ewq@email.com', age=22, scores=[ ], best_friend=none, friends=none, bday=2000/01/01, a_time=12:04, last_order=2000/01/01-12:45) (name = 'Roger', email='roger@email.com', age=10, scores=[ 1 11 111 123 562345 123451234 34623465234 12341234 ], best_friend=none, friends=none, bday=2000/01/01, a_time=12:04, last_order=2000/01/01-12:45)");
|
|
try testParsing(db, "ADD User (name = 'qwe', email='qwe@email.com', age=57, scores=[ ], best_friend=none, friends=none, bday=2000/01/01, a_time=12:04, last_order=2000/01/01-12:45) ('Rodrigo', 'bob@email.com', 55, [ 1 ], {name = 'qwe'}, none, 2000/01/01, 12:04, 2000/01/01-12:45)");
|
|
|
|
try testParsing(db, "GRAB User [name, best_friend] {name = 'Rodrigo'}");
|
|
try testParsing(db, "GRAB User {}");
|
|
}
|
|
|
|
test "GRAB filter with string" {
|
|
const db = DB{ .path = "test1", .schema = "schema/example" };
|
|
try testParsing(db, "GRAB User {name = 'Bob'}");
|
|
try testParsing(db, "GRAB User {name != 'Brittany Rogers'}");
|
|
}
|
|
|
|
test "GRAB with additional data" {
|
|
const db = DB{ .path = "test1", .schema = "schema/example" };
|
|
try testParsing(db, "GRAB User [1] {age < 18}");
|
|
try testParsing(db, "GRAB User [id, name] {age < 18}");
|
|
try testParsing(db, "GRAB User [100; name, age] {age < 18}");
|
|
}
|
|
|
|
test "UPDATE" {
|
|
const db = DB{ .path = "test1", .schema = "schema/example" };
|
|
try testParsing(db, "UPDATE User [1] {name = 'Bob'} TO (email='new@gmail.com')");
|
|
try testParsing(db, "GRAB User {}");
|
|
}
|
|
|
|
test "GRAB filter with int" {
|
|
const db = DB{ .path = "test1", .schema = "schema/example" };
|
|
try testParsing(db, "GRAB User {age = 18}");
|
|
try testParsing(db, "GRAB User {age > -18}");
|
|
try testParsing(db, "GRAB User {age < 18}");
|
|
try testParsing(db, "GRAB User {age <= 18}");
|
|
try testParsing(db, "GRAB User {age >= 18}");
|
|
try testParsing(db, "GRAB User {age != 18}");
|
|
}
|
|
|
|
test "GRAB filter with date" {
|
|
const db = DB{ .path = "test1", .schema = "schema/example" };
|
|
try testParsing(db, "GRAB User {bday > 2000/01/01}");
|
|
try testParsing(db, "GRAB User {a_time < 08:00}");
|
|
try testParsing(db, "GRAB User {last_order > 2000/01/01-12:45}");
|
|
}
|
|
|
|
test "Specific query" {
|
|
const db = DB{ .path = "test1", .schema = "schema/example" };
|
|
try testParsing(db, "GRAB User");
|
|
try testParsing(db, "GRAB User {}");
|
|
try testParsing(db, "GRAB User [1]");
|
|
}
|
|
|
|
test "UPDATE relationship" {
|
|
const db = DB{ .path = "test1", .schema = "schema/example" };
|
|
try testParsing(db, "UPDATE User [1] {name='Bob'} TO (best_friend = {name='Boba'} )");
|
|
try testParsing(db, "GRAB User {}");
|
|
}
|
|
|
|
test "GRAB Relationship Filter" {
|
|
const db = DB{ .path = "test1", .schema = "schema/example" };
|
|
try testParsing(db, "GRAB User {best_friend IN {name = 'Bob'}}");
|
|
try testParsing(db, "GRAB User {best_friend IN {name = 'Boba'}}");
|
|
}
|
|
|
|
test "GRAB Relationship AdditionalData" {
|
|
const db = DB{ .path = "test1", .schema = "schema/example" };
|
|
try testParsing(db, "GRAB User [name, friends] {}");
|
|
try testParsing(db, "GRAB User [name, best_friend] {}");
|
|
}
|
|
|
|
test "GRAB Relationship Sub AdditionalData" {
|
|
const db = DB{ .path = "test1", .schema = "schema/example" };
|
|
try testParsing(db, "GRAB User [name, friends [name]] {}");
|
|
try testParsing(db, "GRAB User [name, best_friend [name, friends [age]]] {}");
|
|
}
|
|
|
|
test "GRAB Relationship AdditionalData Filtered" {
|
|
const db = DB{ .path = "test1", .schema = "schema/example" };
|
|
try testParsing(db, "GRAB User [2; name, best_friend] {name = 'Bob'}");
|
|
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 Relationship dot" {
|
|
// DO I add this ? I'm not sure about this feature
|
|
const db = DB{ .path = "test1", .schema = "schema/example" };
|
|
// try testParsing(db, "GRAB User.best_friend {}");
|
|
// try testParsing(db, "GRAB User.best_friend.best_friend {}");
|
|
// try testParsing(db, "GRAB User.best_friend.posts {}");
|
|
// try testParsing(db, "GRAB User.best_friend.posts.comments {}");
|
|
try testParsing(db, "GRAB User [1] {}");
|
|
}
|
|
|
|
test "DELETE" {
|
|
const db = DB{ .path = "test1", .schema = "schema/example" };
|
|
try testParsing(db, "DELETE User {}");
|
|
}
|
|
|
|
test "3 struct base" {
|
|
const db = DB{ .path = "test2", .schema = "schema/3struct" };
|
|
try testParsing(db, "DELETE User {}");
|
|
try testParsing(db, "DELETE Post {}");
|
|
try testParsing(db, "ADD User (name = 'Bob', email='bob@email.com', age=55, friends=none, posts=none, comments=none, bday=2000/01/01)");
|
|
try testParsing(db, "ADD Post (text = 'Hello every body', at=NOW, from={}, comments=none)");
|
|
try testParsing(db, "ADD Post (text = 'Hello every body', at=NOW, from={}, comments=none)");
|
|
try testParsing(db, "GRAB Post [id, text, at, from [id, name]] {}");
|
|
}
|
|
|
|
test "3 struct both side" {
|
|
const db = DB{ .path = "test2", .schema = "schema/3struct" };
|
|
try testParsing(db, "DELETE User {}");
|
|
try testParsing(db, "DELETE Post {}");
|
|
try testParsing(db, "ADD User (name = 'Bob', email='bob@email.com', age=55, friends=none, posts=none, comments=none, bday=2000/01/01)");
|
|
try testParsing(db, "ADD Post (text = 'Hello every body', at=NOW, from=none, comments=none)");
|
|
//try testParsing(db, "ADD Post (text = 'Hello every body', at=NOW, from={}, comments=none) -> new_post -> UPDATE User {} TO (posts APPEND new_post)");
|
|
// try testParsing(db, "ADD Post (text = 'Hello every body', at=NOW, from={} APPEND TO posts, comments=none)"); Maybe I can use that to be like the above query
|
|
// ADD Post (text = 'Hello every body', at=NOW, from={} TO last_post, comments=none) And this for a single link
|
|
// try testParsing(db, "ADD Post (text = 'Hello every body', at=NOW, from={} APPEND TO [posts, last_post], comments=none)"); Can be an array to add it to multiple list
|
|
// last_post is replaced instead of append
|
|
try testParsing(db, "GRAB Post [id, text, at, from [id, name]] {}");
|
|
try testParsing(db, "GRAB User [id, name] {}");
|
|
}
|
|
|
|
fn testParsing(db: DB, source: [:0]const u8) !void {
|
|
var db_engine = DBEngine.init(db.path, db.schema);
|
|
defer db_engine.deinit();
|
|
|
|
var toker = Tokenizer.init(source);
|
|
var parser = Parser.init(
|
|
&toker,
|
|
&db_engine.file_engine,
|
|
&db_engine.schema_engine,
|
|
);
|
|
|
|
try parser.parse();
|
|
}
|
|
|
|
fn expectParsingError(db: DB, source: [:0]const u8, err: ZipponError) !void {
|
|
var db_engine = DBEngine.init(db.path, db.schema);
|
|
defer db_engine.deinit();
|
|
|
|
var toker = Tokenizer.init(source);
|
|
var parser = Parser.init(
|
|
&toker,
|
|
&db_engine.file_engine,
|
|
&db_engine.schema_engine,
|
|
);
|
|
|
|
try std.testing.expectError(err, parser.parse());
|
|
}
|
|
|
|
test "Parse filter" {
|
|
const db = DB{ .path = "test1", .schema = "schema/example" };
|
|
try testParseFilter(db, "name = 'Adrien'}");
|
|
try testParseFilter(db, "name = 'Adrien' AND age > 11}");
|
|
try testParseFilter(db, "name = 'Adrien' AND (age < 11 OR age > 40)}");
|
|
try testParseFilter(db, "(name = 'Adrien') AND (age < 11 OR age > 40)}");
|
|
try testParseFilter(db, "(name = 'Adrien' OR name = 'Bob') AND (age < 11 OR age > 40)}");
|
|
try testParseFilter(db, "(name = 'Adrien' OR name = 'Bob') AND (age < 11 OR age > 40 AND (age != 20))}");
|
|
}
|
|
|
|
fn testParseFilter(db: DB, source: [:0]const u8) !void {
|
|
var arena = std.heap.ArenaAllocator.init(std.testing.allocator);
|
|
defer arena.deinit();
|
|
const allocator = arena.allocator();
|
|
|
|
var db_engine = DBEngine.init(db.path, db.schema);
|
|
defer db_engine.deinit();
|
|
|
|
var toker = Tokenizer.init(source);
|
|
var parser = Parser.init(
|
|
&toker,
|
|
&db_engine.file_engine,
|
|
&db_engine.schema_engine,
|
|
);
|
|
|
|
var filter = try parser.parseFilter(allocator, "User", false);
|
|
defer filter.deinit();
|
|
std.debug.print("{s}\n", .{source});
|
|
filter.debugPrint();
|
|
}
|