summaryrefslogtreecommitdiff
path: root/official_climb/repository.go
diff options
context:
space:
mode:
Diffstat (limited to 'official_climb/repository.go')
-rw-r--r--official_climb/repository.go97
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
+}