package storage import ( "context" "database/sql" "fmt" _ "modernc.org/sqlite" // SQLite driver ) type Storage struct { db *sql.DB } func Open(path string) (*Storage, error) { db, err := sql.Open("sqlite", path+"?_pragma=journal_mode(wal)&_pragma=busy_timeout(5000)") if err != nil { return nil, fmt.Errorf("open sqlite: %w", err) } if err := db.Ping(); err != nil { db.Close() return nil, fmt.Errorf("ping sqlite: %w", err) } s := &Storage{db: db} if err := s.migrate(context.Background()); err != nil { db.Close() return nil, fmt.Errorf("migrate: %w", err) } return s, nil } func (s *Storage) Close() error { return s.db.Close() } func (s *Storage) migrate(ctx context.Context) error { const ddl = ` CREATE TABLE IF NOT EXISTS show_history ( id INTEGER PRIMARY KEY AUTOINCREMENT, memo_name TEXT NOT NULL, shown_at INTEGER NOT NULL, tier INTEGER NOT NULL DEFAULT 0 ); CREATE INDEX IF NOT EXISTS idx_show_history_memo ON show_history(memo_name); CREATE INDEX IF NOT EXISTS idx_show_history_shown_at ON show_history(shown_at); ` _, err := s.db.ExecContext(ctx, ddl) return err }