Skip to content

Commit 24c77b5

Browse files
- bug fix: defer cancelFunc() cancels the returned rows.Scan() too.
1 parent fe692c2 commit 24c77b5

File tree

3 files changed

+13
-98
lines changed

3 files changed

+13
-98
lines changed

conn.go

Lines changed: 5 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -195,43 +195,16 @@ func (c *Conn) PrepareContext(ctx context.Context, query string) (*Stmt, error)
195195
// The args are for any placeholder parameters in the query.
196196
func (c *Conn) QueryContext(ctx context.Context, query string, args ...interface{}) (*stdSql.Rows, error) {
197197

198-
// Create a context that is used to cancel QueryContext()
199-
cancelCtx, cancelFunc := context.WithCancel(context.Background())
200-
defer cancelFunc()
201-
202-
outChan := make(chan *stdSql.Rows)
203-
errChan := make(chan error)
204-
returnedChan := make(chan struct{}) // Used to indicate that this function has returned
205-
198+
// We can't use the same approach used in ExecContext because defer cancelFunc()
199+
// cancels rows.Scan.
206200
defer func() {
207-
returnedChan <- struct{}{}
208-
}()
209-
210-
go func() {
211-
select {
212-
case <-ctx.Done():
213-
// context has been canceled
201+
if ctx.Err() != nil {
214202
kill(c.killerPool, c.connectionID)
215-
errChan <- ctx.Err()
216-
case <-returnedChan:
217203
}
218204
}()
219205

220-
go func() {
221-
res, err := c.conn.QueryContext(cancelCtx, query, args...)
222-
if err != nil {
223-
errChan <- err
224-
return
225-
}
226-
outChan <- res
227-
}()
228-
229-
select {
230-
case err := <-errChan:
231-
return nil, err
232-
case out := <-outChan:
233-
return out, nil
234-
}
206+
return c.conn.QueryContext(ctx, query, args...)
207+
}
235208

236209
}
237210

stmt.go

Lines changed: 4 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -91,44 +91,15 @@ func (s *Stmt) Query(args ...interface{}) (*stdSql.Rows, error) {
9191
// and returns the query results as a *Rows.
9292
func (s *Stmt) QueryContext(ctx context.Context, args ...interface{}) (*stdSql.Rows, error) {
9393

94-
// Create a context that is used to cancel QueryContext()
95-
cancelCtx, cancelFunc := context.WithCancel(context.Background())
96-
defer cancelFunc()
97-
98-
outChan := make(chan *stdSql.Rows)
99-
errChan := make(chan error)
100-
returnedChan := make(chan struct{}) // Used to indicate that this function has returned
101-
94+
// We can't use the same approach used in ExecContext because defer cancelFunc()
95+
// cancels rows.Scan.
10296
defer func() {
103-
returnedChan <- struct{}{}
104-
}()
105-
106-
go func() {
107-
select {
108-
case <-ctx.Done():
109-
// context has been canceled
97+
if ctx.Err() != nil {
11098
kill(s.killerPool, s.connectionID)
111-
errChan <- ctx.Err()
112-
case <-returnedChan:
11399
}
114100
}()
115101

116-
go func() {
117-
res, err := s.QueryContext(cancelCtx, args...)
118-
if err != nil {
119-
errChan <- err
120-
return
121-
}
122-
outChan <- res
123-
}()
124-
125-
select {
126-
case err := <-errChan:
127-
return nil, err
128-
case out := <-outChan:
129-
return out, nil
130-
}
131-
102+
return s.QueryContext(ctx, args...)
132103
}
133104

134105
// QueryRow executes a prepared query statement with the given arguments.

tx.go

Lines changed: 4 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -177,44 +177,15 @@ func (tx *Tx) Query(query string, args ...interface{}) (*stdSql.Rows, error) {
177177
// QueryContext executes a query that returns rows, typically a SELECT.
178178
func (tx *Tx) QueryContext(ctx context.Context, query string, args ...interface{}) (*stdSql.Rows, error) {
179179

180-
// Create a context that is used to cancel QueryContext()
181-
cancelCtx, cancelFunc := context.WithCancel(context.Background())
182-
defer cancelFunc()
183-
184-
outChan := make(chan *stdSql.Rows)
185-
errChan := make(chan error)
186-
returnedChan := make(chan struct{}) // Used to indicate that this function has returned
187-
180+
// We can't use the same approach used in ExecContext because defer cancelFunc()
181+
// cancels rows.Scan.
188182
defer func() {
189-
returnedChan <- struct{}{}
190-
}()
191-
192-
go func() {
193-
select {
194-
case <-ctx.Done():
195-
// context has been canceled
183+
if ctx.Err() != nil {
196184
kill(tx.killerPool, tx.connectionID)
197-
errChan <- ctx.Err()
198-
case <-returnedChan:
199185
}
200186
}()
201187

202-
go func() {
203-
res, err := tx.tx.QueryContext(cancelCtx, query, args...)
204-
if err != nil {
205-
errChan <- err
206-
return
207-
}
208-
outChan <- res
209-
}()
210-
211-
select {
212-
case err := <-errChan:
213-
return nil, err
214-
case out := <-outChan:
215-
return out, nil
216-
}
217-
188+
return tx.tx.QueryContext(ctx, query, args...)
218189
}
219190

220191
// QueryRow executes a query that is expected to return at most one row.

0 commit comments

Comments
 (0)