src/sydra/compat/wire/session.zig
Purpose
Implements the pgwire handshake and constructs a Session object containing startup metadata (user/database/app name + raw parameters).
This is used by wire/server.zig before entering the per-message loop.
Public API
pub const SessionConfig
Backend “ParameterStatus” defaults:
server_version: []const u8 = "15.2"server_encoding: []const u8 = "UTF8"client_encoding: []const u8 = "UTF8"date_style: []const u8 = "ISO, MDY"time_zone: []const u8 = "UTC"integer_datetimes: []const u8 = "on"standard_conforming_strings: []const u8 = "on"default_database: ?[]const u8 = nullapplication_name_prefix: []const u8 = "sydradb"
pub const Session
Fields:
alloc: std.mem.Allocatoruser: []const u8database: []const u8application_name: []const u8parameters: []protocol.Parameter(allocator-owned copies)
Methods:
pub fn deinit(self: Session) voidfrees all owned allocations (includingparameterskeys/values).pub fn borrowedUser/borrowedDatabase/borrowedApplicationName(self: Session) []const u8
pub const HandshakeError = error{ MissingUser, InvalidStartup, UnsupportedProtocol, CancelRequestUnsupported, OutOfMemory }
pub fn performHandshake(alloc, reader, writer, config) HandshakeError!Session
Handshake steps:
- Calls
protocol.readStartup(alloc, reader, writer, .{}).- Maps
error.UnsupportedProtocolanderror.CancelRequestUnsupportedintoHandshakeError.
- Maps
- Requires a
userstartup parameter.- If missing, writes a
FATALpgwire error (28000,"user parameter required") and returnsHandshakeError.MissingUser.
- If missing, writes a
- Derives:
database= startupdatabaseorconfig.default_databaseoruserapplication_name= startupapplication_nameorconfig.application_name_prefix
- Duplicates
user,database,application_nameinto allocator-owned strings. - Duplicates all startup parameters into allocator-owned
[]protocol.Parameter. - Writes backend responses:
AuthenticationOk- multiple
ParameterStatusentries (fromSessionConfig) ReadyForQuery('I')
The function returns an owned Session whose deinit() must be called by the caller.
User parameter required (excerpt)
const user_param = startup.find("user") orelse {
protocol.writeErrorResponse(writer, "FATAL", "28000", "user parameter required") catch return HandshakeError.InvalidStartup;
return HandshakeError.MissingUser;
};
Backend handshake responses (excerpt)
protocol.writeAuthenticationOk(writer) catch return HandshakeError.InvalidStartup;
for (status_pairs) |pair| {
protocol.writeParameterStatus(writer, pair.key, pair.value) catch return HandshakeError.InvalidStartup;
}
protocol.writeReadyForQuery(writer, 'I') catch return HandshakeError.InvalidStartup;
Key internal helpers
duplicateParameters(alloc, params) ![]protocol.Parameterdeep-copies startup parameters and frees partially-constructed output on error.
duplicateParameters (excerpt)
fn duplicateParameters(alloc: std.mem.Allocator, params: []protocol.Parameter) ![]protocol.Parameter {
const out = try alloc.alloc(protocol.Parameter, params.len);
var idx: usize = 0;
errdefer {
var i: usize = 0;
while (i < idx) : (i += 1) {
alloc.free(@constCast(out[i].key));
alloc.free(@constCast(out[i].value));
}
alloc.free(out);
}
while (idx < params.len) : (idx += 1) {
out[idx] = .{
.key = try alloc.dupe(u8, params[idx].key),
.value = try alloc.dupe(u8, params[idx].value),
};
}
return out;
}