set sqlite user version after migration

This commit is contained in:
saji 2023-07-06 13:46:02 -05:00
parent 969e17a169
commit 62e162e939
3 changed files with 25 additions and 64 deletions

View file

@ -43,10 +43,6 @@ func OpenTelemDb(path string, options ...TelemDbOption) (tdb *TelemDb, err error
} }
} }
// execute database up statement (better hope it is idempotent!)
// FIXME: only do this when it's a new database (instead warn the user about potential version mismatches)
// TODO: store gotelem version (commit hash?) in DB (PRAGMA user_version)
var version int var version int
err = tdb.db.Get(&version, "PRAGMA user_version") err = tdb.db.Get(&version, "PRAGMA user_version")
if err != nil { if err != nil {
@ -56,66 +52,23 @@ func OpenTelemDb(path string, options ...TelemDbOption) (tdb *TelemDb, err error
// get latest version of migrations - then run the SQL in order. // get latest version of migrations - then run the SQL in order.
fmt.Printf("starting version %d\n", version) fmt.Printf("starting version %d\n", version)
version, err = RunMigrations(version, tdb) version, err = RunMigrations(tdb)
fmt.Printf("ending version %d\n", version) fmt.Printf("ending version %d\n", version)
return tdb, err return tdb, err
} }
// the sql commands to create the database. func (tdb *TelemDb) GetVersion() (int, error) {
const sqlDbUp = ` var version int
CREATE TABLE IF NOT EXISTS "bus_events" ( err := tdb.db.Get(&version, "PRAGMA user_version")
"ts" INTEGER NOT NULL, -- timestamp, unix milliseconds return version, err
"id" INTEGER NOT NULL, -- can ID }
"name" TEXT NOT NULL, -- name of base packet
"data" TEXT NOT NULL CHECK(json_valid(data)) -- JSON object describing the data, including index if any
);
CREATE INDEX IF NOT EXISTS "ids_timestamped" ON "bus_events" ( func (tdb *TelemDb) SetVersion(version int) error {
"id", stmt := fmt.Sprintf("PRAGMA user_version %d", version)
"ts" DESC _, err := tdb.db.Exec(stmt)
); return err
}
CREATE INDEX IF NOT EXISTS "times" ON "bus_events" (
"ts" DESC
);
-- this table shows when we started/stopped logging.
CREATE TABLE "drive_records" (
"id" INTEGER NOT NULL UNIQUE, -- unique ID of the drive.
"start_time" INTEGER NOT NULL, -- when the drive started
"end_time" INTEGER, -- when it ended, or NULL if it's ongoing.
"note" TEXT, -- optional description of the segment/experiment/drive
PRIMARY KEY("id" AUTOINCREMENT),
CONSTRAINT "duration_valid" CHECK(end_time is null or start_time < end_time)
);
-- gps logs TODO: use GEOJSON/Spatialite tracks instead?
CREATE TABLE "position_logs" (
"ts" INTEGER NOT NULL,
"source" TEXT NOT NULL,
"lat" REAL NOT NULL,
"lon" REAL NOT NULL,
"elevation" REAL,
CONSTRAINT "no_empty_source" CHECK(source is not "")
);
-- TODO: ensure only one "active" (end_time == null) drive record at a time using triggers/constraints/index
`
// sql sequence to tear down the database.
// not used often, but good to keep track of what's going on.
// Up() then Down() should result in an empty database.
const sqlDbDown = `
DROP TABLE "bus_events";
DROP INDEX "ids_timestamped";
DROP INDEX "times";
DROP TABLE "drive_records";
DROP TABLE "position_logs";
`
// sql expression to insert a bus event into the packets database.1 // sql expression to insert a bus event into the packets database.1
const sqlInsertEvent = ` const sqlInsertEvent = `

View file

@ -24,6 +24,9 @@ type Migration struct {
FileName string FileName string
} }
type MigrationError struct {
}
// getMigrations returns a list of migrations, which are correctly index. zero is nil. // getMigrations returns a list of migrations, which are correctly index. zero is nil.
func getMigrations(files fs.FS) map[int]map[string]Migration { func getMigrations(files fs.FS) map[int]map[string]Migration {
@ -60,8 +63,12 @@ func getMigrations(files fs.FS) map[int]map[string]Migration {
return res return res
} }
// use len to get the highest number migration. func RunMigrations(tdb *TelemDb) (finalVer int, err error) {
func RunMigrations(currentVer int, tdb *TelemDb) (finalVer int, err error) {
currentVer, err := tdb.GetVersion()
if err != nil {
return
}
migrations := getMigrations(migrationsFs) migrations := getMigrations(migrationsFs)
@ -122,10 +129,12 @@ func RunMigrations(currentVer int, tdb *TelemDb) (finalVer int, err error) {
} }
} }
// if all the versions applied correctly, update the PRAGMA user_version in the database.
tx.Commit() tx.Commit()
err = tdb.SetVersion(finalVer)
return return
// yeah, we use goto. Deal with it.
rollback: rollback:
tx.Rollback() tx.Rollback()
return return

View file

@ -57,7 +57,6 @@ func Test_getMigrations(t *testing.T) {
func TestRunMigrations(t *testing.T) { func TestRunMigrations(t *testing.T) {
type args struct { type args struct {
currentVer int
tdb *TelemDb tdb *TelemDb
} }
tests := []struct { tests := []struct {
@ -70,7 +69,7 @@ func TestRunMigrations(t *testing.T) {
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
gotFinalVer, err := RunMigrations(tt.args.currentVer, tt.args.tdb) gotFinalVer, err := RunMigrations(tt.args.tdb)
if (err != nil) != tt.wantErr { if (err != nil) != tt.wantErr {
t.Errorf("RunMigrations() error = %v, wantErr %v", err, tt.wantErr) t.Errorf("RunMigrations() error = %v, wantErr %v", err, tt.wantErr)
return return