func (cn *conn) setupSSLClientCertificates(tlsConf *tls.Config, o values) {
	var missingOk bool
	sslkey := o.Get("sslkey")
	sslcert := o.Get("sslcert")
	if sslkey != "" && sslcert != "" {
		missingOk = false
	} else {
		user, err := user.Current()
		if err != nil {
			return
		}
		sslkey = filepath.Join(user.HomeDir, ".postgresql", "postgresql.key")
		sslcert = filepath.Join(user.HomeDir, ".postgresql", "postgresql.crt")
		missingOk = true
	}
	keyfinfo, err := os.Stat(sslkey)
	if err != nil && missingOk {
		return
	} else if err != nil {
		panic(err)
	}
	_, err = os.Stat(sslcert)
	if err != nil && missingOk {
		return
	} else if err != nil {
		panic(err)
	}
	kmode := keyfinfo.Mode()
	if kmode != kmode&0600 {
		panic(ErrSSLKeyHasWorldPermissions)
	}
	cert, err := tls.LoadX509KeyPair(sslcert, sslkey)
	if err != nil {
		panic(err)
	}
	tlsConf.Certificates = []tls.Certificate{cert}
}
This function sets up SSL client certificates based on either the "sslkey"
and "sslcert" settings (possibly set via the environment variables PGSSLKEY
and PGSSLCERT, respectively), or if they aren't set, from the .postgresql
directory in the user's home directory.  If the file paths are set
explicitly, the files must exist.  The key file must also not be
world-readable, or this function will panic with
ErrSSLKeyHasWorldPermissions.
package pq
import (
	"bufio"
	"crypto/md5"
	"crypto/tls"
	"crypto/x509"
	"database/sql"
	"database/sql/driver"
	"encoding/binary"
	"errors"
	"fmt"
	"github.com/lib/pq/oid"
	"io"
	"io/ioutil"
	"net"
	"os"
	"os/user"
	"path"
	"path/filepath"
	"strconv"
	"strings"
	"time"
	"unicode"
)
var (
	ErrNotSupported              = errors.New("pq: Unsupported command")
	ErrInFailedTransaction       = errors.New("pq: Could not complete operation in a failed transaction")
	ErrSSLNotSupported           = errors.New("pq: SSL is not enabled on the server")
	ErrSSLKeyHasWorldPermissions = errors.New("pq: Private key file has group or world access. Permissions should be u=rw (0600) or less.")
)
type drv struct{}
func (d *drv) Open(name string) (driver.Conn, error) {
	return Open(name)
}
func init() {
	sql.Register("postgres", &drv{})
}
type parameterStatus struct {
	serverVersion int
	currentLocation *time.Location
}
type transactionStatus byte
const (
	txnStatusIdle                transactionStatus = 'I'
	txnStatusIdleInTransaction   transactionStatus = 'T'
	txnStatusInFailedTransaction transactionStatus = 'E'
)
func (s transactionStatus) String() string {
	switch s {
	case txnStatusIdle:
		return "idle"
	case txnStatusIdleInTransaction:
		return "idle in transaction"
	case txnStatusInFailedTransaction:
		return "in a failed transaction"
	default:
		errorf("unknown transactionStatus %d", s)
	}
	panic("not reached")
}
type Dialer interface {
	Dial(network, address string) (net.Conn, error)
	DialTimeout(network, address string, timeout time.Duration) (net.Conn, error)
}
type defaultDialer struct{}
func (d defaultDialer) Dial(ntw, addr string) (net.Conn, error) {
	return net.Dial(ntw, addr)
}
func (d defaultDialer) DialTimeout(ntw, addr string, timeout time.Duration) (net.Conn, error) {
	return net.DialTimeout(ntw, addr, timeout)
}
type conn struct {
	c         net.Conn
	buf       *bufio.Reader
	namei     int
	scratch   [512]byte
	txnStatus transactionStatus
	parameterStatus parameterStatus
	saveMessageType   byte
	saveMessageBuffer []byte
	bad bool
}
func (c *conn) writeBuf(b byte) *writeBuf {
	c.scratch[0] = b
	w := writeBuf(c.scratch[:5])
	return &w
}
func Open(name string) (_ driver.Conn, err error) {
	return DialOpen(defaultDialer{}, name)
}
func DialOpen(d Dialer, name string) (_ driver.Conn, err error) {
	defer func() {
		e := recover()
		if e == nil {
			return
		}
		var ok bool
		err, ok = e.(error)
		if !ok {
			err = fmt.Errorf("pq: unexpected error: %#v", e)
		}
	}()
	o := make(values)
	o.Set("host", "localhost")
	o.Set("port", "5432")
	o.Set("extra_float_digits", "2")
	for k, v := range parseEnviron(os.Environ()) {
		o.Set(k, v)
	}
	if strings.HasPrefix(name, "postgres://") {
		name, err = ParseURL(name)
		if err != nil {
			return nil, err
		}
	}
	if err := parseOpts(name, o); err != nil {
		return nil, err
	}
	if fallback := o.Get("fallback_application_name"); fallback != "" {
		if !o.Isset("application_name") {
			o.Set("application_name", fallback)
		}
	}
	if enc := o.Get("client_encoding"); enc != "" && !isUTF8(enc) {
		return nil, errors.New("client_encoding must be absent or 'UTF8'")
	}
	o.Set("client_encoding", "UTF8")
	if datestyle := o.Get("datestyle"); datestyle != "" {
		if datestyle != "ISO, MDY" {
			panic(fmt.Sprintf("setting datestyle must be absent or %v; got %v",
				"ISO, MDY", datestyle))
		}
	} else {
		o.Set("datestyle", "ISO, MDY")
	}
	if o.Get("user") == "" {
		u, err := userCurrent()
		if err != nil {
			return nil, err
		} else {
			o.Set("user", u)
		}
	}
	c, err := dial(d, o)
	if err != nil {
		return nil, err
	}
	cn := &conn{c: c}
	cn.ssl(o)
	cn.buf = bufio.NewReader(cn.c)
	cn.startup(o)
	err = cn.c.SetDeadline(time.Time{})
	return cn, err
}
func dial(d Dialer, o values) (net.Conn, error) {
	ntw, addr := network(o)
	timeout := o.Get("connect_timeout")
	if timeout != "" && timeout != "0" {
		seconds, err := strconv.ParseInt(timeout, 10, 0)
		if err != nil {
			return nil, fmt.Errorf("invalid value for parameter connect_timeout: %s", err)
		}
		duration := time.Duration(seconds) * time.Second
		deadline := time.Now().Add(duration)
		conn, err := d.DialTimeout(ntw, addr, duration)
		if err != nil {
			return nil, err
		}
		err = conn.SetDeadline(deadline)
		return conn, err
	}
	return d.Dial(ntw, addr)
}
func network(o values) (string, string) {
	host := o.Get("host")
	if strings.HasPrefix(host, "/") {
		sockPath := path.Join(host, ".s.PGSQL."+o.Get("port"))
		return "unix", sockPath
	}
	return "tcp", host + ":" + o.Get("port")
}
type values map[string]string
func (vs values) Set(k, v string) {
	vs[k] = v
}
func (vs values) Get(k string) (v string) {
	return vs[k]
}
func (vs values) Isset(k string) bool {
	_, ok := vs[k]
	return ok
}
type scanner struct {
	s []rune
	i int
}
func newScanner(s string) *scanner {
	return &scanner{[]rune(s), 0}
}
func (s *scanner) Next() (rune, bool) {
	if s.i >= len(s.s) {
		return 0, false
	}
	r := s.s[s.i]
	s.i++
	return r, true
}
func (s *scanner) SkipSpaces() (rune, bool) {
	r, ok := s.Next()
	for unicode.IsSpace(r) && ok {
		r, ok = s.Next()
	}
	return r, ok
}
func parseOpts(name string, o values) error {
	s := newScanner(name)
	for {
		var (
			keyRunes, valRunes []rune
			r                  rune
			ok                 bool
		)
		if r, ok = s.SkipSpaces(); !ok {
			break
		}
		for !unicode.IsSpace(r) && r != '=' {
			keyRunes = append(keyRunes, r)
			if r, ok = s.Next(); !ok {
				break
			}
		}
		if r != '=' {
			r, ok = s.SkipSpaces()
		}
		if r != '=' || !ok {
			return fmt.Errorf(`missing "=" after %q in connection info string"`, string(keyRunes))
		}
		// Skip any whitespace after the =
		if r, ok = s.SkipSpaces(); !ok {
			// If we reach the end here, the last value is just an empty string as per libpq.
			o.Set(string(keyRunes), "")
			break
		}
		if r != '\'' {
			for !unicode.IsSpace(r) {
				if r == '\\' {
					if r, ok = s.Next(); !ok {
						return fmt.Errorf(`missing character after backslash`)
					}
				}
				valRunes = append(valRunes, r)
				if r, ok = s.Next(); !ok {
					break
				}
			}
		} else {
		quote:
			for {
				if r, ok = s.Next(); !ok {
					return fmt.Errorf(`unterminated quoted string literal in connection string`)
				}
				switch r {
				case '\'':
					break quote
				case '\\':
					r, _ = s.Next()
					fallthrough
				default:
					valRunes = append(valRunes, r)
				}
			}
		}
		o.Set(string(keyRunes), string(valRunes))
	}
	return nil
}
func (cn *conn) isInTransaction() bool {
	return cn.txnStatus == txnStatusIdleInTransaction ||
		cn.txnStatus == txnStatusInFailedTransaction
}
func (cn *conn) checkIsInTransaction(intxn bool) {
	if cn.isInTransaction() != intxn {
		cn.bad = true
		errorf("unexpected transaction status %v", cn.txnStatus)
	}
}
func (cn *conn) Begin() (_ driver.Tx, err error) {
	if cn.bad {
		return nil, driver.ErrBadConn
	}
	defer cn.errRecover(&err)
	cn.checkIsInTransaction(false)
	_, commandTag, err := cn.simpleExec("BEGIN")
	if err != nil {
		return nil, err
	}
	if commandTag != "BEGIN" {
		cn.bad = true
		return nil, fmt.Errorf("unexpected command tag %s", commandTag)
	}
	if cn.txnStatus != txnStatusIdleInTransaction {
		cn.bad = true
		return nil, fmt.Errorf("unexpected transaction status %v", cn.txnStatus)
	}
	return cn, nil
}
func (cn *conn) Commit() (err error) {
	if cn.bad {
		return driver.ErrBadConn
	}
	defer cn.errRecover(&err)
	cn.checkIsInTransaction(true)
	// We don't want the client to think that everything is okay if it tries
	// to commit a failed transaction.  However, no matter what we return,
	// database/sql will release this connection back into the free connection
	// pool so we have to abort the current transaction here.  Note that you
	// would get the same behaviour if you issued a COMMIT in a failed
	// transaction, so it's also the least surprising thing to do here.
	if cn.txnStatus == txnStatusInFailedTransaction {
		if err := cn.Rollback(); err != nil {
			return err
		}
		return ErrInFailedTransaction
	}
	_, commandTag, err := cn.simpleExec("COMMIT")
	if err != nil {
		return err
	}
	if commandTag != "COMMIT" {
		cn.bad = true
		return fmt.Errorf("unexpected command tag %s", commandTag)
	}
	cn.checkIsInTransaction(false)
	return nil
}
func (cn *conn) Rollback() (err error) {
	if cn.bad {
		return driver.ErrBadConn
	}
	defer cn.errRecover(&err)
	cn.checkIsInTransaction(true)
	_, commandTag, err := cn.simpleExec("ROLLBACK")
	if err != nil {
		return err
	}
	if commandTag != "ROLLBACK" {
		return fmt.Errorf("unexpected command tag %s", commandTag)
	}
	cn.checkIsInTransaction(false)
	return nil
}
func (cn *conn) gname() string {
	cn.namei++
	return strconv.FormatInt(int64(cn.namei), 10)
}
func (cn *conn) simpleExec(q string) (res driver.Result, commandTag string, err error) {
	b := cn.writeBuf('Q')
	b.string(q)
	cn.send(b)
	for {
		t, r := cn.recv1()
		switch t {
		case 'C':
			res, commandTag = cn.parseComplete(r.string())
		case 'Z':
			cn.processReadyForQuery(r)
			// done
			return
		case 'E':
			err = parseError(r)
		case 'T', 'D', 'I':
			// ignore any results
		default:
			cn.bad = true
			errorf("unknown response for simple query: %q", t)
		}
	}
	panic("not reached")
}
func (cn *conn) simpleQuery(q string) (res driver.Rows, err error) {
	defer cn.errRecover(&err)
	st := &stmt{cn: cn, name: ""}
	b := cn.writeBuf('Q')
	b.string(q)
	cn.send(b)
	for {
		t, r := cn.recv1()
		switch t {
		case 'C', 'I':
			// We allow queries which don't return any results through Query as
			// well as Exec.  We still have to give database/sql a rows object
			// the user can close, though, to avoid connections from being
			// leaked.  A "rows" with done=true works fine for that purpose.
			if err != nil {
				cn.bad = true
				errorf("unexpected message %q in simple query execution", t)
			}
			res = &rows{st: st, done: true}
		case 'Z':
			cn.processReadyForQuery(r)
			// done
			return
		case 'E':
			res = nil
			err = parseError(r)
		case 'D':
			if res == nil {
				cn.bad = true
				errorf("unexpected DataRow in simple query execution")
			}
			// the query didn't fail; kick off to Next
			cn.saveMessage(t, r)
			return
		case 'T':
			// res might be non-nil here if we received a previous
			// CommandComplete, but that's fine; just overwrite it
			res = &rows{st: st}
			st.cols, st.rowTyps = parseMeta(r)
			// To work around a bug in QueryRow in Go 1.2 and earlier, wait
			// until the first DataRow has been received.
		default:
			cn.bad = true
			errorf("unknown response for simple query: %q", t)
		}
	}
	panic("not reached")
}
func (cn *conn) prepareTo(q, stmtName string) (_ *stmt, err error) {
	st := &stmt{cn: cn, name: stmtName}
	b := cn.writeBuf('P')
	b.string(st.name)
	b.string(q)
	b.int16(0)
	cn.send(b)
	b = cn.writeBuf('D')
	b.byte('S')
	b.string(st.name)
	cn.send(b)
	cn.send(cn.writeBuf('S'))
	for {
		t, r := cn.recv1()
		switch t {
		case '1':
		case 't':
			nparams := r.int16()
			st.paramTyps = make([]oid.Oid, nparams)
			for i := range st.paramTyps {
				st.paramTyps[i] = r.oid()
			}
		case 'T':
			st.cols, st.rowTyps = parseMeta(r)
		case 'n':
			// no data
		case 'Z':
			cn.processReadyForQuery(r)
			return st, err
		case 'E':
			err = parseError(r)
		default:
			cn.bad = true
			errorf("unexpected describe rows response: %q", t)
		}
	}
	panic("not reached")
}
func (cn *conn) Prepare(q string) (_ driver.Stmt, err error) {
	if cn.bad {
		return nil, driver.ErrBadConn
	}
	defer cn.errRecover(&err)
	if len(q) >= 4 && strings.EqualFold(q[:4], "COPY") {
		return cn.prepareCopyIn(q)
	}
	return cn.prepareTo(q, cn.gname())
}
func (cn *conn) Close() (err error) {
	if cn.bad {
		return driver.ErrBadConn
	}
	defer cn.errRecover(&err)
	// Don't go through send(); ListenerConn relies on us not scribbling on the
	// scratch buffer of this connection.
	err = cn.sendSimpleMessage('X')
	if err != nil {
		return err
	}
	return cn.c.Close()
}
// Implement the "Queryer" interface
func (cn *conn) Query(query string, args []driver.Value) (_ driver.Rows, err error) {
	if cn.bad {
		return nil, driver.ErrBadConn
	}
	defer cn.errRecover(&err)
	// Check to see if we can use the "simpleQuery" interface, which is
	// *much* faster than going through prepare/exec
	if len(args) == 0 {
		return cn.simpleQuery(query)
	}
	st, err := cn.prepareTo(query, "")
	if err != nil {
		panic(err)
	}
	st.exec(args)
	return &rows{st: st}, nil
}
// Implement the optional "Execer" interface for one-shot queries
func (cn *conn) Exec(query string, args []driver.Value) (_ driver.Result, err error) {
	if cn.bad {
		return nil, driver.ErrBadConn
	}
	defer cn.errRecover(&err)
	// Check to see if we can use the "simpleExec" interface, which is
	// *much* faster than going through prepare/exec
	if len(args) == 0 {
		// ignore commandTag, our caller doesn't care
		r, _, err := cn.simpleExec(query)
		return r, err
	}
	// Use the unnamed statement to defer planning until bind
	// time, or else value-based selectivity estimates cannot be
	// used.
	st, err := cn.prepareTo(query, "")
	if err != nil {
		panic(err)
	}
	r, err := st.Exec(args)
	if err != nil {
		panic(err)
	}
	return r, err
}
// Assumes len(*m) is > 5
func (cn *conn) send(m *writeBuf) {
	b := (*m)[1:]
	binary.BigEndian.PutUint32(b, uint32(len(b)))
	if (*m)[0] == 0 {
		*m = b
	}
	_, err := cn.c.Write(*m)
	if err != nil {
		panic(err)
	}
}
// Send a message of type typ to the server on the other end of cn.  The
// message should have no payload.  This method does not use the scratch
// buffer.
func (cn *conn) sendSimpleMessage(typ byte) (err error) {
	_, err = cn.c.Write([]byte{typ, '\x00', '\x00', '\x00', '\x04'})
	return err
}
// saveMessage memorizes a message and its buffer in the conn struct.
// recvMessage will then return these values on the next call to it.  This
// method is useful in cases where you have to see what the next message is
// going to be (e.g. to see whether it's an error or not) but you can't handle
// the message yourself.
func (cn *conn) saveMessage(typ byte, buf *readBuf) {
	if cn.saveMessageType != 0 {
		cn.bad = true
		errorf("unexpected saveMessageType %d", cn.saveMessageType)
	}
	cn.saveMessageType = typ
	cn.saveMessageBuffer = *buf
}
// recvMessage receives any message from the backend, or returns an error if
// a problem occurred while reading the message.
func (cn *conn) recvMessage(r *readBuf) (byte, error) {
	// workaround for a QueryRow bug, see exec
	if cn.saveMessageType != 0 {
		t := cn.saveMessageType
		*r = cn.saveMessageBuffer
		cn.saveMessageType = 0
		cn.saveMessageBuffer = nil
		return t, nil
	}
	x := cn.scratch[:5]
	_, err := io.ReadFull(cn.buf, x)
	if err != nil {
		return 0, err
	}
	// read the type and length of the message that follows
	t := x[0]
	n := int(binary.BigEndian.Uint32(x[1:])) - 4
	var y []byte
	if n <= len(cn.scratch) {
		y = cn.scratch[:n]
	} else {
		y = make([]byte, n)
	}
	_, err = io.ReadFull(cn.buf, y)
	if err != nil {
		return 0, err
	}
	*r = y
	return t, nil
}
// recv receives a message from the backend, but if an error happened while
// reading the message or the received message was an ErrorResponse, it panics.
// NoticeResponses are ignored.  This function should generally be used only
// during the startup sequence.
func (cn *conn) recv() (t byte, r *readBuf) {
	for {
		var err error
		r = &readBuf{}
		t, err = cn.recvMessage(r)
		if err != nil {
			panic(err)
		}
		switch t {
		case 'E':
			panic(parseError(r))
		case 'N':
			// ignore
		default:
			return
		}
	}
	panic("not reached")
}
// recv1Buf is exactly equivalent to recv1, except it uses a buffer supplied by
// the caller to avoid an allocation.
func (cn *conn) recv1Buf(r *readBuf) byte {
	for {
		t, err := cn.recvMessage(r)
		if err != nil {
			panic(err)
		}
		switch t {
		case 'A', 'N':
			// ignore
		case 'S':
			cn.processParameterStatus(r)
		default:
			return t
		}
	}
	panic("not reached")
}
// recv1 receives a message from the backend, panicking if an error occurs
// while attempting to read it.  All asynchronous messages are ignored, with
// the exception of ErrorResponse.
func (cn *conn) recv1() (t byte, r *readBuf) {
	r = &readBuf{}
	t = cn.recv1Buf(r)
	return t, r
}
func (cn *conn) ssl(o values) {
	verifyCaOnly := false
	tlsConf := tls.Config{}
	switch mode := o.Get("sslmode"); mode {
	case "require", "":
		tlsConf.InsecureSkipVerify = true
	case "verify-ca":
		// We must skip TLS's own verification since it requires full
		// verification since Go 1.3.
		tlsConf.InsecureSkipVerify = true
		verifyCaOnly = true
	case "verify-full":
		tlsConf.ServerName = o.Get("host")
	case "disable":
		return
	default:
		errorf(`unsupported sslmode %q; only "require" (default), "verify-full", and "disable" supported`, mode)
	}
	cn.setupSSLClientCertificates(&tlsConf, o)
	cn.setupSSLCA(&tlsConf, o)
	w := cn.writeBuf(0)
	w.int32(80877103)
	cn.send(w)
	b := cn.scratch[:1]
	_, err := io.ReadFull(cn.c, b)
	if err != nil {
		panic(err)
	}
	if b[0] != 'S' {
		panic(ErrSSLNotSupported)
	}
	client := tls.Client(cn.c, &tlsConf)
	if verifyCaOnly {
		cn.verifyCA(client, &tlsConf)
	}
	cn.c = client
}
// verifyCA carries out a TLS handshake to the server and verifies the
// presented certificate against the effective CA, i.e. the one specified in
// sslrootcert or the system CA if sslrootcert was not specified.
func (cn *conn) verifyCA(client *tls.Conn, tlsConf *tls.Config) {
	err := client.Handshake()
	if err != nil {
		panic(err)
	}
	certs := client.ConnectionState().PeerCertificates
	opts := x509.VerifyOptions{
		DNSName: client.ConnectionState().ServerName,
		Intermediates: x509.NewCertPool(),
		Roots: tlsConf.RootCAs,
	}
	for i, cert := range certs {
		if i == 0 {
			continue
		}
		opts.Intermediates.AddCert(cert)
	}
	_, err = certs[0].Verify(opts)
	if err != nil {
		panic(err)
	}
}
// This function sets up SSL client certificates based on either the "sslkey"
// and "sslcert" settings (possibly set via the environment variables PGSSLKEY