Documentation
¶
Overview ¶
Package sqlx provides transaction management utilities for database operations. It supports nested transactions using savepoints (optional) and context-based executor propagation.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func NewContext ¶ added in v3.3.0
NewContext returns a new context with the given Executor attached. Use this to propagate a transaction through the call stack, allowing nested functions to participate in the same transaction.
Example:
sqlx.Transaction(ctx, db, func(ctx context.Context, tx *sql.Tx) error {
ctx = sqlx.NewContext(ctx, tx)
return doSomething(ctx, db) // doSomething will use tx via FromContext
})
func Transaction ¶
func Transaction(ctx context.Context, exec Executor, fn func(ctx context.Context, tx *sql.Tx) error, opts ...TransactionOption) (xerr error)
Transaction executes fn within a database transaction.
If exec is a *sql.DB, a new transaction is started. The transaction is automatically committed if fn returns nil, or rolled back if fn returns an error or panics.
If exec is already a *sql.Tx (nested transaction), behavior depends on options:
- By default, a savepoint is created for partial rollback support.
- With WithDisableSavepoint(), fn is executed directly without savepoint.
The function handles the context cancellation race condition where the database/sql's internal awaitDone goroutine may rollback the transaction before Commit() is called. In this case, the context error is returned instead of sql.ErrTxDone.
Example:
err := sqlx.Transaction(ctx, db, func(ctx context.Context, tx *sql.Tx) error {
_, err := tx.ExecContext(ctx, "INSERT INTO users (name) VALUES (?)", "Alice")
if err != nil {
return err
}
// Nested transaction using savepoint
return sqlx.Transaction(ctx, tx, func(ctx context.Context, tx *sql.Tx) error {
_, err := tx.ExecContext(ctx, "INSERT INTO logs (msg) VALUES (?)", "user created")
return err
})
})
Types ¶
type Executor ¶
type Executor interface {
ExecContext(ctx context.Context, query string, args ...any) (sql.Result, error)
QueryContext(ctx context.Context, query string, args ...any) (*sql.Rows, error)
QueryRowContext(ctx context.Context, query string, args ...any) *sql.Row
}
Executor defines the common interface for database operations. Both *sql.DB and *sql.Tx implement this interface, allowing code to work with either a direct database connection or within a transaction context.
func FromContext ¶ added in v3.3.0
FromContext retrieves an Executor from the context. If no Executor is found in the context, it returns the provided fallback. This is useful for propagating transactions through the call stack.
Example:
func doSomething(ctx context.Context, db *sql.DB) error {
exec := sqlx.FromContext(ctx, db)
_, err := exec.ExecContext(ctx, "INSERT INTO ...")
return err
}
type TransactionOption ¶
type TransactionOption func(*transactionOptions)
TransactionOption configures transaction behavior.
func WithDisableSavepoint ¶ added in v3.3.0
func WithDisableSavepoint() TransactionOption
WithDisableSavepoint disables savepoint usage for nested transactions. When disabled, if Transaction is called with an existing *sql.Tx, the function will be executed directly without creating a savepoint. This is useful for databases that do not support savepoints.
Note: When savepoints are disabled, errors in nested transactions will affect the entire transaction, not just the nested portion.
func WithTxOptions ¶
func WithTxOptions(txOptions *sql.TxOptions) TransactionOption
WithTxOptions sets the sql.TxOptions for the transaction. This allows configuring isolation level and read-only mode.