Add auto-migration for dirty_issues table
Implement automatic database migration to add the dirty_issues table for existing databases that were created before the incremental export feature (bd-39) was implemented. Changes: - Add migrateDirtyIssuesTable() function in sqlite.go - Check for dirty_issues table existence on database initialization - Create table and index if missing (silent migration) - Call migration after schema initialization in New() The migration: - Queries sqlite_master to check if dirty_issues table exists - If missing, creates the table with proper schema and index - Happens automatically on first database access after upgrade - No user intervention required - Fails safely if table already exists (no-op) Testing: - Created test database without dirty_issues table - Verified table was auto-created on first command - Verified issue was properly marked dirty - All existing tests pass This makes the incremental export feature (bd-39) work seamlessly with existing databases without requiring manual migration steps. Closes bd-51 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -48,6 +48,11 @@ func New(path string) (*SQLiteStorage, error) {
|
||||
return nil, fmt.Errorf("failed to initialize schema: %w", err)
|
||||
}
|
||||
|
||||
// Migrate existing databases to add dirty_issues table if missing
|
||||
if err := migrateDirtyIssuesTable(db); err != nil {
|
||||
return nil, fmt.Errorf("failed to migrate dirty_issues table: %w", err)
|
||||
}
|
||||
|
||||
// Get next ID
|
||||
nextID := getNextID(db)
|
||||
|
||||
@@ -57,6 +62,41 @@ func New(path string) (*SQLiteStorage, error) {
|
||||
}, nil
|
||||
}
|
||||
|
||||
// migrateDirtyIssuesTable checks if the dirty_issues table exists and creates it if missing.
|
||||
// This ensures existing databases created before the incremental export feature get migrated automatically.
|
||||
func migrateDirtyIssuesTable(db *sql.DB) error {
|
||||
// Check if dirty_issues table exists
|
||||
var tableName string
|
||||
err := db.QueryRow(`
|
||||
SELECT name FROM sqlite_master
|
||||
WHERE type='table' AND name='dirty_issues'
|
||||
`).Scan(&tableName)
|
||||
|
||||
if err == sql.ErrNoRows {
|
||||
// Table doesn't exist, create it
|
||||
_, err := db.Exec(`
|
||||
CREATE TABLE dirty_issues (
|
||||
issue_id TEXT PRIMARY KEY,
|
||||
marked_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (issue_id) REFERENCES issues(id) ON DELETE CASCADE
|
||||
);
|
||||
CREATE INDEX idx_dirty_issues_marked_at ON dirty_issues(marked_at);
|
||||
`)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create dirty_issues table: %w", err)
|
||||
}
|
||||
// Table created successfully - no need to log, happens silently
|
||||
return nil
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to check for dirty_issues table: %w", err)
|
||||
}
|
||||
|
||||
// Table exists, no migration needed
|
||||
return nil
|
||||
}
|
||||
|
||||
// getNextID determines the next issue ID to use
|
||||
func getNextID(db *sql.DB) int {
|
||||
// Get prefix from config, default to "bd"
|
||||
|
||||
Reference in New Issue
Block a user