Columnar results
long[], double[], string[] delivered directly, not wrapped in row objects.
HoloDb.Protocol defines how the HoloDb server and client communicate. Instead of sending
results as JSON or row-by-row data structures, it preserves the columnar shape: a long[],
double[], or string[] travels as a typed array over the wire, not as individual
objects — keeping HoloDb's columnar advantage intact when data moves between
processes.
dotnet add package EvaluatedApplications.HoloDb.ProtocolMost consumers should depend on HoloDb.Client instead, which pulls this package in transitively. Depend on it directly only if you're implementing a server.
the win doesn't stop at the wire
Most database protocols trade columnar performance for JSON or ORM convenience. If you run a columnar query — the common case — and the server has to serialize it back to rows, materialize it into objects, and send JSON, you've lost the performance win that made the columnar query fast in the first place. This protocol keeps that win alive. It also encodes the wire format explicitly — no framework assumptions about object graphs or reflection — which makes it predictable (you know exactly what bytes cross the network), versionable (clients and servers from different builds detect incompatibility and fail cleanly), and testable (every message shape can be validated bit-for-bit).
features
long[], double[], string[] delivered directly, not wrapped in row objects.
For non-columnar queries (JOINs, GROUP BY), results are packed into a compact binary row format.
Message boundaries stay safe even over unreliable transports or when connection buffering breaks alignment.
Works over TCP, TLS, or any duplex Stream — this package doesn't provide encryption; TLS is the transport layer's concern.
Frame size limits and count-bounds checks protect against hostile or malformed length prefixes forcing huge allocations.
Client and server compatibility is checked before executing queries, and error semantics distinguish protocol errors from query errors so callers know whether to retry.
client and server side
Client-side (using HoloDb.Client, which wraps this protocol):
using var client = new HoloDbClient("localhost", 5433, token: "mytoken");
await client.ConnectAsync();
// Result comes back as a columnar QueryResult if the query was columnar.
var result = await client.ExecuteAsync("SELECT * FROM prices WHERE date > ?", new[] { arg });
if (result.IsColumnar && result.Columns["price"] is double[] prices)
{
foreach (var p in prices)
Console.WriteLine($"Price: {p}");
}Server-side (using this package to build a server):
var payload = await Wire.ReadFrameAsync(networkStream);
var request = HoloProtocol.DecodeRequest(payload);
if (request.Op == WireOp.Exec)
{
var result = await engine.ExecuteAsync(request.Sql);
var response = HoloProtocol.Result(result);
await Wire.WriteFrameAsync(networkStream, response);
}frozen on purpose
The wire format is frozen: opcode byte values never change, and message field order and types are stable. Old clients can talk to new servers (version negotiation detects incompatibility and fails cleanly), and changes to the protocol are rare and coordinated — both client and server must be rebuilt together.
Depends on: HoloDb (for the QueryResult type that crosses the wire in both directions). Auth tokens travel as plain UTF-8 in the Hello handshake — TLS is assumed by the deployment, not provided by this package. License: proprietary; every capability is free to use today.