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