diff --git a/pgxpool/conn.go b/pgxpool/conn.go index 29ca04d0..0b59d741 100644 --- a/pgxpool/conn.go +++ b/pgxpool/conn.go @@ -70,10 +70,12 @@ func (c *Conn) CopyFrom(ctx context.Context, tableName pgx.Identifier, columnNam return c.Conn().CopyFrom(ctx, tableName, columnNames, rowSrc) } +// Begin starts a transaction block from the *Conn without explicitly setting a transaction mode (see BeginTx with TxOptions if transaction mode is required). func (c *Conn) Begin(ctx context.Context) (pgx.Tx, error) { return c.Conn().Begin(ctx) } +// BeginTx starts a transaction block from the *Conn with txOptions determining the transaction mode. func (c *Conn) BeginTx(ctx context.Context, txOptions pgx.TxOptions) (pgx.Tx, error) { return c.Conn().BeginTx(ctx, txOptions) } diff --git a/pgxpool/pool.go b/pgxpool/pool.go index 54982a55..8b015c20 100644 --- a/pgxpool/pool.go +++ b/pgxpool/pool.go @@ -375,6 +375,7 @@ func (p *Pool) checkMinConns() { } } +// Acquire returns a connection (*Conn) from the Pool func (p *Pool) Acquire(ctx context.Context) (*Conn, error) { for { res, err := p.p.Acquire(ctx) @@ -483,9 +484,18 @@ func (p *Pool) SendBatch(ctx context.Context, b *pgx.Batch) pgx.BatchResults { return &poolBatchResults{br: br, c: c} } +// Begin acquires a connection from the Pool and starts a transaction. Unlike database/sql, the context only affects the begin command. i.e. there is no +// auto-rollback on context cancellation. Begin initiates a transaction block without explicitly setting a transaction mode for the block (see BeginTx with TxOptions if transaction mode is required). +// *pgxpool.Tx is returned, which implements the pgx.Tx interface. +// Commit or Rollback must be called on the returned transaction to finalize the transaction block. func (p *Pool) Begin(ctx context.Context) (pgx.Tx, error) { return p.BeginTx(ctx, pgx.TxOptions{}) } + +// BeginTx acquires a connection from the Pool and starts a transaction with pgx.TxOptions determining the transaction mode. +// Unlike database/sql, the context only affects the begin command. i.e. there is no auto-rollback on context cancellation. +// *pgxpool.Tx is returned, which implements the pgx.Tx interface. +// Commit or Rollback must be called on the returned transaction to finalize the transaction block. func (p *Pool) BeginTx(ctx context.Context, txOptions pgx.TxOptions) (pgx.Tx, error) { c, err := p.Acquire(ctx) if err != nil { @@ -525,6 +535,8 @@ func (p *Pool) CopyFrom(ctx context.Context, tableName pgx.Identifier, columnNam return c.Conn().CopyFrom(ctx, tableName, columnNames, rowSrc) } +// Ping acquires a connection from the Pool and executes an empty sql statement against it. +// If the sql returns without error, the database Ping is considered successful, otherwise, the error is returned. func (p *Pool) Ping(ctx context.Context) error { c, err := p.Acquire(ctx) if err != nil { diff --git a/pgxpool/tx.go b/pgxpool/tx.go index e1c980e1..f983b102 100644 --- a/pgxpool/tx.go +++ b/pgxpool/tx.go @@ -7,11 +7,13 @@ import ( "github.com/jackc/pgx/v4" ) +// Tx represents a database transaction acquired from a Pool. type Tx struct { t pgx.Tx c *Conn } +// Begin starts a pseudo nested transaction implemented with a savepoint. func (tx *Tx) Begin(ctx context.Context) (pgx.Tx, error) { return tx.t.Begin(ctx) } @@ -20,6 +22,9 @@ func (tx *Tx) BeginFunc(ctx context.Context, f func(pgx.Tx) error) error { return tx.t.BeginFunc(ctx, f) } +// Commit commits the transaction and returns the associated connection back to the Pool. Commit will return ErrTxClosed +// if the Tx is already closed, but is otherwise safe to call multiple times. If the commit fails with a rollback status +// (e.g. the transaction was already in a broken state) then ErrTxCommitRollback will be returned. func (tx *Tx) Commit(ctx context.Context) error { err := tx.t.Commit(ctx) if tx.c != nil { @@ -29,6 +34,9 @@ func (tx *Tx) Commit(ctx context.Context) error { return err } +// Rollback rolls back the transaction and returns the associated connection back to the Pool. Rollback will return ErrTxClosed +// if the Tx is already closed, but is otherwise safe to call multiple times. Hence, defer tx.Rollback() is safe even if +// tx.Commit() will be called first in a non-error condition. func (tx *Tx) Rollback(ctx context.Context) error { err := tx.t.Rollback(ctx) if tx.c != nil { diff --git a/tx.go b/tx.go index 973f2b8e..ad399679 100644 --- a/tx.go +++ b/tx.go @@ -10,6 +10,7 @@ import ( "github.com/jackc/pgconn" ) +// TxIsoLevel is the transaction isolation level (serializable, repeatable read, read committed or read uncommitted) type TxIsoLevel string // Transaction isolation levels @@ -20,6 +21,7 @@ const ( ReadUncommitted = TxIsoLevel("read uncommitted") ) +// TxAccessMode is the transaction access mode (read write or read only) type TxAccessMode string // Transaction access modes @@ -28,6 +30,7 @@ const ( ReadOnly = TxAccessMode("read only") ) +// TxDeferrableMode is the transaction deferrable mode (deferrable or not deferrable) type TxDeferrableMode string // Transaction deferrable modes @@ -36,6 +39,7 @@ const ( NotDeferrable = TxDeferrableMode("not deferrable") ) +// TxOptions are transaction modes within a transaction block type TxOptions struct { IsoLevel TxIsoLevel AccessMode TxAccessMode