feat: extend repl

This commit is contained in:
dualfroz committed 2026-09-09 21:02:46 +02:00
1 parent 329e682eab
commit b77a2c9641
1 file changed
+160
+160
View File
@@ -1417,3 +1417,163 @@ test "plain put/get/del run immediately without a transaction" {
var db = try openTemp(&tmp, allocator);
defer db.close();
var repl = Repl.init(allocator, &db);
defer repl.deinit();
const out = try runScript(allocator, &repl, "put a 1\nget a\ndel a\nget a\n");
defer allocator.free(out);
try std.testing.expectEqualStrings("OK\n1\nOK\n(nil)\n", out);
}
test "comments and blank lines are ignored, exit stops the loop early" {
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,
\\# a comment
\\
\\put a 1
\\exit
\\get a
\\
);
defer allocator.free(out);
try std.testing.expectEqualStrings("OK\n", out);
}
test "table select filters by expr and honors --limit/--offset" {
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 items i:1 name=a price=i:10
\\table put items i:2 name=b price=i:20
\\table put items i:3 name=c price=i:30
\\table select items price gt i:10
\\table select items price gt i:10 --limit 1
\\table select items price gt i:10 --offset 1
\\table select items
\\
);
defer allocator.free(out);
try std.testing.expectEqualStrings(
"OK\nOK\nOK\n" ++
"__pk=2\tname=b\tprice=20\n" ++
"__pk=3\tname=c\tprice=30\n" ++
"__pk=2\tname=b\tprice=20\n" ++
"__pk=3\tname=c\tprice=30\n" ++
"__pk=1\tname=a\tprice=10\n" ++
"__pk=2\tname=b\tprice=20\n" ++
"__pk=3\tname=c\tprice=30\n",
out,
);
}
test "table select --order-by sorts by field, honoring :desc and combining with --limit/--offset" {
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();
// Insert with pk NOT in price order, so a bug that sorted only within
// the natural pk scan order (or ignored --order-by entirely) would
// produce a visibly different sequence than asserted below.
const out = try runScript(allocator, &repl,
\\table put items i:1 name=b price=i:20
\\table put items i:2 name=a price=i:30
\\table put items i:3 name=c price=i:10
\\table select items --order-by price
\\table select items --order-by price:desc
\\table select items --order-by price:desc --limit 1 --offset 1
\\
);
defer allocator.free(out);
try std.testing.expectEqualStrings(
"OK\nOK\nOK\n" ++
"__pk=3\tname=c\tprice=10\n" ++
"__pk=1\tname=b\tprice=20\n" ++
"__pk=2\tname=a\tprice=30\n" ++
"__pk=2\tname=a\tprice=30\n" ++
"__pk=1\tname=b\tprice=20\n" ++
"__pk=3\tname=c\tprice=10\n" ++
"__pk=1\tname=b\tprice=20\n",
out,
);
}
test "table select --order-by rejects a malformed direction suffix instead of defaulting to ascending" {
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 items i:1 price=i:5\ntable select items --order-by price:dsc\n");
defer allocator.free(out);
try std.testing.expectEqualStrings("OK\nerror: InvalidPageFlag\n", out);
}
test "table select --order-by with two comma-separated columns sorts by the first, breaking ties with the second" {
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 share city "warsaw" with prices NOT in insertion order, so
// a single-column city sort alone would leave them in whatever order
// they were inserted - only a real `price` tiebreak fixes that.
const out = try runScript(allocator, &repl,
\\table put items i:1 city=warsaw price=i:30
\\table put items i:2 city=krakow price=i:5
\\table put items i:3 city=warsaw price=i:10
\\table select items --order-by city,price
\\
);
defer allocator.free(out);
try std.testing.expectEqualStrings(
"OK\nOK\nOK\n" ++
"__pk=2\tcity=krakow\tprice=5\n" ++
"__pk=3\tcity=warsaw\tprice=10\n" ++
"__pk=1\tcity=warsaw\tprice=30\n",
out,
);
}
test "table select --order-by rejects an empty segment from a doubled comma instead of silently collapsing it" {
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 items i:1 price=i:5\ntable select items --order-by city,,price\n");
defer allocator.free(out);
try std.testing.expectEqualStrings("OK\nerror: InvalidPageFlag\n", out);
}