Skip to content

Commit 400af43

Browse files
authored
Merge pull request #594 from dolthub/aaron/join-iter-memory-leak
sql/plan: Fix join iterators to always Close() their secondary RowIter. Fix Subquery to Dispose its subquery.
2 parents 4b5e169 + 60e129c commit 400af43

File tree

6 files changed

+37
-9
lines changed

6 files changed

+37
-9
lines changed

enginetest/enginetests.go

+2
Original file line numberDiff line numberDiff line change
@@ -3630,6 +3630,8 @@ func TestQueryWithContext(t *testing.T, ctx *sql.Context, e *sqle.Engine, q stri
36303630
require.NoError(err, "Unexpected error for query %s", q)
36313631

36323632
checkResults(t, require, expected, expectedCols, sch, rows, q)
3633+
3634+
require.Equal(0, ctx.Memory.NumCaches())
36333635
}
36343636

36353637
func checkResults(t *testing.T, require *require.Assertions, expected []sql.Row, expectedCols []*sql.Column, sch sql.Schema, rows []sql.Row, q string) {

sql/memory.go

+6
Original file line numberDiff line numberDiff line change
@@ -216,3 +216,9 @@ func (m *MemoryManager) Free() {
216216
}
217217
}
218218
}
219+
220+
func (m *MemoryManager) NumCaches() int {
221+
m.mu.RLock()
222+
defer m.mu.RUnlock()
223+
return len(m.caches)
224+
}

sql/plan/indexed_join.go

+4
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,11 @@ func (i *indexedJoinIter) loadSecondary() (sql.Row, error) {
182182
secondaryRow, err := i.secondary.Next()
183183
if err != nil {
184184
if err == io.EOF {
185+
err = i.secondary.Close(i.ctx)
185186
i.secondary = nil
187+
if err != nil {
188+
return nil, err
189+
}
186190
i.primaryRow = nil
187191
return nil, io.EOF
188192
}

sql/plan/join.go

+12-1
Original file line numberDiff line numberDiff line change
@@ -527,14 +527,21 @@ func (i *joinIter) loadSecondaryInMemory() error {
527527
break
528528
}
529529
if err != nil {
530+
iter.Close(i.ctx)
530531
return err
531532
}
532533

533534
if err := i.secondaryRows.Add(row); err != nil {
535+
iter.Close(i.ctx)
534536
return err
535537
}
536538
}
537539

540+
err = iter.Close(i.ctx)
541+
if err != nil {
542+
return err
543+
}
544+
538545
if len(i.secondaryRows.Get()) == 0 {
539546
return io.EOF
540547
}
@@ -578,7 +585,11 @@ func (i *joinIter) loadSecondary() (row sql.Row, err error) {
578585
rightRow, err := i.secondary.Next()
579586
if err != nil {
580587
if err == io.EOF {
588+
err = i.secondary.Close(i.ctx)
581589
i.secondary = nil
590+
if err != nil {
591+
return nil, err
592+
}
582593
i.primaryRow = nil
583594

584595
// If we got to this point and the mode is still unknown it means
@@ -679,7 +690,6 @@ func (i *joinIter) buildRow(primary, secondary sql.Row) sql.Row {
679690

680691
func (i *joinIter) Close(ctx *sql.Context) (err error) {
681692
i.Dispose()
682-
i.secondary = nil
683693

684694
if i.primary != nil {
685695
if err = i.primary.Close(ctx); err != nil {
@@ -693,6 +703,7 @@ func (i *joinIter) Close(ctx *sql.Context) (err error) {
693703

694704
if i.secondary != nil {
695705
err = i.secondary.Close(ctx)
706+
i.secondary = nil
696707
}
697708

698709
return err

sql/plan/process.go

+12-8
Original file line numberDiff line numberDiff line change
@@ -274,19 +274,23 @@ func (i *trackedRowIter) done() {
274274
}
275275
}
276276

277-
func (i *trackedRowIter) Dispose() {
278-
if i.node != nil {
279-
Inspect(i.node, func(node sql.Node) bool {
280-
sql.Dispose(node)
281-
return true
282-
})
283-
}
284-
InspectExpressions(i.node, func(e sql.Expression) bool {
277+
func disposeNode(n sql.Node) {
278+
Inspect(n, func(node sql.Node) bool {
279+
sql.Dispose(node)
280+
return true
281+
})
282+
InspectExpressions(n, func(e sql.Expression) bool {
285283
sql.Dispose(e)
286284
return true
287285
})
288286
}
289287

288+
func (i *trackedRowIter) Dispose() {
289+
if i.node != nil {
290+
disposeNode(i.node)
291+
}
292+
}
293+
290294
func (i *trackedRowIter) Next() (sql.Row, error) {
291295
row, err := i.iter.Next()
292296
if err != nil {

sql/plan/subquery.go

+1
Original file line numberDiff line numberDiff line change
@@ -439,4 +439,5 @@ func (s *Subquery) Dispose() {
439439
s.disposeFunc()
440440
s.disposeFunc = nil
441441
}
442+
disposeNode(s.Query)
442443
}

0 commit comments

Comments
 (0)