From dcf12634d41ccbfc54953293f2832d1f7c5f34a2 Mon Sep 17 00:00:00 2001 From: Vladimir Simakhin Date: Fri, 13 Dec 2024 09:51:36 +0100 Subject: [PATCH] add shcema version and check to exclude recreate views on every start up --- internal/driver/db_structure.go | 8 ++++ internal/driver/driver.go | 74 ++++++++++++++++++++++++++------- 2 files changed, 67 insertions(+), 15 deletions(-) diff --git a/internal/driver/db_structure.go b/internal/driver/db_structure.go index 6ed5725..5d8214c 100644 --- a/internal/driver/db_structure.go +++ b/internal/driver/db_structure.go @@ -1,6 +1,8 @@ package driver var ( + schemaVersion = "2.0.1" + UUID = ColumnType{SQLite: "TEXT", MySQL: "VARCHAR(36)"} DateTime = ColumnType{SQLite: "TEXT", MySQL: "VARCHAR(10)"} SmallText = ColumnType{SQLite: "TEXT", MySQL: "VARCHAR(255)"} @@ -12,6 +14,12 @@ var ( Blob = ColumnType{SQLite: "BLOB", MySQL: "LONGBLOB"} ) +var metadataTable = NewTable("metadata", "id", ColumnType{SQLite: "INTEGER", MySQL: "INT UNSIGNED AUTO_INCREMENT"}, + []Column{ + {Name: "version", Type: ColumnType{SQLite: "VARCHAR(32)", MySQL: "VARCHAR(32)"}, Properties: "NOT NULL"}, + {Name: "created_at", Type: DateTime}, + }) + var logbookTable = NewTable("logbook", "uuid", UUID, []Column{ {Name: "date", Type: DateTime, Properties: "NOT NULL"}, diff --git a/internal/driver/driver.go b/internal/driver/driver.go index ef2fbae..cd1cd93 100644 --- a/internal/driver/driver.go +++ b/internal/driver/driver.go @@ -4,6 +4,7 @@ import ( "context" "database/sql" "encoding/json" + "fmt" "time" _ "embed" @@ -39,32 +40,75 @@ func OpenDB(engine string, dsn string) (*sql.DB, error) { // validateDB creates db structure in case it's a first run and the schema is empty func validateDB(db *sql.DB, engine string) error { - // check tables - tables := []*Table{logbookTable, airportsTable, customAirportsTable, - settingsTable, licensingTable, attachmentsTable, sessionsTable, - } + metadataTable.initTable(db, engine) + isNewSchema := newShema(db) + if isNewSchema { + // check tables + tables := []*Table{logbookTable, airportsTable, customAirportsTable, + settingsTable, licensingTable, attachmentsTable, sessionsTable, + } + + for _, table := range tables { + if err := table.initTable(db, engine); err != nil { + return err + } + } + + // check views + views := []*View{logbookView, airportsView} + for _, view := range views { + if err := view.initView(db, engine); err != nil { + return err + } + } - for _, table := range tables { - if err := table.initTable(db, engine); err != nil { + // check settings table it's not empty + err := checkSettingsTable(db) + if err != nil { return err } - } - // check views - views := []*View{logbookView, airportsView} - for _, view := range views { - if err := view.initView(db, engine); err != nil { + // update schema version + err = updateSchemaVersion(db) + if err != nil { return err } } - // check settings table it's not empty - err := checkSettingsTable(db) + return nil +} + +func newShema(db *sql.DB) bool { + ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) + defer cancel() + + query := "SELECT version FROM metadata ORDER BY created_at DESC LIMIT 1" + var version string + err := db.QueryRowContext(ctx, query).Scan(&version) if err != nil { - return err + if err == sql.ErrNoRows { + fmt.Printf("No rows found in 'metadata'. Initializing version %s...\n", schemaVersion) + return true + } + fmt.Println(err) + return true } - return nil + if version != schemaVersion { + fmt.Printf("Schema version (%s) mismatch. Initializing version %s...\n", version, schemaVersion) + return true + } + + return false +} + +func updateSchemaVersion(db *sql.DB) error { + ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) + defer cancel() + + query := "INSERT INTO metadata (version, created_at) VALUES (?,?)" + _, err := db.ExecContext(ctx, query, schemaVersion, time.Now().Format("02.01.2006 15:04:05")) + return err } // checkSettingsTable verifies the proper transition to the new settings table