...

Source file src/github.com/lib/pq/conn.go

Documentation: github.com/lib/pq

     1  package pq
     2  
     3  import (
     4  	"bufio"
     5  	"bytes"
     6  	"context"
     7  	"crypto/md5"
     8  	"crypto/sha256"
     9  	"database/sql"
    10  	"database/sql/driver"
    11  	"encoding/binary"
    12  	"errors"
    13  	"fmt"
    14  	"io"
    15  	"net"
    16  	"os"
    17  	"os/user"
    18  	"path"
    19  	"path/filepath"
    20  	"strconv"
    21  	"strings"
    22  	"sync"
    23  	"time"
    24  	"unicode"
    25  
    26  	"github.com/lib/pq/oid"
    27  	"github.com/lib/pq/scram"
    28  )
    29  
    30  // Common error types
    31  var (
    32  	ErrNotSupported              = errors.New("pq: Unsupported command")
    33  	ErrInFailedTransaction       = errors.New("pq: Could not complete operation in a failed transaction")
    34  	ErrSSLNotSupported           = errors.New("pq: SSL is not enabled on the server")
    35  	ErrSSLKeyUnknownOwnership    = errors.New("pq: Could not get owner information for private key, may not be properly protected")
    36  	ErrSSLKeyHasWorldPermissions = errors.New("pq: Private key has world access. Permissions should be u=rw,g=r (0640) if owned by root, or u=rw (0600), or less")
    37  
    38  	ErrCouldNotDetectUsername = errors.New("pq: Could not detect default username. Please provide one explicitly")
    39  
    40  	errUnexpectedReady = errors.New("unexpected ReadyForQuery")
    41  	errNoRowsAffected  = errors.New("no RowsAffected available after the empty statement")
    42  	errNoLastInsertID  = errors.New("no LastInsertId available after the empty statement")
    43  )
    44  
    45  // Compile time validation that our types implement the expected interfaces
    46  var (
    47  	_ driver.Driver = Driver{}
    48  )
    49  
    50  // Driver is the Postgres database driver.
    51  type Driver struct{}
    52  
    53  // Open opens a new connection to the database. name is a connection string.
    54  // Most users should only use it through database/sql package from the standard
    55  // library.
    56  func (d Driver) Open(name string) (driver.Conn, error) {
    57  	return Open(name)
    58  }
    59  
    60  func init() {
    61  	sql.Register("postgres", &Driver{})
    62  }
    63  
    64  type parameterStatus struct {
    65  	// server version in the same format as server_version_num, or 0 if
    66  	// unavailable
    67  	serverVersion int
    68  
    69  	// the current location based on the TimeZone value of the session, if
    70  	// available
    71  	currentLocation *time.Location
    72  }
    73  
    74  type transactionStatus byte
    75  
    76  const (
    77  	txnStatusIdle                transactionStatus = 'I'
    78  	txnStatusIdleInTransaction   transactionStatus = 'T'
    79  	txnStatusInFailedTransaction transactionStatus = 'E'
    80  )
    81  
    82  func (s transactionStatus) String() string {
    83  	switch s {
    84  	case txnStatusIdle:
    85  		return "idle"
    86  	case txnStatusIdleInTransaction:
    87  		return "idle in transaction"
    88  	case txnStatusInFailedTransaction:
    89  		return "in a failed transaction"
    90  	default:
    91  		errorf("unknown transactionStatus %d", s)
    92  	}
    93  
    94  	panic("not reached")
    95  }
    96  
    97  // Dialer is the dialer interface. It can be used to obtain more control over
    98  // how pq creates network connections.
    99  type Dialer interface {
   100  	Dial(network, address string) (net.Conn, error)
   101  	DialTimeout(network, address string, timeout time.Duration) (net.Conn, error)
   102  }
   103  
   104  // DialerContext is the context-aware dialer interface.
   105  type DialerContext interface {
   106  	DialContext(ctx context.Context, network, address string) (net.Conn, error)
   107  }
   108  
   109  type defaultDialer struct {
   110  	d net.Dialer
   111  }
   112  
   113  func (d defaultDialer) Dial(network, address string) (net.Conn, error) {
   114  	return d.d.Dial(network, address)
   115  }
   116  func (d defaultDialer) DialTimeout(
   117  	network, address string, timeout time.Duration,
   118  ) (net.Conn, error) {
   119  	ctx, cancel := context.WithTimeout(context.Background(), timeout)
   120  	defer cancel()
   121  	return d.DialContext(ctx, network, address)
   122  }
   123  func (d defaultDialer) DialContext(ctx context.Context, network, address string) (net.Conn, error) {
   124  	return d.d.DialContext(ctx, network, address)
   125  }
   126  
   127  type conn struct {
   128  	c         net.Conn
   129  	buf       *bufio.Reader
   130  	namei     int
   131  	scratch   [512]byte
   132  	txnStatus transactionStatus
   133  	txnFinish func()
   134  
   135  	// Save connection arguments to use during CancelRequest.
   136  	dialer Dialer
   137  	opts   values
   138  
   139  	// Cancellation key data for use with CancelRequest messages.
   140  	processID int
   141  	secretKey int
   142  
   143  	parameterStatus parameterStatus
   144  
   145  	saveMessageType   byte
   146  	saveMessageBuffer []byte
   147  
   148  	// If an error is set, this connection is bad and all public-facing
   149  	// functions should return the appropriate error by calling get()
   150  	// (ErrBadConn) or getForNext().
   151  	err syncErr
   152  
   153  	// If set, this connection should never use the binary format when
   154  	// receiving query results from prepared statements.  Only provided for
   155  	// debugging.
   156  	disablePreparedBinaryResult bool
   157  
   158  	// Whether to always send []byte parameters over as binary.  Enables single
   159  	// round-trip mode for non-prepared Query calls.
   160  	binaryParameters bool
   161  
   162  	// If true this connection is in the middle of a COPY
   163  	inCopy bool
   164  
   165  	// If not nil, notices will be synchronously sent here
   166  	noticeHandler func(*Error)
   167  
   168  	// If not nil, notifications will be synchronously sent here
   169  	notificationHandler func(*Notification)
   170  
   171  	// GSSAPI context
   172  	gss GSS
   173  }
   174  
   175  type syncErr struct {
   176  	err error
   177  	sync.Mutex
   178  }
   179  
   180  // Return ErrBadConn if connection is bad.
   181  func (e *syncErr) get() error {
   182  	e.Lock()
   183  	defer e.Unlock()
   184  	if e.err != nil {
   185  		return driver.ErrBadConn
   186  	}
   187  	return nil
   188  }
   189  
   190  // Return the error set on the connection. Currently only used by rows.Next.
   191  func (e *syncErr) getForNext() error {
   192  	e.Lock()
   193  	defer e.Unlock()
   194  	return e.err
   195  }
   196  
   197  // Set error, only if it isn't set yet.
   198  func (e *syncErr) set(err error) {
   199  	if err == nil {
   200  		panic("attempt to set nil err")
   201  	}
   202  	e.Lock()
   203  	defer e.Unlock()
   204  	if e.err == nil {
   205  		e.err = err
   206  	}
   207  }
   208  
   209  // Handle driver-side settings in parsed connection string.
   210  func (cn *conn) handleDriverSettings(o values) (err error) {
   211  	boolSetting := func(key string, val *bool) error {
   212  		if value, ok := o[key]; ok {
   213  			if value == "yes" {
   214  				*val = true
   215  			} else if value == "no" {
   216  				*val = false
   217  			} else {
   218  				return fmt.Errorf("unrecognized value %q for %s", value, key)
   219  			}
   220  		}
   221  		return nil
   222  	}
   223  
   224  	err = boolSetting("disable_prepared_binary_result", &cn.disablePreparedBinaryResult)
   225  	if err != nil {
   226  		return err
   227  	}
   228  	return boolSetting("binary_parameters", &cn.binaryParameters)
   229  }
   230  
   231  func (cn *conn) handlePgpass(o values) {
   232  	// if a password was supplied, do not process .pgpass
   233  	if _, ok := o["password"]; ok {
   234  		return
   235  	}
   236  	filename := os.Getenv("PGPASSFILE")
   237  	if filename == "" {
   238  		// XXX this code doesn't work on Windows where the default filename is
   239  		// XXX %APPDATA%\postgresql\pgpass.conf
   240  		// Prefer $HOME over user.Current due to glibc bug: golang.org/issue/13470
   241  		userHome := os.Getenv("HOME")
   242  		if userHome == "" {
   243  			user, err := user.Current()
   244  			if err != nil {
   245  				return
   246  			}
   247  			userHome = user.HomeDir
   248  		}
   249  		filename = filepath.Join(userHome, ".pgpass")
   250  	}
   251  	fileinfo, err := os.Stat(filename)
   252  	if err != nil {
   253  		return
   254  	}
   255  	mode := fileinfo.Mode()
   256  	if mode&(0x77) != 0 {
   257  		// XXX should warn about incorrect .pgpass permissions as psql does
   258  		return
   259  	}
   260  	file, err := os.Open(filename)
   261  	if err != nil {
   262  		return
   263  	}
   264  	defer file.Close()
   265  	scanner := bufio.NewScanner(io.Reader(file))
   266  	// From: https://github.com/tg/pgpass/blob/master/reader.go
   267  	for scanner.Scan() {
   268  		if scanText(scanner.Text(), o) {
   269  			break
   270  		}
   271  	}
   272  }
   273  
   274  // GetFields is a helper function for scanText.
   275  func getFields(s string) []string {
   276  	fs := make([]string, 0, 5)
   277  	f := make([]rune, 0, len(s))
   278  
   279  	var esc bool
   280  	for _, c := range s {
   281  		switch {
   282  		case esc:
   283  			f = append(f, c)
   284  			esc = false
   285  		case c == '\\':
   286  			esc = true
   287  		case c == ':':
   288  			fs = append(fs, string(f))
   289  			f = f[:0]
   290  		default:
   291  			f = append(f, c)
   292  		}
   293  	}
   294  	return append(fs, string(f))
   295  }
   296  
   297  // ScanText assists HandlePgpass in it's objective.
   298  func scanText(line string, o values) bool {
   299  	hostname := o["host"]
   300  	ntw, _ := network(o)
   301  	port := o["port"]
   302  	db := o["dbname"]
   303  	username := o["user"]
   304  	if len(line) == 0 || line[0] == '#' {
   305  		return false
   306  	}
   307  	split := getFields(line)
   308  	if len(split) != 5 {
   309  		return false
   310  	}
   311  	if (split[0] == "*" || split[0] == hostname || (split[0] == "localhost" && (hostname == "" || ntw == "unix"))) && (split[1] == "*" || split[1] == port) && (split[2] == "*" || split[2] == db) && (split[3] == "*" || split[3] == username) {
   312  		o["password"] = split[4]
   313  		return true
   314  	}
   315  	return false
   316  }
   317  
   318  func (cn *conn) writeBuf(b byte) *writeBuf {
   319  	cn.scratch[0] = b
   320  	return &writeBuf{
   321  		buf: cn.scratch[:5],
   322  		pos: 1,
   323  	}
   324  }
   325  
   326  // Open opens a new connection to the database. dsn is a connection string.
   327  // Most users should only use it through database/sql package from the standard
   328  // library.
   329  func Open(dsn string) (_ driver.Conn, err error) {
   330  	return DialOpen(defaultDialer{}, dsn)
   331  }
   332  
   333  // DialOpen opens a new connection to the database using a dialer.
   334  func DialOpen(d Dialer, dsn string) (_ driver.Conn, err error) {
   335  	c, err := NewConnector(dsn)
   336  	if err != nil {
   337  		return nil, err
   338  	}
   339  	c.Dialer(d)
   340  	return c.open(context.Background())
   341  }
   342  
   343  func (c *Connector) open(ctx context.Context) (cn *conn, err error) {
   344  	// Handle any panics during connection initialization.  Note that we
   345  	// specifically do *not* want to use errRecover(), as that would turn any
   346  	// connection errors into ErrBadConns, hiding the real error message from
   347  	// the user.
   348  	defer errRecoverNoErrBadConn(&err)
   349  
   350  	// Create a new values map (copy). This makes it so maps in different
   351  	// connections do not reference the same underlying data structure, so it
   352  	// is safe for multiple connections to concurrently write to their opts.
   353  	o := make(values)
   354  	for k, v := range c.opts {
   355  		o[k] = v
   356  	}
   357  
   358  	cn = &conn{
   359  		opts:   o,
   360  		dialer: c.dialer,
   361  	}
   362  	err = cn.handleDriverSettings(o)
   363  	if err != nil {
   364  		return nil, err
   365  	}
   366  	cn.handlePgpass(o)
   367  
   368  	cn.c, err = dial(ctx, c.dialer, o)
   369  	if err != nil {
   370  		return nil, err
   371  	}
   372  
   373  	err = cn.ssl(o)
   374  	if err != nil {
   375  		if cn.c != nil {
   376  			cn.c.Close()
   377  		}
   378  		return nil, err
   379  	}
   380  
   381  	// cn.startup panics on error. Make sure we don't leak cn.c.
   382  	panicking := true
   383  	defer func() {
   384  		if panicking {
   385  			cn.c.Close()
   386  		}
   387  	}()
   388  
   389  	cn.buf = bufio.NewReader(cn.c)
   390  	cn.startup(o)
   391  
   392  	// reset the deadline, in case one was set (see dial)
   393  	if timeout, ok := o["connect_timeout"]; ok && timeout != "0" {
   394  		err = cn.c.SetDeadline(time.Time{})
   395  	}
   396  	panicking = false
   397  	return cn, err
   398  }
   399  
   400  func dial(ctx context.Context, d Dialer, o values) (net.Conn, error) {
   401  	network, address := network(o)
   402  
   403  	// Zero or not specified means wait indefinitely.
   404  	if timeout, ok := o["connect_timeout"]; ok && timeout != "0" {
   405  		seconds, err := strconv.ParseInt(timeout, 10, 0)
   406  		if err != nil {
   407  			return nil, fmt.Errorf("invalid value for parameter connect_timeout: %s", err)
   408  		}
   409  		duration := time.Duration(seconds) * time.Second
   410  
   411  		// connect_timeout should apply to the entire connection establishment
   412  		// procedure, so we both use a timeout for the TCP connection
   413  		// establishment and set a deadline for doing the initial handshake.
   414  		// The deadline is then reset after startup() is done.
   415  		deadline := time.Now().Add(duration)
   416  		var conn net.Conn
   417  		if dctx, ok := d.(DialerContext); ok {
   418  			ctx, cancel := context.WithTimeout(ctx, duration)
   419  			defer cancel()
   420  			conn, err = dctx.DialContext(ctx, network, address)
   421  		} else {
   422  			conn, err = d.DialTimeout(network, address, duration)
   423  		}
   424  		if err != nil {
   425  			return nil, err
   426  		}
   427  		err = conn.SetDeadline(deadline)
   428  		return conn, err
   429  	}
   430  	if dctx, ok := d.(DialerContext); ok {
   431  		return dctx.DialContext(ctx, network, address)
   432  	}
   433  	return d.Dial(network, address)
   434  }
   435  
   436  func network(o values) (string, string) {
   437  	host := o["host"]
   438  
   439  	if strings.HasPrefix(host, "/") {
   440  		sockPath := path.Join(host, ".s.PGSQL."+o["port"])
   441  		return "unix", sockPath
   442  	}
   443  
   444  	return "tcp", net.JoinHostPort(host, o["port"])
   445  }
   446  
   447  type values map[string]string
   448  
   449  // scanner implements a tokenizer for libpq-style option strings.
   450  type scanner struct {
   451  	s []rune
   452  	i int
   453  }
   454  
   455  // newScanner returns a new scanner initialized with the option string s.
   456  func newScanner(s string) *scanner {
   457  	return &scanner{[]rune(s), 0}
   458  }
   459  
   460  // Next returns the next rune.
   461  // It returns 0, false if the end of the text has been reached.
   462  func (s *scanner) Next() (rune, bool) {
   463  	if s.i >= len(s.s) {
   464  		return 0, false
   465  	}
   466  	r := s.s[s.i]
   467  	s.i++
   468  	return r, true
   469  }
   470  
   471  // SkipSpaces returns the next non-whitespace rune.
   472  // It returns 0, false if the end of the text has been reached.
   473  func (s *scanner) SkipSpaces() (rune, bool) {
   474  	r, ok := s.Next()
   475  	for unicode.IsSpace(r) && ok {
   476  		r, ok = s.Next()
   477  	}
   478  	return r, ok
   479  }
   480  
   481  // parseOpts parses the options from name and adds them to the values.
   482  //
   483  // The parsing code is based on conninfo_parse from libpq's fe-connect.c
   484  func parseOpts(name string, o values) error {
   485  	s := newScanner(name)
   486  
   487  	for {
   488  		var (
   489  			keyRunes, valRunes []rune
   490  			r                  rune
   491  			ok                 bool
   492  		)
   493  
   494  		if r, ok = s.SkipSpaces(); !ok {
   495  			break
   496  		}
   497  
   498  		// Scan the key
   499  		for !unicode.IsSpace(r) && r != '=' {
   500  			keyRunes = append(keyRunes, r)
   501  			if r, ok = s.Next(); !ok {
   502  				break
   503  			}
   504  		}
   505  
   506  		// Skip any whitespace if we're not at the = yet
   507  		if r != '=' {
   508  			r, ok = s.SkipSpaces()
   509  		}
   510  
   511  		// The current character should be =
   512  		if r != '=' || !ok {
   513  			return fmt.Errorf(`missing "=" after %q in connection info string"`, string(keyRunes))
   514  		}
   515  
   516  		// Skip any whitespace after the =
   517  		if r, ok = s.SkipSpaces(); !ok {
   518  			// If we reach the end here, the last value is just an empty string as per libpq.
   519  			o[string(keyRunes)] = ""
   520  			break
   521  		}
   522  
   523  		if r != '\'' {
   524  			for !unicode.IsSpace(r) {
   525  				if r == '\\' {
   526  					if r, ok = s.Next(); !ok {
   527  						return fmt.Errorf(`missing character after backslash`)
   528  					}
   529  				}
   530  				valRunes = append(valRunes, r)
   531  
   532  				if r, ok = s.Next(); !ok {
   533  					break
   534  				}
   535  			}
   536  		} else {
   537  		quote:
   538  			for {
   539  				if r, ok = s.Next(); !ok {
   540  					return fmt.Errorf(`unterminated quoted string literal in connection string`)
   541  				}
   542  				switch r {
   543  				case '\'':
   544  					break quote
   545  				case '\\':
   546  					r, _ = s.Next()
   547  					fallthrough
   548  				default:
   549  					valRunes = append(valRunes, r)
   550  				}
   551  			}
   552  		}
   553  
   554  		o[string(keyRunes)] = string(valRunes)
   555  	}
   556  
   557  	return nil
   558  }
   559  
   560  func (cn *conn) isInTransaction() bool {
   561  	return cn.txnStatus == txnStatusIdleInTransaction ||
   562  		cn.txnStatus == txnStatusInFailedTransaction
   563  }
   564  
   565  func (cn *conn) checkIsInTransaction(intxn bool) {
   566  	if cn.isInTransaction() != intxn {
   567  		cn.err.set(driver.ErrBadConn)
   568  		errorf("unexpected transaction status %v", cn.txnStatus)
   569  	}
   570  }
   571  
   572  func (cn *conn) Begin() (_ driver.Tx, err error) {
   573  	return cn.begin("")
   574  }
   575  
   576  func (cn *conn) begin(mode string) (_ driver.Tx, err error) {
   577  	if err := cn.err.get(); err != nil {
   578  		return nil, err
   579  	}
   580  	defer cn.errRecover(&err)
   581  
   582  	cn.checkIsInTransaction(false)
   583  	_, commandTag, err := cn.simpleExec("BEGIN" + mode)
   584  	if err != nil {
   585  		return nil, err
   586  	}
   587  	if commandTag != "BEGIN" {
   588  		cn.err.set(driver.ErrBadConn)
   589  		return nil, fmt.Errorf("unexpected command tag %s", commandTag)
   590  	}
   591  	if cn.txnStatus != txnStatusIdleInTransaction {
   592  		cn.err.set(driver.ErrBadConn)
   593  		return nil, fmt.Errorf("unexpected transaction status %v", cn.txnStatus)
   594  	}
   595  	return cn, nil
   596  }
   597  
   598  func (cn *conn) closeTxn() {
   599  	if finish := cn.txnFinish; finish != nil {
   600  		finish()
   601  	}
   602  }
   603  
   604  func (cn *conn) Commit() (err error) {
   605  	defer cn.closeTxn()
   606  	if err := cn.err.get(); err != nil {
   607  		return err
   608  	}
   609  	defer cn.errRecover(&err)
   610  
   611  	cn.checkIsInTransaction(true)
   612  	// We don't want the client to think that everything is okay if it tries
   613  	// to commit a failed transaction.  However, no matter what we return,
   614  	// database/sql will release this connection back into the free connection
   615  	// pool so we have to abort the current transaction here.  Note that you
   616  	// would get the same behaviour if you issued a COMMIT in a failed
   617  	// transaction, so it's also the least surprising thing to do here.
   618  	if cn.txnStatus == txnStatusInFailedTransaction {
   619  		if err := cn.rollback(); err != nil {
   620  			return err
   621  		}
   622  		return ErrInFailedTransaction
   623  	}
   624  
   625  	_, commandTag, err := cn.simpleExec("COMMIT")
   626  	if err != nil {
   627  		if cn.isInTransaction() {
   628  			cn.err.set(driver.ErrBadConn)
   629  		}
   630  		return err
   631  	}
   632  	if commandTag != "COMMIT" {
   633  		cn.err.set(driver.ErrBadConn)
   634  		return fmt.Errorf("unexpected command tag %s", commandTag)
   635  	}
   636  	cn.checkIsInTransaction(false)
   637  	return nil
   638  }
   639  
   640  func (cn *conn) Rollback() (err error) {
   641  	defer cn.closeTxn()
   642  	if err := cn.err.get(); err != nil {
   643  		return err
   644  	}
   645  	defer cn.errRecover(&err)
   646  	return cn.rollback()
   647  }
   648  
   649  func (cn *conn) rollback() (err error) {
   650  	cn.checkIsInTransaction(true)
   651  	_, commandTag, err := cn.simpleExec("ROLLBACK")
   652  	if err != nil {
   653  		if cn.isInTransaction() {
   654  			cn.err.set(driver.ErrBadConn)
   655  		}
   656  		return err
   657  	}
   658  	if commandTag != "ROLLBACK" {
   659  		return fmt.Errorf("unexpected command tag %s", commandTag)
   660  	}
   661  	cn.checkIsInTransaction(false)
   662  	return nil
   663  }
   664  
   665  func (cn *conn) gname() string {
   666  	cn.namei++
   667  	return strconv.FormatInt(int64(cn.namei), 10)
   668  }
   669  
   670  func (cn *conn) simpleExec(q string) (res driver.Result, commandTag string, err error) {
   671  	b := cn.writeBuf('Q')
   672  	b.string(q)
   673  	cn.send(b)
   674  
   675  	for {
   676  		t, r := cn.recv1()
   677  		switch t {
   678  		case 'C':
   679  			res, commandTag = cn.parseComplete(r.string())
   680  		case 'Z':
   681  			cn.processReadyForQuery(r)
   682  			if res == nil && err == nil {
   683  				err = errUnexpectedReady
   684  			}
   685  			// done
   686  			return
   687  		case 'E':
   688  			err = parseError(r)
   689  		case 'I':
   690  			res = emptyRows
   691  		case 'T', 'D':
   692  			// ignore any results
   693  		default:
   694  			cn.err.set(driver.ErrBadConn)
   695  			errorf("unknown response for simple query: %q", t)
   696  		}
   697  	}
   698  }
   699  
   700  func (cn *conn) simpleQuery(q string) (res *rows, err error) {
   701  	defer cn.errRecover(&err)
   702  
   703  	b := cn.writeBuf('Q')
   704  	b.string(q)
   705  	cn.send(b)
   706  
   707  	for {
   708  		t, r := cn.recv1()
   709  		switch t {
   710  		case 'C', 'I':
   711  			// We allow queries which don't return any results through Query as
   712  			// well as Exec.  We still have to give database/sql a rows object
   713  			// the user can close, though, to avoid connections from being
   714  			// leaked.  A "rows" with done=true works fine for that purpose.
   715  			if err != nil {
   716  				cn.err.set(driver.ErrBadConn)
   717  				errorf("unexpected message %q in simple query execution", t)
   718  			}
   719  			if res == nil {
   720  				res = &rows{
   721  					cn: cn,
   722  				}
   723  			}
   724  			// Set the result and tag to the last command complete if there wasn't a
   725  			// query already run. Although queries usually return from here and cede
   726  			// control to Next, a query with zero results does not.
   727  			if t == 'C' {
   728  				res.result, res.tag = cn.parseComplete(r.string())
   729  				if res.colNames != nil {
   730  					return
   731  				}
   732  			}
   733  			res.done = true
   734  		case 'Z':
   735  			cn.processReadyForQuery(r)
   736  			// done
   737  			return
   738  		case 'E':
   739  			res = nil
   740  			err = parseError(r)
   741  		case 'D':
   742  			if res == nil {
   743  				cn.err.set(driver.ErrBadConn)
   744  				errorf("unexpected DataRow in simple query execution")
   745  			}
   746  			// the query didn't fail; kick off to Next
   747  			cn.saveMessage(t, r)
   748  			return
   749  		case 'T':
   750  			// res might be non-nil here if we received a previous
   751  			// CommandComplete, but that's fine; just overwrite it
   752  			res = &rows{cn: cn}
   753  			res.rowsHeader = parsePortalRowDescribe(r)
   754  
   755  			// To work around a bug in QueryRow in Go 1.2 and earlier, wait
   756  			// until the first DataRow has been received.
   757  		default:
   758  			cn.err.set(driver.ErrBadConn)
   759  			errorf("unknown response for simple query: %q", t)
   760  		}
   761  	}
   762  }
   763  
   764  type noRows struct{}
   765  
   766  var emptyRows noRows
   767  
   768  var _ driver.Result = noRows{}
   769  
   770  func (noRows) LastInsertId() (int64, error) {
   771  	return 0, errNoLastInsertID
   772  }
   773  
   774  func (noRows) RowsAffected() (int64, error) {
   775  	return 0, errNoRowsAffected
   776  }
   777  
   778  // Decides which column formats to use for a prepared statement.  The input is
   779  // an array of type oids, one element per result column.
   780  func decideColumnFormats(
   781  	colTyps []fieldDesc, forceText bool,
   782  ) (colFmts []format, colFmtData []byte) {
   783  	if len(colTyps) == 0 {
   784  		return nil, colFmtDataAllText
   785  	}
   786  
   787  	colFmts = make([]format, len(colTyps))
   788  	if forceText {
   789  		return colFmts, colFmtDataAllText
   790  	}
   791  
   792  	allBinary := true
   793  	allText := true
   794  	for i, t := range colTyps {
   795  		switch t.OID {
   796  		// This is the list of types to use binary mode for when receiving them
   797  		// through a prepared statement.  If a type appears in this list, it
   798  		// must also be implemented in binaryDecode in encode.go.
   799  		case oid.T_bytea:
   800  			fallthrough
   801  		case oid.T_int8:
   802  			fallthrough
   803  		case oid.T_int4:
   804  			fallthrough
   805  		case oid.T_int2:
   806  			fallthrough
   807  		case oid.T_uuid:
   808  			colFmts[i] = formatBinary
   809  			allText = false
   810  
   811  		default:
   812  			allBinary = false
   813  		}
   814  	}
   815  
   816  	if allBinary {
   817  		return colFmts, colFmtDataAllBinary
   818  	} else if allText {
   819  		return colFmts, colFmtDataAllText
   820  	} else {
   821  		colFmtData = make([]byte, 2+len(colFmts)*2)
   822  		binary.BigEndian.PutUint16(colFmtData, uint16(len(colFmts)))
   823  		for i, v := range colFmts {
   824  			binary.BigEndian.PutUint16(colFmtData[2+i*2:], uint16(v))
   825  		}
   826  		return colFmts, colFmtData
   827  	}
   828  }
   829  
   830  func (cn *conn) prepareTo(q, stmtName string) *stmt {
   831  	st := &stmt{cn: cn, name: stmtName}
   832  
   833  	b := cn.writeBuf('P')
   834  	b.string(st.name)
   835  	b.string(q)
   836  	b.int16(0)
   837  
   838  	b.next('D')
   839  	b.byte('S')
   840  	b.string(st.name)
   841  
   842  	b.next('S')
   843  	cn.send(b)
   844  
   845  	cn.readParseResponse()
   846  	st.paramTyps, st.colNames, st.colTyps = cn.readStatementDescribeResponse()
   847  	st.colFmts, st.colFmtData = decideColumnFormats(st.colTyps, cn.disablePreparedBinaryResult)
   848  	cn.readReadyForQuery()
   849  	return st
   850  }
   851  
   852  func (cn *conn) Prepare(q string) (_ driver.Stmt, err error) {
   853  	if err := cn.err.get(); err != nil {
   854  		return nil, err
   855  	}
   856  	defer cn.errRecover(&err)
   857  
   858  	if len(q) >= 4 && strings.EqualFold(q[:4], "COPY") {
   859  		s, err := cn.prepareCopyIn(q)
   860  		if err == nil {
   861  			cn.inCopy = true
   862  		}
   863  		return s, err
   864  	}
   865  	return cn.prepareTo(q, cn.gname()), nil
   866  }
   867  
   868  func (cn *conn) Close() (err error) {
   869  	// Skip cn.bad return here because we always want to close a connection.
   870  	defer cn.errRecover(&err)
   871  
   872  	// Ensure that cn.c.Close is always run. Since error handling is done with
   873  	// panics and cn.errRecover, the Close must be in a defer.
   874  	defer func() {
   875  		cerr := cn.c.Close()
   876  		if err == nil {
   877  			err = cerr
   878  		}
   879  	}()
   880  
   881  	// Don't go through send(); ListenerConn relies on us not scribbling on the
   882  	// scratch buffer of this connection.
   883  	return cn.sendSimpleMessage('X')
   884  }
   885  
   886  // Implement the "Queryer" interface
   887  func (cn *conn) Query(query string, args []driver.Value) (driver.Rows, error) {
   888  	return cn.query(query, args)
   889  }
   890  
   891  func (cn *conn) query(query string, args []driver.Value) (_ *rows, err error) {
   892  	if err := cn.err.get(); err != nil {
   893  		return nil, err
   894  	}
   895  	if cn.inCopy {
   896  		return nil, errCopyInProgress
   897  	}
   898  	defer cn.errRecover(&err)
   899  
   900  	// Check to see if we can use the "simpleQuery" interface, which is
   901  	// *much* faster than going through prepare/exec
   902  	if len(args) == 0 {
   903  		return cn.simpleQuery(query)
   904  	}
   905  
   906  	if cn.binaryParameters {
   907  		cn.sendBinaryModeQuery(query, args)
   908  
   909  		cn.readParseResponse()
   910  		cn.readBindResponse()
   911  		rows := &rows{cn: cn}
   912  		rows.rowsHeader = cn.readPortalDescribeResponse()
   913  		cn.postExecuteWorkaround()
   914  		return rows, nil
   915  	}
   916  	st := cn.prepareTo(query, "")
   917  	st.exec(args)
   918  	return &rows{
   919  		cn:         cn,
   920  		rowsHeader: st.rowsHeader,
   921  	}, nil
   922  }
   923  
   924  // Implement the optional "Execer" interface for one-shot queries
   925  func (cn *conn) Exec(query string, args []driver.Value) (res driver.Result, err error) {
   926  	if err := cn.err.get(); err != nil {
   927  		return nil, err
   928  	}
   929  	defer cn.errRecover(&err)
   930  
   931  	// Check to see if we can use the "simpleExec" interface, which is
   932  	// *much* faster than going through prepare/exec
   933  	if len(args) == 0 {
   934  		// ignore commandTag, our caller doesn't care
   935  		r, _, err := cn.simpleExec(query)
   936  		return r, err
   937  	}
   938  
   939  	if cn.binaryParameters {
   940  		cn.sendBinaryModeQuery(query, args)
   941  
   942  		cn.readParseResponse()
   943  		cn.readBindResponse()
   944  		cn.readPortalDescribeResponse()
   945  		cn.postExecuteWorkaround()
   946  		res, _, err = cn.readExecuteResponse("Execute")
   947  		return res, err
   948  	}
   949  	// Use the unnamed statement to defer planning until bind
   950  	// time, or else value-based selectivity estimates cannot be
   951  	// used.
   952  	st := cn.prepareTo(query, "")
   953  	r, err := st.Exec(args)
   954  	if err != nil {
   955  		panic(err)
   956  	}
   957  	return r, err
   958  }
   959  
   960  type safeRetryError struct {
   961  	Err error
   962  }
   963  
   964  func (se *safeRetryError) Error() string {
   965  	return se.Err.Error()
   966  }
   967  
   968  func (cn *conn) send(m *writeBuf) {
   969  	n, err := cn.c.Write(m.wrap())
   970  	if err != nil {
   971  		if n == 0 {
   972  			err = &safeRetryError{Err: err}
   973  		}
   974  		panic(err)
   975  	}
   976  }
   977  
   978  func (cn *conn) sendStartupPacket(m *writeBuf) error {
   979  	_, err := cn.c.Write((m.wrap())[1:])
   980  	return err
   981  }
   982  
   983  // Send a message of type typ to the server on the other end of cn.  The
   984  // message should have no payload.  This method does not use the scratch
   985  // buffer.
   986  func (cn *conn) sendSimpleMessage(typ byte) (err error) {
   987  	_, err = cn.c.Write([]byte{typ, '\x00', '\x00', '\x00', '\x04'})
   988  	return err
   989  }
   990  
   991  // saveMessage memorizes a message and its buffer in the conn struct.
   992  // recvMessage will then return these values on the next call to it.  This
   993  // method is useful in cases where you have to see what the next message is
   994  // going to be (e.g. to see whether it's an error or not) but you can't handle
   995  // the message yourself.
   996  func (cn *conn) saveMessage(typ byte, buf *readBuf) {
   997  	if cn.saveMessageType != 0 {
   998  		cn.err.set(driver.ErrBadConn)
   999  		errorf("unexpected saveMessageType %d", cn.saveMessageType)
  1000  	}
  1001  	cn.saveMessageType = typ
  1002  	cn.saveMessageBuffer = *buf
  1003  }
  1004  
  1005  // recvMessage receives any message from the backend, or returns an error if
  1006  // a problem occurred while reading the message.
  1007  func (cn *conn) recvMessage(r *readBuf) (byte, error) {
  1008  	// workaround for a QueryRow bug, see exec
  1009  	if cn.saveMessageType != 0 {
  1010  		t := cn.saveMessageType
  1011  		*r = cn.saveMessageBuffer
  1012  		cn.saveMessageType = 0
  1013  		cn.saveMessageBuffer = nil
  1014  		return t, nil
  1015  	}
  1016  
  1017  	x := cn.scratch[:5]
  1018  	_, err := io.ReadFull(cn.buf, x)
  1019  	if err != nil {
  1020  		return 0, err
  1021  	}
  1022  
  1023  	// read the type and length of the message that follows
  1024  	t := x[0]
  1025  	n := int(binary.BigEndian.Uint32(x[1:])) - 4
  1026  	var y []byte
  1027  	if n <= len(cn.scratch) {
  1028  		y = cn.scratch[:n]
  1029  	} else {
  1030  		y = make([]byte, n)
  1031  	}
  1032  	_, err = io.ReadFull(cn.buf, y)
  1033  	if err != nil {
  1034  		return 0, err
  1035  	}
  1036  	*r = y
  1037  	return t, nil
  1038  }
  1039  
  1040  // recv receives a message from the backend, but if an error happened while
  1041  // reading the message or the received message was an ErrorResponse, it panics.
  1042  // NoticeResponses are ignored.  This function should generally be used only
  1043  // during the startup sequence.
  1044  func (cn *conn) recv() (t byte, r *readBuf) {
  1045  	for {
  1046  		var err error
  1047  		r = &readBuf{}
  1048  		t, err = cn.recvMessage(r)
  1049  		if err != nil {
  1050  			panic(err)
  1051  		}
  1052  		switch t {
  1053  		case 'E':
  1054  			panic(parseError(r))
  1055  		case 'N':
  1056  			if n := cn.noticeHandler; n != nil {
  1057  				n(parseError(r))
  1058  			}
  1059  		case 'A':
  1060  			if n := cn.notificationHandler; n != nil {
  1061  				n(recvNotification(r))
  1062  			}
  1063  		default:
  1064  			return
  1065  		}
  1066  	}
  1067  }
  1068  
  1069  // recv1Buf is exactly equivalent to recv1, except it uses a buffer supplied by
  1070  // the caller to avoid an allocation.
  1071  func (cn *conn) recv1Buf(r *readBuf) byte {
  1072  	for {
  1073  		t, err := cn.recvMessage(r)
  1074  		if err != nil {
  1075  			panic(err)
  1076  		}
  1077  
  1078  		switch t {
  1079  		case 'A':
  1080  			if n := cn.notificationHandler; n != nil {
  1081  				n(recvNotification(r))
  1082  			}
  1083  		case 'N':
  1084  			if n := cn.noticeHandler; n != nil {
  1085  				n(parseError(r))
  1086  			}
  1087  		case 'S':
  1088  			cn.processParameterStatus(r)
  1089  		default:
  1090  			return t
  1091  		}
  1092  	}
  1093  }
  1094  
  1095  // recv1 receives a message from the backend, panicking if an error occurs
  1096  // while attempting to read it.  All asynchronous messages are ignored, with
  1097  // the exception of ErrorResponse.
  1098  func (cn *conn) recv1() (t byte, r *readBuf) {
  1099  	r = &readBuf{}
  1100  	t = cn.recv1Buf(r)
  1101  	return t, r
  1102  }
  1103  
  1104  func (cn *conn) ssl(o values) error {
  1105  	upgrade, err := ssl(o)
  1106  	if err != nil {
  1107  		return err
  1108  	}
  1109  
  1110  	if upgrade == nil {
  1111  		// Nothing to do
  1112  		return nil
  1113  	}
  1114  
  1115  	w := cn.writeBuf(0)
  1116  	w.int32(80877103)
  1117  	if err = cn.sendStartupPacket(w); err != nil {
  1118  		return err
  1119  	}
  1120  
  1121  	b := cn.scratch[:1]
  1122  	_, err = io.ReadFull(cn.c, b)
  1123  	if err != nil {
  1124  		return err
  1125  	}
  1126  
  1127  	if b[0] != 'S' {
  1128  		return ErrSSLNotSupported
  1129  	}
  1130  
  1131  	cn.c, err = upgrade(cn.c)
  1132  	return err
  1133  }
  1134  
  1135  // isDriverSetting returns true iff a setting is purely for configuring the
  1136  // driver's options and should not be sent to the server in the connection
  1137  // startup packet.
  1138  func isDriverSetting(key string) bool {
  1139  	switch key {
  1140  	case "host", "port":
  1141  		return true
  1142  	case "password":
  1143  		return true
  1144  	case "sslmode", "sslcert", "sslkey", "sslrootcert", "sslinline", "sslsni":
  1145  		return true
  1146  	case "fallback_application_name":
  1147  		return true
  1148  	case "connect_timeout":
  1149  		return true
  1150  	case "disable_prepared_binary_result":
  1151  		return true
  1152  	case "binary_parameters":
  1153  		return true
  1154  	case "krbsrvname":
  1155  		return true
  1156  	case "krbspn":
  1157  		return true
  1158  	default:
  1159  		return false
  1160  	}
  1161  }
  1162  
  1163  func (cn *conn) startup(o values) {
  1164  	w := cn.writeBuf(0)
  1165  	w.int32(196608)
  1166  	// Send the backend the name of the database we want to connect to, and the
  1167  	// user we want to connect as.  Additionally, we send over any run-time
  1168  	// parameters potentially included in the connection string.  If the server
  1169  	// doesn't recognize any of them, it will reply with an error.
  1170  	for k, v := range o {
  1171  		if isDriverSetting(k) {
  1172  			// skip options which can't be run-time parameters
  1173  			continue
  1174  		}
  1175  		// The protocol requires us to supply the database name as "database"
  1176  		// instead of "dbname".
  1177  		if k == "dbname" {
  1178  			k = "database"
  1179  		}
  1180  		w.string(k)
  1181  		w.string(v)
  1182  	}
  1183  	w.string("")
  1184  	if err := cn.sendStartupPacket(w); err != nil {
  1185  		panic(err)
  1186  	}
  1187  
  1188  	for {
  1189  		t, r := cn.recv()
  1190  		switch t {
  1191  		case 'K':
  1192  			cn.processBackendKeyData(r)
  1193  		case 'S':
  1194  			cn.processParameterStatus(r)
  1195  		case 'R':
  1196  			cn.auth(r, o)
  1197  		case 'Z':
  1198  			cn.processReadyForQuery(r)
  1199  			return
  1200  		default:
  1201  			errorf("unknown response for startup: %q", t)
  1202  		}
  1203  	}
  1204  }
  1205  
  1206  func (cn *conn) auth(r *readBuf, o values) {
  1207  	switch code := r.int32(); code {
  1208  	case 0:
  1209  		// OK
  1210  	case 3:
  1211  		w := cn.writeBuf('p')
  1212  		w.string(o["password"])
  1213  		cn.send(w)
  1214  
  1215  		t, r := cn.recv()
  1216  		if t != 'R' {
  1217  			errorf("unexpected password response: %q", t)
  1218  		}
  1219  
  1220  		if r.int32() != 0 {
  1221  			errorf("unexpected authentication response: %q", t)
  1222  		}
  1223  	case 5:
  1224  		s := string(r.next(4))
  1225  		w := cn.writeBuf('p')
  1226  		w.string("md5" + md5s(md5s(o["password"]+o["user"])+s))
  1227  		cn.send(w)
  1228  
  1229  		t, r := cn.recv()
  1230  		if t != 'R' {
  1231  			errorf("unexpected password response: %q", t)
  1232  		}
  1233  
  1234  		if r.int32() != 0 {
  1235  			errorf("unexpected authentication response: %q", t)
  1236  		}
  1237  	case 7: // GSSAPI, startup
  1238  		if newGss == nil {
  1239  			errorf("kerberos error: no GSSAPI provider registered (import github.com/lib/pq/auth/kerberos if you need Kerberos support)")
  1240  		}
  1241  		cli, err := newGss()
  1242  		if err != nil {
  1243  			errorf("kerberos error: %s", err.Error())
  1244  		}
  1245  
  1246  		var token []byte
  1247  
  1248  		if spn, ok := o["krbspn"]; ok {
  1249  			// Use the supplied SPN if provided..
  1250  			token, err = cli.GetInitTokenFromSpn(spn)
  1251  		} else {
  1252  			// Allow the kerberos service name to be overridden
  1253  			service := "postgres"
  1254  			if val, ok := o["krbsrvname"]; ok {
  1255  				service = val
  1256  			}
  1257  
  1258  			token, err = cli.GetInitToken(o["host"], service)
  1259  		}
  1260  
  1261  		if err != nil {
  1262  			errorf("failed to get Kerberos ticket: %q", err)
  1263  		}
  1264  
  1265  		w := cn.writeBuf('p')
  1266  		w.bytes(token)
  1267  		cn.send(w)
  1268  
  1269  		// Store for GSSAPI continue message
  1270  		cn.gss = cli
  1271  
  1272  	case 8: // GSSAPI continue
  1273  
  1274  		if cn.gss == nil {
  1275  			errorf("GSSAPI protocol error")
  1276  		}
  1277  
  1278  		b := []byte(*r)
  1279  
  1280  		done, tokOut, err := cn.gss.Continue(b)
  1281  		if err == nil && !done {
  1282  			w := cn.writeBuf('p')
  1283  			w.bytes(tokOut)
  1284  			cn.send(w)
  1285  		}
  1286  
  1287  		// Errors fall through and read the more detailed message
  1288  		// from the server..
  1289  
  1290  	case 10:
  1291  		sc := scram.NewClient(sha256.New, o["user"], o["password"])
  1292  		sc.Step(nil)
  1293  		if sc.Err() != nil {
  1294  			errorf("SCRAM-SHA-256 error: %s", sc.Err().Error())
  1295  		}
  1296  		scOut := sc.Out()
  1297  
  1298  		w := cn.writeBuf('p')
  1299  		w.string("SCRAM-SHA-256")
  1300  		w.int32(len(scOut))
  1301  		w.bytes(scOut)
  1302  		cn.send(w)
  1303  
  1304  		t, r := cn.recv()
  1305  		if t != 'R' {
  1306  			errorf("unexpected password response: %q", t)
  1307  		}
  1308  
  1309  		if r.int32() != 11 {
  1310  			errorf("unexpected authentication response: %q", t)
  1311  		}
  1312  
  1313  		nextStep := r.next(len(*r))
  1314  		sc.Step(nextStep)
  1315  		if sc.Err() != nil {
  1316  			errorf("SCRAM-SHA-256 error: %s", sc.Err().Error())
  1317  		}
  1318  
  1319  		scOut = sc.Out()
  1320  		w = cn.writeBuf('p')
  1321  		w.bytes(scOut)
  1322  		cn.send(w)
  1323  
  1324  		t, r = cn.recv()
  1325  		if t != 'R' {
  1326  			errorf("unexpected password response: %q", t)
  1327  		}
  1328  
  1329  		if r.int32() != 12 {
  1330  			errorf("unexpected authentication response: %q", t)
  1331  		}
  1332  
  1333  		nextStep = r.next(len(*r))
  1334  		sc.Step(nextStep)
  1335  		if sc.Err() != nil {
  1336  			errorf("SCRAM-SHA-256 error: %s", sc.Err().Error())
  1337  		}
  1338  
  1339  	default:
  1340  		errorf("unknown authentication response: %d", code)
  1341  	}
  1342  }
  1343  
  1344  type format int
  1345  
  1346  const formatText format = 0
  1347  const formatBinary format = 1
  1348  
  1349  // One result-column format code with the value 1 (i.e. all binary).
  1350  var colFmtDataAllBinary = []byte{0, 1, 0, 1}
  1351  
  1352  // No result-column format codes (i.e. all text).
  1353  var colFmtDataAllText = []byte{0, 0}
  1354  
  1355  type stmt struct {
  1356  	cn   *conn
  1357  	name string
  1358  	rowsHeader
  1359  	colFmtData []byte
  1360  	paramTyps  []oid.Oid
  1361  	closed     bool
  1362  }
  1363  
  1364  func (st *stmt) Close() (err error) {
  1365  	if st.closed {
  1366  		return nil
  1367  	}
  1368  	if err := st.cn.err.get(); err != nil {
  1369  		return err
  1370  	}
  1371  	defer st.cn.errRecover(&err)
  1372  
  1373  	w := st.cn.writeBuf('C')
  1374  	w.byte('S')
  1375  	w.string(st.name)
  1376  	st.cn.send(w)
  1377  
  1378  	st.cn.send(st.cn.writeBuf('S'))
  1379  
  1380  	t, _ := st.cn.recv1()
  1381  	if t != '3' {
  1382  		st.cn.err.set(driver.ErrBadConn)
  1383  		errorf("unexpected close response: %q", t)
  1384  	}
  1385  	st.closed = true
  1386  
  1387  	t, r := st.cn.recv1()
  1388  	if t != 'Z' {
  1389  		st.cn.err.set(driver.ErrBadConn)
  1390  		errorf("expected ready for query, but got: %q", t)
  1391  	}
  1392  	st.cn.processReadyForQuery(r)
  1393  
  1394  	return nil
  1395  }
  1396  
  1397  func (st *stmt) Query(v []driver.Value) (r driver.Rows, err error) {
  1398  	return st.query(v)
  1399  }
  1400  
  1401  func (st *stmt) query(v []driver.Value) (r *rows, err error) {
  1402  	if err := st.cn.err.get(); err != nil {
  1403  		return nil, err
  1404  	}
  1405  	defer st.cn.errRecover(&err)
  1406  
  1407  	st.exec(v)
  1408  	return &rows{
  1409  		cn:         st.cn,
  1410  		rowsHeader: st.rowsHeader,
  1411  	}, nil
  1412  }
  1413  
  1414  func (st *stmt) Exec(v []driver.Value) (res driver.Result, err error) {
  1415  	if err := st.cn.err.get(); err != nil {
  1416  		return nil, err
  1417  	}
  1418  	defer st.cn.errRecover(&err)
  1419  
  1420  	st.exec(v)
  1421  	res, _, err = st.cn.readExecuteResponse("simple query")
  1422  	return res, err
  1423  }
  1424  
  1425  func (st *stmt) exec(v []driver.Value) {
  1426  	if len(v) >= 65536 {
  1427  		errorf("got %d parameters but PostgreSQL only supports 65535 parameters", len(v))
  1428  	}
  1429  	if len(v) != len(st.paramTyps) {
  1430  		errorf("got %d parameters but the statement requires %d", len(v), len(st.paramTyps))
  1431  	}
  1432  
  1433  	cn := st.cn
  1434  	w := cn.writeBuf('B')
  1435  	w.byte(0) // unnamed portal
  1436  	w.string(st.name)
  1437  
  1438  	if cn.binaryParameters {
  1439  		cn.sendBinaryParameters(w, v)
  1440  	} else {
  1441  		w.int16(0)
  1442  		w.int16(len(v))
  1443  		for i, x := range v {
  1444  			if x == nil {
  1445  				w.int32(-1)
  1446  			} else {
  1447  				b := encode(&cn.parameterStatus, x, st.paramTyps[i])
  1448  				w.int32(len(b))
  1449  				w.bytes(b)
  1450  			}
  1451  		}
  1452  	}
  1453  	w.bytes(st.colFmtData)
  1454  
  1455  	w.next('E')
  1456  	w.byte(0)
  1457  	w.int32(0)
  1458  
  1459  	w.next('S')
  1460  	cn.send(w)
  1461  
  1462  	cn.readBindResponse()
  1463  	cn.postExecuteWorkaround()
  1464  
  1465  }
  1466  
  1467  func (st *stmt) NumInput() int {
  1468  	return len(st.paramTyps)
  1469  }
  1470  
  1471  // parseComplete parses the "command tag" from a CommandComplete message, and
  1472  // returns the number of rows affected (if applicable) and a string
  1473  // identifying only the command that was executed, e.g. "ALTER TABLE".  If the
  1474  // command tag could not be parsed, parseComplete panics.
  1475  func (cn *conn) parseComplete(commandTag string) (driver.Result, string) {
  1476  	commandsWithAffectedRows := []string{
  1477  		"SELECT ",
  1478  		// INSERT is handled below
  1479  		"UPDATE ",
  1480  		"DELETE ",
  1481  		"FETCH ",
  1482  		"MOVE ",
  1483  		"COPY ",
  1484  	}
  1485  
  1486  	var affectedRows *string
  1487  	for _, tag := range commandsWithAffectedRows {
  1488  		if strings.HasPrefix(commandTag, tag) {
  1489  			t := commandTag[len(tag):]
  1490  			affectedRows = &t
  1491  			commandTag = tag[:len(tag)-1]
  1492  			break
  1493  		}
  1494  	}
  1495  	// INSERT also includes the oid of the inserted row in its command tag.
  1496  	// Oids in user tables are deprecated, and the oid is only returned when
  1497  	// exactly one row is inserted, so it's unlikely to be of value to any
  1498  	// real-world application and we can ignore it.
  1499  	if affectedRows == nil && strings.HasPrefix(commandTag, "INSERT ") {
  1500  		parts := strings.Split(commandTag, " ")
  1501  		if len(parts) != 3 {
  1502  			cn.err.set(driver.ErrBadConn)
  1503  			errorf("unexpected INSERT command tag %s", commandTag)
  1504  		}
  1505  		affectedRows = &parts[len(parts)-1]
  1506  		commandTag = "INSERT"
  1507  	}
  1508  	// There should be no affected rows attached to the tag, just return it
  1509  	if affectedRows == nil {
  1510  		return driver.RowsAffected(0), commandTag
  1511  	}
  1512  	n, err := strconv.ParseInt(*affectedRows, 10, 64)
  1513  	if err != nil {
  1514  		cn.err.set(driver.ErrBadConn)
  1515  		errorf("could not parse commandTag: %s", err)
  1516  	}
  1517  	return driver.RowsAffected(n), commandTag
  1518  }
  1519  
  1520  type rowsHeader struct {
  1521  	colNames []string
  1522  	colTyps  []fieldDesc
  1523  	colFmts  []format
  1524  }
  1525  
  1526  type rows struct {
  1527  	cn     *conn
  1528  	finish func()
  1529  	rowsHeader
  1530  	done   bool
  1531  	rb     readBuf
  1532  	result driver.Result
  1533  	tag    string
  1534  
  1535  	next *rowsHeader
  1536  }
  1537  
  1538  func (rs *rows) Close() error {
  1539  	if finish := rs.finish; finish != nil {
  1540  		defer finish()
  1541  	}
  1542  	// no need to look at cn.bad as Next() will
  1543  	for {
  1544  		err := rs.Next(nil)
  1545  		switch err {
  1546  		case nil:
  1547  		case io.EOF:
  1548  			// rs.Next can return io.EOF on both 'Z' (ready for query) and 'T' (row
  1549  			// description, used with HasNextResultSet). We need to fetch messages until
  1550  			// we hit a 'Z', which is done by waiting for done to be set.
  1551  			if rs.done {
  1552  				return nil
  1553  			}
  1554  		default:
  1555  			return err
  1556  		}
  1557  	}
  1558  }
  1559  
  1560  func (rs *rows) Columns() []string {
  1561  	return rs.colNames
  1562  }
  1563  
  1564  func (rs *rows) Result() driver.Result {
  1565  	if rs.result == nil {
  1566  		return emptyRows
  1567  	}
  1568  	return rs.result
  1569  }
  1570  
  1571  func (rs *rows) Tag() string {
  1572  	return rs.tag
  1573  }
  1574  
  1575  func (rs *rows) Next(dest []driver.Value) (err error) {
  1576  	if rs.done {
  1577  		return io.EOF
  1578  	}
  1579  
  1580  	conn := rs.cn
  1581  	if err := conn.err.getForNext(); err != nil {
  1582  		return err
  1583  	}
  1584  	defer conn.errRecover(&err)
  1585  
  1586  	for {
  1587  		t := conn.recv1Buf(&rs.rb)
  1588  		switch t {
  1589  		case 'E':
  1590  			err = parseError(&rs.rb)
  1591  		case 'C', 'I':
  1592  			if t == 'C' {
  1593  				rs.result, rs.tag = conn.parseComplete(rs.rb.string())
  1594  			}
  1595  			continue
  1596  		case 'Z':
  1597  			conn.processReadyForQuery(&rs.rb)
  1598  			rs.done = true
  1599  			if err != nil {
  1600  				return err
  1601  			}
  1602  			return io.EOF
  1603  		case 'D':
  1604  			n := rs.rb.int16()
  1605  			if err != nil {
  1606  				conn.err.set(driver.ErrBadConn)
  1607  				errorf("unexpected DataRow after error %s", err)
  1608  			}
  1609  			if n < len(dest) {
  1610  				dest = dest[:n]
  1611  			}
  1612  			for i := range dest {
  1613  				l := rs.rb.int32()
  1614  				if l == -1 {
  1615  					dest[i] = nil
  1616  					continue
  1617  				}
  1618  				dest[i] = decode(&conn.parameterStatus, rs.rb.next(l), rs.colTyps[i].OID, rs.colFmts[i])
  1619  			}
  1620  			return
  1621  		case 'T':
  1622  			next := parsePortalRowDescribe(&rs.rb)
  1623  			rs.next = &next
  1624  			return io.EOF
  1625  		default:
  1626  			errorf("unexpected message after execute: %q", t)
  1627  		}
  1628  	}
  1629  }
  1630  
  1631  func (rs *rows) HasNextResultSet() bool {
  1632  	hasNext := rs.next != nil && !rs.done
  1633  	return hasNext
  1634  }
  1635  
  1636  func (rs *rows) NextResultSet() error {
  1637  	if rs.next == nil {
  1638  		return io.EOF
  1639  	}
  1640  	rs.rowsHeader = *rs.next
  1641  	rs.next = nil
  1642  	return nil
  1643  }
  1644  
  1645  // QuoteIdentifier quotes an "identifier" (e.g. a table or a column name) to be
  1646  // used as part of an SQL statement.  For example:
  1647  //
  1648  //	tblname := "my_table"
  1649  //	data := "my_data"
  1650  //	quoted := pq.QuoteIdentifier(tblname)
  1651  //	err := db.Exec(fmt.Sprintf("INSERT INTO %s VALUES ($1)", quoted), data)
  1652  //
  1653  // Any double quotes in name will be escaped.  The quoted identifier will be
  1654  // case sensitive when used in a query.  If the input string contains a zero
  1655  // byte, the result will be truncated immediately before it.
  1656  func QuoteIdentifier(name string) string {
  1657  	end := strings.IndexRune(name, 0)
  1658  	if end > -1 {
  1659  		name = name[:end]
  1660  	}
  1661  	return `"` + strings.Replace(name, `"`, `""`, -1) + `"`
  1662  }
  1663  
  1664  // BufferQuoteIdentifier satisfies the same purpose as QuoteIdentifier, but backed by a
  1665  // byte buffer.
  1666  func BufferQuoteIdentifier(name string, buffer *bytes.Buffer) {
  1667  	end := strings.IndexRune(name, 0)
  1668  	if end > -1 {
  1669  		name = name[:end]
  1670  	}
  1671  	buffer.WriteRune('"')
  1672  	buffer.WriteString(strings.Replace(name, `"`, `""`, -1))
  1673  	buffer.WriteRune('"')
  1674  }
  1675  
  1676  // QuoteLiteral quotes a 'literal' (e.g. a parameter, often used to pass literal
  1677  // to DDL and other statements that do not accept parameters) to be used as part
  1678  // of an SQL statement.  For example:
  1679  //
  1680  //	exp_date := pq.QuoteLiteral("2023-01-05 15:00:00Z")
  1681  //	err := db.Exec(fmt.Sprintf("CREATE ROLE my_user VALID UNTIL %s", exp_date))
  1682  //
  1683  // Any single quotes in name will be escaped. Any backslashes (i.e. "\") will be
  1684  // replaced by two backslashes (i.e. "\\") and the C-style escape identifier
  1685  // that PostgreSQL provides ('E') will be prepended to the string.
  1686  func QuoteLiteral(literal string) string {
  1687  	// This follows the PostgreSQL internal algorithm for handling quoted literals
  1688  	// from libpq, which can be found in the "PQEscapeStringInternal" function,
  1689  	// which is found in the libpq/fe-exec.c source file:
  1690  	// https://git.postgresql.org/gitweb/?p=postgresql.git;a=blob;f=src/interfaces/libpq/fe-exec.c
  1691  	//
  1692  	// substitute any single-quotes (') with two single-quotes ('')
  1693  	literal = strings.Replace(literal, `'`, `''`, -1)
  1694  	// determine if the string has any backslashes (\) in it.
  1695  	// if it does, replace any backslashes (\) with two backslashes (\\)
  1696  	// then, we need to wrap the entire string with a PostgreSQL
  1697  	// C-style escape. Per how "PQEscapeStringInternal" handles this case, we
  1698  	// also add a space before the "E"
  1699  	if strings.Contains(literal, `\`) {
  1700  		literal = strings.Replace(literal, `\`, `\\`, -1)
  1701  		literal = ` E'` + literal + `'`
  1702  	} else {
  1703  		// otherwise, we can just wrap the literal with a pair of single quotes
  1704  		literal = `'` + literal + `'`
  1705  	}
  1706  	return literal
  1707  }
  1708  
  1709  func md5s(s string) string {
  1710  	h := md5.New()
  1711  	h.Write([]byte(s))
  1712  	return fmt.Sprintf("%x", h.Sum(nil))
  1713  }
  1714  
  1715  func (cn *conn) sendBinaryParameters(b *writeBuf, args []driver.Value) {
  1716  	// Do one pass over the parameters to see if we're going to send any of
  1717  	// them over in binary.  If we are, create a paramFormats array at the
  1718  	// same time.
  1719  	var paramFormats []int
  1720  	for i, x := range args {
  1721  		_, ok := x.([]byte)
  1722  		if ok {
  1723  			if paramFormats == nil {
  1724  				paramFormats = make([]int, len(args))
  1725  			}
  1726  			paramFormats[i] = 1
  1727  		}
  1728  	}
  1729  	if paramFormats == nil {
  1730  		b.int16(0)
  1731  	} else {
  1732  		b.int16(len(paramFormats))
  1733  		for _, x := range paramFormats {
  1734  			b.int16(x)
  1735  		}
  1736  	}
  1737  
  1738  	b.int16(len(args))
  1739  	for _, x := range args {
  1740  		if x == nil {
  1741  			b.int32(-1)
  1742  		} else {
  1743  			datum := binaryEncode(&cn.parameterStatus, x)
  1744  			b.int32(len(datum))
  1745  			b.bytes(datum)
  1746  		}
  1747  	}
  1748  }
  1749  
  1750  func (cn *conn) sendBinaryModeQuery(query string, args []driver.Value) {
  1751  	if len(args) >= 65536 {
  1752  		errorf("got %d parameters but PostgreSQL only supports 65535 parameters", len(args))
  1753  	}
  1754  
  1755  	b := cn.writeBuf('P')
  1756  	b.byte(0) // unnamed statement
  1757  	b.string(query)
  1758  	b.int16(0)
  1759  
  1760  	b.next('B')
  1761  	b.int16(0) // unnamed portal and statement
  1762  	cn.sendBinaryParameters(b, args)
  1763  	b.bytes(colFmtDataAllText)
  1764  
  1765  	b.next('D')
  1766  	b.byte('P')
  1767  	b.byte(0) // unnamed portal
  1768  
  1769  	b.next('E')
  1770  	b.byte(0)
  1771  	b.int32(0)
  1772  
  1773  	b.next('S')
  1774  	cn.send(b)
  1775  }
  1776  
  1777  func (cn *conn) processParameterStatus(r *readBuf) {
  1778  	var err error
  1779  
  1780  	param := r.string()
  1781  	switch param {
  1782  	case "server_version":
  1783  		var major1 int
  1784  		var major2 int
  1785  		_, err = fmt.Sscanf(r.string(), "%d.%d", &major1, &major2)
  1786  		if err == nil {
  1787  			cn.parameterStatus.serverVersion = major1*10000 + major2*100
  1788  		}
  1789  
  1790  	case "TimeZone":
  1791  		cn.parameterStatus.currentLocation, err = time.LoadLocation(r.string())
  1792  		if err != nil {
  1793  			cn.parameterStatus.currentLocation = nil
  1794  		}
  1795  
  1796  	default:
  1797  		// ignore
  1798  	}
  1799  }
  1800  
  1801  func (cn *conn) processReadyForQuery(r *readBuf) {
  1802  	cn.txnStatus = transactionStatus(r.byte())
  1803  }
  1804  
  1805  func (cn *conn) readReadyForQuery() {
  1806  	t, r := cn.recv1()
  1807  	switch t {
  1808  	case 'Z':
  1809  		cn.processReadyForQuery(r)
  1810  		return
  1811  	default:
  1812  		cn.err.set(driver.ErrBadConn)
  1813  		errorf("unexpected message %q; expected ReadyForQuery", t)
  1814  	}
  1815  }
  1816  
  1817  func (cn *conn) processBackendKeyData(r *readBuf) {
  1818  	cn.processID = r.int32()
  1819  	cn.secretKey = r.int32()
  1820  }
  1821  
  1822  func (cn *conn) readParseResponse() {
  1823  	t, r := cn.recv1()
  1824  	switch t {
  1825  	case '1':
  1826  		return
  1827  	case 'E':
  1828  		err := parseError(r)
  1829  		cn.readReadyForQuery()
  1830  		panic(err)
  1831  	default:
  1832  		cn.err.set(driver.ErrBadConn)
  1833  		errorf("unexpected Parse response %q", t)
  1834  	}
  1835  }
  1836  
  1837  func (cn *conn) readStatementDescribeResponse() (
  1838  	paramTyps []oid.Oid,
  1839  	colNames []string,
  1840  	colTyps []fieldDesc,
  1841  ) {
  1842  	for {
  1843  		t, r := cn.recv1()
  1844  		switch t {
  1845  		case 't':
  1846  			nparams := r.int16()
  1847  			paramTyps = make([]oid.Oid, nparams)
  1848  			for i := range paramTyps {
  1849  				paramTyps[i] = r.oid()
  1850  			}
  1851  		case 'n':
  1852  			return paramTyps, nil, nil
  1853  		case 'T':
  1854  			colNames, colTyps = parseStatementRowDescribe(r)
  1855  			return paramTyps, colNames, colTyps
  1856  		case 'E':
  1857  			err := parseError(r)
  1858  			cn.readReadyForQuery()
  1859  			panic(err)
  1860  		default:
  1861  			cn.err.set(driver.ErrBadConn)
  1862  			errorf("unexpected Describe statement response %q", t)
  1863  		}
  1864  	}
  1865  }
  1866  
  1867  func (cn *conn) readPortalDescribeResponse() rowsHeader {
  1868  	t, r := cn.recv1()
  1869  	switch t {
  1870  	case 'T':
  1871  		return parsePortalRowDescribe(r)
  1872  	case 'n':
  1873  		return rowsHeader{}
  1874  	case 'E':
  1875  		err := parseError(r)
  1876  		cn.readReadyForQuery()
  1877  		panic(err)
  1878  	default:
  1879  		cn.err.set(driver.ErrBadConn)
  1880  		errorf("unexpected Describe response %q", t)
  1881  	}
  1882  	panic("not reached")
  1883  }
  1884  
  1885  func (cn *conn) readBindResponse() {
  1886  	t, r := cn.recv1()
  1887  	switch t {
  1888  	case '2':
  1889  		return
  1890  	case 'E':
  1891  		err := parseError(r)
  1892  		cn.readReadyForQuery()
  1893  		panic(err)
  1894  	default:
  1895  		cn.err.set(driver.ErrBadConn)
  1896  		errorf("unexpected Bind response %q", t)
  1897  	}
  1898  }
  1899  
  1900  func (cn *conn) postExecuteWorkaround() {
  1901  	// Work around a bug in sql.DB.QueryRow: in Go 1.2 and earlier it ignores
  1902  	// any errors from rows.Next, which masks errors that happened during the
  1903  	// execution of the query.  To avoid the problem in common cases, we wait
  1904  	// here for one more message from the database.  If it's not an error the
  1905  	// query will likely succeed (or perhaps has already, if it's a
  1906  	// CommandComplete), so we push the message into the conn struct; recv1
  1907  	// will return it as the next message for rows.Next or rows.Close.
  1908  	// However, if it's an error, we wait until ReadyForQuery and then return
  1909  	// the error to our caller.
  1910  	for {
  1911  		t, r := cn.recv1()
  1912  		switch t {
  1913  		case 'E':
  1914  			err := parseError(r)
  1915  			cn.readReadyForQuery()
  1916  			panic(err)
  1917  		case 'C', 'D', 'I':
  1918  			// the query didn't fail, but we can't process this message
  1919  			cn.saveMessage(t, r)
  1920  			return
  1921  		default:
  1922  			cn.err.set(driver.ErrBadConn)
  1923  			errorf("unexpected message during extended query execution: %q", t)
  1924  		}
  1925  	}
  1926  }
  1927  
  1928  // Only for Exec(), since we ignore the returned data
  1929  func (cn *conn) readExecuteResponse(
  1930  	protocolState string,
  1931  ) (res driver.Result, commandTag string, err error) {
  1932  	for {
  1933  		t, r := cn.recv1()
  1934  		switch t {
  1935  		case 'C':
  1936  			if err != nil {
  1937  				cn.err.set(driver.ErrBadConn)
  1938  				errorf("unexpected CommandComplete after error %s", err)
  1939  			}
  1940  			res, commandTag = cn.parseComplete(r.string())
  1941  		case 'Z':
  1942  			cn.processReadyForQuery(r)
  1943  			if res == nil && err == nil {
  1944  				err = errUnexpectedReady
  1945  			}
  1946  			return res, commandTag, err
  1947  		case 'E':
  1948  			err = parseError(r)
  1949  		case 'T', 'D', 'I':
  1950  			if err != nil {
  1951  				cn.err.set(driver.ErrBadConn)
  1952  				errorf("unexpected %q after error %s", t, err)
  1953  			}
  1954  			if t == 'I' {
  1955  				res = emptyRows
  1956  			}
  1957  			// ignore any results
  1958  		default:
  1959  			cn.err.set(driver.ErrBadConn)
  1960  			errorf("unknown %s response: %q", protocolState, t)
  1961  		}
  1962  	}
  1963  }
  1964  
  1965  func parseStatementRowDescribe(r *readBuf) (colNames []string, colTyps []fieldDesc) {
  1966  	n := r.int16()
  1967  	colNames = make([]string, n)
  1968  	colTyps = make([]fieldDesc, n)
  1969  	for i := range colNames {
  1970  		colNames[i] = r.string()
  1971  		r.next(6)
  1972  		colTyps[i].OID = r.oid()
  1973  		colTyps[i].Len = r.int16()
  1974  		colTyps[i].Mod = r.int32()
  1975  		// format code not known when describing a statement; always 0
  1976  		r.next(2)
  1977  	}
  1978  	return
  1979  }
  1980  
  1981  func parsePortalRowDescribe(r *readBuf) rowsHeader {
  1982  	n := r.int16()
  1983  	colNames := make([]string, n)
  1984  	colFmts := make([]format, n)
  1985  	colTyps := make([]fieldDesc, n)
  1986  	for i := range colNames {
  1987  		colNames[i] = r.string()
  1988  		r.next(6)
  1989  		colTyps[i].OID = r.oid()
  1990  		colTyps[i].Len = r.int16()
  1991  		colTyps[i].Mod = r.int32()
  1992  		colFmts[i] = format(r.int16())
  1993  	}
  1994  	return rowsHeader{
  1995  		colNames: colNames,
  1996  		colFmts:  colFmts,
  1997  		colTyps:  colTyps,
  1998  	}
  1999  }
  2000  
  2001  // parseEnviron tries to mimic some of libpq's environment handling
  2002  //
  2003  // To ease testing, it does not directly reference os.Environ, but is
  2004  // designed to accept its output.
  2005  //
  2006  // Environment-set connection information is intended to have a higher
  2007  // precedence than a library default but lower than any explicitly
  2008  // passed information (such as in the URL or connection string).
  2009  func parseEnviron(env []string) (out map[string]string) {
  2010  	out = make(map[string]string)
  2011  
  2012  	for _, v := range env {
  2013  		parts := strings.SplitN(v, "=", 2)
  2014  
  2015  		accrue := func(keyname string) {
  2016  			out[keyname] = parts[1]
  2017  		}
  2018  		unsupported := func() {
  2019  			panic(fmt.Sprintf("setting %v not supported", parts[0]))
  2020  		}
  2021  
  2022  		// The order of these is the same as is seen in the
  2023  		// PostgreSQL 9.1 manual. Unsupported but well-defined
  2024  		// keys cause a panic; these should be unset prior to
  2025  		// execution. Options which pq expects to be set to a
  2026  		// certain value are allowed, but must be set to that
  2027  		// value if present (they can, of course, be absent).
  2028  		switch parts[0] {
  2029  		case "PGHOST":
  2030  			accrue("host")
  2031  		case "PGHOSTADDR":
  2032  			unsupported()
  2033  		case "PGPORT":
  2034  			accrue("port")
  2035  		case "PGDATABASE":
  2036  			accrue("dbname")
  2037  		case "PGUSER":
  2038  			accrue("user")
  2039  		case "PGPASSWORD":
  2040  			accrue("password")
  2041  		case "PGSERVICE", "PGSERVICEFILE", "PGREALM":
  2042  			unsupported()
  2043  		case "PGOPTIONS":
  2044  			accrue("options")
  2045  		case "PGAPPNAME":
  2046  			accrue("application_name")
  2047  		case "PGSSLMODE":
  2048  			accrue("sslmode")
  2049  		case "PGSSLCERT":
  2050  			accrue("sslcert")
  2051  		case "PGSSLKEY":
  2052  			accrue("sslkey")
  2053  		case "PGSSLROOTCERT":
  2054  			accrue("sslrootcert")
  2055  		case "PGSSLSNI":
  2056  			accrue("sslsni")
  2057  		case "PGREQUIRESSL", "PGSSLCRL":
  2058  			unsupported()
  2059  		case "PGREQUIREPEER":
  2060  			unsupported()
  2061  		case "PGKRBSRVNAME", "PGGSSLIB":
  2062  			unsupported()
  2063  		case "PGCONNECT_TIMEOUT":
  2064  			accrue("connect_timeout")
  2065  		case "PGCLIENTENCODING":
  2066  			accrue("client_encoding")
  2067  		case "PGDATESTYLE":
  2068  			accrue("datestyle")
  2069  		case "PGTZ":
  2070  			accrue("timezone")
  2071  		case "PGGEQO":
  2072  			accrue("geqo")
  2073  		case "PGSYSCONFDIR", "PGLOCALEDIR":
  2074  			unsupported()
  2075  		}
  2076  	}
  2077  
  2078  	return out
  2079  }
  2080  
  2081  // isUTF8 returns whether name is a fuzzy variation of the string "UTF-8".
  2082  func isUTF8(name string) bool {
  2083  	// Recognize all sorts of silly things as "UTF-8", like Postgres does
  2084  	s := strings.Map(alnumLowerASCII, name)
  2085  	return s == "utf8" || s == "unicode"
  2086  }
  2087  
  2088  func alnumLowerASCII(ch rune) rune {
  2089  	if 'A' <= ch && ch <= 'Z' {
  2090  		return ch + ('a' - 'A')
  2091  	}
  2092  	if 'a' <= ch && ch <= 'z' || '0' <= ch && ch <= '9' {
  2093  		return ch
  2094  	}
  2095  	return -1 // discard
  2096  }
  2097  
  2098  // The database/sql/driver package says:
  2099  // All Conn implementations should implement the following interfaces: Pinger, SessionResetter, and Validator.
  2100  var _ driver.Pinger = &conn{}
  2101  var _ driver.SessionResetter = &conn{}
  2102  
  2103  func (cn *conn) ResetSession(ctx context.Context) error {
  2104  	// Ensure bad connections are reported: From database/sql/driver:
  2105  	// If a connection is never returned to the connection pool but immediately reused, then
  2106  	// ResetSession is called prior to reuse but IsValid is not called.
  2107  	return cn.err.get()
  2108  }
  2109  
  2110  func (cn *conn) IsValid() bool {
  2111  	return cn.err.get() == nil
  2112  }
  2113  

View as plain text