package database import ( "context" "fmt" "time" "github.com/jackc/pgx/v5/pgxpool" ) type Artist struct { ID string ExternalID string Name string ArtistType string Country string Genres []string ImageURL string MonitorState MonitorState CreatedAt time.Time UpdatedAt time.Time } type ArtistRepository struct { pool *pgxpool.Pool } func NewArtistRepository(pool *pgxpool.Pool) *ArtistRepository { return &ArtistRepository{pool: pool} } func (r *ArtistRepository) Create(ctx context.Context, a *Artist) error { _, err := r.pool.Exec(ctx, `INSERT INTO artists (external_id, name, artist_type, country, genres, image_url, monitor_state) VALUES ($1, $2, $3, $4, $5, $6, $7) ON CONFLICT (external_id) DO UPDATE SET name = EXCLUDED.name, artist_type = EXCLUDED.artist_type, country = EXCLUDED.country, genres = EXCLUDED.genres, image_url = EXCLUDED.image_url, monitor_state = CASE WHEN artists.monitor_state = 'excluded' THEN artists.monitor_state WHEN artists.monitor_state = 'monitored' THEN artists.monitor_state ELSE EXCLUDED.monitor_state END, updated_at = NOW() RETURNING id, created_at, updated_at`, a.ExternalID, a.Name, a.ArtistType, a.Country, a.Genres, a.ImageURL, a.MonitorState, ) if err != nil { return fmt.Errorf("creating artist: %w", err) } return nil } func (r *ArtistRepository) GetByExternalID(ctx context.Context, externalID string) (*Artist, error) { a := &Artist{} err := r.pool.QueryRow(ctx, `SELECT id, external_id, name, artist_type, country, genres, image_url, monitor_state, created_at, updated_at FROM artists WHERE external_id = $1`, externalID, ).Scan(&a.ID, &a.ExternalID, &a.Name, &a.ArtistType, &a.Country, &a.Genres, &a.ImageURL, &a.MonitorState, &a.CreatedAt, &a.UpdatedAt) if err != nil { return nil, fmt.Errorf("getting artist: %w", err) } return a, nil } func (r *ArtistRepository) GetAll(ctx context.Context) ([]*Artist, error) { rows, err := r.pool.Query(ctx, `SELECT id, external_id, name, artist_type, country, genres, image_url, monitor_state, created_at, updated_at FROM artists ORDER BY name ASC`, ) if err != nil { return nil, fmt.Errorf("listing artists: %w", err) } defer rows.Close() var artists []*Artist for rows.Next() { a := &Artist{} if err := rows.Scan(&a.ID, &a.ExternalID, &a.Name, &a.ArtistType, &a.Country, &a.Genres, &a.ImageURL, &a.MonitorState, &a.CreatedAt, &a.UpdatedAt); err != nil { return nil, fmt.Errorf("scanning artist: %w", err) } artists = append(artists, a) } return artists, nil } func (r *ArtistRepository) GetByID(ctx context.Context, id string) (*Artist, error) { a := &Artist{} err := r.pool.QueryRow(ctx, `SELECT id, external_id, name, artist_type, country, genres, image_url, monitor_state, created_at, updated_at FROM artists WHERE id = $1`, id, ).Scan(&a.ID, &a.ExternalID, &a.Name, &a.ArtistType, &a.Country, &a.Genres, &a.ImageURL, &a.MonitorState, &a.CreatedAt, &a.UpdatedAt) if err != nil { return nil, fmt.Errorf("getting artist: %w", err) } return a, nil }