Revert nil context support

query-exec-mode
bakape 2020-01-11 16:53:50 +02:00
parent 9372218107
commit 9decdbc2ec
6 changed files with 731 additions and 883 deletions

View File

@ -11,13 +11,13 @@ low-level access to PostgreSQL functionality.
## Example Usage ## Example Usage
```go ```go
pgConn, err := pgconn.Connect(nil, os.Getenv("DATABASE_URL")) pgConn, err := pgconn.Connect(context.Background(), os.Getenv("DATABASE_URL"))
if err != nil { if err != nil {
log.Fatalln("pgconn failed to connect:", err) log.Fatalln("pgconn failed to connect:", err)
} }
defer pgConn.Close() defer pgConn.Close()
result := pgConn.ExecParams(nil, "SELECT email FROM users WHERE id=$1", [][]byte{[]byte("123")}, nil, nil, nil) result := pgConn.ExecParams(context.Background(), "SELECT email FROM users WHERE id=$1", [][]byte{[]byte("123")}, nil, nil, nil)
for result.NextRow() { for result.NextRow() {
fmt.Println("User 123 has email:", string(result.Values()[0])) fmt.Println("User 123 has email:", string(result.Values()[0]))
} }

View File

@ -14,16 +14,9 @@ func BenchmarkConnect(b *testing.B) {
benchmarks := []struct { benchmarks := []struct {
name string name string
env string env string
ctx context.Context
}{ }{
// The first benchmark in the list sometimes executes faster, no matter how {"Unix socket", "PGX_TEST_UNIX_SOCKET_CONN_STRING"},
// you reorder it. Nil context is still faster on average. {"TCP", "PGX_TEST_TCP_CONN_STRING"},
//
// Using and empty context other than context.Background() to compare.
{"Unix socket", "PGX_TEST_UNIX_SOCKET_CONN_STRING", context.TODO()},
{"TCP", "PGX_TEST_TCP_CONN_STRING", context.TODO()},
{"Unix socket nil context", "PGX_TEST_UNIX_SOCKET_CONN_STRING", nil},
{"TCP nil context", "PGX_TEST_TCP_CONN_STRING", nil},
} }
for _, bm := range benchmarks { for _, bm := range benchmarks {
@ -35,10 +28,10 @@ func BenchmarkConnect(b *testing.B) {
} }
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
conn, err := pgconn.Connect(bm.ctx, connString) conn, err := pgconn.Connect(context.Background(), connString)
require.Nil(b, err) require.Nil(b, err)
err = conn.Close(bm.ctx) err = conn.Close(context.Background())
require.Nil(b, err) require.Nil(b, err)
} }
}) })
@ -51,9 +44,10 @@ func BenchmarkExec(b *testing.B) {
name string name string
ctx context.Context ctx context.Context
}{ }{
// Using and empty context other than context.Background() to compare. // Using an empty context other than context.Background() to compare
// performance
{"background context", context.Background()},
{"empty context", context.TODO()}, {"empty context", context.TODO()},
{"nil context", nil},
} }
for _, bm := range benchmarks { for _, bm := range benchmarks {
@ -156,9 +150,10 @@ func BenchmarkExecPrepared(b *testing.B) {
name string name string
ctx context.Context ctx context.Context
}{ }{
// Using and empty context other than context.Background() to compare. // Using an empty context other than context.Background() to compare
// performance
{"background context", context.Background()},
{"empty context", context.TODO()}, {"empty context", context.TODO()},
{"nil context", nil},
} }
for _, bm := range benchmarks { for _, bm := range benchmarks {

1
doc.go
View File

@ -22,7 +22,6 @@ Context Support
All potentially blocking operations take a context.Context. If a context is canceled while the method is in progress the All potentially blocking operations take a context.Context. If a context is canceled while the method is in progress the
method immediately returns. In most circumstances, this will close the underlying connection. method immediately returns. In most circumstances, this will close the underlying connection.
A nil context can be passed for convenience. This has the same effect as passing context.Background().
The CancelRequest method may be used to request the PostgreSQL server cancel an in-progress query without forcing the The CancelRequest method may be used to request the PostgreSQL server cancel an in-progress query without forcing the
client to abort. client to abort.

View File

@ -29,25 +29,3 @@ func ensureConnValid(t *testing.T, pgConn *pgconn.PgConn) {
assert.Equal(t, "2", string(result.Rows[1][0])) assert.Equal(t, "2", string(result.Rows[1][0]))
assert.Equal(t, "3", string(result.Rows[2][0])) assert.Equal(t, "3", string(result.Rows[2][0]))
} }
// Run subtest both with a context.Background() and nil context
func splitOnContext(t *testing.T, test func(t *testing.T, ctx context.Context)) {
t.Helper()
cases := [...]struct {
name string
ctx context.Context
}{
{"background context", context.Background()},
{"nil context", nil},
}
for i := range cases {
c := cases[i]
t.Run(c.name, func(t *testing.T) {
t.Helper()
t.Parallel()
test(t, c.ctx)
})
}
}

View File

@ -116,10 +116,6 @@ func ConnectConfig(ctx context.Context, config *Config) (pgConn *PgConn, err err
panic("config must be created by ParseConfig") panic("config must be created by ParseConfig")
} }
if ctx == nil {
ctx = context.Background()
}
// Simplify usage by treating primary config and fallbacks the same. // Simplify usage by treating primary config and fallbacks the same.
fallbackConfigs := []*FallbackConfig{ fallbackConfigs := []*FallbackConfig{
{ {
@ -366,9 +362,7 @@ func (pgConn *PgConn) SendBytes(ctx context.Context, buf []byte) error {
} }
defer pgConn.unlock() defer pgConn.unlock()
switch ctx { if ctx != context.Background() {
case nil, context.Background():
default:
select { select {
case <-ctx.Done(): case <-ctx.Done():
return &contextAlreadyDoneError{err: ctx.Err()} return &contextAlreadyDoneError{err: ctx.Err()}
@ -400,9 +394,7 @@ func (pgConn *PgConn) ReceiveMessage(ctx context.Context) (pgproto3.BackendMessa
} }
defer pgConn.unlock() defer pgConn.unlock()
switch ctx { if ctx != context.Background() {
case nil, context.Background():
default:
select { select {
case <-ctx.Done(): case <-ctx.Done():
return nil, &contextAlreadyDoneError{err: ctx.Err()} return nil, &contextAlreadyDoneError{err: ctx.Err()}
@ -501,9 +493,7 @@ func (pgConn *PgConn) Close(ctx context.Context) error {
defer pgConn.conn.Close() defer pgConn.conn.Close()
switch ctx { if ctx != context.Background() {
case nil, context.Background():
default:
pgConn.contextWatcher.Watch(ctx) pgConn.contextWatcher.Watch(ctx)
defer pgConn.contextWatcher.Unwatch() defer pgConn.contextWatcher.Unwatch()
} }
@ -602,9 +592,7 @@ func (pgConn *PgConn) Prepare(ctx context.Context, name, sql string, paramOIDs [
} }
defer pgConn.unlock() defer pgConn.unlock()
switch ctx { if ctx != context.Background() {
case nil, context.Background():
default:
select { select {
case <-ctx.Done(): case <-ctx.Done():
return nil, &contextAlreadyDoneError{err: ctx.Err()} return nil, &contextAlreadyDoneError{err: ctx.Err()}
@ -693,19 +681,13 @@ func (pgConn *PgConn) CancelRequest(ctx context.Context) error {
// the connection config. This is important in high availability configurations where fallback connections may be // the connection config. This is important in high availability configurations where fallback connections may be
// specified or DNS may be used to load balance. // specified or DNS may be used to load balance.
serverAddr := pgConn.conn.RemoteAddr() serverAddr := pgConn.conn.RemoteAddr()
_ctx := ctx cancelConn, err := pgConn.config.DialFunc(ctx, serverAddr.Network(), serverAddr.String())
if _ctx == nil {
_ctx = context.Background()
}
cancelConn, err := pgConn.config.DialFunc(_ctx, serverAddr.Network(), serverAddr.String())
if err != nil { if err != nil {
return err return err
} }
defer cancelConn.Close() defer cancelConn.Close()
switch ctx { if ctx != context.Background() {
case nil, context.Background():
default:
contextWatcher := ctxwatch.NewContextWatcher( contextWatcher := ctxwatch.NewContextWatcher(
func() { cancelConn.SetDeadline(time.Date(1, 1, 1, 1, 1, 1, 1, time.UTC)) }, func() { cancelConn.SetDeadline(time.Date(1, 1, 1, 1, 1, 1, 1, time.UTC)) },
func() { cancelConn.SetDeadline(time.Time{}) }, func() { cancelConn.SetDeadline(time.Time{}) },
@ -740,9 +722,7 @@ func (pgConn *PgConn) WaitForNotification(ctx context.Context) error {
} }
defer pgConn.unlock() defer pgConn.unlock()
switch ctx { if ctx != context.Background() {
case nil, context.Background():
default:
select { select {
case <-ctx.Done(): case <-ctx.Done():
return ctx.Err() return ctx.Err()
@ -784,11 +764,7 @@ func (pgConn *PgConn) Exec(ctx context.Context, sql string) *MultiResultReader {
ctx: ctx, ctx: ctx,
} }
multiResult := &pgConn.multiResultReader multiResult := &pgConn.multiResultReader
switch ctx { if ctx != context.Background() {
case nil:
pgConn.multiResultReader.ctx = context.Background()
case context.Background():
default:
select { select {
case <-ctx.Done(): case <-ctx.Done():
multiResult.closed = true multiResult.closed = true
@ -882,9 +858,6 @@ func (pgConn *PgConn) execExtendedPrefix(ctx context.Context, paramValues [][]by
ctx: ctx, ctx: ctx,
} }
result := &pgConn.resultReader result := &pgConn.resultReader
if ctx == nil {
pgConn.resultReader.ctx = context.Background()
}
if err := pgConn.lock(); err != nil { if err := pgConn.lock(); err != nil {
result.concludeCommand(nil, err) result.concludeCommand(nil, err)
@ -899,9 +872,7 @@ func (pgConn *PgConn) execExtendedPrefix(ctx context.Context, paramValues [][]by
return result return result
} }
switch ctx { if ctx != context.Background() {
case nil, context.Background():
default:
select { select {
case <-ctx.Done(): case <-ctx.Done():
result.concludeCommand(nil, &contextAlreadyDoneError{err: ctx.Err()}) result.concludeCommand(nil, &contextAlreadyDoneError{err: ctx.Err()})
@ -937,9 +908,7 @@ func (pgConn *PgConn) CopyTo(ctx context.Context, w io.Writer, sql string) (Comm
return nil, err return nil, err
} }
switch ctx { if ctx != context.Background() {
case nil, context.Background():
default:
select { select {
case <-ctx.Done(): case <-ctx.Done():
pgConn.unlock() pgConn.unlock()
@ -1000,9 +969,7 @@ func (pgConn *PgConn) CopyFrom(ctx context.Context, r io.Reader, sql string) (Co
} }
defer pgConn.unlock() defer pgConn.unlock()
switch ctx { if ctx != context.Background() {
case nil, context.Background():
default:
select { select {
case <-ctx.Done(): case <-ctx.Done():
return nil, &contextAlreadyDoneError{err: ctx.Err()} return nil, &contextAlreadyDoneError{err: ctx.Err()}
@ -1396,11 +1363,8 @@ func (pgConn *PgConn) ExecBatch(ctx context.Context, batch *Batch) *MultiResultR
ctx: ctx, ctx: ctx,
} }
multiResult := &pgConn.multiResultReader multiResult := &pgConn.multiResultReader
switch ctx {
case nil: if ctx != context.Background() {
pgConn.multiResultReader.ctx = context.Background()
case context.Background():
default:
select { select {
case <-ctx.Done(): case <-ctx.Done():
multiResult.closed = true multiResult.closed = true

File diff suppressed because it is too large Load Diff