Fixes issue #4790 where StreamRow() could panic with "send on closed
channel" when called concurrently with Close().
Solution:
- Added atomic.Bool closed flag to track Result state
- StreamRow() checks closed flag before sending to prevent most races
- Added defer/recover to gracefully handle edge case where Close()
occurs between check and send
- Rows sent after close are silently dropped (safe behavior)
This approach avoids deadlocks by not holding locks during channel
send operations, while using atomic operations for coordination.
Test now passes consistently without panics.
Fixes#4790🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Adds TestResult_CloseAfterPartialRead to demonstrate issue #4790 where
StreamRow() can panic with "send on closed channel" when called
concurrently with Close().
The test creates a scenario where:
- One goroutine continuously streams rows
- Another goroutine reads a few rows then calls Close()
This exposes the race condition where Close() can close the channel
while StreamRow() is attempting to send, causing a panic.
Temporarily removed synchronization from Result struct to demonstrate
the bug. Test FAILS with panic as expected.
Relates to #4790🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Add test demonstrating bug #4781 - RunBatchSession blocks forever
Test currently skipped as it demonstrates the bug where RunBatchSession
blocks forever if initData.Loaded channel never closes, even when the
context is cancelled. This test will be unskipped after the bug is fixed.
Related to #4781🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Fix#4781: Add context cancellation check to RunBatchSession
Changes RunBatchSession to respect context cancellation when waiting for
initialization. Previously, the function would block forever on the
initData.Loaded channel if it never closed, even when the context was
cancelled. Now uses a select statement to also check ctx.Done().
Fixes#4781🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
* Add test for #4811: query history should have bounded size
* Fix#4811: Enforce bounded size for query history
Add enforceLimit() helper that ensures history never exceeds HistorySize.
Call it from Get(), Push(), and load() to prevent unbounded memory growth
even when history is pre-populated from file or direct manipulation.
* Unskip test demonstrating bug #4805: Concurrent read and close may race
Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Fix#4805: Add synchronization for concurrent StreamRow and Close
The sync.Once in Close() only prevents multiple Close() calls, but
doesn't coordinate with StreamRow() operations. Added a mutex and
closed flag to prevent race conditions when one goroutine streams
rows while another closes the result.
The fix:
- Added mutex (mu) and closed flag to Result struct
- StreamRow checks closed flag before streaming (with RLock)
- Close sets closed flag (with Lock) before closing channel
This prevents "send on closed channel" panics and data races.
Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
- JSON output format has changed to move the rows to under a `rows` property, with timing information under the `metadata` property
- Update timing display to show rows returned and rows fetched, as well as adding verbose mode which lists all scans
- Use enums for output mode and timing mode - timing is now either `on`, `off` or `verbose`
- Bugfix: ensure error is returned from ExecuteSystemClientCall. Closes#4246
- Execute RefreshConnections asyncronously
- Add connection_state table to indicate the loading state of connections
- Optimise RefreshConnections by cloning connection schemas
- Add locking to ensure only a single instance of RefreshConnections runs
- Start executing queries without waiting for connections to load, add smart error handling to wait for required connection
- Optimise autocomplete for high connection count
- Autocomplete and inspect data available before all conections are refreshed
- Update file watcher to respond to CHMOD, so thaat it pickes up deletion of file contents
Closes#3394Closes#3267
STEAMPIPE_CACHE environment variable resolves to service cache enabled as well as client cache enabled
service cache enabled is used by the plugin manager to enable/disable caching on the plugins during startup (runtime toggle is not allowed) - with a max_ttl
client cache enabled is used to enable/disable the cache on the database connection (fdw)
A TTL can also be set on the client side capped to max_ttl on the server