feat: build out protocol
This commit is contained in:
1 parent
6f0790ed87
commit
6ff5e832eb
1 file changed
+156
@@ -2514,3 +2514,159 @@ test "decodeTableSelect rejects an order-by count claiming more columns than wer
|
|||||||
try std.testing.expectError(error.Malformed, decodeTableSelect(allocator, corrupted));
|
try std.testing.expectError(error.Malformed, decodeTableSelect(allocator, corrupted));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "rows round trip through encode and decode" {
|
||||||
|
const allocator = std.testing.allocator;
|
||||||
|
var rows = [_]rowmod.Row{ rowmod.Row.init(allocator), rowmod.Row.init(allocator) };
|
||||||
|
defer for (&rows) |*r| r.deinit();
|
||||||
|
try rows[0].set("name", .{ .text = "ada" });
|
||||||
|
try rows[0].set("age", .{ .int = 36 });
|
||||||
|
try rows[1].set("name", .{ .text = "bob" });
|
||||||
|
try rows[1].set("age", .{ .int = 24 });
|
||||||
|
|
||||||
|
const payload = try encodeRows(allocator, &rows);
|
||||||
|
defer allocator.free(payload);
|
||||||
|
|
||||||
|
const decoded = try decodeRows(allocator, payload);
|
||||||
|
defer freeRows(allocator, decoded);
|
||||||
|
|
||||||
|
try std.testing.expectEqual(@as(usize, 2), decoded.len);
|
||||||
|
try std.testing.expectEqualStrings("ada", decoded[0].get("name").?.text);
|
||||||
|
try std.testing.expectEqual(@as(i64, 36), decoded[0].get("age").?.int);
|
||||||
|
try std.testing.expectEqualStrings("bob", decoded[1].get("name").?.text);
|
||||||
|
try std.testing.expectEqual(@as(i64, 24), decoded[1].get("age").?.int);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "empty row list round trips" {
|
||||||
|
const allocator = std.testing.allocator;
|
||||||
|
const payload = try encodeRows(allocator, &[_]rowmod.Row{});
|
||||||
|
defer allocator.free(payload);
|
||||||
|
const decoded = try decodeRows(allocator, payload);
|
||||||
|
defer freeRows(allocator, decoded);
|
||||||
|
try std.testing.expectEqual(@as(usize, 0), decoded.len);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "JoinMode.fromByte rejects an unknown mode" {
|
||||||
|
try std.testing.expectError(error.UnknownJoinMode, JoinMode.fromByte(9));
|
||||||
|
}
|
||||||
|
|
||||||
|
test "table_join args round trip mode, tables, fields, and both expr texts" {
|
||||||
|
const allocator = std.testing.allocator;
|
||||||
|
const payload = try encodeTableJoin(allocator, .left, "customers", "__pk", "orders", "customer_id", 0, 0, "age gt i:10", "total gt i:0");
|
||||||
|
defer allocator.free(payload);
|
||||||
|
const args = try decodeTableJoin(payload);
|
||||||
|
try std.testing.expectEqual(JoinMode.left, args.mode);
|
||||||
|
try std.testing.expectEqualStrings("customers", args.leftTable);
|
||||||
|
try std.testing.expectEqualStrings("__pk", args.leftField);
|
||||||
|
try std.testing.expectEqualStrings("orders", args.rightTable);
|
||||||
|
try std.testing.expectEqualStrings("customer_id", args.rightField);
|
||||||
|
try std.testing.expectEqual(@as(u32, 0), args.offset);
|
||||||
|
try std.testing.expectEqual(@as(u32, 0), args.limit);
|
||||||
|
try std.testing.expectEqualStrings("age gt i:10", args.leftExprText);
|
||||||
|
try std.testing.expectEqualStrings("total gt i:0", args.rightExprText);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "table_join args round trip with both expr texts empty" {
|
||||||
|
const allocator = std.testing.allocator;
|
||||||
|
const payload = try encodeTableJoin(allocator, .inner, "a", "x", "b", "y", 0, 0, "", "");
|
||||||
|
defer allocator.free(payload);
|
||||||
|
const args = try decodeTableJoin(payload);
|
||||||
|
try std.testing.expectEqual(JoinMode.inner, args.mode);
|
||||||
|
try std.testing.expectEqualStrings("", args.leftExprText);
|
||||||
|
try std.testing.expectEqualStrings("", args.rightExprText);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "table_join args round trip a nonzero offset and limit" {
|
||||||
|
const allocator = std.testing.allocator;
|
||||||
|
const payload = try encodeTableJoin(allocator, .full, "a", "x", "b", "y", 3, 7, "", "");
|
||||||
|
defer allocator.free(payload);
|
||||||
|
const args = try decodeTableJoin(payload);
|
||||||
|
try std.testing.expectEqual(@as(u32, 3), args.offset);
|
||||||
|
try std.testing.expectEqual(@as(u32, 7), args.limit);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "join pairs round trip a fully matched pair (inner-join shape)" {
|
||||||
|
const allocator = std.testing.allocator;
|
||||||
|
var left = rowmod.Row.init(allocator);
|
||||||
|
defer left.deinit();
|
||||||
|
try left.set("name", .{ .text = "ada" });
|
||||||
|
var right = rowmod.Row.init(allocator);
|
||||||
|
defer right.deinit();
|
||||||
|
try right.set("total", .{ .int = 42 });
|
||||||
|
|
||||||
|
const pairs = [_]JoinPair{.{ .left = left, .right = right }};
|
||||||
|
const payload = try encodeJoinedRows(allocator, &pairs);
|
||||||
|
defer allocator.free(payload);
|
||||||
|
|
||||||
|
const decoded = try decodeJoinedRows(allocator, payload);
|
||||||
|
defer freeJoinPairs(allocator, decoded);
|
||||||
|
|
||||||
|
try std.testing.expectEqual(@as(usize, 1), decoded.len);
|
||||||
|
try std.testing.expectEqualStrings("ada", decoded[0].left.?.get("name").?.text);
|
||||||
|
try std.testing.expectEqual(@as(i64, 42), decoded[0].right.?.get("total").?.int);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "join pairs round trip a nil left side and a nil right side" {
|
||||||
|
const allocator = std.testing.allocator;
|
||||||
|
var right = rowmod.Row.init(allocator);
|
||||||
|
defer right.deinit();
|
||||||
|
try right.set("total", .{ .int = 7 });
|
||||||
|
var left = rowmod.Row.init(allocator);
|
||||||
|
defer left.deinit();
|
||||||
|
try left.set("name", .{ .text = "carol" });
|
||||||
|
|
||||||
|
const pairs = [_]JoinPair{
|
||||||
|
.{ .left = null, .right = right },
|
||||||
|
.{ .left = left, .right = null },
|
||||||
|
};
|
||||||
|
const payload = try encodeJoinedRows(allocator, &pairs);
|
||||||
|
defer allocator.free(payload);
|
||||||
|
|
||||||
|
const decoded = try decodeJoinedRows(allocator, payload);
|
||||||
|
defer freeJoinPairs(allocator, decoded);
|
||||||
|
|
||||||
|
try std.testing.expectEqual(@as(usize, 2), decoded.len);
|
||||||
|
try std.testing.expect(decoded[0].left == null);
|
||||||
|
try std.testing.expectEqual(@as(i64, 7), decoded[0].right.?.get("total").?.int);
|
||||||
|
try std.testing.expectEqualStrings("carol", decoded[1].left.?.get("name").?.text);
|
||||||
|
try std.testing.expect(decoded[1].right == null);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "empty join pair list round trips" {
|
||||||
|
const allocator = std.testing.allocator;
|
||||||
|
const payload = try encodeJoinedRows(allocator, &[_]JoinPair{});
|
||||||
|
defer allocator.free(payload);
|
||||||
|
const decoded = try decodeJoinedRows(allocator, payload);
|
||||||
|
defer freeJoinPairs(allocator, decoded);
|
||||||
|
try std.testing.expectEqual(@as(usize, 0), decoded.len);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "table_aggregate args round trip a groupField, several specs, and an expr" {
|
||||||
|
const allocator = std.testing.allocator;
|
||||||
|
const specs = [_]aggregatemod.AggSpec{
|
||||||
|
.{ .field = "", .kind = .count },
|
||||||
|
.{ .field = "total", .kind = .sum },
|
||||||
|
.{ .field = "total", .kind = .max },
|
||||||
|
.{ .field = "city", .kind = .count_distinct },
|
||||||
|
};
|
||||||
|
const payload = try encodeTableAggregate(allocator, "orders", "city", &specs, 0, 0, &.{}, "", "total gt i:10");
|
||||||
|
defer allocator.free(payload);
|
||||||
|
const args = try decodeTableAggregate(allocator, payload);
|
||||||
|
defer allocator.free(args.specs);
|
||||||
|
defer allocator.free(args.orderBy);
|
||||||
|
|
||||||
|
try std.testing.expectEqualStrings("orders", args.table);
|
||||||
|
try std.testing.expectEqualStrings("city", args.groupField);
|
||||||
|
try std.testing.expectEqual(@as(u32, 0), args.offset);
|
||||||
|
try std.testing.expectEqual(@as(u32, 0), args.limit);
|
||||||
|
try std.testing.expectEqualStrings("", args.havingText);
|
||||||
|
try std.testing.expectEqualStrings("total gt i:10", args.exprText);
|
||||||
|
try std.testing.expectEqual(@as(usize, 4), args.specs.len);
|
||||||
|
try std.testing.expectEqual(aggregatemod.AggKind.count, args.specs[0].kind);
|
||||||
|
try std.testing.expectEqualStrings("", args.specs[0].field);
|
||||||
|
try std.testing.expectEqual(aggregatemod.AggKind.sum, args.specs[1].kind);
|
||||||
|
try std.testing.expectEqualStrings("total", args.specs[1].field);
|
||||||
|
try std.testing.expectEqual(aggregatemod.AggKind.max, args.specs[2].kind);
|
||||||
|
try std.testing.expectEqual(aggregatemod.AggKind.count_distinct, args.specs[3].kind);
|
||||||
|
try std.testing.expectEqualStrings("city", args.specs[3].field);
|
||||||
|
}
|
||||||
|
|
||||||
Reference in new issue
Block a user