set sqlite user version after migration
This commit is contained in:
parent
969e17a169
commit
62e162e939
|
@ -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 = `
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -57,8 +57,7 @@ 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 {
|
||||||
name string
|
name string
|
||||||
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue