Documentation
¶
Overview ¶
Package dbutil provides utility functions and helpers for interacting with databases in Go projects.
This package offers enhanced database/sql functionality with features like: - Connection management with retry logic and context support - Query execution helpers with automatic scanning and error context - Transaction management utilities with rollback handling - Context-aware operations for cancellation and timeout support - Convenience generic helpers for scanning rows into slices/structs
Core types and functions ------------------------
- ConfigureDB(db *sql.DB, opts *ConnectionOptions) error
- Helper to apply sensible defaults and connection pooling settings.
- PingWithContext(ctx context.Context, db *sql.DB, timeout time.Duration) error
- Health check that respects context and timeout.
- QueryRow(ctx context.Context, db *sql.DB, query string, args ...interface{}) *sql.Row
- Thin wrapper providing consistent logging and error context.
- QueryRows[T any](ctx context.Context, db *sql.DB, query string, args ...interface{}) ([]T, error)
- Generic helper to run queries and scan results into a slice of T.
- WithTransaction(ctx context.Context, db *sql.DB, fn func(*sql.Tx) error) error
- Run a function within a transaction and automatically rollback on error.
Examples --------
Basic Query Row scan:
var user User
err := dbutil.QueryRowScan(ctx, db, &user, "SELECT id, name, email FROM users WHERE id = $1", 1)
if err != nil {
return err
}
Query multiple rows into a slice using the generic helper:
users, err := dbutil.QueryRows[User](ctx, db, "SELECT id, name, email FROM users WHERE active = $1", true)
if err != nil {
return err
}
Safe transaction usage:
err := dbutil.WithTransaction(ctx, db, func(tx *sql.Tx) error {
if _, err := tx.ExecContext(ctx, "INSERT INTO users (name) VALUES ($1)", "alice"); err != nil {
return err
}
return nil
})
The package is intentionally small and focused on making common database operations less error-prone and easier to read. See the package tests for additional usage patterns and edge cases.
Index ¶
- func ConfigureDB(db *sql.DB, opts *ConnectionOptions) error
- func Count(ctx context.Context, db *sql.DB, query string, args ...any) (int64, error)
- func CountTx(ctx context.Context, tx *sql.Tx, query string, args ...any) (int64, error)
- func DefaultFieldMapper(fieldName string) string
- func Exec(ctx context.Context, db *sql.DB, query string, args ...any) (sql.Result, error)
- func ExecTx(ctx context.Context, tx *sql.Tx, query string, args ...any) (sql.Result, error)
- func Exists(ctx context.Context, db *sql.DB, query string, args ...any) (bool, error)
- func ExistsTx(ctx context.Context, tx *sql.Tx, query string, args ...any) (bool, error)
- func IsConnectionError(err error) bool
- func IsContextError(err error) bool
- func IsNoRowsError(err error) bool
- func PingWithContext(ctx context.Context, db *sql.DB, timeout time.Duration) error
- func PingWithRetry(ctx context.Context, db *sql.DB, attempts int, delay time.Duration) error
- func QueryMap(ctx context.Context, db *sql.DB, query string, args ...any) (map[string]any, error)
- func QueryMapTx(ctx context.Context, tx *sql.Tx, query string, args ...any) (map[string]any, error)
- func QueryMaps(ctx context.Context, db *sql.DB, query string, args ...any) ([]map[string]any, error)
- func QueryMapsTx(ctx context.Context, tx *sql.Tx, query string, args ...any) ([]map[string]any, error)
- func QueryRow(ctx context.Context, db *sql.DB, query string, args ...any) *sql.Row
- func QueryRowScan(ctx context.Context, db *sql.DB, dest any, query string, args ...any) error
- func QueryRowScanTx(ctx context.Context, tx *sql.Tx, dest any, query string, args ...any) error
- func QueryRowTx(ctx context.Context, tx *sql.Tx, query string, args ...any) *sql.Row
- func QueryRows(ctx context.Context, db *sql.DB, query string, args ...any) (*sql.Rows, error)
- func QueryRowsTx(ctx context.Context, tx *sql.Tx, query string, args ...any) (*sql.Rows, error)
- func QuerySlice(ctx context.Context, db *sql.DB, dest any, query string, args ...any) error
- func QuerySliceTx(ctx context.Context, tx *sql.Tx, dest any, query string, args ...any) error
- func QuerySliceWithOptions(ctx context.Context, db *sql.DB, dest any, query string, opts *QueryOptions, ...) error
- func QuerySliceWithOptionsTx(ctx context.Context, tx *sql.Tx, dest any, query string, opts *QueryOptions, ...) error
- func WithTransaction(ctx context.Context, db *sql.DB, fn func(*sql.Tx) error) error
- func WithTransactionOptions(ctx context.Context, db *sql.DB, opts *TransactionOptions, ...) error
- type ConnectionOptions
- type QueryOptions
- type TransactionOptions
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func ConfigureDB ¶
func ConfigureDB(db *sql.DB, opts *ConnectionOptions) error
ConfigureDB configures a database connection with the provided options.
func DefaultFieldMapper ¶
DefaultFieldMapper converts Go struct field names to database column names. It converts CamelCase to snake_case (e.g., "UserID" -> "user_id").
func Exec ¶
Exec executes a query without returning any rows. It returns the number of rows affected and any error encountered.
func IsConnectionError ¶
IsConnectionError checks if an error is a database connection error.
func IsContextError ¶
IsContextError checks if an error is a context cancellation or timeout error.
func IsNoRowsError ¶
IsNoRowsError checks if an error is a sql.ErrNoRows error.
func PingWithContext ¶
PingWithContext pings the database with a context timeout.
func PingWithRetry ¶
PingWithRetry pings the database with retry logic.
func QueryMapTx ¶
QueryMapTx is like QueryMap but uses a transaction.
func QueryMaps ¶
func QueryMaps(ctx context.Context, db *sql.DB, query string, args ...any) ([]map[string]any, error)
QueryMaps executes a query and returns all rows as []map[string]interface{}.
func QueryMapsTx ¶
func QueryMapsTx(ctx context.Context, tx *sql.Tx, query string, args ...any) ([]map[string]any, error)
QueryMapsTx is like QueryMaps but uses a transaction.
func QueryRow ¶
QueryRow executes a query that is expected to return at most one row. It returns a *sql.Row which can be scanned into destination variables.
func QueryRowScan ¶
QueryRowScan executes a query that returns a single row and scans the result into dest. dest should be a pointer to a struct with appropriate db tags.
func QueryRowScanTx ¶
QueryRowScanTx is like QueryRowScan but uses a transaction.
func QueryRowTx ¶
QueryRowTx is like QueryRow but uses a transaction.
func QueryRows ¶
QueryRows executes a query and returns multiple rows. It's the caller's responsibility to close the returned *sql.Rows.
func QueryRowsTx ¶
QueryRowsTx is like QueryRows but uses a transaction.
func QuerySlice ¶
QuerySlice executes a query and scans all rows into a slice of structs. dest should be a pointer to a slice of structs with appropriate db tags.
func QuerySliceTx ¶
QuerySliceTx is like QuerySlice but uses a transaction.
func QuerySliceWithOptions ¶
func QuerySliceWithOptions( ctx context.Context, db *sql.DB, dest any, query string, opts *QueryOptions, args ...any, ) error
QuerySliceWithOptions executes a query and scans all rows into a slice of structs with options.
func QuerySliceWithOptionsTx ¶
func QuerySliceWithOptionsTx( ctx context.Context, tx *sql.Tx, dest any, query string, opts *QueryOptions, args ...any, ) error
QuerySliceWithOptionsTx is like QuerySliceWithOptions but uses a transaction.
func WithTransaction ¶
WithTransaction executes a function within a database transaction. If the function returns an error, the transaction is rolled back. Otherwise, the transaction is committed.
Types ¶
type ConnectionOptions ¶
type ConnectionOptions struct {
// MaxOpenConns sets the maximum number of open connections to the database.
MaxOpenConns int
// MaxIdleConns sets the maximum number of connections in the idle connection pool.
MaxIdleConns int
// ConnMaxLifetime sets the maximum amount of time a connection may be reused.
ConnMaxLifetime time.Duration
// ConnMaxIdleTime sets the maximum amount of time a connection may be idle.
ConnMaxIdleTime time.Duration
// PingTimeout sets the timeout for ping operations.
PingTimeout time.Duration
// RetryAttempts sets the number of retry attempts for failed operations.
RetryAttempts int
// RetryDelay sets the delay between retry attempts.
RetryDelay time.Duration
}
ConnectionOptions holds configuration options for database connections.
func DefaultConnectionOptions ¶
func DefaultConnectionOptions() *ConnectionOptions
DefaultConnectionOptions returns sensible default connection options.
type QueryOptions ¶
type QueryOptions struct {
// Timeout sets the timeout for query execution.
Timeout time.Duration
// MaxRows limits the number of rows returned (0 means no limit).
MaxRows int
// FieldMapper is a function to map struct field names to database column names.
FieldMapper func(string) string
}
QueryOptions holds configuration options for query execution.
func DefaultQueryOptions ¶
func DefaultQueryOptions() *QueryOptions
DefaultQueryOptions returns sensible default query options.
type TransactionOptions ¶
type TransactionOptions struct {
// Isolation sets the transaction isolation level.
Isolation sql.IsolationLevel
// ReadOnly sets whether the transaction is read-only.
ReadOnly bool
// Timeout sets the timeout for the entire transaction.
Timeout time.Duration
}
TransactionOptions holds configuration options for transactions.
func DefaultTransactionOptions ¶
func DefaultTransactionOptions() *TransactionOptions
DefaultTransactionOptions returns sensible default transaction options.