filer: report a SQL listing that fails partway through (#12654)

* filer: report a SQL listing that fails partway through

ListDirectoryPrefixedEntries never checked rows.Err() after its rows.Next()
loop. When the result set failed partway, for example on a lost
connection, rows.Next() returned false and the listing returned the
entries read so far with a nil error, so callers saw a shorter directory
instead of an error. Check rows.Err() once the loop has run to the end,
as the scan in abstract_sql_store_scan.go already does. A listing the
callback stopped on purpose is left alone: rows.Err() would return a
canceled request context's error there.

This covers every store built on AbstractSqlStore (mysql, mysql2,
postgres, postgres2, sqlite).

Signed-off-by: anant <170962632+antcybersec@users.noreply.github.com>

* filer: wait for the canceled SQL listing to release its rows in the test

A fixed sleep let the callback return before database/sql closed the
rows, so a listing that always consulted rows.Err could still pass.
Wait, bounded, until the connection is back in the pool instead.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Signed-off-by: anant <170962632+antcybersec@users.noreply.github.com>
Co-authored-by: anant <170962632+antcybersec@users.noreply.github.com>
Co-authored-by: Chris Lu <chrislusf@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
authored and GitHub committed 2026-11-14 11:14:54 -08:00
1 parent b42993d24a
commit b3a58506aa
2 files changed
+85

No files matched your search

@@ -428,6 +428,7 @@ func (store *AbstractSqlStore) ListDirectoryPrefixedEntries(ctx context.Context,
}
defer rows.Close()
stoppedEarly := false
for rows.Next() {
var name string
var data []byte
@@ -452,10 +453,20 @@ func (store *AbstractSqlStore) ListDirectoryPrefixedEntries(ctx context.Context,
}
if !resEachEntryFunc {
stoppedEarly = true
break
}
}
// rows.Next also returns false when the result set fails partway, for
// example on a lost connection; that must not read as the end of the
// directory. A listing the callback stopped on purpose has no such error
// to report (rows.Err would return a canceled context's error instead).
if err == nil && !stoppedEarly {
if rowsErr := rows.Err(); rowsErr != nil {
err = fmt.Errorf("list %s: %w", dirPath, rowsErr)
}
}
return lastFileName, err
}