feat: grow repl

This commit is contained in:
dualfroz committed 2026-09-10 13:06:40 +02:00
1 parent 4180f7a9b8
commit 46e03bc174
1 file changed
+162
+162
View File
@@ -1890,3 +1890,165 @@ test "table window row_number annotates every row without collapsing, restarting
);
}
test "table window with a comma-separated spec list annotates every row with all columns, sharing one partition/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,sum:total 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\tsum_total=100\n" ++
"__pk=2\tcity=warsaw\ttotal=250\trow_number=2\tsum_total=350\n" ++
"__pk=3\tcity=krakow\ttotal=40\trow_number=1\tsum_total=40\n",
out,
);
}
test "table window sum:field with order runs a running total along the sorted sequence" {
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 sum:total order total
\\
);
defer allocator.free(out);
try std.testing.expectEqualStrings(
"OK\nOK\nOK\n" ++
"__pk=3\tcity=krakow\ttotal=40\tsum_total=40\n" ++
"__pk=1\tcity=warsaw\ttotal=100\tsum_total=140\n" ++
"__pk=2\tcity=warsaw\ttotal=250\tsum_total=390\n",
out,
);
}
test "table window --range shares a tied group's combined total, without it each tied row gets its own running total" {
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();
// Two rows tied at day=1 (10, 20), then one row at day=2 (5).
const out = try runScript(allocator, &repl,
\\table put orders i:1 day=i:1 amount=i:10
\\table put orders i:2 day=i:1 amount=i:20
\\table put orders i:3 day=i:2 amount=i:5
\\table window orders sum:amount order day --range
\\table window orders sum:amount order day
\\
);
defer allocator.free(out);
try std.testing.expectEqualStrings(
"OK\nOK\nOK\n" ++
// --range: both day=1 rows share the tie group's combined total.
"__pk=1\tday=1\tamount=10\tsum_amount=30\n" ++
"__pk=2\tday=1\tamount=20\tsum_amount=30\n" ++
"__pk=3\tday=2\tamount=5\tsum_amount=35\n" ++
// default (ROWS): each physical row keeps its own running total.
"__pk=1\tday=1\tamount=10\tsum_amount=10\n" ++
"__pk=2\tday=1\tamount=20\tsum_amount=30\n" ++
"__pk=3\tday=2\tamount=5\tsum_amount=35\n",
out,
);
}
test "table window --range is rejected together with a ranking kind, not silently ignored" {
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 total=i:100
\\table window orders row_number order total --range
\\
);
defer allocator.free(out);
try std.testing.expectEqualStrings("OK\nerror: RangeNotApplicable\n", out);
}
test "table window sum:field with a partition but no order stamps the same whole-partition total on every row" {
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 sum:total partition city
\\
);
defer allocator.free(out);
try std.testing.expectEqualStrings(
"OK\nOK\nOK\n" ++
"__pk=1\tcity=warsaw\ttotal=100\tsum_total=350\n" ++
"__pk=2\tcity=warsaw\ttotal=250\tsum_total=350\n" ++
"__pk=3\tcity=krakow\ttotal=40\tsum_total=40\n",
out,
);
}
test "table window honors --limit/--offset in partition-then-order display order, not raw scan 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 order total --offset 1 --limit 1
\\
);
defer allocator.free(out);
// Sorted by total ascending: krakow/40 (rownum 1), warsaw/100 (rownum
// 2), warsaw/250 (rownum 3) - offset 1 limit 1 must land on the SECOND
// entry of that sorted walk, not the second row `table put` inserted.
try std.testing.expectEqualStrings(
"OK\nOK\nOK\n" ++
"__pk=1\tcity=warsaw\ttotal=100\trow_number=2\n",
out,
);
}