summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/lib/pq
diff options
context:
space:
mode:
authorChristopher Speller <crspeller@gmail.com>2017-06-21 19:06:17 -0700
committerCorey Hulen <corey@hulen.com>2017-06-21 19:06:17 -0700
commit42f28ab8e374137fe3f5d25424489d879d4724f8 (patch)
tree20353f2446b506d32e6d353b72a57bf48f070389 /vendor/github.com/lib/pq
parent6b39c308d882a0aeac533f8ab1d90b48a2ae4b5a (diff)
downloadchat-42f28ab8e374137fe3f5d25424489d879d4724f8.tar.gz
chat-42f28ab8e374137fe3f5d25424489d879d4724f8.tar.bz2
chat-42f28ab8e374137fe3f5d25424489d879d4724f8.zip
Updating server dependancies (#6712)
Diffstat (limited to 'vendor/github.com/lib/pq')
-rw-r--r--vendor/github.com/lib/pq/conn.go6
-rw-r--r--vendor/github.com/lib/pq/conn_go18.go31
-rw-r--r--vendor/github.com/lib/pq/conn_test.go2
-rw-r--r--vendor/github.com/lib/pq/go18_test.go109
4 files changed, 141 insertions, 7 deletions
diff --git a/vendor/github.com/lib/pq/conn.go b/vendor/github.com/lib/pq/conn.go
index 3e3a5cabc..3b322bc06 100644
--- a/vendor/github.com/lib/pq/conn.go
+++ b/vendor/github.com/lib/pq/conn.go
@@ -506,13 +506,17 @@ func (cn *conn) checkIsInTransaction(intxn bool) {
}
func (cn *conn) Begin() (_ driver.Tx, err error) {
+ return cn.begin("")
+}
+
+func (cn *conn) begin(mode string) (_ driver.Tx, err error) {
if cn.bad {
return nil, driver.ErrBadConn
}
defer cn.errRecover(&err)
cn.checkIsInTransaction(false)
- _, commandTag, err := cn.simpleExec("BEGIN")
+ _, commandTag, err := cn.simpleExec("BEGIN" + mode)
if err != nil {
return nil, err
}
diff --git a/vendor/github.com/lib/pq/conn_go18.go b/vendor/github.com/lib/pq/conn_go18.go
index fa3755d99..ab97a104d 100644
--- a/vendor/github.com/lib/pq/conn_go18.go
+++ b/vendor/github.com/lib/pq/conn_go18.go
@@ -4,8 +4,9 @@ package pq
import (
"context"
+ "database/sql"
"database/sql/driver"
- "errors"
+ "fmt"
"io"
"io/ioutil"
)
@@ -19,6 +20,9 @@ func (cn *conn) QueryContext(ctx context.Context, query string, args []driver.Na
finish := cn.watchCancel(ctx)
r, err := cn.query(query, list)
if err != nil {
+ if finish != nil {
+ finish()
+ }
return nil, err
}
r.finish = finish
@@ -41,13 +45,30 @@ func (cn *conn) ExecContext(ctx context.Context, query string, args []driver.Nam
// Implement the "ConnBeginTx" interface
func (cn *conn) BeginTx(ctx context.Context, opts driver.TxOptions) (driver.Tx, error) {
- if opts.Isolation != 0 {
- return nil, errors.New("isolation levels not supported")
+ var mode string
+
+ switch sql.IsolationLevel(opts.Isolation) {
+ case sql.LevelDefault:
+ // Don't touch mode: use the server's default
+ case sql.LevelReadUncommitted:
+ mode = " ISOLATION LEVEL READ UNCOMMITTED"
+ case sql.LevelReadCommitted:
+ mode = " ISOLATION LEVEL READ COMMITTED"
+ case sql.LevelRepeatableRead:
+ mode = " ISOLATION LEVEL REPEATABLE READ"
+ case sql.LevelSerializable:
+ mode = " ISOLATION LEVEL SERIALIZABLE"
+ default:
+ return nil, fmt.Errorf("pq: isolation level not supported: %d", opts.Isolation)
}
+
if opts.ReadOnly {
- return nil, errors.New("read-only transactions not supported")
+ mode += " READ ONLY"
+ } else {
+ mode += " READ WRITE"
}
- tx, err := cn.Begin()
+
+ tx, err := cn.begin(mode)
if err != nil {
return nil, err
}
diff --git a/vendor/github.com/lib/pq/conn_test.go b/vendor/github.com/lib/pq/conn_test.go
index c9135b727..8c6187fc6 100644
--- a/vendor/github.com/lib/pq/conn_test.go
+++ b/vendor/github.com/lib/pq/conn_test.go
@@ -160,11 +160,11 @@ func TestPgpass(t *testing.T) {
rows, err := txn.Query("SELECT USER")
if err != nil {
txn.Rollback()
- rows.Close()
if expected != "fail" {
t.Fatalf(reason, err)
}
} else {
+ rows.Close()
if expected != "ok" {
t.Fatalf(reason, err)
}
diff --git a/vendor/github.com/lib/pq/go18_test.go b/vendor/github.com/lib/pq/go18_test.go
index cddbfb6a4..4bf6391ef 100644
--- a/vendor/github.com/lib/pq/go18_test.go
+++ b/vendor/github.com/lib/pq/go18_test.go
@@ -5,6 +5,8 @@ package pq
import (
"context"
"database/sql"
+ "runtime"
+ "strings"
"testing"
"time"
)
@@ -155,6 +157,36 @@ func TestContextCancelQuery(t *testing.T) {
}
}
+// TestIssue617 tests that a failed query in QueryContext doesn't lead to a
+// goroutine leak.
+func TestIssue617(t *testing.T) {
+ db := openTestConn(t)
+ defer db.Close()
+
+ const N = 10
+
+ numGoroutineStart := runtime.NumGoroutine()
+ for i := 0; i < N; i++ {
+ func() {
+ ctx, cancel := context.WithCancel(context.Background())
+ defer cancel()
+ _, err := db.QueryContext(ctx, `SELECT * FROM DOESNOTEXIST`)
+ pqErr, _ := err.(*Error)
+ // Expecting "pq: relation \"doesnotexist\" does not exist" error.
+ if err == nil || pqErr == nil || pqErr.Code != "42P01" {
+ t.Fatalf("expected undefined table error, got %v", err)
+ }
+ }()
+ }
+ numGoroutineFinish := runtime.NumGoroutine()
+
+ // We use N/2 and not N because the GC and other actors may increase or
+ // decrease the number of goroutines.
+ if numGoroutineFinish-numGoroutineStart >= N/2 {
+ t.Errorf("goroutine leak detected, was %d, now %d", numGoroutineStart, numGoroutineFinish)
+ }
+}
+
func TestContextCancelBegin(t *testing.T) {
db := openTestConn(t)
defer db.Close()
@@ -208,3 +240,80 @@ func TestContextCancelBegin(t *testing.T) {
}
}
}
+
+func TestTxOptions(t *testing.T) {
+ db := openTestConn(t)
+ defer db.Close()
+ ctx := context.Background()
+
+ tests := []struct {
+ level sql.IsolationLevel
+ isolation string
+ }{
+ {
+ level: sql.LevelDefault,
+ isolation: "",
+ },
+ {
+ level: sql.LevelReadUncommitted,
+ isolation: "read uncommitted",
+ },
+ {
+ level: sql.LevelReadCommitted,
+ isolation: "read committed",
+ },
+ {
+ level: sql.LevelRepeatableRead,
+ isolation: "repeatable read",
+ },
+ {
+ level: sql.LevelSerializable,
+ isolation: "serializable",
+ },
+ }
+
+ for _, test := range tests {
+ for _, ro := range []bool{true, false} {
+ tx, err := db.BeginTx(ctx, &sql.TxOptions{
+ Isolation: test.level,
+ ReadOnly: ro,
+ })
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ var isolation string
+ err = tx.QueryRow("select current_setting('transaction_isolation')").Scan(&isolation)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if test.isolation != "" && isolation != test.isolation {
+ t.Errorf("wrong isolation level: %s != %s", isolation, test.isolation)
+ }
+
+ var isRO string
+ err = tx.QueryRow("select current_setting('transaction_read_only')").Scan(&isRO)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if ro != (isRO == "on") {
+ t.Errorf("read/[write,only] not set: %t != %s for level %s",
+ ro, isRO, test.isolation)
+ }
+
+ tx.Rollback()
+ }
+ }
+
+ _, err := db.BeginTx(ctx, &sql.TxOptions{
+ Isolation: sql.LevelLinearizable,
+ })
+ if err == nil {
+ t.Fatal("expected LevelLinearizable to fail")
+ }
+ if !strings.Contains(err.Error(), "isolation level not supported") {
+ t.Errorf("Expected error to mention isolation level, got %q", err)
+ }
+}