Browse files

init

  • Loading branch information...
0 parents commit df1f1317967381f224717825633bb31354d8767c @bmizerany committed Mar 10, 2012
Showing with 1,333 additions and 0 deletions.
  1. +2 −0 .gitignore
  2. +66 −0 README.md
  3. +74 −0 buf.go
  4. +486 −0 conn.go
  5. +247 −0 conn_test.go
  6. +63 −0 encode.go
  7. +78 −0 error.go
  8. +317 −0 types.go
2 .gitignore
@@ -0,0 +1,2 @@
+.db
+*.test
66 README.md
@@ -0,0 +1,66 @@
+# pq - A pure Go postgres driver for Go's database/sql package
+
+## Install
+
+ go get github.com/bmizerany/pq
+
+## Use
+
+ package main
+
+ import (
+ _ "github.com/bmizerany/pq"
+ "database/sql"
+ )
+
+ func main() {
+ db, err := sql.Open("postgres", "user=pqgotest dbname=pqgotest sslmode=verify-full")
+ // ...
+ }
+
+**Connection String Parameters**
+
+These are a subset of the libpq connection parameters.
+See http://www.postgresql.org/docs/9.0/static/libpq-connect.html
+
+* `dbname` - The name of the database to connect to
+* `user` - The user to sign in as
+* `password` - The user's password
+* `host` - The host to connect to. Values that start with `/` are for unix domain sockets. (default is `localhost`)
+* `port` - The port to bind to. (default is `5432`)
+* `sslmode` - Whether or not to use SSL (default is `require`, this is not the default for libpq)
+ Valid values are:
+ * `disable` - No SSL
+ * `require` - Always SSL (skip verification)
+ * `verify-full` - Always SSL (require verification)
+
+See http://tip.golang.org/pkg/database/sql to learn how to use with `pq` through the `database/sql` package.
+
+## Features
+
+* SSL
+* Handles bad connections for `database/sql`
+* Scan `time.Time` correctly (i.e. `timestamp[tz]`, `time[tz]`, `date`)
+* Scan binary blobs correctly (i.e. `bytea`)
+
+## Future / Things you can help with
+
+* Notifications: `LISTEN`/`NOTIFY`
+* `hstore` sugar (i.e. handling hstore in `rows.Scan`)
+
+## Thank you (alphabetical)
+
+Some of these contributors are from the original library `bmizerany/pq.go` whose
+code still exists in here.
+
+* Blake Gentry (bgentry)
+* Brad Fitzpatrick (bradfitz)
+* Daniel Farina (fdr)
+* Everyone at The Go Team
+* Federico Romero (federomero)
+* Heroku (heroku)
+* Keith Rarick (kr)
+* Mike Lewis (mikelikespie)
+* Ryan Smith (ryandotsmith)
+* Samuel Stauffer (samuel)
+* notedit (notedit)
74 buf.go
@@ -0,0 +1,74 @@
+package pq
+
+import (
+ "bytes"
+ "encoding/binary"
+)
+
+type readBuf []byte
+
+func (b *readBuf) int32() (n int) {
+ n = int(binary.BigEndian.Uint32(*b))
+ *b = (*b)[4:]
+ return
+}
+
+func (b *readBuf) int16() (n int) {
+ n = int(binary.BigEndian.Uint16(*b))
+ *b = (*b)[2:]
+ return
+}
+
+var stringTerm = []byte{0}
+
+func (b *readBuf) string() string {
+ i := bytes.Index(*b, stringTerm)
+ if i < 0 {
+ errorf("invalid message format; expected string terminator")
+ }
+ s := (*b)[:i]
+ *b = (*b)[i+1:]
+ return string(s)
+}
+
+func (b *readBuf) next(n int) (v []byte) {
+ v = (*b)[:n]
+ *b = (*b)[n:]
+ return
+}
+
+func (b *readBuf) byte() byte {
+ return b.next(1)[0]
+}
+
+type writeBuf []byte
+
+func newWriteBuf(c byte) *writeBuf {
+ b := make(writeBuf, 5)
+ b[0] = c
+ return &b
+}
+
+func (b *writeBuf) int32(n int) {
+ x := make([]byte, 4)
+ binary.BigEndian.PutUint32(x, uint32(n))
+ *b = append(*b, x...)
+}
+
+func (b *writeBuf) int16(n int) {
+ x := make([]byte, 2)
+ binary.BigEndian.PutUint16(x, uint16(n))
+ *b = append(*b, x...)
+}
+
+func (b *writeBuf) string(s string) {
+ *b = append(*b, (s + "\000")...)
+}
+
+func (b *writeBuf) byte(c byte) {
+ *b = append(*b, c)
+}
+
+func (b *writeBuf) bytes(v []byte) {
+ *b = append(*b, v...)
+}
486 conn.go
@@ -0,0 +1,486 @@
+package pq
+
+import (
+ "crypto/md5"
+ "crypto/tls"
+ "database/sql"
+ "database/sql/driver"
+ "encoding/binary"
+ "errors"
+ "fmt"
+ "io"
+ "net"
+ "strconv"
+ "strings"
+)
+
+var (
+ ErrSSLNotSupported = errors.New("pq: SSL is not enabled on the server")
+ ErrNotSupported = errors.New("pq: this is postgres, a real database, this isn't a valid command")
+)
+
+type drv struct{}
+
+func (d *drv) Open(name string) (driver.Conn, error) {
+ return Open(name)
+}
+
+func init() {
+ sql.Register("postgres", &drv{})
+}
+
+type conn struct {
+ c net.Conn
+ namei int
+}
+
+func Open(name string) (_ driver.Conn, err error) {
+ defer errRecover(&err)
+
+ o := make(Values)
+ o.Set("host", "localhost")
+ o.Set("port", "5432")
+ parseOpts(name, o)
+
+ c, err := net.Dial(network(o))
+ if err != nil {
+ return nil, err
+ }
+
+ cn := &conn{c: c}
+ cn.ssl(o)
+ cn.startup(o)
+ return cn, nil
+}
+
+func network(o Values) (string, string) {
+ host := o.Get("host")
+
+ if strings.HasPrefix(host, "/") {
+ return "unix", host
+ }
+
+ 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) {
+ v, _ = vs[k]
+ return
+}
+
+func parseOpts(name string, o Values) {
+ if len(name) == 0 {
+ return
+ }
+
+ ps := strings.Split(name, " ")
+ for _, p := range ps {
+ kv := strings.Split(p, "=")
+ if len(kv) < 2 {
+ errorf("invalid option: %q", p)
+ }
+ o.Set(kv[0], kv[1])
+ }
+}
+
+func (cn *conn) Begin() (driver.Tx, error) {
+ st, err := cn.Prepare("BEGIN")
+ if err != nil {
+ return nil, err
+ }
+
+ _, err = st.Exec(nil)
+ return cn, err
+}
+
+func (cn *conn) Commit() error {
+ st, err := cn.Prepare("COMMIT")
+ if err != nil {
+ return err
+ }
+
+ _, err = st.Exec(nil)
+ return err
+}
+
+func (cn *conn) Rollback() error {
+ st, err := cn.Prepare("ROLLBACK")
+ if err != nil {
+ return err
+ }
+
+ _, err = st.Exec(nil)
+ return err
+}
+
+func (cn *conn) gname() string {
+ cn.namei++
+ return strconv.FormatInt(int64(cn.namei), 10)
+}
+
+func (cn *conn) Prepare(q string) (_ driver.Stmt, err error) {
+ defer errRecover(&err)
+
+ st := &stmt{cn: cn, name: cn.gname()}
+
+ b := newWriteBuf('P')
+ b.string(st.name)
+ b.string(q)
+ b.int16(0)
+ cn.send(b)
+
+ b = newWriteBuf('D')
+ b.byte('S')
+ b.string(st.name)
+ cn.send(b)
+
+ cn.send(newWriteBuf('H'))
+
+ t, r := cn.recv()
+ if t != '1' {
+ errorf("unexpected parse response: %q", t)
+ }
+
+ t, r = cn.recv()
+ if t != 't' {
+ errorf("unexpected describe params response: %q", t)
+ }
+ st.nparams = int(r.int16())
+
+ t, r = cn.recv()
+ switch t {
+ case 'T':
+ n := r.int16()
+ st.cols = make([]string, n)
+ st.ooid = make([]int, n)
+ for i := range st.cols {
+ st.cols[i] = r.string()
+ r.next(6)
+ st.ooid[i] = r.int32()
+ r.next(8)
+ }
+ case 'n':
+ // no data
+ default:
+ errorf("unexpected describe rows response: %q", t)
+ }
+
+ return st, nil
+}
+
+func (cn *conn) Close() error {
+ return cn.c.Close()
+}
+
+// Assumes len(*m) is > 5
+func (cn *conn) send(m *writeBuf) {
+ b := (*m)[1:]
+ binary.BigEndian.PutUint32(b, uint32(len(b)))
+
+ if (*m)[0] == 0 {
+ *m = b
+ }
+
+ _, err := cn.c.Write(*m)
+ if err != nil {
+ panic(err)
+ }
+}
+
+func (cn *conn) recv() (t byte, r *readBuf) {
+ for {
+ t, r = cn.recv1()
+ switch t {
+ case 'E':
+ panic(parseError(r))
+ case 'N':
+ // TODO(bmizerany): log notices?
+ default:
+ return
+ }
+ }
+
+ panic("not reached")
+}
+
+func (cn *conn) recv1() (byte, *readBuf) {
+ x := make([]byte, 5)
+ _, err := cn.c.Read(x)
+ if err != nil {
+ panic(err)
+ }
+
+ b := readBuf(x[1:])
+ y := make([]byte, b.int32()-4)
+ _, err = io.ReadFull(cn.c, y)
+ if err != nil {
+ panic(err)
+ }
+
+ return x[0], (*readBuf)(&y)
+}
+
+func (cn *conn) ssl(o Values) {
+ tlsConf := tls.Config{}
+ switch mode := o.Get("sslmode"); mode {
+ case "require", "":
+ tlsConf.InsecureSkipVerify = true
+ case "verify-full":
+ // fall out
+ case "disable":
+ return
+ default:
+ errorf(`unsupported sslmode %q; only "require" (default), "verify-full", and "disable" supported`, mode)
+ }
+
+ w := newWriteBuf(0)
+ w.int32(80877103)
+ cn.send(w)
+
+ b := make([]byte, 1)
+ _, err := io.ReadFull(cn.c, b)
+ if err != nil {
+ panic(err)
+ }
+
+ if b[0] != 'S' {
+ panic(ErrSSLNotSupported)
+ }
+
+ cn.c = tls.Client(cn.c, &tlsConf)
+}
+
+func (cn *conn) startup(o Values) {
+ w := newWriteBuf(0)
+ w.int32(196608)
+ w.string("user")
+ w.string(o.Get("user"))
+ w.string("database")
+ w.string(o.Get("dbname"))
+ w.string("")
+ cn.send(w)
+
+ for {
+ t, r := cn.recv()
+ switch t {
+ case 'K', 'S':
+ case 'R':
+ cn.auth(r)
+ case 'Z':
+ return
+ default:
+ errorf("unknown response for startup: %q", t)
+ }
+ }
+}
+
+func (cn *conn) auth(r *readBuf) {
+ switch code := r.int32(); code {
+ case 0:
+ // OK
+ case 5:
+ s := string(r.next(4))
+ w := newWriteBuf('p')
+ w.string("md5" + md5s(md5s("foo"+"pqgotest")+s))
+ cn.send(w)
+
+ t, r := cn.recv()
+ if t != 'R' {
+ errorf("unexpected password response: %q", t)
+ }
+
+ if r.int32() != 0 {
+ errorf("unexpected authentication resoonse: %q", t)
+ }
+ default:
+ errorf("unknown authentication response: %d", code)
+ }
+}
+
+type stmt struct {
+ cn *conn
+ name string
+ cols []string
+ nparams int
+ ooid []int
+ closed bool
+}
+
+func (st *stmt) Close() (err error) {
+ if st.closed {
+ return nil
+ }
+
+ defer errRecover(&err)
+
+ w := newWriteBuf('C')
+ w.byte('S')
+ w.string(st.name)
+ st.cn.send(w)
+
+ st.cn.send(newWriteBuf('S'))
+
+ t, _ := st.cn.recv()
+ if t != '3' {
+ errorf("unexpected close response: %q", t)
+ }
+ st.closed = true
+
+ t, _ = st.cn.recv()
+ if t != 'Z' {
+ errorf("expected ready for query, but got: %q", t)
+ }
+
+ return nil
+}
+
+func (st *stmt) Query(v []driver.Value) (_ driver.Rows, err error) {
+ defer errRecover(&err)
+
+ st.exec(v)
+
+ return &rows{st: st}, nil
+}
+
+func (st *stmt) Exec(v []driver.Value) (res driver.Result, err error) {
+ defer errRecover(&err)
+ st.exec(v)
+
+ for {
+ t, r := st.cn.recv()
+ switch t {
+ case 'C':
+ res = parseComplete(r.string())
+ case 'Z':
+ // done
+ return
+ case 'D':
+ errorf("unexpected data row returned in Exec; check your query")
+ case 'S':
+ // Ignore
+ default:
+ errorf("unknown exec response: %q", t)
+ }
+ }
+
+ panic("not reached")
+}
+
+func (st *stmt) exec(v []driver.Value) {
+ w := newWriteBuf('B')
+ w.string("")
+ w.string(st.name)
+ w.int16(0)
+ w.int16(len(v))
+ for _, x := range v {
+ if x == nil {
+ w.int32(-1)
+ } else {
+ b := encode(x)
+ w.int32(len(b))
+ w.bytes(b)
+ }
+ }
+ w.int16(0)
+ st.cn.send(w)
+
+ w = newWriteBuf('E')
+ w.string("")
+ w.int32(0)
+ st.cn.send(w)
+
+ st.cn.send(newWriteBuf('S'))
+
+ t, _ := st.cn.recv()
+ if t != '2' {
+ errorf("unexpected bind response: %q", t)
+ }
+}
+
+func (st *stmt) NumInput() int {
+ return st.nparams
+}
+
+type result int64
+
+func (i result) RowsAffected() (int64, error) {
+ return int64(i), nil
+}
+
+func (i result) LastInsertId() (int64, error) {
+ return 0, ErrNotSupported
+}
+
+func parseComplete(s string) driver.Result {
+ parts := strings.Split(s, " ")
+ n, _ := strconv.ParseInt(parts[len(parts)-1], 10, 64)
+ return result(n)
+}
+
+type rows struct {
+ st *stmt
+ done bool
+}
+
+func (rs *rows) Close() error {
+ for {
+ err := rs.Next(nil)
+ switch err {
+ case nil:
+ case io.EOF:
+ return nil
+ default:
+ return err
+ }
+ }
+ panic("not reached")
+}
+
+func (rs *rows) Columns() []string {
+ return rs.st.cols
+}
+
+func (rs *rows) Next(dest []driver.Value) (err error) {
+ if rs.done {
+ return io.EOF
+ }
+
+ defer errRecover(&err)
+
+ for {
+ t, r := rs.st.cn.recv()
+ switch t {
+ case 'C', 'S':
+ continue
+ case 'Z':
+ rs.done = true
+ return io.EOF
+ case 'D':
+ n := r.int16()
+ for i := 0; i < len(dest) && i < n; i++ {
+ l := r.int32()
+ if l == -1 {
+ continue
+ }
+ dest[i] = decode(r.next(l), rs.st.ooid[i])
+ }
+ return
+ default:
+ errorf("unexpected message after execute: %q", t)
+ }
+ }
+
+ panic("not reached")
+}
+
+func md5s(s string) string {
+ h := md5.New()
+ h.Write([]byte(s))
+ return fmt.Sprintf("%x", h.Sum(nil))
+}
247 conn_test.go
@@ -0,0 +1,247 @@
+package pq
+
+import (
+ "database/sql"
+ "database/sql/driver"
+ "io"
+ "reflect"
+ "testing"
+ "time"
+)
+
+var cs = "user=pqgotest sslmode=disable"
+
+func TestExec(t *testing.T) {
+ db, err := sql.Open("postgres", cs)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer db.Close()
+
+ db.Exec("DELETE FROM temp")
+
+ r, err := db.Exec("INSERT INTO temp VALUES (1)")
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if n, _ := r.RowsAffected(); n != 1 {
+ t.Fatalf("expected 1 row affected, not %d", n)
+ }
+}
+
+func TestStatment(t *testing.T) {
+ db, err := sql.Open("postgres", cs)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer db.Close()
+
+ st, err := db.Prepare("SELECT 1")
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ st1, err := db.Prepare("SELECT 2")
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ r, err := st.Query()
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if !r.Next() {
+ t.Fatal("expected row")
+ }
+
+ var i int
+ err = r.Scan(&i)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if i != 1 {
+ t.Fatalf("expected 1, got %d", i)
+ }
+
+ // st1
+
+ r, err = st1.Query()
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if !r.Next() {
+ if r.Err() != nil {
+ t.Fatal(r.Err())
+ }
+ t.Fatal("expected row")
+ }
+
+ err = r.Scan(&i)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if i != 2 {
+ t.Fatalf("expected 2, got %d", i)
+ }
+}
+
+func TestRowsCloseBeforeDone(t *testing.T) {
+ db, err := sql.Open("postgres", cs)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ r, err := db.Query("SELECT 1")
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ err = r.Close()
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if r.Next() {
+ t.Fatal("unexpected row")
+ }
+
+ if r.Err() != nil {
+ t.Fatal(r.Err())
+ }
+}
+
+func TestEncodeDecode(t *testing.T) {
+ db, err := sql.Open("postgres", cs)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer db.Close()
+
+ q := `
+ SELECT
+ '\x000102'::bytea,
+ 'foobar'::text,
+ NULL::integer,
+ '2000-1-1 01:02:03.04-7'::timestamptz
+ WHERE
+ '\x000102'::bytea = $1
+ AND 'foobar'::text = $2
+ AND $3::integer is NULL
+ `
+ // AND '2000-1-1 12:00:00.000000-7'::timestamp = $3
+
+ exp1 := []byte{0, 1, 2}
+ exp2 := "foobar"
+
+ r, err := db.Query(q, exp1, exp2, nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer r.Close()
+
+ if !r.Next() {
+ if r.Err() != nil {
+ t.Fatal(r.Err())
+ }
+ t.Fatal("expected row")
+ }
+
+ var got1 []byte
+ var got2 string
+ var got3 = sql.NullInt64{Valid: true}
+ var got4 time.Time
+
+ err = r.Scan(&got1, &got2, &got3, &got4)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if !reflect.DeepEqual(exp1, got1) {
+ t.Errorf("expected %q byte: %q", exp1, got1)
+ }
+
+ if !reflect.DeepEqual(exp2, got2) {
+ t.Errorf("expected %q byte: %q", exp2, got2)
+ }
+
+ if got3.Valid {
+ t.Fatal("expected invalid")
+ }
+
+ if got4.Year() != 2000 {
+ t.Fatal("wrong year")
+ }
+}
+
+func TestNoData(t *testing.T) {
+ db, err := sql.Open("postgres", cs)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer db.Close()
+
+ st, err := db.Prepare("SELECT 1 WHERE true = false")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer st.Close()
+
+ r, err := st.Query()
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer r.Close()
+
+ if r.Next() {
+ if r.Err() != nil {
+ t.Fatal(r.Err())
+ }
+ t.Fatal("unexpected row")
+ }
+}
+
+func TestPGError(t *testing.T) {
+ db, err := sql.Open("postgres", "user=asdf")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer db.Close()
+
+ _, err = db.Begin()
+ if err == nil {
+ t.Fatal("expected error")
+ }
+
+ if err != driver.ErrBadConn {
+ t.Fatalf("expected a PGError, got: %v", err)
+ }
+}
+
+func TestBadConn(t *testing.T) {
+ var err error
+
+ func() {
+ defer errRecover(&err)
+ panic(io.EOF)
+ }()
+
+ if err != driver.ErrBadConn {
+ t.Fatalf("expected driver.ErrBadConn, got: %#v", err)
+ }
+
+ func() {
+ defer errRecover(&err)
+ e := &PGError{c: make(map[byte]string)}
+ e.c['S'] = Efatal
+ panic(e)
+ }()
+
+ if err != driver.ErrBadConn {
+ t.Fatalf("expected driver.ErrBadConn, got: %#v", err)
+ }
+}
63 encode.go
@@ -0,0 +1,63 @@
+package pq
+
+import (
+ "encoding/hex"
+ "fmt"
+ "time"
+)
+
+func encode(x interface{}) []byte {
+ const timeFormat = "2006-01-02 15:04:05.0000-07"
+
+ switch v := x.(type) {
+ case int64:
+ return []byte(fmt.Sprintf("%d", v))
+ case float32, float64:
+ return []byte(fmt.Sprintf("%f", v))
+ case []byte:
+ return []byte(fmt.Sprintf("\\x%x", v))
+ case string:
+ return []byte(v)
+ case bool:
+ return []byte(fmt.Sprintf("%t", v))
+ case time.Time:
+ return []byte(v.Format(timeFormat))
+ default:
+ errorf("encode: unknown type for %T", v)
+ }
+
+ panic("not reached")
+}
+
+func decode(s []byte, typ int) interface{} {
+ switch typ {
+ case t_bytea:
+ s = s[2:] // trim off "\\x"
+ d := make([]byte, hex.DecodedLen(len(s)))
+ _, err := hex.Decode(d, s)
+ if err != nil {
+ errorf("%s", err)
+ }
+ return d
+ case t_timestamptz:
+ return mustParse("2006-01-02 15:04:05-07", s)
+ case t_timestamp:
+ return mustParse("2006-01-02 15:04:05", s)
+ case t_time:
+ return mustParse("15:04:05", s)
+ case t_timetz:
+ return mustParse("15:04:05-07", s)
+ case t_date:
+ return mustParse("2006-01-02", s)
+ }
+
+ return s
+}
+
+func mustParse(f string, s []byte) time.Time {
+ t, err := time.Parse(f, string(s))
+ if err != nil {
+ errorf("decode: %s", err)
+ }
+ return t
+}
78 error.go
@@ -0,0 +1,78 @@
+package pq
+
+import (
+ "database/sql/driver"
+ "fmt"
+ "io"
+ "runtime"
+)
+
+const (
+ Efatal = "FATAL"
+ Epanic = "PANIC"
+ Ewarning = "WARNING"
+ Enotice = "NOTICE"
+ Edebug = "DEBUG"
+ Einfo = "INFO"
+ Elog = "LOG"
+)
+
+type Error error
+
+type PGError struct {
+ c map[byte]string
+}
+
+func parseError(r *readBuf) *PGError {
+ err := &PGError{make(map[byte]string)}
+ for t := r.byte(); t != 0; t = r.byte() {
+ err.c[t] = r.string()
+ }
+ return err
+}
+
+func (err *PGError) Get(k byte) (v string) {
+ v, _ = err.c[k]
+ return
+}
+
+func (err *PGError) Fatal() bool {
+ return err.Get('S') == Efatal
+}
+
+func (err *PGError) Error() string {
+ var s string
+ for k, v := range err.c {
+ s += fmt.Sprintf(" %c:%q", k, v)
+ }
+ return "pq: " + s[1:]
+}
+
+func errorf(s string, args ...interface{}) {
+ panic(Error(fmt.Errorf("pq: %s", fmt.Sprintf(s, args...))))
+}
+
+func errRecover(err *error) {
+ e := recover()
+ switch v := e.(type) {
+ case nil:
+ // Do nothing
+ case runtime.Error:
+ panic(v)
+ case *PGError:
+ if v.Fatal() {
+ *err = driver.ErrBadConn
+ } else {
+ *err = v
+ }
+ case error:
+ if v == io.EOF {
+ *err = driver.ErrBadConn
+ } else {
+ *err = v
+ }
+
+ default:
+ panic(fmt.Sprintf("unknown error: %#v", e))
+ }
+}
317 types.go
@@ -0,0 +1,317 @@
+package pq
+
+const (
+ t_bool = 16
+ t_bytea = 17
+ t_char = 18
+ t_name = 19
+ t_int8 = 20
+ t_int2 = 21
+ t_int2vector = 22
+ t_int4 = 23
+ t_regproc = 24
+ t_text = 25
+ t_oid = 26
+ t_tid = 27
+ t_xid = 28
+ t_cid = 29
+ t_oidvector = 30
+ t_pg_type = 71
+ t_pg_attribute = 75
+ t_pg_proc = 81
+ t_pg_class = 83
+ t_xml = 142
+ t__xml = 143
+ t_pg_node_tree = 194
+ t_smgr = 210
+ t_point = 600
+ t_lseg = 601
+ t_path = 602
+ t_box = 603
+ t_polygon = 604
+ t_line = 628
+ t__line = 629
+ t_float4 = 700
+ t_float8 = 701
+ t_abstime = 702
+ t_reltime = 703
+ t_tinterval = 704
+ t_unknown = 705
+ t_circle = 718
+ t__circle = 719
+ t_money = 790
+ t__money = 791
+ t_macaddr = 829
+ t_inet = 869
+ t_cidr = 650
+ t__bool = 1000
+ t__bytea = 1001
+ t__char = 1002
+ t__name = 1003
+ t__int2 = 1005
+ t__int2vector = 1006
+ t__int4 = 1007
+ t__regproc = 1008
+ t__text = 1009
+ t__oid = 1028
+ t__tid = 1010
+ t__xid = 1011
+ t__cid = 1012
+ t__oidvector = 1013
+ t__bpchar = 1014
+ t__varchar = 1015
+ t__int8 = 1016
+ t__point = 1017
+ t__lseg = 1018
+ t__path = 1019
+ t__box = 1020
+ t__float4 = 1021
+ t__float8 = 1022
+ t__abstime = 1023
+ t__reltime = 1024
+ t__tinterval = 1025
+ t__polygon = 1027
+ t_aclitem = 1033
+ t__aclitem = 1034
+ t__macaddr = 1040
+ t__inet = 1041
+ t__cidr = 651
+ t__cstring = 1263
+ t_bpchar = 1042
+ t_varchar = 1043
+ t_date = 1082
+ t_time = 1083
+ t_timestamp = 1114
+ t__timestamp = 1115
+ t__date = 1182
+ t__time = 1183
+ t_timestamptz = 1184
+ t__timestamptz = 1185
+ t_interval = 1186
+ t__interval = 1187
+ t__numeric = 1231
+ t_timetz = 1266
+ t__timetz = 1270
+ t_bit = 1560
+ t__bit = 1561
+ t_varbit = 1562
+ t__varbit = 1563
+ t_numeric = 1700
+ t_refcursor = 1790
+ t__refcursor = 2201
+ t_regprocedure = 2202
+ t_regoper = 2203
+ t_regoperator = 2204
+ t_regclass = 2205
+ t_regtype = 2206
+ t__regprocedure = 2207
+ t__regoper = 2208
+ t__regoperator = 2209
+ t__regclass = 2210
+ t__regtype = 2211
+ t_uuid = 2950
+ t__uuid = 2951
+ t_tsvector = 3614
+ t_gtsvector = 3642
+ t_tsquery = 3615
+ t_regconfig = 3734
+ t_regdictionary = 3769
+ t__tsvector = 3643
+ t__gtsvector = 3644
+ t__tsquery = 3645
+ t__regconfig = 3735
+ t__regdictionary = 3770
+ t_txid_snapshot = 2970
+ t__txid_snapshot = 2949
+ t_record = 2249
+ t__record = 2287
+ t_cstring = 2275
+ t_any = 2276
+ t_anyarray = 2277
+ t_void = 2278
+ t_trigger = 2279
+ t_language_handler = 2280
+ t_internal = 2281
+ t_opaque = 2282
+ t_anyelement = 2283
+ t_anynonarray = 2776
+ t_anyenum = 3500
+ t_fdw_handler = 3115
+ t_pg_attrdef = 10000
+ t_pg_constraint = 10001
+ t_pg_inherits = 10002
+ t_pg_index = 10003
+ t_pg_operator = 10004
+ t_pg_opfamily = 10005
+ t_pg_opclass = 10006
+ t_pg_am = 10117
+ t_pg_amop = 10118
+ t_pg_amproc = 10478
+ t_pg_language = 10731
+ t_pg_largeobject_metadata = 10732
+ t_pg_largeobject = 10733
+ t_pg_aggregate = 10734
+ t_pg_statistic = 10735
+ t_pg_rewrite = 10736
+ t_pg_trigger = 10737
+ t_pg_description = 10738
+ t_pg_cast = 10739
+ t_pg_enum = 10936
+ t_pg_namespace = 10937
+ t_pg_conversion = 10938
+ t_pg_depend = 10939
+ t_pg_database = 1248
+ t_pg_db_role_setting = 10940
+ t_pg_tablespace = 10941
+ t_pg_pltemplate = 10942
+ t_pg_authid = 2842
+ t_pg_auth_members = 2843
+ t_pg_shdepend = 10943
+ t_pg_shdescription = 10944
+ t_pg_ts_config = 10945
+ t_pg_ts_config_map = 10946
+ t_pg_ts_dict = 10947
+ t_pg_ts_parser = 10948
+ t_pg_ts_template = 10949
+ t_pg_extension = 10950
+ t_pg_foreign_data_wrapper = 10951
+ t_pg_foreign_server = 10952
+ t_pg_user_mapping = 10953
+ t_pg_foreign_table = 10954
+ t_pg_default_acl = 10955
+ t_pg_seclabel = 10956
+ t_pg_collation = 10957
+ t_pg_toast_2604 = 10958
+ t_pg_toast_2606 = 10959
+ t_pg_toast_2609 = 10960
+ t_pg_toast_1255 = 10961
+ t_pg_toast_2618 = 10962
+ t_pg_toast_3596 = 10963
+ t_pg_toast_2619 = 10964
+ t_pg_toast_2620 = 10965
+ t_pg_toast_1262 = 10966
+ t_pg_toast_2396 = 10967
+ t_pg_toast_2964 = 10968
+ t_pg_roles = 10970
+ t_pg_shadow = 10973
+ t_pg_group = 10976
+ t_pg_user = 10979
+ t_pg_rules = 10982
+ t_pg_views = 10986
+ t_pg_tables = 10989
+ t_pg_indexes = 10993
+ t_pg_stats = 10997
+ t_pg_locks = 11001
+ t_pg_cursors = 11004
+ t_pg_available_extensions = 11007
+ t_pg_available_extension_versions = 11010
+ t_pg_prepared_xacts = 11013
+ t_pg_prepared_statements = 11017
+ t_pg_seclabels = 11020
+ t_pg_settings = 11024
+ t_pg_timezone_abbrevs = 11029
+ t_pg_timezone_names = 11032
+ t_pg_stat_all_tables = 11035
+ t_pg_stat_xact_all_tables = 11039
+ t_pg_stat_sys_tables = 11043
+ t_pg_stat_xact_sys_tables = 11047
+ t_pg_stat_user_tables = 11050
+ t_pg_stat_xact_user_tables = 11054
+ t_pg_statio_all_tables = 11057
+ t_pg_statio_sys_tables = 11061
+ t_pg_statio_user_tables = 11064
+ t_pg_stat_all_indexes = 11067
+ t_pg_stat_sys_indexes = 11071
+ t_pg_stat_user_indexes = 11074
+ t_pg_statio_all_indexes = 11077
+ t_pg_statio_sys_indexes = 11081
+ t_pg_statio_user_indexes = 11084
+ t_pg_statio_all_sequences = 11087
+ t_pg_statio_sys_sequences = 11090
+ t_pg_statio_user_sequences = 11093
+ t_pg_stat_activity = 11096
+ t_pg_stat_replication = 11099
+ t_pg_stat_database = 11102
+ t_pg_stat_database_conflicts = 11105
+ t_pg_stat_user_functions = 11108
+ t_pg_stat_xact_user_functions = 11112
+ t_pg_stat_bgwriter = 11116
+ t_pg_user_mappings = 11119
+ t_cardinal_number = 11669
+ t_character_data = 11671
+ t_sql_identifier = 11672
+ t_information_schema_catalog_name = 11674
+ t_time_stamp = 11676
+ t_yes_or_no = 11677
+ t_applicable_roles = 11680
+ t_administrable_role_authorizations = 11684
+ t_attributes = 11687
+ t_character_sets = 11691
+ t_check_constraint_routine_usage = 11695
+ t_check_constraints = 11699
+ t_collations = 11703
+ t_collation_character_set_applicability = 11706
+ t_column_domain_usage = 11709
+ t_column_privileges = 11713
+ t_column_udt_usage = 11717
+ t_columns = 11721
+ t_constraint_column_usage = 11725
+ t_constraint_table_usage = 11729
+ t_domain_constraints = 11733
+ t_domain_udt_usage = 11737
+ t_domains = 11740
+ t_enabled_roles = 11744
+ t_key_column_usage = 11747
+ t_parameters = 11751
+ t_referential_constraints = 11755
+ t_role_column_grants = 11759
+ t_routine_privileges = 11762
+ t_role_routine_grants = 11766
+ t_routines = 11769
+ t_schemata = 11773
+ t_sequences = 11776
+ t_sql_features = 11780
+ t_pg_toast_11779 = 11782
+ t_sql_implementation_info = 11785
+ t_pg_toast_11784 = 11787
+ t_sql_languages = 11790
+ t_pg_toast_11789 = 11792
+ t_sql_packages = 11795
+ t_pg_toast_11794 = 11797
+ t_sql_parts = 11800
+ t_pg_toast_11799 = 11802
+ t_sql_sizing = 11805
+ t_pg_toast_11804 = 11807
+ t_sql_sizing_profiles = 11810
+ t_pg_toast_11809 = 11812
+ t_table_constraints = 11815
+ t_table_privileges = 11819
+ t_role_table_grants = 11823
+ t_tables = 11826
+ t_triggered_update_columns = 11830
+ t_triggers = 11834
+ t_usage_privileges = 11838
+ t_role_usage_grants = 11842
+ t_view_column_usage = 11845
+ t_view_routine_usage = 11849
+ t_view_table_usage = 11853
+ t_views = 11857
+ t_data_type_privileges = 11861
+ t_element_types = 11865
+ t__pg_foreign_data_wrappers = 11869
+ t_foreign_data_wrapper_options = 11872
+ t_foreign_data_wrappers = 11875
+ t__pg_foreign_servers = 11878
+ t_foreign_server_options = 11882
+ t_foreign_servers = 11885
+ t__pg_foreign_tables = 11888
+ t_foreign_table_options = 11892
+ t_foreign_tables = 11895
+ t__pg_user_mappings = 11898
+ t_user_mapping_options = 11901
+ t_user_mappings = 11905
+ t_t = 16806
+ t__t = 16805
+ t_temp = 16810
+ t__temp = 16809
+)

0 comments on commit df1f131

Please sign in to comment.