diff options
| author | Martin Kagamino Lehoux <martin@lehoux.net> | 2026-08-14 19:40:42 +0200 |
|---|---|---|
| committer | Martin Kagamino Lehoux <martin@lehoux.net> | 2026-08-14 19:40:42 +0200 |
| commit | 3eebdfbe4a6033a0bef0acdaa13061dd830c65d6 (patch) | |
| tree | 498d450b4a722793bb3d3efebfdd9224f7252a08 /official_climb/repository.go | |
| parent | eac1145e29e1a2a2ff5d9654ca010071a5840843 (diff) | |
refactor: split official climb concerns
Diffstat (limited to 'official_climb/repository.go')
| -rw-r--r-- | official_climb/repository.go | 97 |
1 files changed, 97 insertions, 0 deletions
diff --git a/official_climb/repository.go b/official_climb/repository.go new file mode 100644 index 0000000..1feb6a9 --- /dev/null +++ b/official_climb/repository.go @@ -0,0 +1,97 @@ +package official_climb + +import ( + "database/sql" + "fmt" + "time" + + "github.com/jftuga/geodist" +) + +const columns = "id, name, start_latitude, start_longitude, end_latitude, end_longitude, created_at, updated_at" + +func Create(db *sql.DB, climb OfficialClimb) (OfficialClimb, error) { + if err := climb.validate(); err != nil { + return OfficialClimb{}, err + } + result, err := db.Exec(` + INSERT INTO official_climbs (name, start_latitude, start_longitude, end_latitude, end_longitude) + VALUES (?, ?, ?, ?, ?) + `, climb.Name, climb.StartCoord.Lat, climb.StartCoord.Lon, climb.EndCoord.Lat, climb.EndCoord.Lon) + if err != nil { + return OfficialClimb{}, fmt.Errorf("create official climb: %w", err) + } + id, err := result.LastInsertId() + if err != nil { + return OfficialClimb{}, fmt.Errorf("read official climb id: %w", err) + } + created, found, err := GetByID(db, id) + if err != nil { + return OfficialClimb{}, err + } + if !found { + return OfficialClimb{}, fmt.Errorf("official climb %d was not found after creation", id) + } + return created, nil +} + +func List(db *sql.DB) ([]OfficialClimb, error) { + rows, err := db.Query("SELECT " + columns + " FROM official_climbs ORDER BY id") + if err != nil { + return nil, fmt.Errorf("list official climbs: %w", err) + } + defer rows.Close() + + climbs := make([]OfficialClimb, 0) + for rows.Next() { + climb, err := scan(rows) + if err != nil { + return nil, err + } + climbs = append(climbs, climb) + } + if err := rows.Err(); err != nil { + return nil, fmt.Errorf("iterate official climbs: %w", err) + } + return climbs, nil +} + +func GetByID(db *sql.DB, id int64) (OfficialClimb, bool, error) { + row := db.QueryRow("SELECT "+columns+" FROM official_climbs WHERE id = ?", id) + climb, err := scan(row) + if err == sql.ErrNoRows { + return OfficialClimb{}, false, nil + } + if err != nil { + return OfficialClimb{}, false, fmt.Errorf("get official climb %d: %w", id, err) + } + return climb, true, nil +} + +type scanner interface { + Scan(dest ...any) error +} + +func scan(s scanner) (OfficialClimb, error) { + var ( + climb OfficialClimb + startLatitude, startLongitude float64 + endLatitude, endLongitude float64 + createdAt, updatedAt string + ) + if err := s.Scan(&climb.ID, &climb.Name, &startLatitude, &startLongitude, &endLatitude, &endLongitude, &createdAt, &updatedAt); err != nil { + return OfficialClimb{}, err + } + climb.StartCoord = geodist.Coord{Lat: startLatitude, Lon: startLongitude} + climb.EndCoord = geodist.Coord{Lat: endLatitude, Lon: endLongitude} + var err error + climb.CreatedAt, err = time.Parse(time.RFC3339, createdAt) + if err != nil { + return OfficialClimb{}, fmt.Errorf("invalid official_climbs.created_at: %w", err) + } + climb.UpdatedAt, err = time.Parse(time.RFC3339, updatedAt) + if err != nil { + return OfficialClimb{}, fmt.Errorf("invalid official_climbs.updated_at: %w", err) + } + return climb, nil +} |