Connection lifecycle: open, authenticate, fail over across hosts, close.
Contains:
- Authentication helpers (enforceAuthAllowed, filterSaslByRequireAuth, selectScramMechanism) that the auth loop in connectToHost consumes.
- connectToHost — the single-host bootstrap: socket → SSL → startup → auth loop → ParameterStatus/BackendKeyData → extension OID discovery.
- connect — the public entry: multi-host failover, targetSessionAttrs handling, optional connectTimeout, top-level connect tracing.
- orderedHosts — the host list to try, reordered per loadBalanceHosts (lbhRandom shuffles it once per connection).
- close — idempotent teardown: stop background listen pump, send Terminate, drop transport handles.
Imports simple_query for checkSessionAttrs (failover probe). Re-exported through pg_connection.nim.
Procs
proc close(conn: PgConnection): Future[void] {....stackTrace: false, raises: [Exception, ValueError, LibraryError, SslError], tags: [RootEffect], forbids: [].}
- Close the connection. Idempotent: safe to call multiple times.
proc connect(config: ConnConfig): Future[PgConnection] {. ...raises: [Exception, ValueError, PgConnectionError, CatchableError], tags: [RootEffect, WriteIOEffect, TimeEffect], forbids: [].}
- Establish a new connection to a PostgreSQL server. Supports multi-host failover: tries each host in order, or in a random order when loadBalanceHosts == lbhRandom (libpq load_balance_hosts). Respects targetSessionAttrs to select the appropriate server type. connectTimeout is applied per host (libpq semantics): each host attempt gets its own budget, so the total wait may reach connectTimeout * hosts.
proc connect(dsn: string): Future[PgConnection] {....raises: [Exception, ValueError, PgConnectionError, CatchableError, PgError], tags: [RootEffect, WriteIOEffect, TimeEffect, ReadIOEffect], forbids: [].}
- Shorthand for connect(parseDsn(dsn)).
proc connectToHost(config: ConnConfig; entry: HostEntry): Future[PgConnection] {. ...stackTrace: false, raises: [Exception, ValueError, CancelledError, PgConnectionError, OSError, LibraryError, SslError, CatchableError], tags: [RootEffect, WriteIOEffect, TimeEffect], forbids: [].}
- Connect to a single PostgreSQL host. Internal helper for multi-host connect. Dials entry.hostaddr when given (bypassing name resolution), otherwise entry.host; SSL certificate verification always uses entry.host.
proc enforceAuthAllowed(authMethod: AuthMethod; allowed: set[AuthMethod]; offered: string = "") {....raises: [PgConnectionError], tags: [], forbids: [].}
proc filterSaslByRequireAuth(mechs: seq[string]; allowed: set[AuthMethod]): seq[ string] {....raises: [], tags: [], forbids: [].}
- Filter a server-offered SASL mechanism list by the client's requireAuth policy. An empty allowed set performs no filtering (matching libpq semantics when require_auth is unset).
proc orderedHosts(config: ConnConfig): seq[HostEntry] {. ...raises: [PgConnectionError], tags: [], forbids: [].}
-
getHosts, reordered per config.loadBalanceHosts. With lbhRandom (libpq load_balance_hosts=random) the configured host list is shuffled once per call, so a pool of connections spreads across hosts. With lbhDisable (default) the configured order is preserved. Only the multi-host list is reordered — multiple addresses behind a single host name are not shuffled (attemptHost dials the first resolved address).
The shuffle is seeded from the OS secure random source (std/sysrand) into a local std/random RNG, so it is safe under --threads:on, does not require the application to call randomize(), and keeps no module-level state.
proc selectScramMechanism(sslEnabled: bool; serverCertDer: openArray[byte]; saslMechanisms: seq[string]; mode: ChannelBindingMode): tuple[ mechanism: string, cbType: string, cbData: seq[byte], cbSupportedButUnused: bool] {....raises: [PgConnectionError], tags: [RootEffect], forbids: [].}
- Pick the SCRAM mechanism and channel-binding material for a SASL authentication attempt. Raises PgConnectionError when the server-offered mechanisms cannot satisfy mode. cbSupportedButUnused is true only when TLS is in use, plain SCRAM-SHA-256 was selected, and the server did not offer SCRAM-SHA-256-PLUS; the caller then emits a "y,," gs2 header so the server can detect a SCRAM-SHA-256-PLUS downgrade (libpq parity). When the server offered -PLUS but it could not be used (e.g. the certificate was unavailable), or for cbDisable, it stays false so a "n,," header is sent.