From 65f3079498283dccc7c4d26fe5a34c198b949c1f Mon Sep 17 00:00:00 2001 From: Josh Huckabee Date: Tue, 25 Jun 2013 16:13:22 -0700 Subject: [PATCH] Replace github.com/bmizerany/pq with github.com/lib/pq postgres driver. Change-Id: If62fd5b489696171c8be6b42a988e1c7d0a634d0 --- cmd/camtool/dbinit.go | 2 +- pkg/index/postgres/postgres_test.go | 2 +- pkg/index/postgres/postgresindexer.go | 2 +- third_party/github.com/bmizerany/pq/buf.go | 74 -- third_party/github.com/bmizerany/pq/conn.go | 659 ------------------ .../github.com/bmizerany/pq/conn_test.go | 443 ------------ third_party/github.com/bmizerany/pq/encode.go | 108 --- .../github.com/bmizerany/pq/encode_test.go | 26 - third_party/github.com/bmizerany/pq/error.go | 108 --- third_party/github.com/bmizerany/pq/types.go | 317 --------- third_party/github.com/bmizerany/pq/url.go | 68 -- .../github.com/bmizerany/pq/url_test.go | 53 -- 12 files changed, 3 insertions(+), 1859 deletions(-) delete mode 100644 third_party/github.com/bmizerany/pq/buf.go delete mode 100644 third_party/github.com/bmizerany/pq/conn.go delete mode 100644 third_party/github.com/bmizerany/pq/conn_test.go delete mode 100644 third_party/github.com/bmizerany/pq/encode.go delete mode 100644 third_party/github.com/bmizerany/pq/encode_test.go delete mode 100644 third_party/github.com/bmizerany/pq/error.go delete mode 100644 third_party/github.com/bmizerany/pq/types.go delete mode 100644 third_party/github.com/bmizerany/pq/url.go delete mode 100644 third_party/github.com/bmizerany/pq/url_test.go diff --git a/cmd/camtool/dbinit.go b/cmd/camtool/dbinit.go index 5ffe93219..c4eefd28e 100644 --- a/cmd/camtool/dbinit.go +++ b/cmd/camtool/dbinit.go @@ -29,7 +29,7 @@ import ( "camlistore.org/pkg/index/postgres" "camlistore.org/pkg/index/sqlite" - _ "camlistore.org/third_party/github.com/bmizerany/pq" + _ "camlistore.org/third_party/github.com/lib/pq" _ "camlistore.org/third_party/github.com/ziutek/mymysql/godrv" ) diff --git a/pkg/index/postgres/postgres_test.go b/pkg/index/postgres/postgres_test.go index a1d124ecf..4dd8983da 100644 --- a/pkg/index/postgres/postgres_test.go +++ b/pkg/index/postgres/postgres_test.go @@ -29,7 +29,7 @@ import ( "camlistore.org/pkg/index/postgres" "camlistore.org/pkg/test/testdep" - _ "camlistore.org/third_party/github.com/bmizerany/pq" + _ "camlistore.org/third_party/github.com/lib/pq" ) var ( diff --git a/pkg/index/postgres/postgresindexer.go b/pkg/index/postgres/postgresindexer.go index 3327679e9..0d2cf9d2f 100644 --- a/pkg/index/postgres/postgresindexer.go +++ b/pkg/index/postgres/postgresindexer.go @@ -27,7 +27,7 @@ import ( "camlistore.org/pkg/index/sqlindex" "camlistore.org/pkg/jsonconfig" - _ "camlistore.org/third_party/github.com/bmizerany/pq" + _ "camlistore.org/third_party/github.com/lib/pq" ) type myIndexStorage struct { diff --git a/third_party/github.com/bmizerany/pq/buf.go b/third_party/github.com/bmizerany/pq/buf.go deleted file mode 100644 index c6be5d6ee..000000000 --- a/third_party/github.com/bmizerany/pq/buf.go +++ /dev/null @@ -1,74 +0,0 @@ -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...) -} diff --git a/third_party/github.com/bmizerany/pq/conn.go b/third_party/github.com/bmizerany/pq/conn.go deleted file mode 100644 index 2c8a5aaca..000000000 --- a/third_party/github.com/bmizerany/pq/conn.go +++ /dev/null @@ -1,659 +0,0 @@ -package pq - -import ( - "bufio" - "crypto/md5" - "crypto/tls" - "database/sql" - "database/sql/driver" - "encoding/binary" - "errors" - "fmt" - "io" - "net" - "os" - "os/user" - "path" - "strconv" - "strings" -) - -var ( - ErrSSLNotSupported = errors.New("pq: SSL is not enabled on the server") - ErrNotSupported = errors.New("pq: invalid 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 - buf *bufio.Reader - namei int -} - -func Open(name string) (_ driver.Conn, err error) { - defer errRecover(&err) - defer errRecoverWithPGReason(&err) - - o := make(Values) - - // A number of defaults are applied here, in this order: - // - // * Very low precedence defaults applied in every situation - // * Environment variables - // * Explicitly passed connection information - o.Set("host", "localhost") - o.Set("port", "5432") - - // Default the username, but ignore errors, because a user - // passed in via environment variable or connection string - // would be okay. This can result in connections failing - // *sometimes* if the client relies on being able to determine - // the current username and there are intermittent problems. - u, err := user.Current() - if err == nil { - o.Set("user", u.Username) - } - - for k, v := range parseEnviron(os.Environ()) { - o.Set(k, v) - } - - parseOpts(name, o) - - c, err := net.Dial(network(o)) - if err != nil { - return nil, err - } - - cn := &conn{c: c} - cn.ssl(o) - cn.buf = bufio.NewReader(cn.c) - cn.startup(o) - return cn, nil -} - -func network(o Values) (string, string) { - host := o.Get("host") - - if strings.HasPrefix(host, "/") { - sockPath := path.Join(host, ".s.PGSQL."+o.Get("port")) - return "unix", sockPath - } - - return "tcp", host + ":" + o.Get("port") -} - -type Values map[string]string - -func (vs Values) Set(k, v string) { - vs[k] = v -} - -func (vs Values) Get(k string) (v string) { - 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) { - _, err := cn.Exec("BEGIN", nil) - if err != nil { - return nil, err - } - return cn, err -} - -func (cn *conn) Commit() error { - _, err := cn.Exec("COMMIT", nil) - return err -} - -func (cn *conn) Rollback() error { - _, err := cn.Exec("ROLLBACK", nil) - return err -} - -func (cn *conn) gname() string { - cn.namei++ - return strconv.FormatInt(int64(cn.namei), 10) -} - -func (cn *conn) simpleQuery(q string) (res driver.Result, err error) { - defer errRecover(&err) - - b := newWriteBuf('Q') - b.string(q) - cn.send(b) - - for { - t, r := cn.recv1() - switch t { - case 'C': - res = parseComplete(r.string()) - case 'Z': - // done - return - case 'E': - err = parseError(r) - case 'T', 'N': - // ignore - default: - errorf("unknown response for simple query: %q", t) - } - } - panic("not reached") -} - -func (cn *conn) prepareTo(q, stmtName string) (_ driver.Stmt, err error) { - defer errRecover(&err) - - st := &stmt{cn: cn, name: stmtName, query: q} - - 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('S')) - - for { - t, r := cn.recv1() - switch t { - case '1', '2', 'N': - case 't': - st.nparams = int(r.int16()) - 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 - case 'Z': - return st, err - case 'E': - err = parseError(r) - default: - errorf("unexpected describe rows response: %q", t) - } - } - - panic("not reached") -} - -func (cn *conn) Prepare(q string) (driver.Stmt, error) { - return cn.prepareTo(q, cn.gname()) -} - -func (cn *conn) Close() (err error) { - defer errRecover(&err) - cn.send(newWriteBuf('X')) - - return cn.c.Close() -} - -// Implement the optional "Execer" interface for one-shot queries -func (cn *conn) Exec(query string, args []driver.Value) (_ driver.Result, err error) { - defer errRecover(&err) - - // Check to see if we can use the "simpleQuery" interface, which is - // *much* faster than going through prepare/exec - if len(args) == 0 { - return cn.simpleQuery(query) - } - - // Use the unnamed statement to defer planning until bind - // time, or else value-based selectivity estimates cannot be - // used. - st, err := cn.prepareTo(query, "") - if err != nil { - panic(err) - } - - r, err := st.Exec(args) - if err != nil { - panic(err) - } - - return r, err -} - -// Assumes len(*m) is > 5 -func (cn *conn) send(m *writeBuf) { - b := (*m)[1:] - binary.BigEndian.PutUint32(b, uint32(len(b))) - - if (*m)[0] == 0 { - *m = b - } - - _, err := cn.c.Write(*m) - if err != nil { - panic(err) - } -} - -func (cn *conn) recv() (t byte, r *readBuf) { - for { - t, r = cn.recv1() - switch t { - case 'E': - panic(parseError(r)) - case 'N': - // ignore - default: - return - } - } - - panic("not reached") -} - -func (cn *conn) recv1() (byte, *readBuf) { - x := make([]byte, 5) - _, err := io.ReadFull(cn.buf, x) - if err != nil { - panic(err) - } - - b := readBuf(x[1:]) - y := make([]byte, b.int32()-4) - _, err = io.ReadFull(cn.buf, 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, o) - case 'Z': - return - default: - errorf("unknown response for startup: %q", t) - } - } -} - -func (cn *conn) auth(r *readBuf, o Values) { - switch code := r.int32(); code { - case 0: - // OK - case 5: - s := string(r.next(4)) - w := newWriteBuf('p') - w.string("md5" + md5s(md5s(o.Get("password")+o.Get("user"))+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 - query 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) - - if len(v) == 0 { - return st.cn.simpleQuery(st.query) - } - st.exec(v) - - for { - t, r := st.cn.recv1() - switch t { - case 'E': - err = parseError(r) - case 'C': - res = parseComplete(r.string()) - case 'Z': - // done - return - case 'D': - errorf("unexpected data row returned in Exec; check your query") - case 'S', 'N': - // 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')) - - var err error - for { - t, r := st.cn.recv1() - switch t { - case 'E': - err = parseError(r) - case '2': - if err != nil { - panic(err) - } - return - case 'Z': - if err != nil { - panic(err) - } - return - case 'N': - // ignore - default: - 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.recv1() - switch t { - case 'E': - err = parseError(r) - case 'C', 'S', 'N': - continue - case 'Z': - rs.done = true - if err != nil { - return err - } - return io.EOF - case 'D': - n := r.int16() - for i := 0; i < len(dest) && i < n; i++ { - l := r.int32() - if l == -1 { - dest[i] = nil - 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)) -} - -// parseEnviron tries to mimic some of libpq's environment handling -// -// To ease testing, it does not directly reference os.Environ, but is -// designed to accept its output. -// -// Environment-set connection information is intended to have a higher -// precedence than a library default but lower than any explicitly -// passed information (such as in the URL or connection string). -func parseEnviron(env []string) (out map[string]string) { - out = make(map[string]string) - - for _, v := range env { - parts := strings.SplitN(v, "=", 2) - - accrue := func(keyname string) { - out[keyname] = parts[1] - } - - // The order of these is the same as is seen in the - // PostgreSQL 9.1 manual, with omissions briefly - // noted. - switch parts[0] { - case "PGHOST": - accrue("host") - case "PGHOSTADDR": - accrue("hostaddr") - case "PGPORT": - accrue("port") - case "PGDATABASE": - accrue("dbname") - case "PGUSER": - accrue("user") - case "PGPASSWORD": - accrue("password") - // skip PGPASSFILE, PGSERVICE, PGSERVICEFILE, - // PGREALM - case "PGOPTIONS": - accrue("options") - case "PGAPPNAME": - accrue("application_name") - case "PGSSLMODE": - accrue("sslmode") - case "PGREQUIRESSL": - accrue("requiressl") - case "PGSSLCERT": - accrue("sslcert") - case "PGSSLKEY": - accrue("sslkey") - case "PGSSLROOTCERT": - accrue("sslrootcert") - case "PGSSLCRL": - accrue("sslcrl") - case "PGREQUIREPEER": - accrue("requirepeer") - case "PGKRBSRVNAME": - accrue("krbsrvname") - case "PGGSSLIB": - accrue("gsslib") - case "PGCONNECT_TIMEOUT": - accrue("connect_timeout") - case "PGCLIENTENCODING": - accrue("client_encoding") - // skip PGDATESTYLE, PGTZ, PGGEQO, PGSYSCONFDIR, - // PGLOCALEDIR - } - } - - return out -} diff --git a/third_party/github.com/bmizerany/pq/conn_test.go b/third_party/github.com/bmizerany/pq/conn_test.go deleted file mode 100644 index 5553db124..000000000 --- a/third_party/github.com/bmizerany/pq/conn_test.go +++ /dev/null @@ -1,443 +0,0 @@ -package pq - -import ( - "database/sql" - "database/sql/driver" - "io" - "os" - "reflect" - "testing" - "time" -) - -type Fatalistic interface { - Fatal(args ...interface{}) -} - -func openTestConn(t Fatalistic) *sql.DB { - datname := os.Getenv("PGDATABASE") - sslmode := os.Getenv("PGSSLMODE") - - if datname == "" { - os.Setenv("PGDATABASE", "pqgotest") - } - - if sslmode == "" { - os.Setenv("PGSSLMODE", "disable") - } - - conn, err := sql.Open("postgres", "") - if err != nil { - t.Fatal(err) - } - - return conn -} - -func TestExec(t *testing.T) { - db := openTestConn(t) - defer db.Close() - - _, err := db.Exec("CREATE TEMP TABLE temp (a int)") - if err != nil { - t.Fatal(err) - } - - 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) - } - - r, err = db.Exec("INSERT INTO temp VALUES ($1), ($2), ($3)", 1, 2, 3) - if err != nil { - t.Fatal(err) - } - - if n, _ := r.RowsAffected(); n != 3 { - t.Fatalf("expected 3 row affected, not %d", n) - } -} - -func TestStatment(t *testing.T) { - db := openTestConn(t) - 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) - } - defer r.Close() - - 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 - - r1, err := st1.Query() - if err != nil { - t.Fatal(err) - } - defer r1.Close() - - if !r1.Next() { - if r.Err() != nil { - t.Fatal(r1.Err()) - } - t.Fatal("expected row") - } - - err = r1.Scan(&i) - if err != nil { - t.Fatal(err) - } - - if i != 2 { - t.Fatalf("expected 2, got %d", i) - } -} - -func TestRowsCloseBeforeDone(t *testing.T) { - db := openTestConn(t) - defer db.Close() - - 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 := openTestConn(t) - defer db.Close() - - q := ` - SELECT - '\x000102'::bytea, - 'foobar'::text, - NULL::integer, - '2000-1-1 01:02:03.04-7'::timestamptz, - 0::boolean, - 123, - 3.14::float8 - 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 - var got5, got6, got7 interface{} - - err = r.Scan(&got1, &got2, &got3, &got4, &got5, &got6, &got7) - 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") - } - - if got5 != false { - t.Fatalf("expected false, got %q", got5) - } - - if got6 != int64(123) { - t.Fatalf("expected 123, got %d", got6) - } - - if got7 != float64(3.14) { - t.Fatalf("expected 3.14, got %f", got7) - } -} - -func TestNoData(t *testing.T) { - db := openTestConn(t) - 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) { - // Don't use the normal connection setup, this is intended to - // blow up in the startup packet from a non-existent user. - db, err := sql.Open("postgres", "user=thisuserreallydoesntexist") - if err != nil { - t.Fatal(err) - } - defer db.Close() - - _, err = db.Begin() - if err == nil { - t.Fatal("expected error") - } - - if err, ok := err.(PGError); !ok { - 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) - } -} - -func TestErrorOnExec(t *testing.T) { - db := openTestConn(t) - defer db.Close() - - sql := "DO $$BEGIN RAISE unique_violation USING MESSAGE='foo'; END; $$;" - _, err := db.Exec(sql) - _, ok := err.(PGError) - if !ok { - t.Fatalf("expected PGError, was: %#v", err) - } - - _, err = db.Exec("SELECT 1 WHERE true = false") // returns no rows - if err != nil { - t.Fatal(err) - } -} - -func TestErrorOnQuery(t *testing.T) { - db := openTestConn(t) - defer db.Close() - - sql := "DO $$BEGIN RAISE unique_violation USING MESSAGE='foo'; END; $$;" - r, err := db.Query(sql) - if err != nil { - t.Fatal(err) - } - defer r.Close() - - if r.Next() { - t.Fatal("unexpected row, want error") - } - - _, ok := r.Err().(PGError) - if !ok { - t.Fatalf("expected PGError, was: %#v", r.Err()) - } - - r, err = db.Query("SELECT 1 WHERE true = false") // returns no rows - if err != nil { - t.Fatal(err) - } - - if r.Next() { - t.Fatal("unexpected row") - } -} - -func TestBindError(t *testing.T) { - db := openTestConn(t) - defer db.Close() - - _, err := db.Exec("create temp table test (i integer)") - if err != nil { - t.Fatal(err) - } - - _, err = db.Query("select * from test where i=$1", "hhh") - if err == nil { - t.Fatal("expected an error") - } - - // Should not get error here - r, err := db.Query("select * from test where i=$1", 1) - if err != nil { - t.Fatal(err) - } - defer r.Close() -} - -func TestParseEnviron(t *testing.T) { - expected := map[string]string{"dbname": "hello", "user": "goodbye"} - results := parseEnviron([]string{"PGDATABASE=hello", "PGUSER=goodbye"}) - if !reflect.DeepEqual(expected, results) { - t.Fatalf("Expected: %#v Got: %#v", expected, results) - } -} - -func TestExecerInterface(t *testing.T) { - // Gin up a straw man private struct just for the type check - cn := &conn{c: nil} - var cni interface{} = cn - - _, ok := cni.(driver.Execer) - if !ok { - t.Fatal("Driver doesn't implement Execer") - } -} - -func TestNullAfterNonNull(t *testing.T) { - db := openTestConn(t) - defer db.Close() - - r, err := db.Query("SELECT 9::integer UNION SELECT NULL::integer") - if err != nil { - t.Fatal(err) - } - - var n sql.NullInt64 - - if !r.Next() { - if r.Err() != nil { - t.Fatal(err) - } - t.Fatal("expected row") - } - - if err := r.Scan(&n); err != nil { - t.Fatal(err) - } - - if n.Int64 != 9 { - t.Fatalf("expected 2, not %d", n.Int64) - } - - if !r.Next() { - if r.Err() != nil { - t.Fatal(err) - } - t.Fatal("expected row") - } - - if err := r.Scan(&n); err != nil { - t.Fatal(err) - } - - if n.Valid { - t.Fatal("expected n to be invalid") - } - - if n.Int64 != 0 { - t.Fatalf("expected n to 2, not %d", n.Int64) - } -} - -// Stress test the performance of parsing results from the wire. -func BenchmarkResultParsing(b *testing.B) { - b.StopTimer() - - db := openTestConn(b) - defer db.Close() - _, err := db.Exec("BEGIN") - if err != nil { - b.Fatal(err) - } - - b.StartTimer() - for i := 0; i < b.N; i++ { - res, err := db.Query("SELECT generate_series(1, 50000)") - if err != nil { - b.Fatal(err) - } - res.Close() - } -} diff --git a/third_party/github.com/bmizerany/pq/encode.go b/third_party/github.com/bmizerany/pq/encode.go deleted file mode 100644 index c55598ac6..000000000 --- a/third_party/github.com/bmizerany/pq/encode.go +++ /dev/null @@ -1,108 +0,0 @@ -package pq - -import ( - "database/sql/driver" - "encoding/hex" - "fmt" - "strconv" - "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) - case t_bool: - return s[0] == 't' - case t_int8, t_int2, t_int4: - i, err := strconv.ParseInt(string(s), 10, 64) - if err != nil { - errorf("%s", err) - } - return i - case t_float4, t_float8: - bits := 64 - if typ == t_float4 { - bits = 32 - } - f, err := strconv.ParseFloat(string(s), bits) - if err != nil { - errorf("%s", err) - } - return f - } - - return s -} - -func mustParse(f string, s []byte) time.Time { - str := string(s) - // Special case until time.Parse bug is fixed: - // http://code.google.com/p/go/issues/detail?id=3487 - if str[len(str)-2] == '.' { - str += "0" - } - t, err := time.Parse(f, str) - if err != nil { - errorf("decode: %s", err) - } - return t -} - -type NullTime struct { - Time time.Time - Valid bool // Valid is true if Time is not NULL -} - -// Scan implements the Scanner interface. -func (nt *NullTime) Scan(value interface{}) error { - nt.Time, nt.Valid = value.(time.Time) - return nil -} - -// Value implements the driver Valuer interface. -func (nt NullTime) Value() (driver.Value, error) { - if !nt.Valid { - return nil, nil - } - return nt.Time, nil -} diff --git a/third_party/github.com/bmizerany/pq/encode_test.go b/third_party/github.com/bmizerany/pq/encode_test.go deleted file mode 100644 index fb1723cdf..000000000 --- a/third_party/github.com/bmizerany/pq/encode_test.go +++ /dev/null @@ -1,26 +0,0 @@ -package pq - -import ( - "testing" - "time" -) - -func TestScanTimestamp(t *testing.T) { - var nt NullTime - tn := time.Now() - (&nt).Scan(tn) - if !nt.Valid { - t.Errorf("Expected Valid=false") - } - if nt.Time != tn { - t.Errorf("Time value mismatch") - } -} - -func TestScanNilTimestamp(t *testing.T) { - var nt NullTime - (&nt).Scan(nil) - if nt.Valid { - t.Errorf("Expected Valid=false") - } -} diff --git a/third_party/github.com/bmizerany/pq/error.go b/third_party/github.com/bmizerany/pq/error.go deleted file mode 100644 index 9384ab3ef..000000000 --- a/third_party/github.com/bmizerany/pq/error.go +++ /dev/null @@ -1,108 +0,0 @@ -package pq - -import ( - "database/sql/driver" - "fmt" - "io" - "net" - "runtime" -) - -const ( - Efatal = "FATAL" - Epanic = "PANIC" - Ewarning = "WARNING" - Enotice = "NOTICE" - Edebug = "DEBUG" - Einfo = "INFO" - Elog = "LOG" -) - -type Error error - -type PGError interface { - Error() string - Fatal() bool - Get(k byte) (v string) -} -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...)))) -} - -type SimplePGError struct { - pgError -} - -func (err *SimplePGError) Error() string { - return "pq: " + err.Get('M') -} - -func errRecoverWithPGReason(err *error) { - e := recover() - switch v := e.(type) { - case nil: - // Do nothing - case *pgError: - // Return a SimplePGError in place - *err = &SimplePGError{*v} - default: - // Otherwise re-panic - panic(e) - } -} - -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 *net.OpError: - *err = driver.ErrBadConn - case error: - if v == io.EOF || v.(error).Error() == "remote error: handshake failure" { - *err = driver.ErrBadConn - } else { - *err = v - } - - default: - panic(fmt.Sprintf("unknown error: %#v", e)) - } -} diff --git a/third_party/github.com/bmizerany/pq/types.go b/third_party/github.com/bmizerany/pq/types.go deleted file mode 100644 index d37aaca79..000000000 --- a/third_party/github.com/bmizerany/pq/types.go +++ /dev/null @@ -1,317 +0,0 @@ -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 -) diff --git a/third_party/github.com/bmizerany/pq/url.go b/third_party/github.com/bmizerany/pq/url.go deleted file mode 100644 index 4e32cea8e..000000000 --- a/third_party/github.com/bmizerany/pq/url.go +++ /dev/null @@ -1,68 +0,0 @@ -package pq - -import ( - "fmt" - nurl "net/url" - "sort" - "strings" -) - -// ParseURL converts url to a connection string for driver.Open. -// Example: -// -// "postgres://bob:secret@1.2.3.4:5432/mydb?sslmode=verify-full" -// -// converts to: -// -// "user=bob password=secret host=1.2.3.4 port=5432 dbname=mydb sslmode=verify-full" -// -// A minimal example: -// -// "postgres://" -// -// This will be blank, causing driver.Open to use all of the defaults -func ParseURL(url string) (string, error) { - u, err := nurl.Parse(url) - if err != nil { - return "", err - } - - if u.Scheme != "postgres" { - return "", fmt.Errorf("invalid connection protocol: %s", u.Scheme) - } - - var kvs []string - accrue := func(k, v string) { - if v != "" { - kvs = append(kvs, k+"="+v) - } - } - - if u.User != nil { - v := u.User.Username() - accrue("user", v) - - v, _ = u.User.Password() - accrue("password", v) - } - - i := strings.Index(u.Host, ":") - if i < 0 { - accrue("host", u.Host) - } else { - accrue("host", u.Host[:i]) - accrue("port", u.Host[i+1:]) - } - - if u.Path != "" { - accrue("dbname", u.Path[1:]) - } - - q := u.Query() - for k, _ := range q { - accrue(k, q.Get(k)) - } - - sort.Strings(kvs) // Makes testing easier (not a performance concern) - return strings.Join(kvs, " "), nil -} diff --git a/third_party/github.com/bmizerany/pq/url_test.go b/third_party/github.com/bmizerany/pq/url_test.go deleted file mode 100644 index ef77ef009..000000000 --- a/third_party/github.com/bmizerany/pq/url_test.go +++ /dev/null @@ -1,53 +0,0 @@ -package pq - -import ( - "testing" -) - -func TestSimpleParseURL(t *testing.T) { - expected := "host=hostname.remote" - str, err := ParseURL("postgres://hostname.remote") - if err != nil { - t.Fatal(err) - } - - if str != expected { - t.Fatalf("unexpected result from ParseURL:\n+ %v\n- %v", str, expected) - } -} - -func TestFullParseURL(t *testing.T) { - expected := "dbname=database host=hostname.remote password=secret port=1234 user=username" - str, err := ParseURL("postgres://username:secret@hostname.remote:1234/database") - if err != nil { - t.Fatal(err) - } - - if str != expected { - t.Fatalf("unexpected result from ParseURL:\n+ %s\n- %s", str, expected) - } -} - -func TestInvalidProtocolParseURL(t *testing.T) { - _, err := ParseURL("http://hostname.remote") - switch err { - case nil: - t.Fatal("Expected an error from parsing invalid protocol") - default: - msg := "invalid connection protocol: http" - if err.Error() != msg { - t.Fatal("Unexpected error message:\n+ %s\n- %s", err.Error(), msg) - } - } -} - -func TestMinimalURL(t *testing.T) { - cs, err := ParseURL("postgres://") - if err != nil { - t.Fatal(err) - } - - if cs != "" { - t.Fatalf("expected blank connection string, got: %q", cs) - } -}