package pgxpool

import (
	
	
	
	
	
	
	
	

	
	
	
)

var (
	defaultMaxConns          = int32(4)
	defaultMinConns          = int32(0)
	defaultMinIdleConns      = int32(0)
	defaultMaxConnLifetime   = time.Hour
	defaultMaxConnIdleTime   = time.Minute * 30
	defaultHealthCheckPeriod = time.Minute
)

type connResource struct {
	conn       *pgx.Conn
	conns      []Conn
	poolRows   []poolRow
	poolRowss  []poolRows
	maxAgeTime time.Time
}

func ( *connResource) ( *Pool,  *puddle.Resource[*connResource]) *Conn {
	if len(.conns) == 0 {
		.conns = make([]Conn, 128)
	}

	 := &.conns[len(.conns)-1]
	.conns = .conns[0 : len(.conns)-1]

	.res = 
	.p = 

	return 
}

func ( *connResource) ( *Conn,  pgx.Row) *poolRow {
	if len(.poolRows) == 0 {
		.poolRows = make([]poolRow, 128)
	}

	 := &.poolRows[len(.poolRows)-1]
	.poolRows = .poolRows[0 : len(.poolRows)-1]

	.c = 
	.r = 

	return 
}

func ( *connResource) ( *Conn,  pgx.Rows) *poolRows {
	if len(.poolRowss) == 0 {
		.poolRowss = make([]poolRows, 128)
	}

	 := &.poolRowss[len(.poolRowss)-1]
	.poolRowss = .poolRowss[0 : len(.poolRowss)-1]

	.c = 
	.r = 

	return 
}

// Pool allows for connection reuse.
type Pool struct {
	// 64 bit fields accessed with atomics must be at beginning of struct to guarantee alignment for certain 32-bit
	// architectures. See BUGS section of https://pkg.go.dev/sync/atomic and https://github.com/jackc/pgx/issues/1288.
	newConnsCount        int64
	lifetimeDestroyCount int64
	idleDestroyCount     int64

	p                     *puddle.Pool[*connResource]
	config                *Config
	beforeConnect         func(context.Context, *pgx.ConnConfig) error
	afterConnect          func(context.Context, *pgx.Conn) error
	prepareConn           func(context.Context, *pgx.Conn) (bool, error)
	afterRelease          func(*pgx.Conn) bool
	beforeClose           func(*pgx.Conn)
	shouldPing            func(context.Context, ShouldPingParams) bool
	minConns              int32
	minIdleConns          int32
	maxConns              int32
	maxConnLifetime       time.Duration
	maxConnLifetimeJitter time.Duration
	maxConnIdleTime       time.Duration
	healthCheckPeriod     time.Duration
	pingTimeout           time.Duration

	healthCheckMu    sync.Mutex
	healthCheckTimer *time.Timer

	healthCheckChan chan struct{}

	acquireTracer AcquireTracer
	releaseTracer ReleaseTracer

	closeOnce sync.Once
	closeChan chan struct{}
}

// ShouldPingParams are the parameters passed to ShouldPing.
type ShouldPingParams struct {
	Conn         *pgx.Conn
	IdleDuration time.Duration
}

// Config is the configuration struct for creating a pool. It must be created by [ParseConfig] and then it can be
// modified.
type Config struct {
	ConnConfig *pgx.ConnConfig

	// BeforeConnect is called before a new connection is made. It is passed a copy of the underlying pgx.ConnConfig and
	// will not impact any existing open connections.
	BeforeConnect func(context.Context, *pgx.ConnConfig) error

	// AfterConnect is called after a connection is established, but before it is added to the pool.
	AfterConnect func(context.Context, *pgx.Conn) error

	// BeforeAcquire is called before a connection is acquired from the pool. It must return true to allow the
	// acquisition or false to indicate that the connection should be destroyed and a different connection should be
	// acquired.
	//
	// Deprecated: Use PrepareConn instead. If both PrepareConn and BeforeAcquire are set, PrepareConn will take
	// precedence, ignoring BeforeAcquire.
	BeforeAcquire func(context.Context, *pgx.Conn) bool

	// PrepareConn is called before a connection is acquired from the pool. If this function returns true, the connection
	// is considered valid, otherwise the connection is destroyed. If the function returns a non-nil error, the instigating
	// query will fail with the returned error.
	//
	// Specifically, this means that:
	//
	// 	- If it returns true and a nil error, the query proceeds as normal.
	// 	- If it returns true and an error, the connection will be returned to the pool, and the instigating query will fail with the returned error.
	// 	- If it returns false, and an error, the connection will be destroyed, and the query will fail with the returned error.
	// 	- If it returns false and a nil error, the connection will be destroyed, and the instigating query will be retried on a new connection.
	PrepareConn func(context.Context, *pgx.Conn) (bool, error)

	// AfterRelease is called after a connection is released, but before it is returned to the pool. It must return true to
	// return the connection to the pool or false to destroy the connection.
	AfterRelease func(*pgx.Conn) bool

	// BeforeClose is called right before a connection is closed and removed from the pool.
	BeforeClose func(*pgx.Conn)

	// ShouldPing is called after a connection is acquired from the pool. If it returns true, the connection is pinged to check for liveness.
	// If this func is not set, the default behavior is to ping connections that have been idle for at least 1 second.
	ShouldPing func(context.Context, ShouldPingParams) bool

	// MaxConnLifetime is the duration since creation after which a connection will be automatically closed.
	MaxConnLifetime time.Duration

	// MaxConnLifetimeJitter is the duration after MaxConnLifetime to randomly decide to close a connection.
	// This helps prevent all connections from being closed at the exact same time, starving the pool.
	MaxConnLifetimeJitter time.Duration

	// MaxConnIdleTime is the duration after which an idle connection will be automatically closed by the health check.
	MaxConnIdleTime time.Duration

	// PingTimeout is the maximum amount of time to wait for a connection to pong before considering it as unhealthy and
	// destroying it. If zero, the default is no timeout.
	PingTimeout time.Duration

	// MaxConns is the maximum size of the pool. The default is the greater of 4 or runtime.NumCPU().
	MaxConns int32

	// MinConns is the minimum size of the pool. After connection closes, the pool might dip below MinConns. A low
	// number of MinConns might mean the pool is empty after MaxConnLifetime until the health check has a chance
	// to create new connections.
	MinConns int32

	// MinIdleConns is the minimum number of idle connections in the pool. You can increase this to ensure that
	// there are always idle connections available. This can help reduce tail latencies during request processing,
	// as you can avoid the latency of establishing a new connection while handling requests. It is superior
	// to MinConns for this purpose.
	// Similar to MinConns, the pool might temporarily dip below MinIdleConns after connection closes.
	MinIdleConns int32

	// HealthCheckPeriod is the duration between checks of the health of idle connections.
	HealthCheckPeriod time.Duration

	createdByParseConfig bool // Used to enforce created by ParseConfig rule.
}

// Copy returns a deep copy of the config that is safe to use and modify.
// The only exception is the tls.Config:
// according to the tls.Config docs it must not be modified after creation.
func ( *Config) () *Config {
	 := new(Config)
	* = *
	.ConnConfig = .ConnConfig.Copy()
	return 
}

// ConnString returns the connection string as parsed by pgxpool.ParseConfig into pgxpool.Config.
func ( *Config) () string { return .ConnConfig.ConnString() }

// New creates a new Pool. See [ParseConfig] for information on connString format.
func ( context.Context,  string) (*Pool, error) {
	,  := ParseConfig()
	if  != nil {
		return nil, 
	}

	return NewWithConfig(, )
}

// NewWithConfig creates a new Pool. config must have been created by [ParseConfig].
func ( context.Context,  *Config) (*Pool, error) {
	// Default values are set in ParseConfig. Enforce initial creation by ParseConfig rather than setting defaults from
	// zero values.
	if !.createdByParseConfig {
		panic("config must be created by ParseConfig")
	}

	 := .PrepareConn
	if  == nil && .BeforeAcquire != nil {
		 = func( context.Context,  *pgx.Conn) (bool, error) {
			return .BeforeAcquire(, ), nil
		}
	}

	 := &Pool{
		config:                ,
		beforeConnect:         .BeforeConnect,
		afterConnect:          .AfterConnect,
		prepareConn:           ,
		afterRelease:          .AfterRelease,
		beforeClose:           .BeforeClose,
		minConns:              .MinConns,
		minIdleConns:          .MinIdleConns,
		maxConns:              .MaxConns,
		maxConnLifetime:       .MaxConnLifetime,
		maxConnLifetimeJitter: .MaxConnLifetimeJitter,
		maxConnIdleTime:       .MaxConnIdleTime,
		pingTimeout:           .PingTimeout,
		healthCheckPeriod:     .HealthCheckPeriod,
		healthCheckChan:       make(chan struct{}, 1),
		closeChan:             make(chan struct{}),
	}

	if ,  := .ConnConfig.Tracer.(AcquireTracer);  {
		.acquireTracer = 
	}

	if ,  := .ConnConfig.Tracer.(ReleaseTracer);  {
		.releaseTracer = 
	}

	if .ShouldPing != nil {
		.shouldPing = .ShouldPing
	} else {
		.shouldPing = func( context.Context,  ShouldPingParams) bool {
			return .IdleDuration > time.Second
		}
	}

	var  error
	.p,  = puddle.NewPool(
		&puddle.Config[*connResource]{
			Constructor: func( context.Context) (*connResource, error) {
				atomic.AddInt64(&.newConnsCount, 1)
				 := .config.ConnConfig.Copy()

				// Connection will continue in background even if Acquire is canceled. Ensure that a connect won't hang forever.
				if .ConnectTimeout <= 0 {
					.ConnectTimeout = 2 * time.Minute
				}

				if .beforeConnect != nil {
					if  := .beforeConnect(, );  != nil {
						return nil, 
					}
				}

				,  := pgx.ConnectConfig(, )
				if  != nil {
					return nil, 
				}

				if .afterConnect != nil {
					 = .afterConnect(, )
					if  != nil {
						.Close()
						return nil, 
					}
				}

				 := rand.Float64() * .MaxConnLifetimeJitter.Seconds()
				 := time.Now().Add(.MaxConnLifetime).Add(time.Duration() * time.Second)

				 := &connResource{
					conn:       ,
					conns:      make([]Conn, 64),
					poolRows:   make([]poolRow, 64),
					poolRowss:  make([]poolRows, 64),
					maxAgeTime: ,
				}

				return , nil
			},
			Destructor: func( *connResource) {
				,  := context.WithTimeout(context.Background(), 15*time.Second)
				 := .conn
				if .beforeClose != nil {
					.beforeClose()
				}
				.Close()
				select {
				case <-.PgConn().CleanupDone():
				case <-.Done():
				}
				()
			},
			MaxSize: .MaxConns,
		},
	)
	if  != nil {
		return nil, 
	}

	go func() {
		 := max(int(.minConns), int(.minIdleConns))
		.createIdleResources(, )
		.backgroundHealthCheck()
	}()

	return , nil
}

// ParseConfig builds a Config from connString. It parses connString with the same behavior as [pgx.ParseConfig] with the
// addition of the following variables:
//
//   - pool_max_conns: integer greater than 0 (default 4)
//   - pool_min_conns: integer 0 or greater (default 0)
//   - pool_max_conn_lifetime: duration string (default 1 hour)
//   - pool_max_conn_idle_time: duration string (default 30 minutes)
//   - pool_health_check_period: duration string (default 1 minute)
//   - pool_max_conn_lifetime_jitter: duration string (default 0)
//
// See Config for definitions of these arguments.
//
//	# Example Keyword/Value
//	user=jack password=secret host=pg.example.com port=5432 dbname=mydb sslmode=verify-ca pool_max_conns=10 pool_max_conn_lifetime=1h30m
//
//	# Example URL
//	postgres://jack:secret@pg.example.com:5432/mydb?sslmode=verify-ca&pool_max_conns=10&pool_max_conn_lifetime=1h30m
func ( string) (*Config, error) {
	,  := pgx.ParseConfig()
	if  != nil {
		return nil, 
	}

	 := &Config{
		ConnConfig:           ,
		createdByParseConfig: true,
	}

	if ,  := .ConnConfig.Config.RuntimeParams["pool_max_conns"];  {
		delete(.Config.RuntimeParams, "pool_max_conns")
		,  := strconv.ParseInt(, 10, 32)
		if  != nil {
			return nil, pgconn.NewParseConfigError(, "cannot parse pool_max_conns", )
		}
		if  < 1 {
			return nil, pgconn.NewParseConfigError(, "pool_max_conns too small", )
		}
		.MaxConns = int32()
	} else {
		.MaxConns = defaultMaxConns
		if  := int32(runtime.NumCPU());  > .MaxConns {
			.MaxConns = 
		}
	}

	if ,  := .ConnConfig.Config.RuntimeParams["pool_min_conns"];  {
		delete(.Config.RuntimeParams, "pool_min_conns")
		,  := strconv.ParseInt(, 10, 32)
		if  != nil {
			return nil, pgconn.NewParseConfigError(, "cannot parse pool_min_conns", )
		}
		.MinConns = int32()
	} else {
		.MinConns = defaultMinConns
	}

	if ,  := .ConnConfig.Config.RuntimeParams["pool_min_idle_conns"];  {
		delete(.Config.RuntimeParams, "pool_min_idle_conns")
		,  := strconv.ParseInt(, 10, 32)
		if  != nil {
			return nil, pgconn.NewParseConfigError(, "cannot parse pool_min_idle_conns", )
		}
		.MinIdleConns = int32()
	} else {
		.MinIdleConns = defaultMinIdleConns
	}

	if ,  := .ConnConfig.Config.RuntimeParams["pool_max_conn_lifetime"];  {
		delete(.Config.RuntimeParams, "pool_max_conn_lifetime")
		,  := time.ParseDuration()
		if  != nil {
			return nil, pgconn.NewParseConfigError(, "cannot parse pool_max_conn_lifetime", )
		}
		.MaxConnLifetime = 
	} else {
		.MaxConnLifetime = defaultMaxConnLifetime
	}

	if ,  := .ConnConfig.Config.RuntimeParams["pool_max_conn_idle_time"];  {
		delete(.Config.RuntimeParams, "pool_max_conn_idle_time")
		,  := time.ParseDuration()
		if  != nil {
			return nil, pgconn.NewParseConfigError(, "cannot parse pool_max_conn_idle_time", )
		}
		.MaxConnIdleTime = 
	} else {
		.MaxConnIdleTime = defaultMaxConnIdleTime
	}

	if ,  := .ConnConfig.Config.RuntimeParams["pool_health_check_period"];  {
		delete(.Config.RuntimeParams, "pool_health_check_period")
		,  := time.ParseDuration()
		if  != nil {
			return nil, pgconn.NewParseConfigError(, "cannot parse pool_health_check_period", )
		}
		.HealthCheckPeriod = 
	} else {
		.HealthCheckPeriod = defaultHealthCheckPeriod
	}

	if ,  := .ConnConfig.Config.RuntimeParams["pool_max_conn_lifetime_jitter"];  {
		delete(.Config.RuntimeParams, "pool_max_conn_lifetime_jitter")
		,  := time.ParseDuration()
		if  != nil {
			return nil, pgconn.NewParseConfigError(, "cannot parse pool_max_conn_lifetime_jitter", )
		}
		.MaxConnLifetimeJitter = 
	}

	return , nil
}

// Close closes all connections in the pool and rejects future Acquire calls. Blocks until all connections are returned
// to pool and closed.
func ( *Pool) () {
	.closeOnce.Do(func() {
		close(.closeChan)
		.p.Close()
	})
}

func ( *Pool) ( *puddle.Resource[*connResource]) bool {
	return time.Now().After(.Value().maxAgeTime)
}

func ( *Pool) () {
	const  = 500 * time.Millisecond

	.healthCheckMu.Lock()
	defer .healthCheckMu.Unlock()

	if .healthCheckTimer == nil {
		// Destroy is asynchronous so we give it time to actually remove itself from
		// the pool otherwise we might try to check the pool size too soon
		.healthCheckTimer = time.AfterFunc(, func() {
			select {
			case <-.closeChan:
			case .healthCheckChan <- struct{}{}:
			default:
			}
		})
		return
	}

	.healthCheckTimer.Reset()
}

func ( *Pool) () {
	 := time.NewTicker(.healthCheckPeriod)
	defer .Stop()
	for {
		select {
		case <-.closeChan:
			return
		case <-.healthCheckChan:
			.checkHealth()
		case <-.C:
			.checkHealth()
		}
	}
}

func ( *Pool) () {
	for {
		// If checkMinConns failed we don't destroy any connections since we couldn't
		// even get to minConns
		if  := .checkMinConns();  != nil {
			// Should we log this error somewhere?
			break
		}
		if !.checkConnsHealth() {
			// Since we didn't destroy any connections we can stop looping
			break
		}
		// Technically Destroy is asynchronous but 500ms should be enough for it to
		// remove it from the underlying pool
		select {
		case <-.closeChan:
			return
		case <-time.After(500 * time.Millisecond):
		}
	}
}

// checkConnsHealth will check all idle connections, destroy a connection if
// it's idle or too old, and returns true if any were destroyed
func ( *Pool) () bool {
	var  bool
	 := .Stat().TotalConns()
	 := .p.AcquireAllIdle()
	for ,  := range  {
		// We're okay going under minConns if the lifetime is up
		if .isExpired() &&  >= .minConns {
			atomic.AddInt64(&.lifetimeDestroyCount, 1)
			.Destroy()
			 = true
			// Since Destroy is async we manually decrement totalConns.
			--
		} else if .IdleDuration() > .maxConnIdleTime &&  > .minConns {
			atomic.AddInt64(&.idleDestroyCount, 1)
			.Destroy()
			 = true
			// Since Destroy is async we manually decrement totalConns.
			--
		} else {
			.ReleaseUnused()
		}
	}
	return 
}

func ( *Pool) () error {
	// TotalConns can include ones that are being destroyed but we should have
	// sleep(500ms) around all of the destroys to help prevent that from throwing
	// off this check

	// Create the number of connections needed to get to both minConns and minIdleConns
	 := .Stat()
	 := max(.minConns-.TotalConns(), .minIdleConns-.IdleConns())
	if  > 0 {
		return .createIdleResources(context.Background(), int())
	}
	return nil
}

func ( *Pool) ( context.Context,  int) error {
	,  := context.WithCancel()
	defer ()

	 := make(chan error, )

	for range  {
		go func() {
			 := .p.CreateResource()
			// Ignore ErrNotAvailable since it means that the pool has become full since we started creating resource.
			if  == puddle.ErrNotAvailable {
				 = nil
			}
			 <- 
		}()
	}

	var  error
	for range  {
		 := <-
		if  != nil &&  == nil {
			()
			 = 
		}
	}

	return 
}

// Acquire returns a connection (*Conn) from the Pool
func ( *Pool) ( context.Context) ( *Conn,  error) {
	if .acquireTracer != nil {
		 = .acquireTracer.TraceAcquireStart(, , TraceAcquireStartData{})
		defer func() {
			var  *pgx.Conn
			if  != nil {
				 = .Conn()
			}
			.acquireTracer.TraceAcquireEnd(, , TraceAcquireEndData{Conn: , Err: })
		}()
	}

	// Try to acquire from the connection pool up to maxConns + 1 times, so that
	// any that fatal errors would empty the pool and still at least try 1 fresh
	// connection.
	for range int(.maxConns) + 1 {
		,  := .p.Acquire()
		if  != nil {
			return nil, 
		}

		 := .Value()

		 := ShouldPingParams{Conn: .conn, IdleDuration: .IdleDuration()}
		if .shouldPing(, ) {
			 := func() error {
				 := 
				if .pingTimeout > 0 {
					var  context.CancelFunc
					,  = context.WithTimeout(, .pingTimeout)
					defer ()
				}
				return .conn.Ping()
			}()
			if  != nil {
				.Destroy()
				continue
			}
		}

		if .prepareConn != nil {
			,  := .prepareConn(, .conn)
			if ! {
				.Destroy()
			}
			if  != nil {
				if  {
					.Release()
				}
				return nil, 
			}
			if ! {
				continue
			}
		}

		return .getConn(, ), nil
	}
	return nil, errors.New("pgxpool: too many failed attempts acquiring connection; likely bug in PrepareConn, BeforeAcquire, or ShouldPing hook")
}

// AcquireFunc acquires a *Conn and calls f with that *Conn. ctx will only affect the Acquire. It has no effect on the
// call of f. The return value is either an error acquiring the *Conn or the return value of f. The *Conn is
// automatically released after the call of f.
func ( *Pool) ( context.Context,  func(*Conn) error) error {
	,  := .Acquire()
	if  != nil {
		return 
	}
	defer .Release()

	return ()
}

// AcquireAllIdle atomically acquires all currently idle connections. Its intended use is for health check and
// keep-alive functionality. It does not update pool statistics.
func ( *Pool) ( context.Context) []*Conn {
	 := .p.AcquireAllIdle()
	 := make([]*Conn, 0, len())
	for ,  := range  {
		 := .Value()
		if .prepareConn != nil {
			,  := .prepareConn(, .conn)
			if ! ||  != nil {
				.Destroy()
				continue
			}
		}
		 = append(, .getConn(, ))
	}

	return 
}

// Reset closes all connections, but leaves the pool open. It is intended for use when an error is detected that would
// disrupt all connections (such as a network interruption or a server state change).
//
// It is safe to reset a pool while connections are checked out. Those connections will be closed when they are returned
// to the pool.
func ( *Pool) () {
	.p.Reset()
}

// Config returns a copy of config that was used to initialize this pool.
func ( *Pool) () *Config { return .config.Copy() }

// Stat returns a pgxpool.Stat struct with a snapshot of Pool statistics.
func ( *Pool) () *Stat {
	return &Stat{
		s:                    .p.Stat(),
		newConnsCount:        atomic.LoadInt64(&.newConnsCount),
		lifetimeDestroyCount: atomic.LoadInt64(&.lifetimeDestroyCount),
		idleDestroyCount:     atomic.LoadInt64(&.idleDestroyCount),
	}
}

// Exec acquires a connection from the Pool and executes the given SQL.
// SQL can be either a prepared statement name or an SQL string.
// Arguments should be referenced positionally from the SQL string as $1, $2, etc.
// The acquired connection is returned to the pool when the Exec function returns.
func ( *Pool) ( context.Context,  string,  ...any) (pgconn.CommandTag, error) {
	,  := .Acquire()
	if  != nil {
		return pgconn.CommandTag{}, 
	}
	defer .Release()

	return .Exec(, , ...)
}

// Query acquires a connection and executes a query that returns pgx.Rows.
// Arguments should be referenced positionally from the SQL string as $1, $2, etc.
// See pgx.Rows documentation to close the returned Rows and return the acquired connection to the Pool.
//
// If there is an error, the returned pgx.Rows will be returned in an error state.
// If preferred, ignore the error returned from Query and handle errors using the returned pgx.Rows.
//
// For extra control over how the query is executed, the types QuerySimpleProtocol, QueryResultFormats, and
// QueryResultFormatsByOID may be used as the first args to control exactly how the query is executed. This is rarely
// needed. See the documentation for those types for details.
func ( *Pool) ( context.Context,  string,  ...any) (pgx.Rows, error) {
	,  := .Acquire()
	if  != nil {
		return errRows{err: }, 
	}

	,  := .Query(, , ...)
	if  != nil {
		.Release()
		return errRows{err: }, 
	}

	return .getPoolRows(), nil
}

// QueryRow acquires a connection and executes a query that is expected
// to return at most one row (pgx.Row). Errors are deferred until pgx.Row's
// Scan method is called. If the query selects no rows, pgx.Row's Scan will
// return ErrNoRows. Otherwise, pgx.Row's Scan scans the first selected row
// and discards the rest. The acquired connection is returned to the Pool when
// pgx.Row's Scan method is called.
//
// Arguments should be referenced positionally from the SQL string as $1, $2, etc.
//
// For extra control over how the query is executed, the types QuerySimpleProtocol, QueryResultFormats, and
// QueryResultFormatsByOID may be used as the first args to control exactly how the query is executed. This is rarely
// needed. See the documentation for those types for details.
func ( *Pool) ( context.Context,  string,  ...any) pgx.Row {
	,  := .Acquire()
	if  != nil {
		return errRow{err: }
	}

	 := .QueryRow(, , ...)
	return .getPoolRow()
}

func ( *Pool) ( context.Context,  *pgx.Batch) pgx.BatchResults {
	,  := .Acquire()
	if  != nil {
		return errBatchResults{err: }
	}

	 := .SendBatch(, )
	return &poolBatchResults{br: , 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 ( *Pool) ( context.Context) (pgx.Tx, error) {
	return .BeginTx(, 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 ( *Pool) ( context.Context,  pgx.TxOptions) (pgx.Tx, error) {
	,  := .Acquire()
	if  != nil {
		return nil, 
	}

	,  := .BeginTx(, )
	if  != nil {
		.Release()
		return nil, 
	}

	return &Tx{t: , c: }, nil
}

func ( *Pool) ( context.Context,  pgx.Identifier,  []string,  pgx.CopyFromSource) (int64, error) {
	,  := .Acquire()
	if  != nil {
		return 0, 
	}
	defer .Release()

	return .Conn().CopyFrom(, , , )
}

// 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 ( *Pool) ( context.Context) error {
	,  := .Acquire()
	if  != nil {
		return 
	}
	defer .Release()
	return .Ping()
}