postgres

package
v1.0.1 Latest Latest
Warning

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

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

Documentation

Index

Constants

View Source
const DriverTypePostgres = "pgx"

DriverTypePostgres is the sql driver name registered by pgx stdlib.

Variables

This section is empty.

Functions

func CloseAll

func CloseAll() error

CloseAll closes all connections (best effort).

func CloseCluster

func CloseCluster(clusterName string) error

CloseCluster closes a specific cluster connection (useful for graceful shutdown / tests).

func ConvertQueryAndNamedParams

func ConvertQueryAndNamedParams(query string, params ...map[string]any) (string, []any)

ConvertQueryAndNamedParams converts ":name" tokens into Postgres positional params ($1,$2,...) and returns ordered param values.

This implementation is robust against: - Postgres casts like "col::int" (won't treat ::int as a param) - Single-quoted strings: 'text :not_a_param' - Dollar-quoted strings: $$ ... :not_a_param ... $$

Constraints (intentional for safety): - Named tokens must be [A-Za-z0-9_]+ and be prefixed by single ':' - The params maps must use keys like ":name" (same as your mysql helper)

func DeleteByPrimaryKey

func DeleteByPrimaryKey(dbctx *DBContext, tableName, pkColumn string, pkValue any) (int64, error)

func DeleteByPrimaryKeyContext

func DeleteByPrimaryKeyContext(ctx context.Context, dbctx *DBContext, tableName, pkColumn string, pkValue any) (int64, error)

func ExecuteReadQuery

func ExecuteReadQuery(dbctx *DBContext, queryInput ReadQueryInput) ([]map[string]any, error)

ExecuteReadQuery runs a read-only SELECT query. It returns []map[string]any where each value is typed (int64, bool, time.Time, string, nil, etc).

NOTE: We do NOT prepare implicitly here. Preparing without using the prepared statement is wasteful and can break assumptions under PgBouncer. If you want explicit prepare, do it at the call site (or add an optional flag and execute via stmt).

func ExecuteReadQueryContext

func ExecuteReadQueryContext(ctx context.Context, dbctx *DBContext, queryInput ReadQueryInput) ([]map[string]any, error)

func ExecuteWriteQuery

func ExecuteWriteQuery(dbctx *DBContext, query string, params []any) (int64, int64, error)

ExecuteWriteQuery executes an INSERT/UPDATE/DELETE query. Note: Postgres generally does NOT support LastInsertId(). Prefer `RETURNING id` and QueryRow/Scan for inserts that need IDs.

func ExecuteWriteQueryContext

func ExecuteWriteQueryContext(ctx context.Context, dbctx *DBContext, query string, params []any) (int64, int64, error)

func GetParameterizedInClause

func GetParameterizedInClause[T any](columnName string, columnValueArray []T) (string, map[string]any)

GetParameterizedInClause generates a named IN clause like ":id1,:id2,..." and returns a map of placeholders to values. This keeps your mysql helper API style.

func HashKey

func HashKey(query string, args map[string]any) (string, error)

HashKey creates a deterministic hash for query+args map (same intent as your mysql helper).

func InsertFromMap

func InsertFromMap(dbctx *DBContext, tableName string, data map[string]any) (int64, int64, error)

InsertFromMap inserts a record using map[column]value. Uses Postgres placeholders ($1..$N).

func InsertFromMapContext

func InsertFromMapContext(ctx context.Context, dbctx *DBContext, tableName string, data map[string]any) (int64, int64, error)

func InsertFromStruct

func InsertFromStruct(dbctx *DBContext, tableName string, data any) (int64, int64, error)

InsertFromStruct inserts one record into a table based on struct db tags. Uses Postgres placeholders ($1..$N).

func InsertFromStructContext

func InsertFromStructContext(ctx context.Context, dbctx *DBContext, tableName string, data any) (int64, int64, error)

func MultiInsertFromStructsArray

func MultiInsertFromStructsArray[T any](dbctx *DBContext, tableName string, data []T) (int64, error)

MultiInsertFromStructsArray performs a bulk insert using a slice of structs, generating Postgres placeholders ($1..$N).

func MultiInsertFromStructsArrayContext

func MultiInsertFromStructsArrayContext[T any](ctx context.Context, dbctx *DBContext, tableName string, data []T) (int64, error)

func SetConnectionConfig

func SetConnectionConfig(clusterName string, config *ConnectionConfig)

SetConnectionConfig registers config for a cluster.

func SetConnectionConfigE

func SetConnectionConfigE(clusterName string, config *ConnectionConfig) error

func SoftDeleteByPrimaryKey

func SoftDeleteByPrimaryKey(dbctx *DBContext, tableName, deleteCol, pkCol string, value any) (int64, error)

func SoftDeleteByPrimaryKeyContext

func SoftDeleteByPrimaryKeyContext(ctx context.Context, dbctx *DBContext, tableName, deleteCol, pkCol string, value any) (int64, error)

func UpdateFromMap

func UpdateFromMap(dbctx *DBContext, tableName string, data map[string]any, whereClause string, params ...any) (int64, error)

UpdateFromMap updates rows using map[column]value and a WHERE clause. whereClause may contain either: - Postgres placeholders ($N), OR - '?' placeholders (which will be converted to $N starting at the correct position)

func UpdateFromMapContext

func UpdateFromMapContext(ctx context.Context, dbctx *DBContext, tableName string, data map[string]any, whereClause string, params ...any) (int64, error)

Types

type ConnectionConfig

type ConnectionConfig struct {
	Host     string
	Port     string
	UserName string
	Password string
	DbName   string

	// TLS/SSL: "disable", "require", "verify-ca", "verify-full"
	SSLMode string

	// Pool sizing (per process)
	MaxOpenConn int
	MaxIdleConn int

	ConnMaxLifetime time.Duration
	ConnMaxIdleTime time.Duration

	// Defaults applied if zero.
	ConnectTimeout time.Duration
	PingTimeout    time.Duration

	// DefaultQueryTimeout is used by DBContext when it needs to add a timeout
	// to context-less calls.
	DefaultQueryTimeout time.Duration

	// PgBouncer config — if transaction/statement pooling, we will disable
	// server-side prepared statements at the driver level.
	PgBouncer PgBouncerMode

	// RuntimeParams are sent to Postgres at connection startup:
	// application_name, search_path, statement_timeout, timezone, etc.
	RuntimeParams map[string]string
}

ConnectionConfig holds settings for connecting to Postgres.

func (*ConnectionConfig) Validate

func (c *ConnectionConfig) Validate() error

type DBContext

type DBContext struct {
	// Tx represents an active PostgreSQL transaction.
	// If set, all SQL operations are executed inside this transaction.
	Tx Tx

	// Conn is a direct PostgreSQL connection interface.
	// Used when Tx is nil.
	Conn PostgresDbInterface

	// Cluster is a named PostgreSQL cluster.
	// Used to lazily obtain a connection if both Tx and Conn are nil.
	Cluster string

	// DefaultTimeout is applied when callers use non-context methods
	// (Exec/Query/Prepare) or pass a context without deadline.
	//
	// If <= 0, no implicit deadline is added.
	DefaultTimeout time.Duration

	// ExecFn optionally overrides execution of non-query statements.
	ExecFn func(ctx context.Context, query string, args ...any) (sql.Result, error)

	// PrepareFn optionally overrides preparation of SQL statements.
	PrepareFn func(ctx context.Context, query string) (*sql.Stmt, error)

	// QueryFn optionally overrides execution of queries returning rows.
	QueryFn func(ctx context.Context, query string, args ...any) (*sql.Rows, error)
}

DBContext defines a contextual wrapper around PostgreSQL execution logic. It allows SQL operations to be executed using:

  1. An existing transaction (Tx)
  2. A manually supplied database connection (Conn)
  3. A lazily resolved cluster-based connection (Cluster)

DBContext also supports function overrides (ExecFn, PrepareFn, QueryFn) to inject custom behavior such as:

  • Unit test mocks
  • Observability / tracing wrappers
  • Query auditing
  • Fault injection

IMPORTANT: Prefer the Context variants (ExecContext/QueryContext/PrepareContext). The non-context methods call the context variants with context.Background().

func (*DBContext) Exec

func (ctx *DBContext) Exec(query string, args ...any) (sql.Result, error)

Exec executes a SQL statement that does not return rows. It uses context.Background() and applies DefaultTimeout if configured.

func (*DBContext) ExecContext

func (ctx *DBContext) ExecContext(c context.Context, query string, args ...any) (sql.Result, error)

ExecContext executes a SQL statement that does not return rows (INSERT, UPDATE, DELETE, etc).

Resolution order:

  1. ExecFn override (if set)
  2. Tx.ExecContext() / Tx.Exec()
  3. Conn.ExecContext() / Conn.Exec()
  4. Cluster-based connection via Connect()

func (*DBContext) Prepare

func (ctx *DBContext) Prepare(query string) (*sql.Stmt, error)

Prepare creates a prepared SQL statement. It uses context.Background() and applies DefaultTimeout if configured.

func (*DBContext) PrepareContext

func (ctx *DBContext) PrepareContext(c context.Context, query string) (*sql.Stmt, error)

PrepareContext prepares a SQL statement.

Resolution order:

  1. PrepareFn override (if set)
  2. Tx.PrepareContext() / Tx.Prepare()
  3. Conn.PrepareContext() / Conn.Prepare()
  4. Cluster-based connection via Connect()

func (*DBContext) Query

func (ctx *DBContext) Query(query string, args ...any) (*sql.Rows, error)

Query executes a SQL query that returns rows. It uses context.Background() and applies DefaultTimeout if configured.

func (*DBContext) QueryContext

func (ctx *DBContext) QueryContext(c context.Context, query string, args ...any) (*sql.Rows, error)

QueryContext executes a SQL query that returns rows.

Resolution order:

  1. QueryFn override (if set)
  2. Tx.QueryContext() / Tx.Query()
  3. Conn.QueryContext() / Conn.Query()
  4. Cluster-based connection via Connect()

type PgBouncerMode

type PgBouncerMode string

PgBouncerMode defines how PgBouncer pools backend connections. Only transaction/statement pooling is incompatible with server-side prepares.

Values:

  • "" (empty): not using PgBouncer / unknown
  • "session"
  • "transaction"
  • "statement"
const (
	PgBouncerNone        PgBouncerMode = ""
	PgBouncerSession     PgBouncerMode = "session"
	PgBouncerTransaction PgBouncerMode = "transaction"
	PgBouncerStatement   PgBouncerMode = "statement"
)

type PostgresDb

type PostgresDb struct {
	DB *sql.DB
}

PostgresDb embeds *sql.DB to avoid wrapper traps while still allowing Raw() to be explicit.

func (*PostgresDb) Begin

func (pdb *PostgresDb) Begin() (*sql.Tx, error)

func (*PostgresDb) BeginTx

func (pdb *PostgresDb) BeginTx(ctx context.Context, opts *sql.TxOptions) (*sql.Tx, error)

func (*PostgresDb) Close

func (pdb *PostgresDb) Close() error

Ensure PostgresDb implements PostgresDbInterface without wrapper rework.

func (*PostgresDb) Exec

func (pdb *PostgresDb) Exec(query string, args ...any) (sql.Result, error)

func (*PostgresDb) ExecContext

func (pdb *PostgresDb) ExecContext(ctx context.Context, query string, args ...any) (sql.Result, error)

func (*PostgresDb) Ping

func (pdb *PostgresDb) Ping() error

func (*PostgresDb) PingContext

func (pdb *PostgresDb) PingContext(ctx context.Context) error

func (*PostgresDb) Prepare

func (pdb *PostgresDb) Prepare(query string) (*sql.Stmt, error)

func (*PostgresDb) PrepareContext

func (pdb *PostgresDb) PrepareContext(ctx context.Context, query string) (*sql.Stmt, error)

func (*PostgresDb) Query

func (pdb *PostgresDb) Query(query string, args ...any) (*sql.Rows, error)

func (*PostgresDb) QueryContext

func (pdb *PostgresDb) QueryContext(ctx context.Context, query string, args ...any) (*sql.Rows, error)

func (*PostgresDb) QueryRow

func (pdb *PostgresDb) QueryRow(query string, args ...any) *sql.Row

func (*PostgresDb) QueryRowContext

func (pdb *PostgresDb) QueryRowContext(ctx context.Context, query string, args ...any) *sql.Row

func (*PostgresDb) Raw

func (pdb *PostgresDb) Raw() *sql.DB

func (*PostgresDb) SetConnMaxIdleTime

func (pdb *PostgresDb) SetConnMaxIdleTime(d time.Duration)

func (*PostgresDb) SetConnMaxLifetime

func (pdb *PostgresDb) SetConnMaxLifetime(d time.Duration)

func (*PostgresDb) SetMaxIdleConns

func (pdb *PostgresDb) SetMaxIdleConns(n int)

func (*PostgresDb) SetMaxOpenConns

func (pdb *PostgresDb) SetMaxOpenConns(n int)

func (*PostgresDb) Stats

func (pdb *PostgresDb) Stats() sql.DBStats

type PostgresDbConnector

type PostgresDbConnector struct {
	DB *PostgresDb
}

PostgresDbConnector opens *sql.DB using sql.Open.

func (*PostgresDbConnector) Open

func (pdbc *PostgresDbConnector) Open(driverName, dataSourceName string) (PostgresDbInterface, error)

type PostgresDbConnectorInterface

type PostgresDbConnectorInterface interface {
	Open(driverName string, dataSourceName string) (PostgresDbInterface, error)
}

PostgresDbConnectorInterface defines behavior for opening a connection.

type PostgresDbInterface

type PostgresDbInterface interface {
	Close() error
	Ping() error
	PingContext(ctx context.Context) error

	Exec(query string, args ...any) (sql.Result, error)
	ExecContext(ctx context.Context, query string, args ...any) (sql.Result, error)

	Query(query string, args ...any) (*sql.Rows, error)
	QueryContext(ctx context.Context, query string, args ...any) (*sql.Rows, error)

	QueryRow(query string, args ...any) *sql.Row
	QueryRowContext(ctx context.Context, query string, args ...any) *sql.Row

	Prepare(query string) (*sql.Stmt, error)
	PrepareContext(ctx context.Context, query string) (*sql.Stmt, error)

	Begin() (*sql.Tx, error)
	BeginTx(ctx context.Context, opts *sql.TxOptions) (*sql.Tx, error)

	SetConnMaxLifetime(d time.Duration)
	SetMaxIdleConns(n int)
	SetMaxOpenConns(n int)
	SetConnMaxIdleTime(d time.Duration)
	Stats() sql.DBStats

	Raw() *sql.DB
}

PostgresDbInterface is intentionally broad enough to support DBContext without wrapper traps. PostgresDb embeds *sql.DB, so it satisfies this without re-implementing methods.

Raw() exists as an escape hatch for tooling/migrations/sqlc/etc.

func Connect

func Connect(connector PostgresDbConnectorInterface, clusterName string) (PostgresDbInterface, error)

Connect returns a singleton connection per clusterName (per process).

type ReadQueryInput

type ReadQueryInput struct {
	Query             string
	Params            []any
	CapitaliseColumns bool
}

ReadQueryInput mirrors your mysql helper pattern.

type Tx

type Tx interface {
	Exec(query string, args ...any) (sql.Result, error)
	Prepare(query string) (*sql.Stmt, error)
	Query(query string, args ...any) (*sql.Rows, error)
}

Tx is the minimal transaction/connection surface used by DBContext. It matches *sql.Tx methods for easy compatibility and test mocking.

type TxContext

type TxContext interface {
	ExecContext(ctx context.Context, query string, args ...any) (sql.Result, error)
	PrepareContext(ctx context.Context, query string) (*sql.Stmt, error)
	QueryContext(ctx context.Context, query string, args ...any) (*sql.Rows, error)
}

TxContext is an optional extension for transactions that support context methods. *sql.Tx implements these.

Jump to

Keyboard shortcuts

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