Files
cheesy-arena-lite/model/database.go

156 lines
4.3 KiB
Go
Raw Normal View History

2014-05-24 00:39:22 -07:00
// Copyright 2014 Team 254. All Rights Reserved.
// Author: pat@patfairbank.com (Patrick Fairbank)
//
// Functions for manipulating the per-event SQLite datastore.
package model
2014-05-24 00:39:22 -07:00
import (
"bitbucket.org/liamstask/goose/lib/goose"
"database/sql"
"encoding/json"
2014-08-28 19:32:18 -07:00
"fmt"
"github.com/Team254/cheesy-arena-lite/game"
2014-05-24 00:39:22 -07:00
"github.com/jmoiron/modl"
_ "github.com/mattn/go-sqlite3"
"go.etcd.io/bbolt"
2014-08-28 19:32:18 -07:00
"io"
"os"
"path/filepath"
2014-08-28 19:32:18 -07:00
"strings"
"time"
2014-05-24 00:39:22 -07:00
)
2014-08-28 19:32:18 -07:00
const backupsDir = "db/backups"
2014-05-24 00:39:22 -07:00
const migrationsDir = "db/migrations"
var BaseDir = "." // Mutable for testing
2014-05-24 00:39:22 -07:00
type Database struct {
Path string
db *sql.DB
sponsorSlideMap *modl.DbMap
scheduleBlockMap *modl.DbMap
userSessionMap *modl.DbMap
bolt *bbolt.DB
allianceTeamTable *table
awardTable *table
eventSettingsTable *table
lowerThirdTable *table
matchTable *table
matchResultTable *table
rankingTable *table
teamTable *table
2014-05-24 00:39:22 -07:00
}
// Opens the SQLite database at the given path, creating it if it doesn't exist, and runs any pending
// migrations.
func OpenDatabase(filename string) (*Database, error) {
2014-05-24 00:39:22 -07:00
// Find and run the migrations using goose. This also auto-creates the DB.
database := Database{Path: filename}
migrationsPath := filepath.Join(BaseDir, migrationsDir)
dbDriver := goose.DBDriver{"sqlite3", database.Path, "github.com/mattn/go-sqlite3", &goose.Sqlite3Dialect{}}
dbConf := goose.DBConf{MigrationsDir: migrationsPath, Env: "prod", Driver: dbDriver}
target, err := goose.GetMostRecentDBVersion(migrationsPath)
2014-05-24 00:39:22 -07:00
if err != nil {
return nil, err
}
err = goose.RunMigrations(&dbConf, migrationsPath, target)
2014-05-24 00:39:22 -07:00
if err != nil {
return nil, err
}
db, err := sql.Open("sqlite3", database.Path)
2014-05-24 00:39:22 -07:00
if err != nil {
return nil, err
}
database.db = db
2014-05-24 00:39:22 -07:00
database.mapTables()
database.bolt, err = bbolt.Open(database.Path+".bolt", 0644, &bbolt.Options{NoSync: true, Timeout: time.Second})
if err != nil {
return nil, err
}
// Register tables.
if database.allianceTeamTable, err = database.newTable(AllianceTeam{}); err != nil {
return nil, err
}
if database.awardTable, err = database.newTable(Award{}); err != nil {
return nil, err
}
if database.eventSettingsTable, err = database.newTable(EventSettings{}); err != nil {
return nil, err
}
if database.lowerThirdTable, err = database.newTable(LowerThird{}); err != nil {
return nil, err
}
if database.matchTable, err = database.newTable(Match{}); err != nil {
return nil, err
}
if database.matchResultTable, err = database.newTable(MatchResult{}); err != nil {
return nil, err
}
if database.rankingTable, err = database.newTable(game.Ranking{}); err != nil {
return nil, err
}
if database.teamTable, err = database.newTable(Team{}); err != nil {
return nil, err
}
2014-05-24 00:39:22 -07:00
return &database, nil
}
func (database *Database) Close() error {
2014-05-24 00:39:22 -07:00
database.db.Close()
return database.bolt.Close()
2014-05-24 00:39:22 -07:00
}
2014-08-28 19:32:18 -07:00
// Creates a copy of the current database and saves it to the backups directory.
func (database *Database) Backup(eventName, reason string) error {
backupsPath := filepath.Join(BaseDir, backupsDir)
err := os.MkdirAll(backupsPath, 0755)
2014-08-28 19:32:18 -07:00
if err != nil {
return err
}
filename := fmt.Sprintf("%s/%s_%s_%s.db", backupsPath, strings.Replace(eventName, " ", "_", -1),
2014-08-28 21:44:22 -07:00
time.Now().Format("20060102150405"), reason)
src, err := os.Open(database.Path)
2014-08-28 19:32:18 -07:00
if err != nil {
return err
}
defer src.Close()
dest, err := os.Create(filename)
if err != nil {
return err
}
defer dest.Close()
if _, err := io.Copy(dest, src); err != nil {
return err
}
return nil
}
2014-05-24 00:39:22 -07:00
// Sets up table-object associations.
func (database *Database) mapTables() {
dialect := new(modl.SqliteDialect)
2014-08-25 20:18:37 -07:00
database.sponsorSlideMap = modl.NewDbMap(database.db, dialect)
database.sponsorSlideMap.AddTableWithName(SponsorSlide{}, "sponsor_slides").SetKeys(true, "Id")
2018-08-24 20:51:37 -07:00
database.scheduleBlockMap = modl.NewDbMap(database.db, dialect)
database.scheduleBlockMap.AddTableWithName(ScheduleBlock{}, "schedule_blocks").SetKeys(true, "Id")
database.userSessionMap = modl.NewDbMap(database.db, dialect)
database.userSessionMap.AddTableWithName(UserSession{}, "user_sessions").SetKeys(true, "Id")
2014-05-24 00:39:22 -07:00
}
func serializeHelper(target *string, source interface{}) error {
bytes, err := json.Marshal(source)
if err != nil {
return err
}
*target = string(bytes)
return nil
}