Skip to content

Commit 04c77ed

Browse files
committed
Don't return ErrBadConn from Open()
Functionality-wise, there's no reason to return ErrBadConn from Open() since returning *any* error will make sure that the connection is not put into the pool. But there's a very good reason not to return ErrBadConn; it makes diagnosing problems during connection establishment completely impossible without either having access to the server logs or interpreting captured network traffic. This is a minor backwards compatibility breakage, since we used to return ErrBadConn in a lot of cases previously. However, there were several cases were we returned the real error instead, so any caller assuming that they would either get a nil or ErrBadConn from Open was already broken. Based on initial work from Paul Jolly, after discussions with Paul and Eric Chlebek.
1 parent b021d0e commit 04c77ed

File tree

2 files changed

+25
-16
lines changed

2 files changed

+25
-16
lines changed

conn.go

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,22 @@ func (c *conn) writeBuf(b byte) *writeBuf {
8989
}
9090

9191
func Open(name string) (_ driver.Conn, err error) {
92-
defer errRecover(&err)
92+
defer func() {
93+
// Handle any panics during connection initialization. Note that we
94+
// specifically do *not* want to use errRecover(), as that would turn
95+
// any connection errors into ErrBadConns, hiding the real error
96+
// message from the user.
97+
e := recover()
98+
if e == nil {
99+
// Do nothing
100+
return
101+
}
102+
var ok bool
103+
err, ok = e.(error)
104+
if !ok {
105+
err = fmt.Errorf("pq: unexpected error: %#v", e)
106+
}
107+
}()
93108

94109
o := make(values)
95110

conn_test.go

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -448,7 +448,7 @@ func TestNoData(t *testing.T) {
448448
}
449449
}
450450

451-
func TestError(t *testing.T) {
451+
func TestErrorDuringStartup(t *testing.T) {
452452
// Don't use the normal connection setup, this is intended to
453453
// blow up in the startup packet from a non-existent user.
454454
db, err := openTestConnConninfo("user=thisuserreallydoesntexist")
@@ -462,8 +462,11 @@ func TestError(t *testing.T) {
462462
t.Fatal("expected error")
463463
}
464464

465-
if err != driver.ErrBadConn {
466-
t.Fatalf("expected driver.ErrBadConn, got: %v", err)
465+
e, ok := err.(*Error)
466+
if !ok {
467+
t.Fatalf("expected Error, got %#v", err)
468+
} else if e.Code.Name() != "invalid_authorization_specification" {
469+
t.Fatalf("expected invalid_authorization_specification, got %s (%+v)", e.Code.Name(), err)
467470
}
468471
}
469472

@@ -1123,8 +1126,7 @@ func TestParseOpts(t *testing.T) {
11231126
func TestRuntimeParameters(t *testing.T) {
11241127
type RuntimeTestResult int
11251128
const (
1126-
ResultBadConn RuntimeTestResult = iota
1127-
ResultPanic
1129+
ResultUnknown RuntimeTestResult = iota
11281130
ResultSuccess
11291131
ResultError // other error
11301132
)
@@ -1136,10 +1138,10 @@ func TestRuntimeParameters(t *testing.T) {
11361138
expectedOutcome RuntimeTestResult
11371139
}{
11381140
// invalid parameter
1139-
{"DOESNOTEXIST=foo", "", "", ResultBadConn},
1141+
{"DOESNOTEXIST=foo", "", "", ResultError},
11401142
// we can only work with a specific value for these two
11411143
{"client_encoding=SQL_ASCII", "", "", ResultError},
1142-
{"datestyle='ISO, YDM'", "", "", ResultPanic},
1144+
{"datestyle='ISO, YDM'", "", "", ResultError},
11431145
// "options" should work exactly as it does in libpq
11441146
{"options='-c search_path=pqgotest'", "search_path", "pqgotest", ResultSuccess},
11451147
// pq should override client_encoding in this case
@@ -1167,16 +1169,8 @@ func TestRuntimeParameters(t *testing.T) {
11671169
}
11681170

11691171
tryGetParameterValue := func() (value string, outcome RuntimeTestResult) {
1170-
defer func() {
1171-
if p := recover(); p != nil {
1172-
outcome = ResultPanic
1173-
}
1174-
}()
11751172
row := db.QueryRow("SELECT current_setting($1)", test.param)
11761173
err = row.Scan(&value)
1177-
if err == driver.ErrBadConn {
1178-
return "", ResultBadConn
1179-
}
11801174
if err != nil {
11811175
return "", ResultError
11821176
}

0 commit comments

Comments
 (0)