Files
box-box/internal/store/meetings.go

296 lines
7.3 KiB
Go

package store
import (
"database/sql"
"fmt"
"time"
)
// UpsertMeeting inserts or updates a meeting by meeting_key.
func (s *Store) UpsertMeeting(m Meeting) error {
if m.UpdatedAt.IsZero() {
m.UpdatedAt = time.Now()
}
_, err := s.db.Exec(`
INSERT INTO meetings (
meeting_key, meeting_name, meeting_official_name, location,
country_code, country_name, circuit_key, circuit_short_name,
gmt_offset, date_start, date_end, year, updated_at
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
ON CONFLICT(meeting_key) DO UPDATE SET
meeting_name = excluded.meeting_name,
meeting_official_name = excluded.meeting_official_name,
location = excluded.location,
country_code = excluded.country_code,
country_name = excluded.country_name,
circuit_key = excluded.circuit_key,
circuit_short_name = excluded.circuit_short_name,
gmt_offset = excluded.gmt_offset,
date_start = excluded.date_start,
date_end = excluded.date_end,
year = excluded.year,
updated_at = excluded.updated_at
`,
m.MeetingKey,
m.MeetingName,
nullString(m.MeetingOfficialName),
nullString(m.Location),
nullString(m.CountryCode),
nullString(m.CountryName),
nullableZeroInt(m.CircuitKey),
nullString(m.CircuitShortName),
nullString(m.GMTOffset),
nullString(m.DateStart),
nullString(m.DateEnd),
m.Year,
m.UpdatedAt.Unix(),
)
if err != nil {
return fmt.Errorf("upsert meeting: %w", err)
}
return nil
}
// GetMeeting returns a meeting by key.
func (s *Store) GetMeeting(meetingKey int) (Meeting, error) {
var m Meeting
var updatedAt int64
var officialName, location, countryCode, countryName sql.NullString
var circuitKey sql.NullInt64
var circuitShortName, gmtOffset, dateStart, dateEnd sql.NullString
err := s.db.QueryRow(`
SELECT meeting_key, meeting_name, meeting_official_name, location,
country_code, country_name, circuit_key, circuit_short_name,
gmt_offset, date_start, date_end, year, updated_at
FROM meetings
WHERE meeting_key = ?
`, meetingKey).Scan(
&m.MeetingKey,
&m.MeetingName,
&officialName,
&location,
&countryCode,
&countryName,
&circuitKey,
&circuitShortName,
&gmtOffset,
&dateStart,
&dateEnd,
&m.Year,
&updatedAt,
)
if err != nil {
return Meeting{}, err
}
m.MeetingOfficialName = officialName.String
m.Location = location.String
m.CountryCode = countryCode.String
m.CountryName = countryName.String
if circuitKey.Valid {
m.CircuitKey = int(circuitKey.Int64)
}
m.CircuitShortName = circuitShortName.String
m.GMTOffset = gmtOffset.String
m.DateStart = dateStart.String
m.DateEnd = dateEnd.String
m.UpdatedAt = time.Unix(updatedAt, 0)
return m, nil
}
// ListMeetingsByYear returns meetings for a season ordered by start date.
func (s *Store) ListMeetingsByYear(year int) ([]Meeting, error) {
rows, err := s.db.Query(`
SELECT meeting_key, meeting_name, meeting_official_name, location,
country_code, country_name, circuit_key, circuit_short_name,
gmt_offset, date_start, date_end, year, updated_at
FROM meetings
WHERE year = ?
ORDER BY date_start ASC, meeting_key ASC
`, year)
if err != nil {
return nil, err
}
defer rows.Close()
return scanMeetings(rows)
}
// UpsertSession inserts or updates a session by session_key.
func (s *Store) UpsertSession(sess Session) error {
if sess.UpdatedAt.IsZero() {
sess.UpdatedAt = time.Now()
}
_, err := s.db.Exec(`
INSERT INTO sessions (
session_key, meeting_key, session_name, session_type,
circuit_key, date_start, date_end, gmt_offset, updated_at
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
ON CONFLICT(session_key) DO UPDATE SET
meeting_key = excluded.meeting_key,
session_name = excluded.session_name,
session_type = excluded.session_type,
circuit_key = excluded.circuit_key,
date_start = excluded.date_start,
date_end = excluded.date_end,
gmt_offset = excluded.gmt_offset,
updated_at = excluded.updated_at
`,
sess.SessionKey,
sess.MeetingKey,
sess.SessionName,
sess.SessionType,
nullableZeroInt(sess.CircuitKey),
nullString(sess.DateStart),
nullString(sess.DateEnd),
nullString(sess.GMTOffset),
sess.UpdatedAt.Unix(),
)
if err != nil {
return fmt.Errorf("upsert session: %w", err)
}
return nil
}
// GetSession returns a session by key.
func (s *Store) GetSession(sessionKey int) (Session, error) {
var sess Session
var updatedAt int64
var circuitKey sql.NullInt64
var dateStart, dateEnd, gmtOffset sql.NullString
err := s.db.QueryRow(`
SELECT session_key, meeting_key, session_name, session_type,
circuit_key, date_start, date_end, gmt_offset, updated_at
FROM sessions
WHERE session_key = ?
`, sessionKey).Scan(
&sess.SessionKey,
&sess.MeetingKey,
&sess.SessionName,
&sess.SessionType,
&circuitKey,
&dateStart,
&dateEnd,
&gmtOffset,
&updatedAt,
)
if err != nil {
return Session{}, err
}
if circuitKey.Valid {
sess.CircuitKey = int(circuitKey.Int64)
}
sess.DateStart = dateStart.String
sess.DateEnd = dateEnd.String
sess.GMTOffset = gmtOffset.String
sess.UpdatedAt = time.Unix(updatedAt, 0)
return sess, nil
}
// ListSessionsByMeeting returns sessions for a meeting ordered by start time.
func (s *Store) ListSessionsByMeeting(meetingKey int) ([]Session, error) {
rows, err := s.db.Query(`
SELECT session_key, meeting_key, session_name, session_type,
circuit_key, date_start, date_end, gmt_offset, updated_at
FROM sessions
WHERE meeting_key = ?
ORDER BY date_start ASC, session_key ASC
`, meetingKey)
if err != nil {
return nil, err
}
defer rows.Close()
return scanSessions(rows)
}
func scanMeetings(rows *sql.Rows) ([]Meeting, error) {
var out []Meeting
for rows.Next() {
var m Meeting
var updatedAt int64
var officialName, location, countryCode, countryName sql.NullString
var circuitKey sql.NullInt64
var circuitShortName, gmtOffset, dateStart, dateEnd sql.NullString
if err := rows.Scan(
&m.MeetingKey,
&m.MeetingName,
&officialName,
&location,
&countryCode,
&countryName,
&circuitKey,
&circuitShortName,
&gmtOffset,
&dateStart,
&dateEnd,
&m.Year,
&updatedAt,
); err != nil {
return nil, err
}
m.MeetingOfficialName = officialName.String
m.Location = location.String
m.CountryCode = countryCode.String
m.CountryName = countryName.String
if circuitKey.Valid {
m.CircuitKey = int(circuitKey.Int64)
}
m.CircuitShortName = circuitShortName.String
m.GMTOffset = gmtOffset.String
m.DateStart = dateStart.String
m.DateEnd = dateEnd.String
m.UpdatedAt = time.Unix(updatedAt, 0)
out = append(out, m)
}
return out, rows.Err()
}
func scanSessions(rows *sql.Rows) ([]Session, error) {
var out []Session
for rows.Next() {
var sess Session
var updatedAt int64
var circuitKey sql.NullInt64
var dateStart, dateEnd, gmtOffset sql.NullString
if err := rows.Scan(
&sess.SessionKey,
&sess.MeetingKey,
&sess.SessionName,
&sess.SessionType,
&circuitKey,
&dateStart,
&dateEnd,
&gmtOffset,
&updatedAt,
); err != nil {
return nil, err
}
if circuitKey.Valid {
sess.CircuitKey = int(circuitKey.Int64)
}
sess.DateStart = dateStart.String
sess.DateEnd = dateEnd.String
sess.GMTOffset = gmtOffset.String
sess.UpdatedAt = time.Unix(updatedAt, 0)
out = append(out, sess)
}
return out, rows.Err()
}
func nullableZeroInt(v int) any {
if v == 0 {
return nil
}
return v
}