feat: build out repl

This commit is contained in:
dualfroz committed 2026-09-10 11:04:25 +02:00
1 parent 4ab4567114
commit 4180f7a9b8
1 file changed
+159
+159
View File
@@ -1731,3 +1731,162 @@ test "table join respects --limit and --offset like table select does" {
var repl = Repl.init(allocator, &db); var repl = Repl.init(allocator, &db);
defer repl.deinit(); defer repl.deinit();
const out = try runScript(allocator, &repl,
\\table put customers i:1 name=alice
\\table put customers i:2 name=bob
\\table put customers i:3 name=carol
\\table join --left customers __pk orders customer_id --offset 1 --limit 1
\\table join --left customers __pk orders customer_id --offset 50
\\
);
defer allocator.free(out);
try std.testing.expectEqualStrings(
"OK\nOK\nOK\n" ++
// --offset 1 --limit 1: skip alice, keep exactly bob.
"L __pk=2\tname=bob\n" ++
"R (nil)\n" ++
// --offset 50 is past the end of a 3-row left outer join: nothing.
"",
out,
);
}
test "table join needs exactly four positional args after mode flags" {
const allocator = std.testing.allocator;
var tmp = std.testing.tmpDir(.{});
defer tmp.cleanup();
var db = try openTemp(&tmp, allocator);
defer db.close();
var repl = Repl.init(allocator, &db);
defer repl.deinit();
const out = try runScript(allocator, &repl, "table join --left customers __pk orders\n");
defer allocator.free(out);
try std.testing.expectEqualStrings("error: WrongArgCount\n", out);
}
test "table aggregate groups by field with count/sum/avg/min/max, matching main.zig's CLI output" {
const allocator = std.testing.allocator;
var tmp = std.testing.tmpDir(.{});
defer tmp.cleanup();
var db = try openTemp(&tmp, allocator);
defer db.close();
var repl = Repl.init(allocator, &db);
defer repl.deinit();
const out = try runScript(allocator, &repl,
\\table put orders i:1 city=warsaw total=i:100
\\table put orders i:2 city=warsaw total=i:250
\\table put orders i:3 city=krakow total=i:40
\\table aggregate orders city count,sum:total,avg:total,min:total,max:total
\\
);
defer allocator.free(out);
try std.testing.expectEqualStrings(
"OK\nOK\nOK\n" ++
"group=warsaw\tcount=2\tsum_total=350\tavg_total=175\tmin_total=100\tmax_total=250\n" ++
"group=krakow\tcount=1\tsum_total=40\tavg_total=40\tmin_total=40\tmax_total=40\n",
out,
);
}
test "table aggregate distinct:field counts unique values, collapsing repeats within a group" {
const allocator = std.testing.allocator;
var tmp = std.testing.tmpDir(.{});
defer tmp.cleanup();
var db = try openTemp(&tmp, allocator);
defer db.close();
var repl = Repl.init(allocator, &db);
defer repl.deinit();
const out = try runScript(allocator, &repl,
\\table put orders i:1 city=warsaw region=mazovia
\\table put orders i:2 city=warsaw region=mazovia
\\table put orders i:3 city=warsaw region=innerwarsaw
\\table put orders i:4 city=krakow region=malopolska
\\table aggregate orders city count,distinct:region
\\table aggregate orders * distinct:region
\\
);
defer allocator.free(out);
try std.testing.expectEqualStrings(
"OK\nOK\nOK\nOK\n" ++
"group=warsaw\tcount=3\tcount_distinct_region=2\n" ++
"group=krakow\tcount=1\tcount_distinct_region=1\n" ++
"count_distinct_region=3\n",
out,
);
}
test "table aggregate with * groups nothing and honors an expr filter before aggregating" {
const allocator = std.testing.allocator;
var tmp = std.testing.tmpDir(.{});
defer tmp.cleanup();
var db = try openTemp(&tmp, allocator);
defer db.close();
var repl = Repl.init(allocator, &db);
defer repl.deinit();
const out = try runScript(allocator, &repl,
\\table put orders i:1 city=warsaw total=i:100
\\table put orders i:2 city=warsaw total=i:250
\\table put orders i:3 city=krakow total=i:40
\\table aggregate orders * count,sum:total
\\table aggregate orders * count,sum:total total gt i:50
\\
);
defer allocator.free(out);
try std.testing.expectEqualStrings(
"OK\nOK\nOK\n" ++
"count=3\tsum_total=390\n" ++
"count=2\tsum_total=350\n",
out,
);
}
test "table aggregate rejects an invalid spec without crashing" {
const allocator = std.testing.allocator;
var tmp = std.testing.tmpDir(.{});
defer tmp.cleanup();
var db = try openTemp(&tmp, allocator);
defer db.close();
var repl = Repl.init(allocator, &db);
defer repl.deinit();
const out = try runScript(allocator, &repl, "table aggregate orders city bogus:total\n");
defer allocator.free(out);
try std.testing.expectEqualStrings("error: InvalidArgument\n", out);
}
test "table window row_number annotates every row without collapsing, restarting per partition in order" {
const allocator = std.testing.allocator;
var tmp = std.testing.tmpDir(.{});
defer tmp.cleanup();
var db = try openTemp(&tmp, allocator);
defer db.close();
var repl = Repl.init(allocator, &db);
defer repl.deinit();
const out = try runScript(allocator, &repl,
\\table put orders i:1 city=warsaw total=i:100
\\table put orders i:2 city=warsaw total=i:250
\\table put orders i:3 city=krakow total=i:40
\\table window orders row_number partition city order total
\\
);
defer allocator.free(out);
try std.testing.expectEqualStrings(
"OK\nOK\nOK\n" ++
"__pk=1\tcity=warsaw\ttotal=100\trow_number=1\n" ++
"__pk=2\tcity=warsaw\ttotal=250\trow_number=2\n" ++
"__pk=3\tcity=krakow\ttotal=40\trow_number=1\n",
out,
);
}