pgxprepared

package
v1.0.0 Latest Latest
Warning

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

Go to latest
Published: Sep 14, 2026 License: Apache-2.0 Imports: 8 Imported by: 0

Documentation

Overview

Package pgxprepared demonstrates a bounded cache of SQLGuard prepared values in front of pgx-style Exec, Query, and QueryRow operations. Cache hits reuse parsing but every call repeats prepared validation before the wrapped executor is invoked.

The cache retains exact SQL strings as keys. Its SQLGuard Prepared values retain parsed identifiers, literals, and byte values. Applications should prefer stable parameterized SQL with positional arguments instead of embedding sensitive values. Cache capacity and MaxSQLBytes bound entry count and eligible key length; they are retention controls, not a heap quota, because parsed-tree size is not measured. Eviction and Go garbage collection do not guarantee prompt memory zeroization.

SQLGuard Prepared values are client-side parsed representations, not pgx or PostgreSQL server prepared statements. Executing a manually registered statement by passing its name as SQL is unsupported because pgx may execute text different from the string validated by this wrapper. Batch operations, transactions (including nested transactions), CopyFrom, and calls through an unwrapped executor are also outside the guarded boundary. Arguments that implement pgx.QueryRewriter are rejected.

This package is an illustrative example, not an official production adapter. Its API has no compatibility guarantee.

Index

Examples

Constants

This section is empty.

Variables

View Source
var ErrQueryRewriterUnsupported = errors.New(
	"sqlguard pgx-prepared example: query rewriting is unsupported",
)

ErrQueryRewriterUnsupported reports that an argument could replace SQL after it has passed validation.

Functions

This section is empty.

Types

type CacheOptions

type CacheOptions struct {
	Capacity    int
	MaxSQLBytes int
}

CacheOptions configures bounded prepared-value retention for one GuardedDB.

type Executor

type Executor interface {
	Exec(ctx context.Context, sql string, arguments ...any) (pgconn.CommandTag, error)
	Query(ctx context.Context, sql string, args ...any) (pgx.Rows, error)
	QueryRow(ctx context.Context, sql string, args ...any) pgx.Row
}

Executor is the subset of pgx connection and pool operations guarded by the example.

type GuardedDB

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

GuardedDB demonstrates a prepared-validation cache around a narrow subset of pgx. It is an illustrative example rather than a production-ready adapter.

Example
package main

import (
	"context"

	"github.com/jackc/pgx/v5"
	"github.com/jackc/pgx/v5/pgconn"

	sqlguard "github.com/almostinf/postgres-sqlguard"
	pgxprepared "github.com/almostinf/postgres-sqlguard/example/pgx-prepared"
)

type exampleExecutor struct{}

func (exampleExecutor) Exec(context.Context, string, ...any) (pgconn.CommandTag, error) {
	return pgconn.NewCommandTag("UPDATE 1"), nil
}

func (exampleExecutor) Query(context.Context, string, ...any) (pgx.Rows, error) {
	return nil, nil
}

func (exampleExecutor) QueryRow(context.Context, string, ...any) pgx.Row {
	return nil
}

func main() {
	engine, err := sqlguard.NewEngine(sqlguard.EngineOptions{})
	if err != nil {
		return
	}

	guarded, err := pgxprepared.NewGuardedDB(engine, exampleExecutor{}, pgxprepared.CacheOptions{
		Capacity:    128,
		MaxSQLBytes: 4096,
	})
	if err != nil {
		return
	}

	const sql = "UPDATE accounts SET active = $1 WHERE id = $2"

	_, _ = guarded.Exec(context.Background(), sql, true, 42)
	_, _ = guarded.Exec(context.Background(), sql, false, 84)
}

func NewGuardedDB

func NewGuardedDB(
	validator PreparedValidator,
	executor Executor,
	options CacheOptions,
) (*GuardedDB, error)

NewGuardedDB validates its collaborators and cache limits and constructs an illustrative pgx wrapper with a private fixed-capacity LRU cache.

func (*GuardedDB) Exec

func (db *GuardedDB) Exec(
	ctx context.Context,
	sql string,
	arguments ...any,
) (pgconn.CommandTag, error)

Exec validates SQL through the prepared cache before delegating to the wrapped executor.

func (*GuardedDB) Query

func (db *GuardedDB) Query(ctx context.Context, sql string, args ...any) (pgx.Rows, error)

Query validates SQL through the prepared cache before delegating to the wrapped executor.

func (*GuardedDB) QueryRow

func (db *GuardedDB) QueryRow(ctx context.Context, sql string, args ...any) pgx.Row

QueryRow validates SQL through the prepared cache before delegating to the wrapped executor. Guard failures are returned by the resulting row's Scan.

type PreparedValidator

type PreparedValidator interface {
	Prepare(context.Context, string) (sqlguard.Prepared, error)
	ValidatePrepared(context.Context, sqlguard.Prepared) error
}

PreparedValidator is the prepared-validation behavior required by GuardedDB.

Jump to

Keyboard shortcuts

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