func (cn *conn) Query(query string, args []driver.Value) (_ driver.Rows, err error) {
	defer errRecover(&err)
	if len(args) == 0 {
		return cn.simpleQuery(query)
	}
	st, err := cn.prepareToSimpleStmt(query, "")
	if err != nil {
		panic(err)
	}
	st.exec(args)
	return &rows{st: st}, nil
}
Implement the "Queryer" interface
package pq
import (
	"bufio"
	"crypto/md5"
	"crypto/tls"
	"database/sql"
	"database/sql/driver"
	"encoding/binary"
	"errors"
	"fmt"
	"github.com/lib/pq/oid"
	"io"
	"net"
	"os"
	"path"
	"strconv"
	"strings"
	"time"
	"unicode"
)
var (
	ErrSSLNotSupported     = errors.New("pq: SSL is not enabled on the server")
	ErrNotSupported        = errors.New("pq: Unsupported command")
	ErrInFailedTransaction = errors.New("pq: Could not complete operation in a failed transaction")
)
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 conn struct {
	c         net.Conn
	buf       *bufio.Reader
	namei     int
	scratch   [512]byte
	txnStatus transactionStatus
	parameterStatus parameterStatus
	saveMessageType   byte
	saveMessageBuffer *readBuf
}
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) {
	defer errRecover(&err)
	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)
		}
	}
	o.Unset("fallback_application_name")
	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(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(o values) (net.Conn, error) {
	ntw, addr := network(o)
	timeout := o.Get("connect_timeout")
	o.Unset("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 := net.DialTimeout(ntw, addr, duration)
		if err != nil {
			return nil, err
		}
		err = conn.SetDeadline(deadline)
		return conn, err
	}
	return net.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
}
func (vs values) Unset(k string) {
	delete(vs, k)
}
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 {
		errorf("unexpected transaction status %v", cn.txnStatus)
	}
}
func (cn *conn) Begin() (_ driver.Tx, err error) {
	defer errRecover(&err)
	cn.checkIsInTransaction(false)
	_, commandTag, err := cn.simpleExec("BEGIN")
	if err != nil {
		return nil, err
	}
	if commandTag != "BEGIN" {
		return nil, fmt.Errorf("unexpected command tag %s", commandTag)
	}
	if cn.txnStatus != txnStatusIdleInTransaction {
		return nil, fmt.Errorf("unexpected transaction status %v", cn.txnStatus)
	}
	return cn, nil
}
func (cn *conn) Commit() (err error) {
	defer 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" {
		return fmt.Errorf("unexpected command tag %s", commandTag)
	}
	cn.checkIsInTransaction(false)
	return nil
}
func (cn *conn) Rollback() (err error) {
	defer 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) {
	defer errRecover(&err)
	b := cn.writeBuf('Q')
	b.string(q)
	cn.send(b)
	for {
		t, r := cn.recv1()
		switch t {
		case 'C':
			res, commandTag = parseComplete(r.string())
		case 'Z':
			cn.processReadyForQuery(r)
			// done
			return
		case 'E':
			err = parseError(r)
		case 'T', 'D':
			// ignore any results
		default:
			errorf("unknown response for simple query: %q", t)
		}
	}
	panic("not reached")
}
func (cn *conn) simpleQuery(q string) (res driver.Rows, err error) {
	defer errRecover(&err)
	st := &stmt{cn: cn, name: "", query: q}
	b := cn.writeBuf('Q')
	b.string(q)
	cn.send(b)
	for {
		t, r := cn.recv1()
		switch t {
		case 'C':
			// 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 {
				errorf("unexpected CommandComplete in simple query execution")
			}
			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 {
				errorf("unexpected DataRow in simple query execution")
			}
			// the query didn't fail; kick off to Next
			cn.saveMessage(t, r)
			return
		case 'T':
			if res != nil {
				errorf("unexpected RowDescription in simple query execution")
			}
			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:
			errorf("unknown response for simple query: %q", t)
		}
	}
	panic("not reached")
}
func (cn *conn) prepareTo(q, stmtName string) (_ driver.Stmt, err error) {
	return cn.prepareToSimpleStmt(q, stmtName)
}
func (cn *conn) prepareToSimpleStmt(q, stmtName string) (_ *stmt, err error) {
	defer errRecover(&err)
	st := &stmt{cn: cn, name: stmtName, query: q}
	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 := int(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:
			errorf("unexpected describe rows response: %q", t)
		}
	}
	panic("not reached")
}
func (cn *conn) Prepare(q string) (driver.Stmt, error) {
	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) {
	defer 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