feat: expand server
This commit is contained in:
1 parent
097f1ca9fc
commit
50b9f57522
1 file changed
+156
+156
@@ -4219,3 +4219,159 @@ test "server table_aggregate reports a non-numeric sum field as bad_request, not
|
||||
try std.testing.expectError(client_mod.ClientError.ServerBadRequest, err);
|
||||
}
|
||||
|
||||
test "server table_window annotates remote rows with row_number, partition-then-order matching the local library result" {
|
||||
const allocator = std.testing.allocator;
|
||||
var tmp = std.testing.tmpDir(.{});
|
||||
defer tmp.cleanup();
|
||||
const path = try tmp.dir.realpathAlloc(allocator, ".");
|
||||
defer allocator.free(path);
|
||||
|
||||
var db = try testDb(allocator, path);
|
||||
defer db.close();
|
||||
try seedAggregateOrders(allocator, &db);
|
||||
|
||||
const address = try std.net.Address.parseIp("127.0.0.1", 0);
|
||||
var server = try Server.init(allocator, &db, address);
|
||||
try server.start();
|
||||
defer server.stop();
|
||||
|
||||
const client_mod = @import("client.zig");
|
||||
var client = try client_mod.Client.connect(allocator, server.boundAddress());
|
||||
defer client.close();
|
||||
|
||||
const partitionBy = [_][]const u8{"city"};
|
||||
const orderBy = [_]querymod.OrderBy{.{ .field = "total", .descending = false }};
|
||||
const specs = [_]windowmod.WindowSpec{.{ .field = "", .kind = .row_number }};
|
||||
const results = try client.tableWindow(allocator, "orders", &specs, &partitionBy, &orderBy, 0, 0, "", .rows);
|
||||
defer protocol.freeWindowRows(allocator, results);
|
||||
|
||||
// First-seen partition order (warsaw at pk1, krakow at pk3), sorted by
|
||||
// total within each partition: warsaw 100 then 250, krakow 40 alone.
|
||||
try std.testing.expectEqual(@as(usize, 3), results.len);
|
||||
try std.testing.expectEqualStrings("warsaw", results[0].row.get("city").?.text);
|
||||
try std.testing.expectEqual(@as(i64, 100), results[0].row.get("total").?.int);
|
||||
try std.testing.expectEqual(@as(i64, 1), results[0].values[0].int);
|
||||
try std.testing.expectEqualStrings("warsaw", results[1].row.get("city").?.text);
|
||||
try std.testing.expectEqual(@as(i64, 250), results[1].row.get("total").?.int);
|
||||
try std.testing.expectEqual(@as(i64, 2), results[1].values[0].int);
|
||||
try std.testing.expectEqualStrings("krakow", results[2].row.get("city").?.text);
|
||||
try std.testing.expectEqual(@as(i64, 1), results[2].values[0].int);
|
||||
}
|
||||
|
||||
test "server table_window honors offset/limit to page rows in partition-then-order display order, not raw scan order" {
|
||||
const allocator = std.testing.allocator;
|
||||
var tmp = std.testing.tmpDir(.{});
|
||||
defer tmp.cleanup();
|
||||
const path = try tmp.dir.realpathAlloc(allocator, ".");
|
||||
defer allocator.free(path);
|
||||
|
||||
var db = try testDb(allocator, path);
|
||||
defer db.close();
|
||||
try seedAggregateOrders(allocator, &db);
|
||||
|
||||
const address = try std.net.Address.parseIp("127.0.0.1", 0);
|
||||
var server = try Server.init(allocator, &db, address);
|
||||
try server.start();
|
||||
defer server.stop();
|
||||
|
||||
const client_mod = @import("client.zig");
|
||||
var client = try client_mod.Client.connect(allocator, server.boundAddress());
|
||||
defer client.close();
|
||||
|
||||
const partitionBy = [_][]const u8{"city"};
|
||||
const orderBy = [_]querymod.OrderBy{.{ .field = "total", .descending = false }};
|
||||
const specs = [_]windowmod.WindowSpec{.{ .field = "", .kind = .row_number }};
|
||||
|
||||
const all = try client.tableWindow(allocator, "orders", &specs, &partitionBy, &orderBy, 0, 0, "", .rows);
|
||||
defer protocol.freeWindowRows(allocator, all);
|
||||
try std.testing.expectEqual(@as(usize, 3), all.len);
|
||||
|
||||
const paged = try client.tableWindow(allocator, "orders", &specs, &partitionBy, &orderBy, 1, 1, "", .rows);
|
||||
defer protocol.freeWindowRows(allocator, paged);
|
||||
try std.testing.expectEqual(@as(usize, 1), paged.len);
|
||||
try std.testing.expectEqual(all[1].values[0].int, paged[0].values[0].int);
|
||||
try std.testing.expectEqual(all[1].row.get("total").?.int, paged[0].row.get("total").?.int);
|
||||
}
|
||||
|
||||
test "server table_window with MULTIPLE specs returns one WindowRow.values entry per spec, in request order, over real TCP" {
|
||||
const allocator = std.testing.allocator;
|
||||
var tmp = std.testing.tmpDir(.{});
|
||||
defer tmp.cleanup();
|
||||
const path = try tmp.dir.realpathAlloc(allocator, ".");
|
||||
defer allocator.free(path);
|
||||
|
||||
var db = try testDb(allocator, path);
|
||||
defer db.close();
|
||||
try seedAggregateOrders(allocator, &db);
|
||||
|
||||
const address = try std.net.Address.parseIp("127.0.0.1", 0);
|
||||
var server = try Server.init(allocator, &db, address);
|
||||
try server.start();
|
||||
defer server.stop();
|
||||
|
||||
const client_mod = @import("client.zig");
|
||||
var client = try client_mod.Client.connect(allocator, server.boundAddress());
|
||||
defer client.close();
|
||||
|
||||
const partitionBy = [_][]const u8{"city"};
|
||||
const orderBy = [_]querymod.OrderBy{.{ .field = "total", .descending = false }};
|
||||
const specs = [_]windowmod.WindowSpec{
|
||||
.{ .field = "", .kind = .row_number },
|
||||
.{ .field = "total", .kind = .sum },
|
||||
};
|
||||
const results = try client.tableWindow(allocator, "orders", &specs, &partitionBy, &orderBy, 0, 0, "", .rows);
|
||||
defer protocol.freeWindowRows(allocator, results);
|
||||
|
||||
try std.testing.expectEqual(@as(usize, 3), results.len);
|
||||
try std.testing.expectEqual(@as(usize, 2), results[0].values.len);
|
||||
// warsaw: total 100 then 250 (running sum), krakow: total 40 alone.
|
||||
try std.testing.expectEqualStrings("warsaw", results[0].row.get("city").?.text);
|
||||
try std.testing.expectEqual(@as(i64, 1), results[0].values[0].int);
|
||||
try std.testing.expectEqual(@as(i64, 100), results[0].values[1].int);
|
||||
try std.testing.expectEqualStrings("warsaw", results[1].row.get("city").?.text);
|
||||
try std.testing.expectEqual(@as(i64, 2), results[1].values[0].int);
|
||||
try std.testing.expectEqual(@as(i64, 350), results[1].values[1].int);
|
||||
try std.testing.expectEqualStrings("krakow", results[2].row.get("city").?.text);
|
||||
try std.testing.expectEqual(@as(i64, 1), results[2].values[0].int);
|
||||
try std.testing.expectEqual(@as(i64, 40), results[2].values[1].int);
|
||||
}
|
||||
|
||||
test "server table_window with a partition but no order runs a whole-partition sum, matching sum:field semantics" {
|
||||
const allocator = std.testing.allocator;
|
||||
var tmp = std.testing.tmpDir(.{});
|
||||
defer tmp.cleanup();
|
||||
const path = try tmp.dir.realpathAlloc(allocator, ".");
|
||||
defer allocator.free(path);
|
||||
|
||||
var db = try testDb(allocator, path);
|
||||
defer db.close();
|
||||
try seedAggregateOrders(allocator, &db);
|
||||
|
||||
const address = try std.net.Address.parseIp("127.0.0.1", 0);
|
||||
var server = try Server.init(allocator, &db, address);
|
||||
try server.start();
|
||||
defer server.stop();
|
||||
|
||||
const client_mod = @import("client.zig");
|
||||
var client = try client_mod.Client.connect(allocator, server.boundAddress());
|
||||
defer client.close();
|
||||
|
||||
const partitionBy = [_][]const u8{"city"};
|
||||
const specs = [_]windowmod.WindowSpec{.{ .field = "total", .kind = .sum }};
|
||||
const results = try client.tableWindow(allocator, "orders", &specs, &partitionBy, &.{}, 0, 0, "", .rows);
|
||||
defer protocol.freeWindowRows(allocator, results);
|
||||
|
||||
try std.testing.expectEqual(@as(usize, 3), results.len);
|
||||
for (results) |wr| {
|
||||
const expected: i64 = if (std.mem.eql(u8, wr.row.get("city").?.text, "warsaw")) 350 else 40;
|
||||
try std.testing.expectEqual(expected, wr.values[0].int);
|
||||
}
|
||||
}
|
||||
|
||||
test "server table_window RANGE frame groups tied rows by day, ROWS gives each row its own running total, over real TCP" {
|
||||
const allocator = std.testing.allocator;
|
||||
var tmp = std.testing.tmpDir(.{});
|
||||
defer tmp.cleanup();
|
||||
const path = try tmp.dir.realpathAlloc(allocator, ".");
|
||||
defer allocator.free(path);
|
||||
|
||||
Reference in new issue
Block a user