package pgconn

import (
	
	
	
	
	
	
	
	
	
	
	
	
	
	

	
	
	
	
	
)

const (
	connStatusUninitialized = iota
	connStatusConnecting
	connStatusClosed
	connStatusIdle
	connStatusBusy
)

// Notice represents a notice response message reported by the PostgreSQL server. Be aware that this is distinct from
// LISTEN/NOTIFY notification.
type Notice PgError

// Notification is a message received from the PostgreSQL LISTEN/NOTIFY system
type Notification struct {
	PID     uint32 // backend pid that sent the notification
	Channel string // channel from which notification was received
	Payload string
}

// DialFunc is a function that can be used to connect to a PostgreSQL server.
type DialFunc func(ctx context.Context, network, addr string) (net.Conn, error)

// LookupFunc is a function that can be used to lookup IPs addrs from host. Optionally an ip:port combination can be
// returned in order to override the connection string's port.
type LookupFunc func(ctx context.Context, host string) (addrs []string, err error)

// BuildFrontendFunc is a function that can be used to create Frontend implementation for connection.
type BuildFrontendFunc func(r io.Reader, w io.Writer) *pgproto3.Frontend

// NoticeHandler is a function that can handle notices received from the PostgreSQL server. Notices can be received at
// any time, usually during handling of a query response. The *PgConn is provided so the handler is aware of the origin
// of the notice, but it must not invoke any query method. Be aware that this is distinct from LISTEN/NOTIFY
// notification.
type NoticeHandler func(*PgConn, *Notice)

// NotificationHandler is a function that can handle notifications received from the PostgreSQL server. Notifications
// can be received at any time, usually during handling of a query response. The *PgConn is provided so the handler is
// aware of the origin of the notice, but it must not invoke any query method. Be aware that this is distinct from a
// notice event.
type NotificationHandler func(*PgConn, *Notification)

// PgConn is a low-level PostgreSQL connection handle. It is not safe for concurrent usage.
type PgConn struct {
	conn              net.Conn
	pid               uint32            // backend pid
	secretKey         uint32            // key to use to send a cancel query message to the server
	parameterStatuses map[string]string // parameters that have been reported by the server
	txStatus          byte
	frontend          *pgproto3.Frontend
	bgReader          *bgreader.BGReader
	slowWriteTimer    *time.Timer

	config *Config

	status byte // One of connStatus* constants

	bufferingReceive    bool
	bufferingReceiveMux sync.Mutex
	bufferingReceiveMsg pgproto3.BackendMessage
	bufferingReceiveErr error

	peekedMsg pgproto3.BackendMessage

	// Reusable / preallocated resources
	resultReader      ResultReader
	multiResultReader MultiResultReader
	pipeline          Pipeline
	contextWatcher    *ctxwatch.ContextWatcher
	fieldDescriptions [16]FieldDescription

	cleanupDone chan struct{}
}

// Connect establishes a connection to a PostgreSQL server using the environment and connString (in URL or DSN format)
// to provide configuration. See documentation for [ParseConfig] for details. ctx can be used to cancel a connect attempt.
func ( context.Context,  string) (*PgConn, error) {
	,  := ParseConfig()
	if  != nil {
		return nil, 
	}

	return ConnectConfig(, )
}

// Connect establishes a connection to a PostgreSQL server using the environment and connString (in URL or DSN format)
// and ParseConfigOptions to provide additional configuration. See documentation for [ParseConfig] for details. ctx can be
// used to cancel a connect attempt.
func ( context.Context,  string,  ParseConfigOptions) (*PgConn, error) {
	,  := ParseConfigWithOptions(, )
	if  != nil {
		return nil, 
	}

	return ConnectConfig(, )
}

// Connect establishes a connection to a PostgreSQL server using config. config must have been constructed with
// [ParseConfig]. ctx can be used to cancel a connect attempt.
//
// If config.Fallbacks are present they will sequentially be tried in case of error establishing network connection. An
// authentication error will terminate the chain of attempts (like libpq:
// https://www.postgresql.org/docs/11/libpq-connect.html#LIBPQ-MULTIPLE-HOSTS) and be returned as the error. Otherwise,
// if all attempts fail the last error is returned.
func ( context.Context,  *Config) ( *PgConn,  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")
	}

	// Simplify usage by treating primary config and fallbacks the same.
	 := []*FallbackConfig{
		{
			Host:      .Host,
			Port:      .Port,
			TLSConfig: .TLSConfig,
		},
	}
	 = append(, .Fallbacks...)
	 := 
	,  = expandWithIPs(, .LookupFunc, )
	if  != nil {
		return nil, &connectError{config: , msg: "hostname resolving error", err: }
	}

	if len() == 0 {
		return nil, &connectError{config: , msg: "hostname resolving error", err: errors.New("ip addr wasn't found")}
	}

	 := false
	var  *FallbackConfig
	for ,  := range  {
		// ConnectTimeout restricts the whole connection process.
		if .ConnectTimeout != 0 {
			// create new context first time or when previous host was different
			if  == 0 || ([].Host != [-1].Host) {
				var  context.CancelFunc
				,  = context.WithTimeout(, .ConnectTimeout)
				defer ()
			}
		} else {
			 = 
		}
		,  = connect(, , , false)
		if  == nil {
			 = true
			break
		} else if ,  := .(*PgError);  {
			 = &connectError{config: , msg: "server error", err: }
			const  = "28P01"                    // wrong password
			const  = "28000" // wrong password or bad pg_hba.conf settings
			const  = "3D000"                // db does not exist
			const  = "42501"              // missing connect privilege
			if .Code ==  ||
				.Code ==  && .TLSConfig != nil ||
				.Code ==  ||
				.Code ==  {
				break
			}
		} else if ,  := .(*connectError);  {
			if ,  := .err.(*NotPreferredError);  {
				 = 
			}
		}
	}

	if ! &&  != nil {
		,  = connect(, , , true)
		if ,  := .(*PgError);  {
			 = &connectError{config: , msg: "server error", err: }
		}
	}

	if  != nil {
		return nil,  // no need to wrap in connectError because it will already be wrapped in all cases except PgError
	}

	if .AfterConnect != nil {
		 := .AfterConnect(, )
		if  != nil {
			.conn.Close()
			return nil, &connectError{config: , msg: "AfterConnect error", err: }
		}
	}

	return , nil
}

func expandWithIPs( context.Context,  LookupFunc,  []*FallbackConfig) ([]*FallbackConfig, error) {
	var  []*FallbackConfig

	var  []error

	for ,  := range  {
		// skip resolve for unix sockets
		if isAbsolutePath(.Host) {
			 = append(, &FallbackConfig{
				Host:      .Host,
				Port:      .Port,
				TLSConfig: .TLSConfig,
			})

			continue
		}

		,  := (, .Host)
		if  != nil {
			 = append(, )
			continue
		}

		for ,  := range  {
			, ,  := net.SplitHostPort()
			if  == nil {
				,  := strconv.ParseUint(, 10, 16)
				if  != nil {
					return nil, fmt.Errorf("error parsing port (%s) from lookup: %w", , )
				}
				 = append(, &FallbackConfig{
					Host:      ,
					Port:      uint16(),
					TLSConfig: .TLSConfig,
				})
			} else {
				 = append(, &FallbackConfig{
					Host:      ,
					Port:      .Port,
					TLSConfig: .TLSConfig,
				})
			}
		}
	}

	// See https://github.com/jackc/pgx/issues/1464. When Go 1.20 can be used in pgx consider using errors.Join so all
	// errors are reported.
	if len() == 0 && len() > 0 {
		return nil, [0]
	}

	return , nil
}

func connect( context.Context,  *Config,  *FallbackConfig,
	 bool,
) (*PgConn, error) {
	 := new(PgConn)
	.config = 
	.cleanupDone = make(chan struct{})

	var  error
	,  := NetworkAddress(.Host, .Port)
	,  := .DialFunc(, , )
	if  != nil {
		return nil, &connectError{config: , msg: "dial error", err: normalizeTimeoutError(, )}
	}

	.conn = 
	.contextWatcher = newContextWatcher()
	.contextWatcher.Watch()

	if .TLSConfig != nil {
		,  := startTLS(, .TLSConfig)
		.contextWatcher.Unwatch() // Always unwatch `netConn` after TLS.
		if  != nil {
			.Close()
			return nil, &connectError{config: , msg: "tls error", err: }
		}

		.conn = 
		.contextWatcher = newContextWatcher()
		.contextWatcher.Watch()
	}

	defer .contextWatcher.Unwatch()

	.parameterStatuses = make(map[string]string)
	.status = connStatusConnecting
	.bgReader = bgreader.New(.conn)
	.slowWriteTimer = time.AfterFunc(time.Duration(math.MaxInt64), .bgReader.Start)
	.slowWriteTimer.Stop()
	.frontend = .BuildFrontend(.bgReader, .conn)

	 := pgproto3.StartupMessage{
		ProtocolVersion: pgproto3.ProtocolVersionNumber,
		Parameters:      make(map[string]string),
	}

	// Copy default run-time params
	for ,  := range .RuntimeParams {
		.Parameters[] = 
	}

	.Parameters["user"] = .User
	if .Database != "" {
		.Parameters["database"] = .Database
	}

	.frontend.Send(&)
	if  := .flushWithPotentialWriteReadDeadlock();  != nil {
		.conn.Close()
		return nil, &connectError{config: , msg: "failed to write startup message", err: normalizeTimeoutError(, )}
	}

	for {
		,  := .receiveMessage()
		if  != nil {
			.conn.Close()
			if ,  := .(*PgError);  {
				return nil, 
			}
			return nil, &connectError{config: , msg: "failed to receive message", err: normalizeTimeoutError(, )}
		}

		switch msg := .(type) {
		case *pgproto3.BackendKeyData:
			.pid = .ProcessID
			.secretKey = .SecretKey

		case *pgproto3.AuthenticationOk:
		case *pgproto3.AuthenticationCleartextPassword:
			 = .txPasswordMessage(.config.Password)
			if  != nil {
				.conn.Close()
				return nil, &connectError{config: , msg: "failed to write password message", err: }
			}
		case *pgproto3.AuthenticationMD5Password:
			 := "md5" + hexMD5(hexMD5(.config.Password+.config.User)+string(.Salt[:]))
			 = .txPasswordMessage()
			if  != nil {
				.conn.Close()
				return nil, &connectError{config: , msg: "failed to write password message", err: }
			}
		case *pgproto3.AuthenticationSASL:
			 = .scramAuth(.AuthMechanisms)
			if  != nil {
				.conn.Close()
				return nil, &connectError{config: , msg: "failed SASL auth", err: }
			}
		case *pgproto3.AuthenticationGSS:
			 = .gssAuth()
			if  != nil {
				.conn.Close()
				return nil, &connectError{config: , msg: "failed GSS auth", err: }
			}
		case *pgproto3.ReadyForQuery:
			.status = connStatusIdle
			if .ValidateConnect != nil {
				// ValidateConnect may execute commands that cause the context to be watched again. Unwatch first to avoid
				// the watch already in progress panic. This is that last thing done by this method so there is no need to
				// restart the watch after ValidateConnect returns.
				//
				// See https://github.com/jackc/pgconn/issues/40.
				.contextWatcher.Unwatch()

				 := .ValidateConnect(, )
				if  != nil {
					if ,  := .(*NotPreferredError);  &&  {
						return , nil
					}
					.conn.Close()
					return nil, &connectError{config: , msg: "ValidateConnect failed", err: }
				}
			}
			return , nil
		case *pgproto3.ParameterStatus, *pgproto3.NoticeResponse:
			// handled by ReceiveMessage
		case *pgproto3.ErrorResponse:
			.conn.Close()
			return nil, ErrorResponseToPgError()
		default:
			.conn.Close()
			return nil, &connectError{config: , msg: "received unexpected message", err: }
		}
	}
}

func newContextWatcher( net.Conn) *ctxwatch.ContextWatcher {
	return ctxwatch.NewContextWatcher(
		func() { .SetDeadline(time.Date(1, 1, 1, 1, 1, 1, 1, time.UTC)) },
		func() { .SetDeadline(time.Time{}) },
	)
}

func startTLS( net.Conn,  *tls.Config) (net.Conn, error) {
	 := binary.Write(, binary.BigEndian, []int32{8, 80877103})
	if  != nil {
		return nil, 
	}

	 := make([]byte, 1)
	if _,  = io.ReadFull(, );  != nil {
		return nil, 
	}

	if [0] != 'S' {
		return nil, errors.New("server refused TLS connection")
	}

	return tls.Client(, ), nil
}

func ( *PgConn) ( string) ( error) {
	.frontend.Send(&pgproto3.PasswordMessage{Password: })
	return .flushWithPotentialWriteReadDeadlock()
}

func hexMD5( string) string {
	 := md5.New()
	io.WriteString(, )
	return hex.EncodeToString(.Sum(nil))
}

func ( *PgConn) () chan struct{} {
	if .bufferingReceive {
		panic("BUG: signalMessage when already in progress")
	}

	.bufferingReceive = true
	.bufferingReceiveMux.Lock()

	 := make(chan struct{})
	go func() {
		.bufferingReceiveMsg, .bufferingReceiveErr = .frontend.Receive()
		.bufferingReceiveMux.Unlock()
		close()
	}()

	return 
}

// ReceiveMessage receives one wire protocol message from the PostgreSQL server. It must only be used when the
// connection is not busy. e.g. It is an error to call ReceiveMessage while reading the result of a query. The messages
// are still handled by the core pgconn message handling system so receiving a NotificationResponse will still trigger
// the OnNotification callback.
//
// This is a very low level method that requires deep understanding of the PostgreSQL wire protocol to use correctly.
// See https://www.postgresql.org/docs/current/protocol.html.
func ( *PgConn) ( context.Context) (pgproto3.BackendMessage, error) {
	if  := .lock();  != nil {
		return nil, 
	}
	defer .unlock()

	if  != context.Background() {
		select {
		case <-.Done():
			return nil, newContextAlreadyDoneError()
		default:
		}
		.contextWatcher.Watch()
		defer .contextWatcher.Unwatch()
	}

	,  := .receiveMessage()
	if  != nil {
		 = &pgconnError{
			msg:         "receive message failed",
			err:         normalizeTimeoutError(, ),
			safeToRetry: true,
		}
	}
	return , 
}

// peekMessage peeks at the next message without setting up context cancellation.
func ( *PgConn) () (pgproto3.BackendMessage, error) {
	if .peekedMsg != nil {
		return .peekedMsg, nil
	}

	var  pgproto3.BackendMessage
	var  error
	if .bufferingReceive {
		.bufferingReceiveMux.Lock()
		 = .bufferingReceiveMsg
		 = .bufferingReceiveErr
		.bufferingReceiveMux.Unlock()
		.bufferingReceive = false

		// If a timeout error happened in the background try the read again.
		var  net.Error
		if errors.As(, &) && .Timeout() {
			,  = .frontend.Receive()
		}
	} else {
		,  = .frontend.Receive()
	}

	if  != nil {
		// Close on anything other than timeout error - everything else is fatal
		var  net.Error
		 := errors.As(, &)
		if !( && .Timeout()) {
			.asyncClose()
		}

		return nil, 
	}

	.peekedMsg = 
	return , nil
}

// receiveMessage receives a message without setting up context cancellation
func ( *PgConn) () (pgproto3.BackendMessage, error) {
	,  := .peekMessage()
	if  != nil {
		return nil, 
	}
	.peekedMsg = nil

	switch msg := .(type) {
	case *pgproto3.ReadyForQuery:
		.txStatus = .TxStatus
	case *pgproto3.ParameterStatus:
		.parameterStatuses[.Name] = .Value
	case *pgproto3.ErrorResponse:
		if .Severity == "FATAL" {
			.status = connStatusClosed
			.conn.Close() // Ignore error as the connection is already broken and there is already an error to return.
			close(.cleanupDone)
			return nil, ErrorResponseToPgError()
		}
	case *pgproto3.NoticeResponse:
		if .config.OnNotice != nil {
			.config.OnNotice(, noticeResponseToNotice())
		}
	case *pgproto3.NotificationResponse:
		if .config.OnNotification != nil {
			.config.OnNotification(, &Notification{PID: .PID, Channel: .Channel, Payload: .Payload})
		}
	}

	return , nil
}

// Conn returns the underlying net.Conn. This rarely necessary. If the connection will be directly used for reading or
// writing then SyncConn should usually be called before Conn.
func ( *PgConn) () net.Conn {
	return .conn
}

// PID returns the backend PID.
func ( *PgConn) () uint32 {
	return .pid
}

// TxStatus returns the current TxStatus as reported by the server in the ReadyForQuery message.
//
// Possible return values:
//
//	'I' - idle / not in transaction
//	'T' - in a transaction
//	'E' - in a failed transaction
//
// See https://www.postgresql.org/docs/current/protocol-message-formats.html.
func ( *PgConn) () byte {
	return .txStatus
}

// SecretKey returns the backend secret key used to send a cancel query message to the server.
func ( *PgConn) () uint32 {
	return .secretKey
}

// Frontend returns the underlying *pgproto3.Frontend. This rarely necessary.
func ( *PgConn) () *pgproto3.Frontend {
	return .frontend
}

// Close closes a connection. It is safe to call Close on a already closed connection. Close attempts a clean close by
// sending the exit message to PostgreSQL. However, this could block so ctx is available to limit the time to wait. The
// underlying net.Conn.Close() will always be called regardless of any other errors.
func ( *PgConn) ( context.Context) error {
	if .status == connStatusClosed {
		return nil
	}
	.status = connStatusClosed

	defer close(.cleanupDone)
	defer .conn.Close()

	if  != context.Background() {
		// Close may be called while a cancellable query is in progress. This will most often be triggered by panic when
		// a defer closes the connection (possibly indirectly via a transaction or a connection pool). Unwatch to end any
		// previous watch. It is safe to Unwatch regardless of whether a watch is already is progress.
		//
		// See https://github.com/jackc/pgconn/issues/29
		.contextWatcher.Unwatch()

		.contextWatcher.Watch()
		defer .contextWatcher.Unwatch()
	}

	// Ignore any errors sending Terminate message and waiting for server to close connection.
	// This mimics the behavior of libpq PQfinish. It calls closePGconn which calls sendTerminateConn which purposefully
	// ignores errors.
	//
	// See https://github.com/jackc/pgx/issues/637
	.frontend.Send(&pgproto3.Terminate{})
	.flushWithPotentialWriteReadDeadlock()

	return .conn.Close()
}

// asyncClose marks the connection as closed and asynchronously sends a cancel query message and closes the underlying
// connection.
func ( *PgConn) () {
	if .status == connStatusClosed {
		return
	}
	.status = connStatusClosed

	go func() {
		defer close(.cleanupDone)
		defer .conn.Close()

		 := time.Now().Add(time.Second * 15)

		,  := context.WithDeadline(context.Background(), )
		defer ()

		.CancelRequest()

		.conn.SetDeadline()

		.frontend.Send(&pgproto3.Terminate{})
		.flushWithPotentialWriteReadDeadlock()
	}()
}

// CleanupDone returns a channel that will be closed after all underlying resources have been cleaned up. A closed
// connection is no longer usable, but underlying resources, in particular the net.Conn, may not have finished closing
// yet. This is because certain errors such as a context cancellation require that the interrupted function call return
// immediately, but the error may also cause the connection to be closed. In these cases the underlying resources are
// closed asynchronously.
//
// This is only likely to be useful to connection pools. It gives them a way avoid establishing a new connection while
// an old connection is still being cleaned up and thereby exceeding the maximum pool size.
func ( *PgConn) () chan (struct{}) {
	return .cleanupDone
}

// IsClosed reports if the connection has been closed.
//
// CleanupDone() can be used to determine if all cleanup has been completed.
func ( *PgConn) () bool {
	return .status < connStatusIdle
}

// IsBusy reports if the connection is busy.
func ( *PgConn) () bool {
	return .status == connStatusBusy
}

// lock locks the connection.
func ( *PgConn) () error {
	switch .status {
	case connStatusBusy:
		return &connLockError{status: "conn busy"} // This only should be possible in case of an application bug.
	case connStatusClosed:
		return &connLockError{status: "conn closed"}
	case connStatusUninitialized:
		return &connLockError{status: "conn uninitialized"}
	}
	.status = connStatusBusy
	return nil
}

func ( *PgConn) () {
	switch .status {
	case connStatusBusy:
		.status = connStatusIdle
	case connStatusClosed:
	default:
		panic("BUG: cannot unlock unlocked connection") // This should only be possible if there is a bug in this package.
	}
}

// ParameterStatus returns the value of a parameter reported by the server (e.g.
// server_version). Returns an empty string for unknown parameters.
func ( *PgConn) ( string) string {
	return .parameterStatuses[]
}

// CommandTag is the status text returned by PostgreSQL for a query.
type CommandTag struct {
	s string
}

// NewCommandTag makes a CommandTag from s.
func ( string) CommandTag {
	return CommandTag{s: }
}

// RowsAffected returns the number of rows affected. If the CommandTag was not
// for a row affecting command (e.g. "CREATE TABLE") then it returns 0.
func ( CommandTag) () int64 {
	// Find last non-digit
	 := -1
	for  := len(.s) - 1;  >= 0; -- {
		if .s[] >= '0' && .s[] <= '9' {
			 = 
		} else {
			break
		}
	}

	if  == -1 {
		return 0
	}

	var  int64
	for ,  := range .s[:] {
		 = *10 + int64(-'0')
	}

	return 
}

func ( CommandTag) () string {
	return .s
}

// Insert is true if the command tag starts with "INSERT".
func ( CommandTag) () bool {
	return strings.HasPrefix(.s, "INSERT")
}

// Update is true if the command tag starts with "UPDATE".
func ( CommandTag) () bool {
	return strings.HasPrefix(.s, "UPDATE")
}

// Delete is true if the command tag starts with "DELETE".
func ( CommandTag) () bool {
	return strings.HasPrefix(.s, "DELETE")
}

// Select is true if the command tag starts with "SELECT".
func ( CommandTag) () bool {
	return strings.HasPrefix(.s, "SELECT")
}

type FieldDescription struct {
	Name                 string
	TableOID             uint32
	TableAttributeNumber uint16
	DataTypeOID          uint32
	DataTypeSize         int16
	TypeModifier         int32
	Format               int16
}

func ( *PgConn) ( []FieldDescription,  *pgproto3.RowDescription) []FieldDescription {
	if cap() >= len(.Fields) {
		 = [:len(.Fields):len(.Fields)]
	} else {
		 = make([]FieldDescription, len(.Fields))
	}

	for  := range .Fields {
		[].Name = string(.Fields[].Name)
		[].TableOID = .Fields[].TableOID
		[].TableAttributeNumber = .Fields[].TableAttributeNumber
		[].DataTypeOID = .Fields[].DataTypeOID
		[].DataTypeSize = .Fields[].DataTypeSize
		[].TypeModifier = .Fields[].TypeModifier
		[].Format = .Fields[].Format
	}

	return 
}

type StatementDescription struct {
	Name      string
	SQL       string
	ParamOIDs []uint32
	Fields    []FieldDescription
}

// Prepare creates a prepared statement. If the name is empty, the anonymous prepared statement will be used. This
// allows Prepare to also to describe statements without creating a server-side prepared statement.
func ( *PgConn) ( context.Context, ,  string,  []uint32) (*StatementDescription, error) {
	if  := .lock();  != nil {
		return nil, 
	}
	defer .unlock()

	if  != context.Background() {
		select {
		case <-.Done():
			return nil, newContextAlreadyDoneError()
		default:
		}
		.contextWatcher.Watch()
		defer .contextWatcher.Unwatch()
	}

	.frontend.SendParse(&pgproto3.Parse{Name: , Query: , ParameterOIDs: })
	.frontend.SendDescribe(&pgproto3.Describe{ObjectType: 'S', Name: })
	.frontend.SendSync(&pgproto3.Sync{})
	 := .flushWithPotentialWriteReadDeadlock()
	if  != nil {
		.asyncClose()
		return nil, 
	}

	 := &StatementDescription{Name: , SQL: }

	var  error

:
	for {
		,  := .receiveMessage()
		if  != nil {
			.asyncClose()
			return nil, normalizeTimeoutError(, )
		}

		switch msg := .(type) {
		case *pgproto3.ParameterDescription:
			.ParamOIDs = make([]uint32, len(.ParameterOIDs))
			copy(.ParamOIDs, .ParameterOIDs)
		case *pgproto3.RowDescription:
			.Fields = .convertRowDescription(nil, )
		case *pgproto3.ErrorResponse:
			 = ErrorResponseToPgError()
		case *pgproto3.ReadyForQuery:
			break 
		}
	}

	if  != nil {
		return nil, 
	}
	return , nil
}

// ErrorResponseToPgError converts a wire protocol error message to a *PgError.
func ( *pgproto3.ErrorResponse) *PgError {
	return &PgError{
		Severity:         .Severity,
		Code:             string(.Code),
		Message:          string(.Message),
		Detail:           string(.Detail),
		Hint:             .Hint,
		Position:         .Position,
		InternalPosition: .InternalPosition,
		InternalQuery:    string(.InternalQuery),
		Where:            string(.Where),
		SchemaName:       string(.SchemaName),
		TableName:        string(.TableName),
		ColumnName:       string(.ColumnName),
		DataTypeName:     string(.DataTypeName),
		ConstraintName:   .ConstraintName,
		File:             string(.File),
		Line:             .Line,
		Routine:          string(.Routine),
	}
}

func noticeResponseToNotice( *pgproto3.NoticeResponse) *Notice {
	 := ErrorResponseToPgError((*pgproto3.ErrorResponse)())
	return (*Notice)()
}

// CancelRequest sends a cancel request to the PostgreSQL server. It returns an error if unable to deliver the cancel
// request, but lack of an error does not ensure that the query was canceled. As specified in the documentation, there
// is no way to be sure a query was canceled. See https://www.postgresql.org/docs/11/protocol-flow.html#id-1.10.5.7.9
func ( *PgConn) ( context.Context) error {
	// Open a cancellation request to the same server. The address is taken from the net.Conn directly instead of reusing
	// the connection config. This is important in high availability configurations where fallback connections may be
	// specified or DNS may be used to load balance.
	 := .conn.RemoteAddr()
	var  string
	var  string
	if .Network() == "unix" {
		// for unix sockets, RemoteAddr() calls getpeername() which returns the name the
		// server passed to bind(). For Postgres, this is always a relative path "./.s.PGSQL.5432"
		// so connecting to it will fail. Fall back to the config's value
		,  = NetworkAddress(.config.Host, .config.Port)
	} else {
		,  = .Network(), .String()
	}
	,  := .config.DialFunc(, , )
	if  != nil {
		// In case of unix sockets, RemoteAddr() returns only the file part of the path. If the
		// first connect failed, try the config.
		if .Network() != "unix" {
			return 
		}
		,  := NetworkAddress(.config.Host, .config.Port)
		,  = .config.DialFunc(, , )
		if  != nil {
			return 
		}
	}
	defer .Close()

	if  != context.Background() {
		 := ctxwatch.NewContextWatcher(
			func() { .SetDeadline(time.Date(1, 1, 1, 1, 1, 1, 1, time.UTC)) },
			func() { .SetDeadline(time.Time{}) },
		)
		.Watch()
		defer .Unwatch()
	}

	 := make([]byte, 16)
	binary.BigEndian.PutUint32([0:4], 16)
	binary.BigEndian.PutUint32([4:8], 80877102)
	binary.BigEndian.PutUint32([8:12], uint32(.pid))
	binary.BigEndian.PutUint32([12:16], uint32(.secretKey))
	// Postgres will process the request and close the connection
	// so when don't need to read the reply
	// https://www.postgresql.org/docs/current/protocol-flow.html#id-1.10.6.7.10
	_,  = .Write()
	return 
}

// WaitForNotification waits for a LISTON/NOTIFY message to be received. It returns an error if a notification was not
// received.
func ( *PgConn) ( context.Context) error {
	if  := .lock();  != nil {
		return 
	}
	defer .unlock()

	if  != context.Background() {
		select {
		case <-.Done():
			return newContextAlreadyDoneError()
		default:
		}

		.contextWatcher.Watch()
		defer .contextWatcher.Unwatch()
	}

	for {
		,  := .receiveMessage()
		if  != nil {
			return normalizeTimeoutError(, )
		}

		switch .(type) {
		case *pgproto3.NotificationResponse:
			return nil
		}
	}
}

// Exec executes SQL via the PostgreSQL simple query protocol. SQL may contain multiple queries. Execution is
// implicitly wrapped in a transaction unless a transaction is already in progress or SQL contains transaction control
// statements.
//
// Prefer ExecParams unless executing arbitrary SQL that may contain multiple queries.
func ( *PgConn) ( context.Context,  string) *MultiResultReader {
	if  := .lock();  != nil {
		return &MultiResultReader{
			closed: true,
			err:    ,
		}
	}

	.multiResultReader = MultiResultReader{
		pgConn: ,
		ctx:    ,
	}
	 := &.multiResultReader
	if  != context.Background() {
		select {
		case <-.Done():
			.closed = true
			.err = newContextAlreadyDoneError()
			.unlock()
			return 
		default:
		}
		.contextWatcher.Watch()
	}

	.frontend.SendQuery(&pgproto3.Query{String: })
	 := .flushWithPotentialWriteReadDeadlock()
	if  != nil {
		.asyncClose()
		.contextWatcher.Unwatch()
		.closed = true
		.err = 
		.unlock()
		return 
	}

	return 
}

// ExecParams executes a command via the PostgreSQL extended query protocol.
//
// sql is a SQL command string. It may only contain one query. Parameter substitution is positional using $1, $2, $3,
// etc.
//
// paramValues are the parameter values. It must be encoded in the format given by paramFormats.
//
// paramOIDs is a slice of data type OIDs for paramValues. If paramOIDs is nil, the server will infer the data type for
// all parameters. Any paramOID element that is 0 that will cause the server to infer the data type for that parameter.
// ExecParams will panic if len(paramOIDs) is not 0, 1, or len(paramValues).
//
// paramFormats is a slice of format codes determining for each paramValue column whether it is encoded in text or
// binary format. If paramFormats is nil all params are text format. ExecParams will panic if
// len(paramFormats) is not 0, 1, or len(paramValues).
//
// resultFormats is a slice of format codes determining for each result column whether it is encoded in text or
// binary format. If resultFormats is nil all results will be in text format.
//
// ResultReader must be closed before PgConn can be used again.
func ( *PgConn) ( context.Context,  string,  [][]byte,  []uint32,  []int16,  []int16) *ResultReader {
	 := .execExtendedPrefix(, )
	if .closed {
		return 
	}

	.frontend.SendParse(&pgproto3.Parse{Query: , ParameterOIDs: })
	.frontend.SendBind(&pgproto3.Bind{ParameterFormatCodes: , Parameters: , ResultFormatCodes: })

	.execExtendedSuffix()

	return 
}

// ExecPrepared enqueues the execution of a prepared statement via the PostgreSQL extended query protocol.
//
// paramValues are the parameter values. It must be encoded in the format given by paramFormats.
//
// paramFormats is a slice of format codes determining for each paramValue column whether it is encoded in text or
// binary format. If paramFormats is nil all params are text format. ExecPrepared will panic if
// len(paramFormats) is not 0, 1, or len(paramValues).
//
// resultFormats is a slice of format codes determining for each result column whether it is encoded in text or
// binary format. If resultFormats is nil all results will be in text format.
//
// ResultReader must be closed before PgConn can be used again.
func ( *PgConn) ( context.Context,  string,  [][]byte,  []int16,  []int16) *ResultReader {
	 := .execExtendedPrefix(, )
	if .closed {
		return 
	}

	.frontend.SendBind(&pgproto3.Bind{PreparedStatement: , ParameterFormatCodes: , Parameters: , ResultFormatCodes: })

	.execExtendedSuffix()

	return 
}

func ( *PgConn) ( context.Context,  [][]byte) *ResultReader {
	.resultReader = ResultReader{
		pgConn: ,
		ctx:    ,
	}
	 := &.resultReader

	if  := .lock();  != nil {
		.concludeCommand(CommandTag{}, )
		.closed = true
		return 
	}

	if len() > math.MaxUint16 {
		.concludeCommand(CommandTag{}, fmt.Errorf("extended protocol limited to %v parameters", math.MaxUint16))
		.closed = true
		.unlock()
		return 
	}

	if  != context.Background() {
		select {
		case <-.Done():
			.concludeCommand(CommandTag{}, newContextAlreadyDoneError())
			.closed = true
			.unlock()
			return 
		default:
		}
		.contextWatcher.Watch()
	}

	return 
}

func ( *PgConn) ( *ResultReader) {
	.frontend.SendDescribe(&pgproto3.Describe{ObjectType: 'P'})
	.frontend.SendExecute(&pgproto3.Execute{})
	.frontend.SendSync(&pgproto3.Sync{})

	 := .flushWithPotentialWriteReadDeadlock()
	if  != nil {
		.asyncClose()
		.concludeCommand(CommandTag{}, )
		.contextWatcher.Unwatch()
		.closed = true
		.unlock()
		return
	}

	.readUntilRowDescription()
}

// CopyTo executes the copy command sql and copies the results to w.
func ( *PgConn) ( context.Context,  io.Writer,  string) (CommandTag, error) {
	if  := .lock();  != nil {
		return CommandTag{}, 
	}

	if  != context.Background() {
		select {
		case <-.Done():
			.unlock()
			return CommandTag{}, newContextAlreadyDoneError()
		default:
		}
		.contextWatcher.Watch()
		defer .contextWatcher.Unwatch()
	}

	// Send copy to command
	.frontend.SendQuery(&pgproto3.Query{String: })

	 := .flushWithPotentialWriteReadDeadlock()
	if  != nil {
		.asyncClose()
		.unlock()
		return CommandTag{}, 
	}

	// Read results
	var  CommandTag
	var  error
	for {
		,  := .receiveMessage()
		if  != nil {
			.asyncClose()
			return CommandTag{}, normalizeTimeoutError(, )
		}

		switch msg := .(type) {
		case *pgproto3.CopyDone:
		case *pgproto3.CopyData:
			,  := .Write(.Data)
			if  != nil {
				.asyncClose()
				return CommandTag{}, 
			}
		case *pgproto3.ReadyForQuery:
			.unlock()
			return , 
		case *pgproto3.CommandComplete:
			 = .makeCommandTag(.CommandTag)
		case *pgproto3.ErrorResponse:
			 = ErrorResponseToPgError()
		}
	}
}

// CopyFrom executes the copy command sql and copies all of r to the PostgreSQL server.
//
// Note: context cancellation will only interrupt operations on the underlying PostgreSQL network connection. Reads on r
// could still block.
func ( *PgConn) ( context.Context,  io.Reader,  string) (CommandTag, error) {
	if  := .lock();  != nil {
		return CommandTag{}, 
	}
	defer .unlock()

	if  != context.Background() {
		select {
		case <-.Done():
			return CommandTag{}, newContextAlreadyDoneError()
		default:
		}
		.contextWatcher.Watch()
		defer .contextWatcher.Unwatch()
	}

	// Send copy from query
	.frontend.SendQuery(&pgproto3.Query{String: })
	 := .flushWithPotentialWriteReadDeadlock()
	if  != nil {
		.asyncClose()
		return CommandTag{}, 
	}

	// Send copy data
	 := make(chan struct{})
	 := make(chan error, 1)
	 := .signalMessage()
	var  sync.WaitGroup
	.Add(1)

	go func() {
		defer .Done()
		 := iobufpool.Get(65536)
		defer iobufpool.Put()
		(*)[0] = 'd'

		for {
			,  := .Read((*)[5:cap(*)])
			if  > 0 {
				* = (*)[0 : +5]
				pgio.SetInt32((*)[1:], int32(+4))

				 := .frontend.SendUnbufferedEncodedCopyData(*)
				if  != nil {
					// Write errors are always fatal, but we can't use asyncClose because we are in a different goroutine. Not
					// setting pgConn.status or closing pgConn.cleanupDone for the same reason.
					.conn.Close()

					 <- 
					return
				}
			}
			if  != nil {
				 <- 
				return
			}

			select {
			case <-:
				return
			default:
			}
		}
	}()

	var  error
	var  error
	for  == nil &&  == nil {
		select {
		case  = <-:
		case <-:
			// If pgConn.receiveMessage encounters an error it will call pgConn.asyncClose. But that is a race condition with
			// the goroutine. So instead check pgConn.bufferingReceiveErr which will have been set by the signalMessage. If an
			// error is found then forcibly close the connection without sending the Terminate message.
			if  := .bufferingReceiveErr;  != nil {
				.status = connStatusClosed
				.conn.Close()
				close(.cleanupDone)
				return CommandTag{}, normalizeTimeoutError(, )
			}
			,  := .receiveMessage()

			switch msg := .(type) {
			case *pgproto3.ErrorResponse:
				 = ErrorResponseToPgError()
			default:
				 = .signalMessage()
			}
		}
	}
	close()
	// Make sure io goroutine finishes before writing.
	.Wait()

	if  == io.EOF ||  != nil {
		.frontend.Send(&pgproto3.CopyDone{})
	} else {
		.frontend.Send(&pgproto3.CopyFail{Message: .Error()})
	}
	 = .flushWithPotentialWriteReadDeadlock()
	if  != nil {
		.asyncClose()
		return CommandTag{}, 
	}

	// Read results
	var  CommandTag
	for {
		,  := .receiveMessage()
		if  != nil {
			.asyncClose()
			return CommandTag{}, normalizeTimeoutError(, )
		}

		switch msg := .(type) {
		case *pgproto3.ReadyForQuery:
			return , 
		case *pgproto3.CommandComplete:
			 = .makeCommandTag(.CommandTag)
		case *pgproto3.ErrorResponse:
			 = ErrorResponseToPgError()
		}
	}
}

// MultiResultReader is a reader for a command that could return multiple results such as Exec or ExecBatch.
type MultiResultReader struct {
	pgConn   *PgConn
	ctx      context.Context
	pipeline *Pipeline

	rr *ResultReader

	closed bool
	err    error
}

// ReadAll reads all available results. Calling ReadAll is mutually exclusive with all other MultiResultReader methods.
func ( *MultiResultReader) () ([]*Result, error) {
	var  []*Result

	for .NextResult() {
		 = append(, .ResultReader().Read())
	}
	 := .Close()

	return , 
}

func ( *MultiResultReader) () (pgproto3.BackendMessage, error) {
	,  := .pgConn.receiveMessage()
	if  != nil {
		.pgConn.contextWatcher.Unwatch()
		.err = normalizeTimeoutError(.ctx, )
		.closed = true
		.pgConn.asyncClose()
		return nil, .err
	}

	switch msg := .(type) {
	case *pgproto3.ReadyForQuery:
		.closed = true
		if .pipeline != nil {
			.pipeline.expectedReadyForQueryCount--
		} else {
			.pgConn.contextWatcher.Unwatch()
			.pgConn.unlock()
		}
	case *pgproto3.ErrorResponse:
		.err = ErrorResponseToPgError()
	}

	return , nil
}

// NextResult returns advances the MultiResultReader to the next result and returns true if a result is available.
func ( *MultiResultReader) () bool {
	for !.closed && .err == nil {
		,  := .receiveMessage()
		if  != nil {
			return false
		}

		switch msg := .(type) {
		case *pgproto3.RowDescription:
			.pgConn.resultReader = ResultReader{
				pgConn:            .pgConn,
				multiResultReader: ,
				ctx:               .ctx,
				fieldDescriptions: .pgConn.convertRowDescription(.pgConn.fieldDescriptions[:], ),
			}

			.rr = &.pgConn.resultReader
			return true
		case *pgproto3.CommandComplete:
			.pgConn.resultReader = ResultReader{
				commandTag:       .pgConn.makeCommandTag(.CommandTag),
				commandConcluded: true,
				closed:           true,
			}
			.rr = &.pgConn.resultReader
			return true
		case *pgproto3.EmptyQueryResponse:
			return false
		}
	}

	return false
}

// ResultReader returns the current ResultReader.
func ( *MultiResultReader) () *ResultReader {
	return .rr
}

// Close closes the MultiResultReader and returns the first error that occurred during the MultiResultReader's use.
func ( *MultiResultReader) () error {
	for !.closed {
		,  := .receiveMessage()
		if  != nil {
			return .err
		}
	}

	return .err
}

// ResultReader is a reader for the result of a single query.
type ResultReader struct {
	pgConn            *PgConn
	multiResultReader *MultiResultReader
	pipeline          *Pipeline
	ctx               context.Context

	fieldDescriptions []FieldDescription
	rowValues         [][]byte
	commandTag        CommandTag
	commandConcluded  bool
	closed            bool
	err               error
}

// Result is the saved query response that is returned by calling Read on a ResultReader.
type Result struct {
	FieldDescriptions []FieldDescription
	Rows              [][][]byte
	CommandTag        CommandTag
	Err               error
}

// Read saves the query response to a Result.
func ( *ResultReader) () *Result {
	 := &Result{}

	for .NextRow() {
		if .FieldDescriptions == nil {
			.FieldDescriptions = make([]FieldDescription, len(.FieldDescriptions()))
			copy(.FieldDescriptions, .FieldDescriptions())
		}

		 := .Values()
		 := make([][]byte, len())
		for  := range  {
			[] = make([]byte, len([]))
			copy([], [])
		}
		.Rows = append(.Rows, )
	}

	.CommandTag, .Err = .Close()

	return 
}

// NextRow advances the ResultReader to the next row and returns true if a row is available.
func ( *ResultReader) () bool {
	for !.commandConcluded {
		,  := .receiveMessage()
		if  != nil {
			return false
		}

		switch msg := .(type) {
		case *pgproto3.DataRow:
			.rowValues = .Values
			return true
		}
	}

	return false
}

// FieldDescriptions returns the field descriptions for the current result set. The returned slice is only valid until
// the ResultReader is closed. It may return nil (for example, if the query did not return a result set or an error was
// encountered.)
func ( *ResultReader) () []FieldDescription {
	return .fieldDescriptions
}

// Values returns the current row data. NextRow must have been previously been called. The returned [][]byte is only
// valid until the next NextRow call or the ResultReader is closed.
func ( *ResultReader) () [][]byte {
	return .rowValues
}

// Close consumes any remaining result data and returns the command tag or
// error.
func ( *ResultReader) () (CommandTag, error) {
	if .closed {
		return .commandTag, .err
	}
	.closed = true

	for !.commandConcluded {
		,  := .receiveMessage()
		if  != nil {
			return CommandTag{}, .err
		}
	}

	if .multiResultReader == nil && .pipeline == nil {
		for {
			,  := .receiveMessage()
			if  != nil {
				return CommandTag{}, .err
			}

			switch msg := .(type) {
			// Detect a deferred constraint violation where the ErrorResponse is sent after CommandComplete.
			case *pgproto3.ErrorResponse:
				.err = ErrorResponseToPgError()
			case *pgproto3.ReadyForQuery:
				.pgConn.contextWatcher.Unwatch()
				.pgConn.unlock()
				return .commandTag, .err
			}
		}
	}

	return .commandTag, .err
}

// readUntilRowDescription ensures the ResultReader's fieldDescriptions are loaded. It does not return an error as any
// error will be stored in the ResultReader.
func ( *ResultReader) () {
	for !.commandConcluded {
		// Peek before receive to avoid consuming a DataRow if the result set does not include a RowDescription method.
		// This should never happen under normal pgconn usage, but it is possible if SendBytes and ReceiveResults are
		// manually used to construct a query that does not issue a describe statement.
		,  := .pgConn.peekMessage()
		if ,  := .(*pgproto3.DataRow);  {
			return
		}

		// Consume the message
		, _ = .receiveMessage()
		if ,  := .(*pgproto3.RowDescription);  {
			return
		}
	}
}

func ( *ResultReader) () ( pgproto3.BackendMessage,  error) {
	if .multiResultReader == nil {
		,  = .pgConn.receiveMessage()
	} else {
		,  = .multiResultReader.receiveMessage()
	}

	if  != nil {
		 = normalizeTimeoutError(.ctx, )
		.concludeCommand(CommandTag{}, )
		.pgConn.contextWatcher.Unwatch()
		.closed = true
		if .multiResultReader == nil {
			.pgConn.asyncClose()
		}

		return nil, .err
	}

	switch msg := .(type) {
	case *pgproto3.RowDescription:
		.fieldDescriptions = .pgConn.convertRowDescription(.pgConn.fieldDescriptions[:], )
	case *pgproto3.CommandComplete:
		.concludeCommand(.pgConn.makeCommandTag(.CommandTag), nil)
	case *pgproto3.EmptyQueryResponse:
		.concludeCommand(CommandTag{}, nil)
	case *pgproto3.ErrorResponse:
		.concludeCommand(CommandTag{}, ErrorResponseToPgError())
	}

	return , nil
}

func ( *ResultReader) ( CommandTag,  error) {
	// Keep the first error that is recorded. Store the error before checking if the command is already concluded to
	// allow for receiving an error after CommandComplete but before ReadyForQuery.
	if  != nil && .err == nil {
		.err = 
	}

	if .commandConcluded {
		return
	}

	.commandTag = 
	.rowValues = nil
	.commandConcluded = true
}

// Batch is a collection of queries that can be sent to the PostgreSQL server in a single round-trip.
type Batch struct {
	buf []byte
}

// ExecParams appends an ExecParams command to the batch. See PgConn.ExecParams for parameter descriptions.
func ( *Batch) ( string,  [][]byte,  []uint32,  []int16,  []int16) {
	.buf = (&pgproto3.Parse{Query: , ParameterOIDs: }).Encode(.buf)
	.ExecPrepared("", , , )
}

// ExecPrepared appends an ExecPrepared e command to the batch. See PgConn.ExecPrepared for parameter descriptions.
func ( *Batch) ( string,  [][]byte,  []int16,  []int16) {
	.buf = (&pgproto3.Bind{PreparedStatement: , ParameterFormatCodes: , Parameters: , ResultFormatCodes: }).Encode(.buf)
	.buf = (&pgproto3.Describe{ObjectType: 'P'}).Encode(.buf)
	.buf = (&pgproto3.Execute{}).Encode(.buf)
}

// ExecBatch executes all the queries in batch in a single round-trip. Execution is implicitly transactional unless a
// transaction is already in progress or SQL contains transaction control statements. This is a simpler way of executing
// multiple queries in a single round trip than using pipeline mode.
func ( *PgConn) ( context.Context,  *Batch) *MultiResultReader {
	if  := .lock();  != nil {
		return &MultiResultReader{
			closed: true,
			err:    ,
		}
	}

	.multiResultReader = MultiResultReader{
		pgConn: ,
		ctx:    ,
	}
	 := &.multiResultReader

	if  != context.Background() {
		select {
		case <-.Done():
			.closed = true
			.err = newContextAlreadyDoneError()
			.unlock()
			return 
		default:
		}
		.contextWatcher.Watch()
	}

	.buf = (&pgproto3.Sync{}).Encode(.buf)

	.enterPotentialWriteReadDeadlock()
	defer .exitPotentialWriteReadDeadlock()
	,  := .conn.Write(.buf)
	if  != nil {
		.closed = true
		.err = 
		.unlock()
		return 
	}

	return 
}

// EscapeString escapes a string such that it can safely be interpolated into a SQL command string. It does not include
// the surrounding single quotes.
//
// The current implementation requires that standard_conforming_strings=on and client_encoding="UTF8". If these
// conditions are not met an error will be returned. It is possible these restrictions will be lifted in the future.
func ( *PgConn) ( string) (string, error) {
	if .ParameterStatus("standard_conforming_strings") != "on" {
		return "", errors.New("EscapeString must be run with standard_conforming_strings=on")
	}

	if .ParameterStatus("client_encoding") != "UTF8" {
		return "", errors.New("EscapeString must be run with client_encoding=UTF8")
	}

	return strings.Replace(, "'", "''", -1), nil
}

// CheckConn checks the underlying connection without writing any bytes. This is currently implemented by doing a read
// with a very short deadline. This can be useful because a TCP connection can be broken such that a write will appear
// to succeed even though it will never actually reach the server. Reading immediately before a write will detect this
// condition. If this is done immediately before sending a query it reduces the chances a query will be sent that fails
// without the client knowing whether the server received it or not.
//
// Deprecated: CheckConn is deprecated in favor of Ping. CheckConn cannot detect all types of broken connections where
// the write would still appear to succeed. Prefer Ping unless on a high latency connection.
func ( *PgConn) () error {
	,  := context.WithTimeout(context.Background(), 1*time.Millisecond)
	defer ()

	,  := .ReceiveMessage()
	if  != nil {
		if !Timeout() {
			return 
		}
	}

	return nil
}

// Ping pings the server. This can be useful because a TCP connection can be broken such that a write will appear to
// succeed even though it will never actually reach the server. Pinging immediately before sending a query reduces the
// chances a query will be sent that fails without the client knowing whether the server received it or not.
func ( *PgConn) ( context.Context) error {
	return .Exec(, "-- ping").Close()
}

// makeCommandTag makes a CommandTag. It does not retain a reference to buf or buf's underlying memory.
func ( *PgConn) ( []byte) CommandTag {
	return CommandTag{s: string()}
}

// enterPotentialWriteReadDeadlock must be called before a write that could deadlock if the server is simultaneously
// blocked writing to us.
func ( *PgConn) () {
	// The time to wait is somewhat arbitrary. A Write should only take as long as the syscall and memcpy to the OS
	// outbound network buffer unless the buffer is full (which potentially is a block). It needs to be long enough for
	// the normal case, but short enough not to kill performance if a block occurs.
	//
	// In addition, on Windows the default timer resolution is 15.6ms. So setting the timer to less than that is
	// ineffective.
	if .slowWriteTimer.Reset(15 * time.Millisecond) {
		panic("BUG: slow write timer already active")
	}
}

// exitPotentialWriteReadDeadlock must be called after a call to enterPotentialWriteReadDeadlock.
func ( *PgConn) () {
	// The state of the timer is not relevant upon exiting the potential slow write. It may both
	// fire (due to a slow write), or not fire (due to a fast write).
	_ = .slowWriteTimer.Stop()
	.bgReader.Stop()
}

func ( *PgConn) () error {
	.enterPotentialWriteReadDeadlock()
	defer .exitPotentialWriteReadDeadlock()
	 := .frontend.Flush()
	return 
}

// SyncConn prepares the underlying net.Conn for direct use. PgConn may internally buffer reads or use goroutines for
// background IO. This means that any direct use of the underlying net.Conn may be corrupted if a read is already
// buffered or a read is in progress. SyncConn drains read buffers and stops background IO. In some cases this may
// require sending a ping to the server. ctx can be used to cancel this operation. This should be called before any
// operation that will use the underlying net.Conn directly. e.g. Before Conn() or Hijack().
//
// This should not be confused with the PostgreSQL protocol Sync message.
func ( *PgConn) ( context.Context) error {
	for  := 0;  < 10; ++ {
		if .bgReader.Status() == bgreader.StatusStopped && .frontend.ReadBufferLen() == 0 {
			return nil
		}

		 := .Ping()
		if  != nil {
			return fmt.Errorf("SyncConn: Ping failed while syncing conn: %w", )
		}
	}

	// This should never happen. Only way I can imagine this occuring is if the server is constantly sending data such as
	// LISTEN/NOTIFY or log notifications such that we never can get an empty buffer.
	return errors.New("SyncConn: conn never synchronized")
}

// HijackedConn is the result of hijacking a connection.
//
// Due to the necessary exposure of internal implementation details, it is not covered by the semantic versioning
// compatibility.
type HijackedConn struct {
	Conn              net.Conn
	PID               uint32            // backend pid
	SecretKey         uint32            // key to use to send a cancel query message to the server
	ParameterStatuses map[string]string // parameters that have been reported by the server
	TxStatus          byte
	Frontend          *pgproto3.Frontend
	Config            *Config
}

// Hijack extracts the internal connection data. pgConn must be in an idle state. SyncConn should be called immediately
// before Hijack. pgConn is unusable after hijacking. Hijacking is typically only useful when using pgconn to establish
// a connection, but taking complete control of the raw connection after that (e.g. a load balancer or proxy).
//
// Due to the necessary exposure of internal implementation details, it is not covered by the semantic versioning
// compatibility.
func ( *PgConn) () (*HijackedConn, error) {
	if  := .lock();  != nil {
		return nil, 
	}
	.status = connStatusClosed

	return &HijackedConn{
		Conn:              .conn,
		PID:               .pid,
		SecretKey:         .secretKey,
		ParameterStatuses: .parameterStatuses,
		TxStatus:          .txStatus,
		Frontend:          .frontend,
		Config:            .config,
	}, nil
}

// Construct created a PgConn from an already established connection to a PostgreSQL server. This is the inverse of
// PgConn.Hijack. The connection must be in an idle state.
//
// hc.Frontend is replaced by a new pgproto3.Frontend built by hc.Config.BuildFrontend.
//
// Due to the necessary exposure of internal implementation details, it is not covered by the semantic versioning
// compatibility.
func ( *HijackedConn) (*PgConn, error) {
	 := &PgConn{
		conn:              .Conn,
		pid:               .PID,
		secretKey:         .SecretKey,
		parameterStatuses: .ParameterStatuses,
		txStatus:          .TxStatus,
		frontend:          .Frontend,
		config:            .Config,

		status: connStatusIdle,

		cleanupDone: make(chan struct{}),
	}

	.contextWatcher = newContextWatcher(.conn)
	.bgReader = bgreader.New(.conn)
	.slowWriteTimer = time.AfterFunc(time.Duration(math.MaxInt64), .bgReader.Start)
	.slowWriteTimer.Stop()
	.frontend = .Config.BuildFrontend(.bgReader, .conn)

	return , nil
}

// Pipeline represents a connection in pipeline mode.
//
// SendPrepare, SendQueryParams, and SendQueryPrepared queue requests to the server. These requests are not written until
// pipeline is flushed by Flush or Sync. Sync must be called after the last request is queued. Requests between
// synchronization points are implicitly transactional unless explicit transaction control statements have been issued.
//
// The context the pipeline was started with is in effect for the entire life of the Pipeline.
//
// For a deeper understanding of pipeline mode see the PostgreSQL documentation for the extended query protocol
// (https://www.postgresql.org/docs/current/protocol-flow.html#PROTOCOL-FLOW-EXT-QUERY) and the libpq pipeline mode
// (https://www.postgresql.org/docs/current/libpq-pipeline-mode.html).
type Pipeline struct {
	conn *PgConn
	ctx  context.Context

	expectedReadyForQueryCount int
	pendingSync                bool

	err    error
	closed bool
}

// PipelineSync is returned by GetResults when a ReadyForQuery message is received.
type PipelineSync struct{}

// CloseComplete is returned by GetResults when a CloseComplete message is received.
type CloseComplete struct{}

// StartPipeline switches the connection to pipeline mode and returns a *Pipeline. In pipeline mode requests can be sent
// to the server without waiting for a response. Close must be called on the returned *Pipeline to return the connection
// to normal mode. While in pipeline mode, no methods that communicate with the server may be called except
// CancelRequest and Close. ctx is in effect for entire life of the *Pipeline.
//
// Prefer ExecBatch when only sending one group of queries at once.
func ( *PgConn) ( context.Context) *Pipeline {
	if  := .lock();  != nil {
		return &Pipeline{
			closed: true,
			err:    ,
		}
	}

	.pipeline = Pipeline{
		conn: ,
		ctx:  ,
	}
	 := &.pipeline

	if  != context.Background() {
		select {
		case <-.Done():
			.closed = true
			.err = newContextAlreadyDoneError()
			.unlock()
			return 
		default:
		}
		.contextWatcher.Watch()
	}

	return 
}

// SendPrepare is the pipeline version of *PgConn.Prepare.
func ( *Pipeline) (,  string,  []uint32) {
	if .closed {
		return
	}
	.pendingSync = true

	.conn.frontend.SendParse(&pgproto3.Parse{Name: , Query: , ParameterOIDs: })
	.conn.frontend.SendDescribe(&pgproto3.Describe{ObjectType: 'S', Name: })
}

// SendDeallocate deallocates a prepared statement.
func ( *Pipeline) ( string) {
	if .closed {
		return
	}
	.pendingSync = true

	.conn.frontend.SendClose(&pgproto3.Close{ObjectType: 'S', Name: })
}

// SendQueryParams is the pipeline version of *PgConn.QueryParams.
func ( *Pipeline) ( string,  [][]byte,  []uint32,  []int16,  []int16) {
	if .closed {
		return
	}
	.pendingSync = true

	.conn.frontend.SendParse(&pgproto3.Parse{Query: , ParameterOIDs: })
	.conn.frontend.SendBind(&pgproto3.Bind{ParameterFormatCodes: , Parameters: , ResultFormatCodes: })
	.conn.frontend.SendDescribe(&pgproto3.Describe{ObjectType: 'P'})
	.conn.frontend.SendExecute(&pgproto3.Execute{})
}

// SendQueryPrepared is the pipeline version of *PgConn.QueryPrepared.
func ( *Pipeline) ( string,  [][]byte,  []int16,  []int16) {
	if .closed {
		return
	}
	.pendingSync = true

	.conn.frontend.SendBind(&pgproto3.Bind{PreparedStatement: , ParameterFormatCodes: , Parameters: , ResultFormatCodes: })
	.conn.frontend.SendDescribe(&pgproto3.Describe{ObjectType: 'P'})
	.conn.frontend.SendExecute(&pgproto3.Execute{})
}

// Flush flushes the queued requests without establishing a synchronization point.
func ( *Pipeline) () error {
	if .closed {
		if .err != nil {
			return .err
		}
		return errors.New("pipeline closed")
	}

	 := .conn.flushWithPotentialWriteReadDeadlock()
	if  != nil {
		 = normalizeTimeoutError(.ctx, )

		.conn.asyncClose()

		.conn.contextWatcher.Unwatch()
		.conn.unlock()
		.closed = true
		.err = 
		return 
	}

	return nil
}

// Sync establishes a synchronization point and flushes the queued requests.
func ( *Pipeline) () error {
	.conn.frontend.SendSync(&pgproto3.Sync{})
	 := .Flush()
	if  != nil {
		return 
	}

	.pendingSync = false
	.expectedReadyForQueryCount++

	return nil
}

// GetResults gets the next results. If results are present, results may be a *ResultReader, *StatementDescription, or
// *PipelineSync. If an ErrorResponse is received from the server, results will be nil and err will be a *PgError. If no
// results are available, results and err will both be nil.
func ( *Pipeline) () ( any,  error) {
	if .expectedReadyForQueryCount == 0 {
		return nil, nil
	}

	for {
		,  := .conn.receiveMessage()
		if  != nil {
			return nil, 
		}

		switch msg := .(type) {
		case *pgproto3.RowDescription:
			.conn.resultReader = ResultReader{
				pgConn:            .conn,
				pipeline:          ,
				ctx:               .ctx,
				fieldDescriptions: .conn.convertRowDescription(.conn.fieldDescriptions[:], ),
			}
			return &.conn.resultReader, nil
		case *pgproto3.CommandComplete:
			.conn.resultReader = ResultReader{
				commandTag:       .conn.makeCommandTag(.CommandTag),
				commandConcluded: true,
				closed:           true,
			}
			return &.conn.resultReader, nil
		case *pgproto3.ParseComplete:
			,  := .conn.peekMessage()
			if  != nil {
				return nil, 
			}
			if ,  := .(*pgproto3.ParameterDescription);  {
				return .getResultsPrepare()
			}
		case *pgproto3.CloseComplete:
			return &CloseComplete{}, nil
		case *pgproto3.ReadyForQuery:
			.expectedReadyForQueryCount--
			return &PipelineSync{}, nil
		case *pgproto3.ErrorResponse:
			 := ErrorResponseToPgError()
			return nil, 
		}

	}
}

func ( *Pipeline) () (*StatementDescription, error) {
	 := &StatementDescription{}

	for {
		,  := .conn.receiveMessage()
		if  != nil {
			.conn.asyncClose()
			return nil, normalizeTimeoutError(.ctx, )
		}

		switch msg := .(type) {
		case *pgproto3.ParameterDescription:
			.ParamOIDs = make([]uint32, len(.ParameterOIDs))
			copy(.ParamOIDs, .ParameterOIDs)
		case *pgproto3.RowDescription:
			.Fields = .conn.convertRowDescription(nil, )
			return , nil

		// NoData is returned instead of RowDescription when there is no expected result. e.g. An INSERT without a RETURNING
		// clause.
		case *pgproto3.NoData:
			return , nil

		// These should never happen here. But don't take chances that could lead to a deadlock.
		case *pgproto3.ErrorResponse:
			 := ErrorResponseToPgError()
			return nil, 
		case *pgproto3.CommandComplete:
			.conn.asyncClose()
			return nil, errors.New("BUG: received CommandComplete while handling Describe")
		case *pgproto3.ReadyForQuery:
			.conn.asyncClose()
			return nil, errors.New("BUG: received ReadyForQuery while handling Describe")
		}
	}
}

// Close closes the pipeline and returns the connection to normal mode.
func ( *Pipeline) () error {
	if .closed {
		return .err
	}
	.closed = true

	if .pendingSync {
		.conn.asyncClose()
		.err = errors.New("pipeline has unsynced requests")
		.conn.contextWatcher.Unwatch()
		.conn.unlock()

		return .err
	}

	for .expectedReadyForQueryCount > 0 {
		,  := .GetResults()
		if  != nil {
			.err = 
			var  *PgError
			if !errors.As(, &) {
				.conn.asyncClose()
				break
			}
		}
	}

	.conn.contextWatcher.Unwatch()
	.conn.unlock()

	return .err
}