Documentation
¶
Index ¶
- func OpenDB(c driver.Connector, opts ...Option) *sql.DB
- func Register(name, baseDriver string, opts ...Option) (err error)
- func WrapConnector(base driver.Connector, opts ...Option) driver.Connector
- func WrapDriver(base driver.Driver, opts ...Option) driver.Driver
- type Guard
- type Option
- func WithAnalysisCacheSize(n int) Option
- func WithAnalyzer(a *analyzer.Analyzer) Option
- func WithFindingDedup(window time.Duration) Option
- func WithN1Detection(threshold int, window time.Duration) Option
- func WithParser(p analyzer.Parser) Option
- func WithReporter(r reporter.Reporter) Option
- func WithSlowQueryThreshold(d time.Duration) Option
- type QueryTracker
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func OpenDB ¶
OpenDB wraps a driver.Connector and returns an analyzed *sql.DB. Use this when you already hold a connector — for example pgx's stdlib.GetConnector or a driver-specific Connector — and don't want a global registration.
connector := stdlib.GetConnector(*pgxConfig) db := middleware.OpenDB(connector)
func Register ¶
Register wraps the database/sql driver currently registered under baseDriver and registers the analyzed result under name. Afterwards sql.Open(name, dsn) yields a *sql.DB whose every query is analyzed.
middleware.Register("sqlguard-sqlite", "sqlite3")
db, _ := sql.Open("sqlguard-sqlite", ":memory:")
It returns an error if name is already registered or baseDriver is not a known driver.
func WrapConnector ¶
WrapConnector returns a driver.Connector that analyzes every query executed through connections it produces.
Types ¶
type Guard ¶
type Guard struct {
// contains filtered or unexported fields
}
Guard is the single shared analysis core. It runs the configured analyzer and reporter against every executed query, measures latency, and feeds the N+1 tracker. Every interception point — the database/sql driver chain and every out-of-tree integration (pgxguard, …) — drives the same Guard so analysis logic, redaction, fingerprinting, N+1, the parser seam and config live here exactly once. Integrations must build on Guard rather than re-implementing check/latency by hand (that path silently loses redaction-by-default and fingerprints).
A Guard is safe for concurrent use.
func (*Guard) Analyzer ¶
Analyzer returns the configured analyzer. Useful for integrations that need the canonical redact/fingerprint helpers without re-deriving policy.
func (*Guard) CheckLatency ¶
CheckLatency reports a slow-query finding if elapsed exceeds the threshold.
func (*Guard) Observe ¶
Observe analyzes a query and times its execution. The returned function must be called once the underlying operation completes; it records latency only when err is nil (a failed query's latency is meaningless). It is designed for split start/end interception points such as pgx tracers: call Observe in the start hook, stash the closure, invoke it in the end hook with the operation error.
func (*Guard) ResetN1 ¶
func (g *Guard) ResetN1()
ResetN1 clears the N+1 tracker's accumulated state. Call this at a per-request boundary (e.g. end of an HTTP handler) so N+1 detection is scoped to a single logical unit of work rather than process-global. It is a no-op when N+1 detection is not enabled.
type Option ¶
type Option func(*options)
Option configures the runtime guard.
func WithAnalysisCacheSize ¶
WithAnalysisCacheSize sets the maximum number of distinct query strings whose analysis results are memoized, so a recurring query is parsed and rule-checked once instead of on every execution. The cache is an LRU keyed on the exact query string (correct even for the literal-sensitive rules). Default is 1024. Pass 0 to disable the cache and analyze every query.
func WithAnalyzer ¶
WithAnalyzer sets a custom analyzer. Default is analyzer.Default().
func WithFindingDedup ¶
WithFindingDedup sets the window within which a repeated static finding — the same rule firing on the same canonical query shape — is reported at most once. This keeps a recurring query (or a prepared statement run in a loop) from flooding the log sink with the same warning on every execution. The default is one minute. Pass 0 to disable dedup and report every occurrence (the legacy behavior). Slow-query and N+1 findings have their own emission policy and are unaffected.
func WithN1Detection ¶
WithN1Detection enables N+1 query detection with the given threshold and window. When the same query pattern is executed threshold times within window, a warning is reported.
func WithParser ¶
WithParser sets the SQL parser the analyzer uses. Default is the zero-dependency analyzer.FallbackParser. Pass a real dialect parser (e.g. from sqlguard/parsers/pgparser) for exact, structural analysis.
func WithReporter ¶
WithReporter sets a custom reporter. Default is ConsoleReporter.
func WithSlowQueryThreshold ¶
WithSlowQueryThreshold sets the duration above which a query is flagged as slow. Default is 200ms.
type QueryTracker ¶
type QueryTracker struct {
// contains filtered or unexported fields
}
QueryTracker detects N+1 query patterns at runtime. It tracks normalized query patterns and flags when the same pattern is executed more than a threshold number of times within a time window.
func NewQueryTracker ¶
func NewQueryTracker(threshold int, window time.Duration, reportFn func([]analyzer.Result)) *QueryTracker
NewQueryTracker creates a tracker that flags when the same query pattern appears more than threshold times within the given window.
func (*QueryTracker) Reset ¶
func (qt *QueryTracker) Reset()
Reset clears all tracked queries. Call this between requests.
func (*QueryTracker) Track ¶
func (qt *QueryTracker) Track(query string)
Track records a query execution and reports if N+1 pattern is detected.