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
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
46 var (
47 _ driver.Driver = Driver{}
48 )
49
50
51 type Driver struct{}
52
53
54
55
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
66
67 serverVersion int
68
69
70
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
98
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
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
136 dialer Dialer
137 opts values
138
139
140 processID int
141 secretKey int
142
143 parameterStatus parameterStatus
144
145 saveMessageType byte
146 saveMessageBuffer []byte
147
148
149
150
151 err syncErr
152
153
154
155
156 disablePreparedBinaryResult bool
157
158
159
160 binaryParameters bool
161
162
163 inCopy bool
164
165
166 noticeHandler func(*Error)
167
168
169 notificationHandler func(*Notification)
170
171
172 gss GSS
173 }
174
175 type syncErr struct {
176 err error
177 sync.Mutex
178 }
179
180
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
191 func (e *syncErr) getForNext() error {
192 e.Lock()
193 defer e.Unlock()
194 return e.err
195 }
196
197
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
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
233 if _, ok := o["password"]; ok {
234 return
235 }
236 filename := os.Getenv("PGPASSFILE")
237 if filename == "" {
238
239
240
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
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
267 for scanner.Scan() {
268 if scanText(scanner.Text(), o) {
269 break
270 }
271 }
272 }
273
274
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
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
327
328
329 func Open(dsn string) (_ driver.Conn, err error) {
330 return DialOpen(defaultDialer{}, dsn)
331 }
332
333
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
345
346
347
348 defer errRecoverNoErrBadConn(&err)
349
350
351
352
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
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
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
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
412
413
414
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
450 type scanner struct {
451 s []rune
452 i int
453 }
454
455
456 func newScanner(s string) *scanner {
457 return &scanner{[]rune(s), 0}
458 }
459
460
461
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
472
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
482
483
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
499 for !unicode.IsSpace(r) && r != '=' {
500 keyRunes = append(keyRunes, r)
501 if r, ok = s.Next(); !ok {
502 break
503 }
504 }
505
506
507 if r != '=' {
508 r, ok = s.SkipSpaces()
509 }
510
511
512 if r != '=' || !ok {
513 return fmt.Errorf(`missing "=" after %q in connection info string"`, string(keyRunes))
514 }
515
516
517 if r, ok = s.SkipSpaces(); !ok {
518
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
613
614
615
616
617
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
686 return
687 case 'E':
688 err = parseError(r)
689 case 'I':
690 res = emptyRows
691 case 'T', 'D':
692
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
712
713
714
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
725
726
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
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
747 cn.saveMessage(t, r)
748 return
749 case 'T':
750
751
752 res = &rows{cn: cn}
753 res.rowsHeader = parsePortalRowDescribe(r)
754
755
756
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
779
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
797
798
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
870 defer cn.errRecover(&err)
871
872
873
874 defer func() {
875 cerr := cn.c.Close()
876 if err == nil {
877 err = cerr
878 }
879 }()
880
881
882
883 return cn.sendSimpleMessage('X')
884 }
885
886
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
901
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
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
932
933 if len(args) == 0 {
934
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
950
951
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
984
985
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
992
993
994
995
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
1006
1007 func (cn *conn) recvMessage(r *readBuf) (byte, error) {
1008
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
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
1041
1042
1043
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
1070
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
1096
1097
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
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
1136
1137
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
1167
1168
1169
1170 for k, v := range o {
1171 if isDriverSetting(k) {
1172
1173 continue
1174 }
1175
1176
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
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:
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
1250 token, err = cli.GetInitTokenFromSpn(spn)
1251 } else {
1252
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
1270 cn.gss = cli
1271
1272 case 8:
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
1288
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
1350 var colFmtDataAllBinary = []byte{0, 1, 0, 1}
1351
1352
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)
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
1472
1473
1474
1475 func (cn *conn) parseComplete(commandTag string) (driver.Result, string) {
1476 commandsWithAffectedRows := []string{
1477 "SELECT ",
1478
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
1496
1497
1498
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
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
1543 for {
1544 err := rs.Next(nil)
1545 switch err {
1546 case nil:
1547 case io.EOF:
1548
1549
1550
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
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
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
1665
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
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686 func QuoteLiteral(literal string) string {
1687
1688
1689
1690
1691
1692
1693 literal = strings.Replace(literal, `'`, `''`, -1)
1694
1695
1696
1697
1698
1699 if strings.Contains(literal, `\`) {
1700 literal = strings.Replace(literal, `\`, `\\`, -1)
1701 literal = ` E'` + literal + `'`
1702 } else {
1703
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
1717
1718
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)
1757 b.string(query)
1758 b.int16(0)
1759
1760 b.next('B')
1761 b.int16(0)
1762 cn.sendBinaryParameters(b, args)
1763 b.bytes(colFmtDataAllText)
1764
1765 b.next('D')
1766 b.byte('P')
1767 b.byte(0)
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
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
1902
1903
1904
1905
1906
1907
1908
1909
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
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
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
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
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
2002
2003
2004
2005
2006
2007
2008
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
2023
2024
2025
2026
2027
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
2082 func isUTF8(name string) bool {
2083
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
2096 }
2097
2098
2099
2100 var _ driver.Pinger = &conn{}
2101 var _ driver.SessionResetter = &conn{}
2102
2103 func (cn *conn) ResetSession(ctx context.Context) error {
2104
2105
2106
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