pgxguard

package module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 8, 2026 License: MIT Imports: 5 Imported by: 0

Documentation

Overview

Package pgxguard integrates sqlguard with pgx/v5 — the native, dominant PostgreSQL driver for Go (pgx/pgxpool, not the database/sql shim).

It hooks pgx's own tracer seam (pgx.QueryTracer + pgx.BatchTracer), which is the idiomatic extension point every pgx ecosystem tool uses, so every Query/QueryRow/Exec and every SendBatch is analyzed without a method list or a wrapper type.

Composability is a first-class concern: pgx allows exactly one Tracer per config, and production services usually already set one (otelpgx). Apply and ApplyPool therefore *compose* with any existing tracer via pgx's own multitracer rather than overwriting it.

Usage with a pool:

cfg, _ := pgxpool.ParseConfig(dsn)
pgxguard.ApplyPool(cfg) // composes with cfg.ConnConfig.Tracer if set
pool, _ := pgxpool.NewWithConfig(ctx, cfg)

Usage with a single connection:

cfg, _ := pgx.ParseConfig(dsn)
pgxguard.Apply(cfg)
conn, _ := pgx.ConnectConfig(ctx, cfg)

Analysis is driven by the single sqlguard core (middleware.Guard), so redaction-by-default, stable fingerprints, the pluggable real-grammar parser, slow-query and N+1 detection all behave identically to the database/sql driver wrapper. Configure with the standard middleware options:

pgxguard.NewTracer(
    middleware.WithSlowQueryThreshold(50*time.Millisecond),
    middleware.WithN1Detection(10, time.Second),
)

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Apply

func Apply(cfg *pgx.ConnConfig, opts ...middleware.Option) *pgx.ConnConfig

Apply installs a sqlguard Tracer on a *pgx.ConnConfig, composing with any tracer already configured (via pgx's multitracer) instead of overwriting it — so it coexists with otelpgx and friends. opts are the standard middleware options. Returns the same cfg for chaining.

func ApplyPool

func ApplyPool(cfg *pgxpool.Config, opts ...middleware.Option) *pgxpool.Config

ApplyPool installs a sqlguard Tracer on a *pgxpool.Config (delegating to Apply on the embedded ConnConfig), composing with any existing tracer. Returns the same cfg for chaining.

Types

type Tracer

type Tracer struct {
	// contains filtered or unexported fields
}

Tracer implements pgx.QueryTracer and pgx.BatchTracer, driving every traced statement through the shared sqlguard analysis core.

It deliberately does not implement pgx.PrepareTracer: prepared statements are still analyzed when executed (execution routes through QueryTracer), so tracing Prepare as well would double-report findings and inflate N+1 counts. CopyFrom carries no SQL and is out of scope by nature.

func NewTracer

func NewTracer(opts ...middleware.Option) *Tracer

NewTracer builds a Tracer. It accepts the standard sqlguard middleware options (WithAnalyzer, WithReporter, WithSlowQueryThreshold, WithParser, WithN1Detection, …) — the same option set the database/sql driver wrapper uses, so there is no parallel configuration surface to drift.

func (*Tracer) ResetN1

func (t *Tracer) ResetN1()

ResetN1 clears N+1 tracker state. Call it at a per-request boundary (e.g. end of an HTTP handler) to scope N+1 detection to one unit of work. No-op unless WithN1Detection was passed to NewTracer.

func (*Tracer) TraceBatchEnd

func (t *Tracer) TraceBatchEnd(_ context.Context, _ *pgx.Conn, _ pgx.TraceBatchEndData)

TraceBatchEnd is a no-op (per-statement analysis happens in TraceBatchQuery).

func (*Tracer) TraceBatchQuery

func (t *Tracer) TraceBatchQuery(_ context.Context, _ *pgx.Conn, data pgx.TraceBatchQueryData)

TraceBatchQuery analyzes each statement in a batch (static rules + N+1). Per-statement latency is not exposed by pgx's batch tracer — only the whole-batch round trip — so slow-query timing is intentionally not reported here rather than reported wrongly.

func (*Tracer) TraceBatchStart

func (t *Tracer) TraceBatchStart(ctx context.Context, _ *pgx.Conn, _ pgx.TraceBatchStartData) context.Context

TraceBatchStart is a no-op: the batch's SQL is only known per-query, in TraceBatchQuery.

func (*Tracer) TraceQueryEnd

func (t *Tracer) TraceQueryEnd(ctx context.Context, _ *pgx.Conn, data pgx.TraceQueryEndData)

TraceQueryEnd closes the latency window. Latency is recorded only on success (Guard.Observe drops it when data.Err != nil — a failed query's duration is meaningless).

func (*Tracer) TraceQueryStart

func (t *Tracer) TraceQueryStart(ctx context.Context, _ *pgx.Conn, data pgx.TraceQueryStartData) context.Context

TraceQueryStart runs static analysis + N+1 tracking and starts the latency timer, stashing the end closure in the returned context.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL