Add UnderlyingConn(ctx) for safer scoped DB access

- Add UnderlyingConn method to Storage interface
- Implement in SQLiteStorage for scoped connection access
- Useful for migrations and DDL operations
- Add comprehensive tests for basic access, DDL, context cancellation, and concurrent connections
- Closes bd-66, bd-22, bd-24, bd-38, bd-39, bd-56

Amp-Thread-ID: https://ampcode.com/threads/T-e47963af-4ace-4914-a0ae-4737f77be6ff
Co-authored-by: Amp <amp@ampcode.com>
This commit is contained in:
Steve Yegge
2025-10-22 22:05:58 -07:00
parent fb64a33b99
commit 3fae41cb35
4 changed files with 243 additions and 9 deletions

View File

@@ -1963,3 +1963,40 @@ func (s *SQLiteStorage) IsClosed() bool {
func (s *SQLiteStorage) UnderlyingDB() *sql.DB {
return s.db
}
// UnderlyingConn returns a single connection from the pool for scoped use.
//
// This provides a connection with explicit lifetime boundaries, useful for:
// - One-time DDL operations (CREATE TABLE, ALTER TABLE)
// - Migration scripts that need transaction control
// - Operations that benefit from connection-level state
//
// IMPORTANT: The caller MUST close the connection when done:
//
// conn, err := storage.UnderlyingConn(ctx)
// if err != nil {
// return err
// }
// defer conn.Close()
//
// For general queries and transactions, prefer UnderlyingDB() which manages
// the connection pool automatically.
//
// EXAMPLE (extension table migration):
//
// conn, err := storage.UnderlyingConn(ctx)
// if err != nil {
// return err
// }
// defer conn.Close()
//
// _, err = conn.ExecContext(ctx, `
// CREATE TABLE IF NOT EXISTS vc_executions (
// id INTEGER PRIMARY KEY AUTOINCREMENT,
// issue_id TEXT NOT NULL,
// FOREIGN KEY (issue_id) REFERENCES issues(id) ON DELETE CASCADE
// )
// `)
func (s *SQLiteStorage) UnderlyingConn(ctx context.Context) (*sql.Conn, error) {
return s.db.Conn(ctx)
}