feat: expand repl
This commit is contained in:
1 parent
b77a2c9641
commit
4ab4567114
1 file changed
+154
+154
@@ -1577,3 +1577,157 @@ test "table select --order-by rejects an empty segment from a doubled comma inst
|
||||
try std.testing.expectEqualStrings("OK\nerror: InvalidPageFlag\n", out);
|
||||
}
|
||||
|
||||
test "table select reports a parse error on malformed expr 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 select items price bogus i:1\n");
|
||||
defer allocator.free(out);
|
||||
try std.testing.expectEqualStrings("error: UnknownOperator\n", out);
|
||||
}
|
||||
|
||||
test "table explain reports full_scan, an index, and a composite index, matching what table select would actually use" {
|
||||
const allocator = std.testing.allocator;
|
||||
var tmp = std.testing.tmpDir(.{});
|
||||
defer tmp.cleanup();
|
||||
var db = try openTemp(&tmp, allocator);
|
||||
defer db.close();
|
||||
|
||||
{
|
||||
var table = try Table.open(&db, allocator, "users");
|
||||
defer table.deinit();
|
||||
try table.createIndex("age");
|
||||
try table.createCompositeIndex("city_age", &.{ "city", "age" });
|
||||
}
|
||||
|
||||
var repl = Repl.init(allocator, &db);
|
||||
defer repl.deinit();
|
||||
|
||||
const out = try runScript(allocator, &repl,
|
||||
\\table put users i:1 city=s:warsaw age=i:30
|
||||
\\table explain users
|
||||
\\table explain users city eq s:warsaw
|
||||
\\table explain users age eq i:30
|
||||
\\table explain users city eq s:warsaw and age eq i:30
|
||||
\\
|
||||
);
|
||||
defer allocator.free(out);
|
||||
try std.testing.expectEqualStrings(
|
||||
"OK\n" ++
|
||||
"full scan (no usable index)\n" ++
|
||||
"full scan (no usable index)\n" ++
|
||||
"index 'age' (equality)\n" ++
|
||||
"composite index 'city_age' (equality, 2/2 columns matched)\n",
|
||||
out,
|
||||
);
|
||||
}
|
||||
|
||||
test "table update applies --set to matching rows, prints the count, and leaves other rows untouched" {
|
||||
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 users i:1 city=s:warsaw active=i:0
|
||||
\\table put users i:2 city=s:warsaw active=i:0
|
||||
\\table put users i:3 city=s:krakow active=i:0
|
||||
\\table update users --set active=i:1 city eq s:warsaw
|
||||
\\table select users --order-by __pk
|
||||
\\
|
||||
);
|
||||
defer allocator.free(out);
|
||||
try std.testing.expectEqualStrings(
|
||||
"OK\nOK\nOK\n" ++
|
||||
"2\n" ++
|
||||
"__pk=1\tcity=warsaw\tactive=1\n" ++
|
||||
"__pk=2\tcity=warsaw\tactive=1\n" ++
|
||||
"__pk=3\tcity=krakow\tactive=0\n",
|
||||
out,
|
||||
);
|
||||
}
|
||||
|
||||
test "table update without --set is rejected as MissingSetFlag instead of silently updating nothing" {
|
||||
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 users i:1 city=s:warsaw\ntable update users city eq s:warsaw\n");
|
||||
defer allocator.free(out);
|
||||
try std.testing.expectEqualStrings("OK\nerror: MissingSetFlag\n", out);
|
||||
}
|
||||
|
||||
test "table join inner/left/right/full match main.zig's L/R printing" {
|
||||
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 customers i:1 name=alice
|
||||
\\table put customers i:2 name=bob
|
||||
\\table put orders i:100 customer_id=i:1 total=i:50
|
||||
\\table put orders i:101 customer_id=i:999 total=i:5
|
||||
\\table join customers __pk orders customer_id
|
||||
\\table join --left customers __pk orders customer_id
|
||||
\\table join --right customers __pk orders customer_id
|
||||
\\table join --full customers __pk orders customer_id
|
||||
\\
|
||||
);
|
||||
defer allocator.free(out);
|
||||
try std.testing.expectEqualStrings(
|
||||
// plain inner join: only alice/order100 matches, bob and the orphan
|
||||
// order are absent.
|
||||
"OK\nOK\nOK\nOK\n" ++
|
||||
"L __pk=1\tname=alice\n" ++
|
||||
"R __pk=100\tcustomer_id=1\ttotal=50\n" ++
|
||||
// --left: bob survives with R (nil), the orphan order is still absent.
|
||||
"L __pk=1\tname=alice\n" ++
|
||||
"R __pk=100\tcustomer_id=1\ttotal=50\n" ++
|
||||
"L __pk=2\tname=bob\n" ++
|
||||
"R (nil)\n" ++
|
||||
// --right: the orphan order survives with L (nil), bob is absent.
|
||||
"L __pk=1\tname=alice\n" ++
|
||||
"R __pk=100\tcustomer_id=1\ttotal=50\n" ++
|
||||
"L (nil)\n" ++
|
||||
"R __pk=101\tcustomer_id=999\ttotal=5\n" ++
|
||||
// --full: both bob and the orphan order survive.
|
||||
"L __pk=1\tname=alice\n" ++
|
||||
"R __pk=100\tcustomer_id=1\ttotal=50\n" ++
|
||||
"L __pk=2\tname=bob\n" ++
|
||||
"R (nil)\n" ++
|
||||
"L (nil)\n" ++
|
||||
"R __pk=101\tcustomer_id=999\ttotal=5\n",
|
||||
out,
|
||||
);
|
||||
}
|
||||
|
||||
test "table join respects --limit and --offset like table select does" {
|
||||
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();
|
||||
|
||||
Reference in new issue
Block a user