feat: extend repl
This commit is contained in:
1 parent
329e682eab
commit
b77a2c9641
1 file changed
+160
+160
@@ -1417,3 +1417,163 @@ test "plain put/get/del run immediately without a transaction" {
|
|||||||
var db = try openTemp(&tmp, allocator);
|
var db = try openTemp(&tmp, allocator);
|
||||||
defer db.close();
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
Reference in new issue
Block a user