diff options
| author | Peter Stone <thepeterstone@gmail.com> | 2026-03-21 21:24:02 +0000 |
|---|---|---|
| committer | Peter Stone <thepeterstone@gmail.com> | 2026-03-21 21:24:02 +0000 |
| commit | 764d4d2d07449aec72c87afe941b7c63ea05e08c (patch) | |
| tree | 042b157cfff2ab358b5bb9b891f26944133b7065 /internal/store/sqlite.go | |
| parent | 5f4f59fc6302a4e44773d4a939ae7b3304d61f1f (diff) | |
feat: Phase 1 — remove bug feature and dead code
- Delete Bug struct, BugToAtom, SourceBug, TypeBug, TypeNote
- Remove bug store methods (SaveBug, GetBugs, ResolveBug, etc.)
- Remove HandleGetBugs, HandleReportBug, bug branches in handlers
- Remove bug routes, bugs.html template, bug UI from index.html
- Remove AddMealToPlanner stub + interface method
- Migration 018: DROP TABLE IF EXISTS bugs
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Diffstat (limited to 'internal/store/sqlite.go')
| -rw-r--r-- | internal/store/sqlite.go | 114 |
1 files changed, 42 insertions, 72 deletions
diff --git a/internal/store/sqlite.go b/internal/store/sqlite.go index 366b24e..33edbf2 100644 --- a/internal/store/sqlite.go +++ b/internal/store/sqlite.go @@ -73,20 +73,54 @@ func (s *Store) DB() *sql.DB { return s.db } -// runMigrations executes all migration files in order +// runMigrations executes all migration files in order, skipping already-applied ones. func (s *Store) runMigrations() error { - // Get migration files from configured directory + // Check if schema_migrations exists before creating it — used to detect legacy DBs. + var trackingExists int + s.db.QueryRow(`SELECT COUNT(*) FROM sqlite_master WHERE type='table' AND name='schema_migrations'`).Scan(&trackingExists) + + if _, err := s.db.Exec(`CREATE TABLE IF NOT EXISTS schema_migrations ( + filename TEXT PRIMARY KEY, + applied_at DATETIME DEFAULT CURRENT_TIMESTAMP + )`); err != nil { + return fmt.Errorf("failed to create schema_migrations table: %w", err) + } + pattern := filepath.Join(s.migrationDir, "*.sql") migrationFiles, err := filepath.Glob(pattern) if err != nil { return fmt.Errorf("failed to read migration files: %w", err) } - // Sort migrations by filename sort.Strings(migrationFiles) - // Execute each migration + // If schema_migrations was just created on a pre-existing DB (legacy), seed all + // current migration filenames as applied so we don't re-run them. + if trackingExists == 0 { + var existingTables int + s.db.QueryRow(`SELECT COUNT(*) FROM sqlite_master WHERE type='table' AND name != 'schema_migrations'`).Scan(&existingTables) + if existingTables > 0 { + for _, file := range migrationFiles { + name := filepath.Base(file) + if _, err := s.db.Exec(`INSERT OR IGNORE INTO schema_migrations (filename) VALUES (?)`, name); err != nil { + return fmt.Errorf("failed to seed migration record %s: %w", name, err) + } + } + return nil + } + } + for _, file := range migrationFiles { + name := filepath.Base(file) + + var count int + if err := s.db.QueryRow(`SELECT COUNT(*) FROM schema_migrations WHERE filename = ?`, name).Scan(&count); err != nil { + return fmt.Errorf("failed to check migration %s: %w", name, err) + } + if count > 0 { + continue // already applied + } + content, err := os.ReadFile(file) if err != nil { return fmt.Errorf("failed to read migration %s: %w", file, err) @@ -95,6 +129,10 @@ func (s *Store) runMigrations() error { if _, err := s.db.Exec(string(content)); err != nil { return fmt.Errorf("failed to execute migration %s: %w", file, err) } + + if _, err := s.db.Exec(`INSERT INTO schema_migrations (filename) VALUES (?)`, name); err != nil { + return fmt.Errorf("failed to record migration %s: %w", name, err) + } } return nil @@ -588,74 +626,6 @@ func (s *Store) ClearSyncToken(service string) error { return err } -// Bug represents a user-reported bug -type Bug struct { - ID int64 - Description string - CreatedAt time.Time - ResolvedAt *time.Time -} - -// SaveBug saves a new bug report -func (s *Store) SaveBug(description string) error { - _, err := s.db.Exec(`INSERT INTO bugs (description) VALUES (?)`, description) - return err -} - -// GetBugs retrieves all bugs, newest first -func (s *Store) GetBugs() ([]Bug, error) { - rows, err := s.db.Query(`SELECT id, description, created_at, resolved_at FROM bugs ORDER BY created_at DESC`) - if err != nil { - return nil, err - } - defer func() { _ = rows.Close() }() - - var bugs []Bug - for rows.Next() { - var b Bug - var resolvedAt sql.NullTime - if err := rows.Scan(&b.ID, &b.Description, &b.CreatedAt, &resolvedAt); err != nil { - return nil, err - } - if resolvedAt.Valid { - b.ResolvedAt = &resolvedAt.Time - } - bugs = append(bugs, b) - } - return bugs, rows.Err() -} - -// GetUnresolvedBugs retrieves bugs that haven't been resolved yet -func (s *Store) GetUnresolvedBugs() ([]Bug, error) { - rows, err := s.db.Query(`SELECT id, description, created_at FROM bugs WHERE resolved_at IS NULL ORDER BY created_at DESC`) - if err != nil { - return nil, err - } - defer func() { _ = rows.Close() }() - - var bugs []Bug - for rows.Next() { - var b Bug - if err := rows.Scan(&b.ID, &b.Description, &b.CreatedAt); err != nil { - return nil, err - } - bugs = append(bugs, b) - } - return bugs, rows.Err() -} - -// ResolveBug marks a bug as resolved -func (s *Store) ResolveBug(id int64) error { - _, err := s.db.Exec(`UPDATE bugs SET resolved_at = CURRENT_TIMESTAMP WHERE id = ?`, id) - return err -} - -// UnresolveBug marks a bug as unresolved (reopens it) -func (s *Store) UnresolveBug(id int64) error { - _, err := s.db.Exec(`UPDATE bugs SET resolved_at = NULL WHERE id = ?`, id) - return err -} - // UserShoppingItem represents a user-added shopping item type UserShoppingItem struct { ID int64 |
