Documentation
¶
Overview ¶
Package pgshim is the PostgreSQL wire-protocol front-end for bintrail's time-travel engine (#1008). It lets a PostgreSQL operator run single-row AS OF queries from psql / a PG driver:
psql "host=127.0.0.1 port=5433 user=<tenant> dbname=<schema>" SELECT * FROM _flashback.orders AS OF '5 minutes ago' WHERE id = 42; SELECT * FROM _snapshot.orders AS OF '5 minutes ago' WHERE id = 42; SELECT * FROM orders AS OF '5 minutes ago' WHERE id = 42; -- bare form
and get rows back over the PostgreSQL protocol, served from the SAME out-of-band index + baseline the MySQL shim uses. It reuses internal/shim verbatim: the parser (shim.Parse → a protocol-neutral TimeTravelQuery) and the wire-neutral resolve seam (Handler.ResolveFlashbackRow / ResolveSnapshotRow / ColumnsFor / PKColumnCheck, resolve.go). Only the render is PostgreSQL-typed here — RowDescription / DataRow / CommandComplete instead of *mysql.Result.
Scope (matches the current PostgreSQL time-travel maturity, #593):
- single-row AS OF (WHERE <pk> = <value>) for _flashback and _snapshot.
- full-table AS OF is REFUSED with actionable remediation (the PostgreSQL baseline still omits CREATE TABLE, slice E) — never a silent partial.
- _diff is refused (use `bintrail-pg reconstruct --history`).
- simple query protocol only (psql uses it natively; a pgx client sets QueryExecModeSimpleProtocol). The extended query protocol is declined with a clear error and a resync, so a default-mode client is not left hanging.
Addressing: the connect `database` parameter is the bintrail SCHEMA (the PostgreSQL schema name, e.g. `public`); flashback-vs-snapshot semantics are selected by the `_flashback.` / `_snapshot.` table prefix in the query, exactly like the MySQL shim. (This differs from the issue's tentative `dbname=_flashback` note, which the engine's schema-from-connection model does not support without a parser change; the query-prefix model needs none and is strictly more capable — one connection reaches every virtual schema.)
Auth mirrors the MySQL shim: a cleartext credential validated per tenant against shim.yaml. This is loopback-default; front a TLS terminator (or run on loopback behind a local proxy) for a non-loopback bind — the same posture as the MySQL shim behind ProxySQL. Package placement is deliberate: pgproto3 is github.com/jackc/pgx/v5/pgproto3, which the cliapp pgfree guard bans from the core bintrail binary, so this front-end is linked ONLY by cmd/bintrail-pg.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Serve ¶
Serve accepts PostgreSQL wire-protocol connections until ctx is canceled or the listener closes. Mirrors internal/cli.serveLoop: one goroutine per connection, each with its own shim.Handler; exponential accept backoff so a transient listener hiccup does not burn CPU; an optional connection cap.
Types ¶
type Config ¶
type Config struct {
// IndexDB is the open, migrated bintrail index the engine reads.
IndexDB *sql.DB
// ShimConfig is the engine config (IndexDBName, BaselineDir/S3, NoArchive,
// AllowGaps, QueryTimeout). FullTableGate is unused here — full-table is
// refused — and AuthMethod is a MySQL concept, also unused.
ShimConfig shim.Config
// Auth validates the per-tenant cleartext password (loaded from shim.yaml).
Auth shim.TenantAuth
// AllowedSchemas maps tenant username → allowed_schemas (#824/#1261),
// built with shim.UserAllowedSchemas from the same shim.yaml the MySQL
// front-end loads. A username ABSENT from the map is unrestricted, which
// is what an empty/omitted allowed_schemas means; nil disables the gate
// for every tenant.
AllowedSchemas map[string][]string
// Logger; nil → slog.Default().
Logger *slog.Logger
// MaxConns caps concurrent connections; 0 = unlimited.
MaxConns int
}
Config carries everything the front-end needs. The engine lives in internal/shim; this package only speaks the wire.