package pgx

import (
	
	
	
	
	

	
)

type TxIsoLevel string
Transaction isolation levels
const (
	Serializable    = TxIsoLevel("serializable")
	RepeatableRead  = TxIsoLevel("repeatable read")
	ReadCommitted   = TxIsoLevel("read committed")
	ReadUncommitted = TxIsoLevel("read uncommitted")
)

type TxAccessMode string
Transaction access modes
const (
	ReadWrite = TxAccessMode("read write")
	ReadOnly  = TxAccessMode("read only")
)

type TxDeferrableMode string
Transaction deferrable modes
const (
	Deferrable    = TxDeferrableMode("deferrable")
	NotDeferrable = TxDeferrableMode("not deferrable")
)

type TxOptions struct {
	IsoLevel       TxIsoLevel
	AccessMode     TxAccessMode
	DeferrableMode TxDeferrableMode
}

func ( TxOptions) () string {
	 := &bytes.Buffer{}
	.WriteString("begin")
	if .IsoLevel != "" {
		fmt.Fprintf(, " isolation level %s", .IsoLevel)
	}
	if .AccessMode != "" {
		fmt.Fprintf(, " %s", .AccessMode)
	}
	if .DeferrableMode != "" {
		fmt.Fprintf(, " %s", .DeferrableMode)
	}

	return .String()
}

var ErrTxClosed = errors.New("tx is closed")
ErrTxCommitRollback occurs when an error has occurred in a transaction and Commit() is called. PostgreSQL accepts COMMIT on aborted transactions, but it is treated as ROLLBACK.
var ErrTxCommitRollback = errors.New("commit unexpectedly resulted in rollback")
Begin starts a transaction. Unlike database/sql, the context only affects the begin command. i.e. there is no auto-rollback on context cancellation.
func ( *Conn) ( context.Context) (Tx, error) {
	return .BeginTx(, TxOptions{})
}
BeginTx starts a transaction with 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.
func ( *Conn) ( context.Context,  TxOptions) (Tx, error) {
	,  := .Exec(, .beginSQL())
begin should never fail unless there is an underlying connection issue or a context timeout. In either case, the connection is possibly broken.
		.die(errors.New("failed to begin transaction"))
		return nil, 
	}

	return &dbTx{conn: }, nil
}
BeginFunc starts a transaction and calls f. If f does not return an error the transaction is committed. If f returns an error the transaction is rolled back. The context will be used when executing the transaction control statements (BEGIN, ROLLBACK, and COMMIT) but does not otherwise affect the execution of f.
func ( *Conn) ( context.Context,  func(Tx) error) ( error) {
	return .BeginTxFunc(, TxOptions{}, )
}
BeginTxFunc starts a transaction with txOptions determining the transaction mode and calls f. If f does not return an error the transaction is committed. If f returns an error the transaction is rolled back. The context will be used when executing the transaction control statements (BEGIN, ROLLBACK, and COMMIT) but does not otherwise affect the execution of f.
func ( *Conn) ( context.Context,  TxOptions,  func(Tx) error) ( error) {
	var  Tx
	,  = .BeginTx(, )
	if  != nil {
		return 
	}
	defer func() {
		 := .Rollback()
		if !( == nil || errors.Is(, ErrTxClosed)) {
			 = 
		}
	}()

	 := ()
	if  != nil {
		_ = .Rollback() // ignore rollback error as there is already an error to return
		return 
	}

	return .Commit()
}
Tx represents a database transaction. Tx is an interface instead of a struct to enable connection pools to be implemented without relying on internal pgx state, to support pseudo-nested transactions with savepoints, and to allow tests to mock transactions. However, adding a method to an interface is technically a breaking change. If new methods are added to Conn it may be desirable to add them to Tx as well. Because of this the Tx interface is partially excluded from semantic version requirements. Methods will not be removed or changed, but new methods may be added.
Begin starts a pseudo nested transaction.
	Begin(ctx context.Context) (Tx, error)
BeginFunc starts a pseudo nested transaction and executes f. If f does not return an err the pseudo nested transaction will be committed. If it does then it will be rolled back.
	BeginFunc(ctx context.Context, f func(Tx) error) (err error)
Commit commits the transaction if this is a real transaction or releases the savepoint if this is a pseudo nested transaction. 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.
	Commit(ctx context.Context) error
Rollback rolls back the transaction if this is a real transaction or rolls back to the savepoint if this is a pseudo nested transaction. Rollback will return ErrTxClosed if the Tx is already closed, but is otherwise safe to call multiple times. Hence, a defer tx.Rollback() is safe even if tx.Commit() will be called first in a non-error condition. Any other failure of a real transaction will result in the connection being closed.
	Rollback(ctx context.Context) error

	CopyFrom(ctx context.Context, tableName Identifier, columnNames []string, rowSrc CopyFromSource) (int64, error)
	SendBatch(ctx context.Context, b *Batch) BatchResults
	LargeObjects() LargeObjects

	Prepare(ctx context.Context, name, sql string) (*pgconn.StatementDescription, error)

	Exec(ctx context.Context, sql string, arguments ...interface{}) (commandTag pgconn.CommandTag, err error)
	Query(ctx context.Context, sql string, args ...interface{}) (Rows, error)
	QueryRow(ctx context.Context, sql string, args ...interface{}) Row
	QueryFunc(ctx context.Context, sql string, args []interface{}, scans []interface{}, f func(QueryFuncRow) error) (pgconn.CommandTag, error)
Conn returns the underlying *Conn that on which this transaction is executing.
	Conn() *Conn
}
dbTx represents a database transaction. All dbTx methods return ErrTxClosed if Commit or Rollback has already been called on the dbTx.
Begin starts a pseudo nested transaction implemented with a savepoint.
func ( *dbTx) ( context.Context) (Tx, error) {
	if .closed {
		return nil, ErrTxClosed
	}

	.savepointNum++
	,  := .conn.Exec(, "savepoint sp_"+strconv.FormatInt(.savepointNum, 10))
	if  != nil {
		return nil, 
	}

	return &dbSavepoint{tx: , savepointNum: .savepointNum}, nil
}

func ( *dbTx) ( context.Context,  func(Tx) error) ( error) {
	if .closed {
		return ErrTxClosed
	}

	var  Tx
	,  = .Begin()
	if  != nil {
		return 
	}
	defer func() {
		 := .Rollback()
		if !( == nil || errors.Is(, ErrTxClosed)) {
			 = 
		}
	}()

	 := ()
	if  != nil {
		_ = .Rollback() // ignore rollback error as there is already an error to return
		return 
	}

	return .Commit()
}
Commit commits the transaction.
func ( *dbTx) ( context.Context) error {
	if .closed {
		return ErrTxClosed
	}

	,  := .conn.Exec(, "commit")
	.closed = true
	if  != nil {
		if .conn.PgConn().TxStatus() != 'I' {
			_ = .conn.Close() // already have error to return
		}
		return 
	}
	if string() == "ROLLBACK" {
		return ErrTxCommitRollback
	}

	return nil
}
Rollback rolls back the transaction. Rollback will return ErrTxClosed if the Tx is already closed, but is otherwise safe to call multiple times. Hence, a defer tx.Rollback() is safe even if tx.Commit() will be called first in a non-error condition.
func ( *dbTx) ( context.Context) error {
	if .closed {
		return ErrTxClosed
	}

	,  := .conn.Exec(, "rollback")
	.closed = true
A rollback failure leaves the connection in an undefined state
		.conn.die(fmt.Errorf("rollback failed: %w", ))
		return 
	}

	return nil
}
Exec delegates to the underlying *Conn
func ( *dbTx) ( context.Context,  string,  ...interface{}) ( pgconn.CommandTag,  error) {
	return .conn.Exec(, , ...)
}
Prepare delegates to the underlying *Conn
func ( *dbTx) ( context.Context, ,  string) (*pgconn.StatementDescription, error) {
	if .closed {
		return nil, ErrTxClosed
	}

	return .conn.Prepare(, , )
}
Query delegates to the underlying *Conn
func ( *dbTx) ( context.Context,  string,  ...interface{}) (Rows, error) {
Because checking for errors can be deferred to the *Rows, build one with the error
		 := ErrTxClosed
		return &connRows{closed: true, err: }, 
	}

	return .conn.Query(, , ...)
}
QueryRow delegates to the underlying *Conn
func ( *dbTx) ( context.Context,  string,  ...interface{}) Row {
	,  := .Query(, , ...)
	return (*connRow)(.(*connRows))
}
QueryFunc delegates to the underlying *Conn.
func ( *dbTx) ( context.Context,  string,  []interface{},  []interface{},  func(QueryFuncRow) error) (pgconn.CommandTag, error) {
	if .closed {
		return nil, ErrTxClosed
	}

	return .conn.QueryFunc(, , , , )
}
CopyFrom delegates to the underlying *Conn
func ( *dbTx) ( context.Context,  Identifier,  []string,  CopyFromSource) (int64, error) {
	if .closed {
		return 0, ErrTxClosed
	}

	return .conn.CopyFrom(, , , )
}
SendBatch delegates to the underlying *Conn
func ( *dbTx) ( context.Context,  *Batch) BatchResults {
	if .closed {
		return &batchResults{err: ErrTxClosed}
	}

	return .conn.SendBatch(, )
}
LargeObjects returns a LargeObjects instance for the transaction.
func ( *dbTx) () LargeObjects {
	return LargeObjects{tx: }
}

func ( *dbTx) () *Conn {
	return .conn
}
dbSavepoint represents a nested transaction implemented by a savepoint.
Begin starts a pseudo nested transaction implemented with a savepoint.
func ( *dbSavepoint) ( context.Context) (Tx, error) {
	if .closed {
		return nil, ErrTxClosed
	}

	return .tx.Begin()
}

func ( *dbSavepoint) ( context.Context,  func(Tx) error) ( error) {
	if .closed {
		return ErrTxClosed
	}

	return .tx.BeginFunc(, )
}
Commit releases the savepoint essentially committing the pseudo nested transaction.
func ( *dbSavepoint) ( context.Context) error {
	if .closed {
		return ErrTxClosed
	}

	,  := .Exec(, "release savepoint sp_"+strconv.FormatInt(.savepointNum, 10))
	.closed = true
	return 
}
Rollback rolls back to the savepoint essentially rolling back the pseudo nested transaction. Rollback will return ErrTxClosed if the dbSavepoint is already closed, but is otherwise safe to call multiple times. Hence, a defer sp.Rollback() is safe even if sp.Commit() will be called first in a non-error condition.
func ( *dbSavepoint) ( context.Context) error {
	if .closed {
		return ErrTxClosed
	}

	,  := .Exec(, "rollback to savepoint sp_"+strconv.FormatInt(.savepointNum, 10))
	.closed = true
	return 
}
Exec delegates to the underlying Tx
func ( *dbSavepoint) ( context.Context,  string,  ...interface{}) ( pgconn.CommandTag,  error) {
	if .closed {
		return nil, ErrTxClosed
	}

	return .tx.Exec(, , ...)
}
Prepare delegates to the underlying Tx
func ( *dbSavepoint) ( context.Context, ,  string) (*pgconn.StatementDescription, error) {
	if .closed {
		return nil, ErrTxClosed
	}

	return .tx.Prepare(, , )
}
Query delegates to the underlying Tx
func ( *dbSavepoint) ( context.Context,  string,  ...interface{}) (Rows, error) {
Because checking for errors can be deferred to the *Rows, build one with the error
		 := ErrTxClosed
		return &connRows{closed: true, err: }, 
	}

	return .tx.Query(, , ...)
}
QueryRow delegates to the underlying Tx
func ( *dbSavepoint) ( context.Context,  string,  ...interface{}) Row {
	,  := .Query(, , ...)
	return (*connRow)(.(*connRows))
}
QueryFunc delegates to the underlying Tx.
func ( *dbSavepoint) ( context.Context,  string,  []interface{},  []interface{},  func(QueryFuncRow) error) (pgconn.CommandTag, error) {
	if .closed {
		return nil, ErrTxClosed
	}

	return .tx.QueryFunc(, , , , )
}
CopyFrom delegates to the underlying *Conn
func ( *dbSavepoint) ( context.Context,  Identifier,  []string,  CopyFromSource) (int64, error) {
	if .closed {
		return 0, ErrTxClosed
	}

	return .tx.CopyFrom(, , , )
}
SendBatch delegates to the underlying *Conn
func ( *dbSavepoint) ( context.Context,  *Batch) BatchResults {
	if .closed {
		return &batchResults{err: ErrTxClosed}
	}

	return .tx.SendBatch(, )
}

func ( *dbSavepoint) () LargeObjects {
	return LargeObjects{tx: }
}

func ( *dbSavepoint) () *Conn {
	return .tx.Conn()